diff --git a/lib/client/edit/ace.js b/lib/client/edit/ace.js
index 886d89d3..a1beaabc 100644
--- a/lib/client/edit/ace.js
+++ b/lib/client/edit/ace.js
@@ -30,7 +30,7 @@
(function() {
-var ACE_NAMESPACE = "";
+var ACE_NAMESPACE = "ace";
var global = (function() {
return this;
@@ -169,7 +169,7 @@ exportAce(ACE_NAMESPACE);
})();
-define('ace/ace', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/dom', 'ace/lib/event', 'ace/editor', 'ace/edit_session', 'ace/undomanager', 'ace/virtual_renderer', 'ace/multi_select', 'ace/worker/worker_client', 'ace/keyboard/hash_handler', 'ace/placeholder', 'ace/mode/folding/fold_mode', 'ace/theme/textmate', 'ace/config'], function(require, exports, module) {
+ace.define('ace/ace', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/dom', 'ace/lib/event', 'ace/editor', 'ace/edit_session', 'ace/undomanager', 'ace/virtual_renderer', 'ace/multi_select', 'ace/worker/worker_client', 'ace/keyboard/hash_handler', 'ace/placeholder', 'ace/mode/folding/fold_mode', 'ace/theme/textmate', 'ace/config'], function(require, exports, module) {
require("./lib/fixoldbrowsers");
@@ -229,7 +229,7 @@ exports.EditSession = EditSession;
exports.UndoManager = UndoManager;
});
-define('ace/lib/fixoldbrowsers', ['require', 'exports', 'module' , 'ace/lib/regexp', 'ace/lib/es5-shim'], function(require, exports, module) {
+ace.define('ace/lib/fixoldbrowsers', ['require', 'exports', 'module' , 'ace/lib/regexp', 'ace/lib/es5-shim'], function(require, exports, module) {
require("./regexp");
@@ -237,7 +237,7 @@ require("./es5-shim");
});
-define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, exports, module) {
var real = {
exec: RegExp.prototype.exec,
@@ -309,7 +309,7 @@ define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, ex
});
-define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) {
function Empty() {}
@@ -1006,7 +1006,7 @@ var toObject = function (o) {
});
-define('ace/lib/dom', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/dom', ['require', 'exports', 'module' ], function(require, exports, module) {
if (typeof document == "undefined")
@@ -1239,7 +1239,7 @@ exports.getParentWindow = function(document) {
});
-define('ace/lib/event', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/useragent', 'ace/lib/dom'], function(require, exports, module) {
+ace.define('ace/lib/event', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/useragent', 'ace/lib/dom'], function(require, exports, module) {
var keys = require("./keys");
@@ -1341,9 +1341,9 @@ else {
}
exports.addMouseWheelListener = function(el, callback) {
- var factor = 8;
- var listener = function(e) {
- if (e.wheelDelta !== undefined) {
+ if ("onmousewheel" in el) {
+ var factor = 8;
+ exports.addListener(el, "mousewheel", function(e) {
if (e.wheelDeltaX !== undefined) {
e.wheelX = -e.wheelDeltaX / factor;
e.wheelY = -e.wheelDeltaY / factor;
@@ -1351,8 +1351,16 @@ exports.addMouseWheelListener = function(el, callback) {
e.wheelX = 0;
e.wheelY = -e.wheelDelta / factor;
}
- }
- else {
+ callback(e);
+ });
+ } else if ("onwheel" in el) {
+ exports.addListener(el, "wheel", function(e) {
+ e.wheelX = (e.deltaX || 0) * 5;
+ e.wheelY = (e.deltaY || 0) * 5;
+ callback(e);
+ });
+ } else {
+ exports.addListener(el, "DOMMouseScroll", function(e) {
if (e.axis && e.axis == e.HORIZONTAL_AXIS) {
e.wheelX = (e.detail || 0) * 5;
e.wheelY = 0;
@@ -1360,11 +1368,9 @@ exports.addMouseWheelListener = function(el, callback) {
e.wheelX = 0;
e.wheelY = (e.detail || 0) * 5;
}
- }
- callback(e);
- };
- exports.addListener(el, "DOMMouseScroll", listener);
- exports.addListener(el, "mousewheel", listener);
+ callback(e);
+ });
+ }
};
exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbackName) {
@@ -1426,6 +1432,29 @@ function normalizeCommandKeys(callback, e, keyCode) {
| (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0);
}
+ if (!useragent.isMac && pressedKeys) {
+ if (pressedKeys[91] || pressedKeys[92])
+ hashId |= 8;
+ if (pressedKeys.altGr) {
+ if ((3 & hashId) != 3)
+ pressedKeys.altGr = 0
+ else
+ return;
+ }
+ if (keyCode == 18 || keyCode == 17) {
+ var location = e.location || e.keyLocation;
+ if (keyCode == 17 && location == 1) {
+ ts = e.timeStamp;
+ } else if (keyCode == 18 && hashId == 3 && location == 2) {
+ var dt = -ts;
+ ts = e.timeStamp;
+ dt += ts;
+ if (dt < 3)
+ pressedKeys.altGr = true;
+ }
+ }
+ }
+
if (keyCode in keys.MODIFIER_KEYS) {
switch (keys.MODIFIER_KEYS[keyCode]) {
case "Alt":
@@ -1444,19 +1473,28 @@ function normalizeCommandKeys(callback, e, keyCode) {
keyCode = 0;
}
- if (!useragent.isMac && pressedKeys[91] || pressedKeys[92])
- hashId |= 8;
-
if (hashId & 8 && (keyCode == 91 || keyCode == 93)) {
keyCode = 0;
}
+
+ if (!hashId && keyCode == 13) {
+ if (e.keyLocation || e.location == 3) {
+ callback(e, hashId, -keyCode)
+ if (e.defaultPrevented)
+ return;
+ }
+ }
if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) {
return false;
}
+
+
+
return callback(e, hashId, keyCode);
}
-var pressedKeys = Object.create(null);
+var pressedKeys = null;
+var ts = 0;
exports.addCommandKeyListener = function(el, callback) {
var addListener = exports.addListener;
if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) {
@@ -1488,9 +1526,12 @@ exports.addCommandKeyListener = function(el, callback) {
pressedKeys[e.keyCode] = null;
});
- addListener(el, "focus", function(e) {
+ if (!pressedKeys) {
pressedKeys = Object.create(null);
- });
+ addListener(window, "focus", function(e) {
+ pressedKeys = Object.create(null);
+ });
+ }
}
};
@@ -1525,7 +1566,7 @@ else
};
});
-define('ace/lib/keys', ['require', 'exports', 'module' , 'ace/lib/oop'], function(require, exports, module) {
+ace.define('ace/lib/keys', ['require', 'exports', 'module' , 'ace/lib/oop'], function(require, exports, module) {
var oop = require("./oop");
@@ -1568,6 +1609,7 @@ var Keys = (function() {
103: "Numpad7",
104: "Numpad8",
105: "Numpad9",
+ '-13': "NumpadEnter",
112: "F1",
113: "F2",
114: "F3",
@@ -1617,7 +1659,7 @@ exports.keyCodeToString = function(keyCode) {
});
-define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
exports.inherits = (function() {
@@ -1643,7 +1685,7 @@ exports.implement = function(proto, mixin) {
});
-define('ace/lib/useragent', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/useragent', ['require', 'exports', 'module' ], function(require, exports, module) {
exports.OS = {
LINUX: "LINUX",
MAC: "MAC",
@@ -1686,7 +1728,7 @@ exports.isTouchPad = ua.indexOf("TouchPad") >= 0;
});
-define('ace/editor', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/lang', 'ace/lib/useragent', 'ace/keyboard/textinput', 'ace/mouse/mouse_handler', 'ace/mouse/fold_handler', 'ace/keyboard/keybinding', 'ace/edit_session', 'ace/search', 'ace/range', 'ace/lib/event_emitter', 'ace/commands/command_manager', 'ace/commands/default_commands', 'ace/config'], function(require, exports, module) {
+ace.define('ace/editor', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/lang', 'ace/lib/useragent', 'ace/keyboard/textinput', 'ace/mouse/mouse_handler', 'ace/mouse/fold_handler', 'ace/keyboard/keybinding', 'ace/edit_session', 'ace/search', 'ace/range', 'ace/lib/event_emitter', 'ace/commands/command_manager', 'ace/commands/default_commands', 'ace/config'], function(require, exports, module) {
require("./lib/fixoldbrowsers");
@@ -1723,6 +1765,11 @@ var Editor = function(renderer, session) {
wrap: true
});
+ this.$historyTracker = this.$historyTracker.bind(this);
+ this.commands.on("exec", this.$historyTracker);
+
+ this.$initOperationListeners();
+
this.setSession(session || new EditSession(""));
config.resetOptions(this);
config._emit("editor", this);
@@ -1731,6 +1778,114 @@ var Editor = function(renderer, session) {
(function(){
oop.implement(this, EventEmitter);
+
+ this.$initOperationListeners = function() {
+ function last(a) {return a[a.length - 1]};
+
+ this.selections = [];
+ this.commands.on("exec", function(e) {
+ this.startOperation(e);
+
+ var command = e.command;
+ if (command.group == "fileJump") {
+ var prev = this.prevOp;
+ if (!prev || prev.command.group != "fileJump") {
+ this.lastFileJumpPos = last(this.selections)
+ }
+ } else {
+ this.lastFileJumpPos = null;
+ }
+ }.bind(this), true);
+
+ this.commands.on("afterExec", function(e) {
+ var command = e.command;
+
+ if (command.group == "fileJump") {
+ if (this.lastFileJumpPos && !this.curOp.selectionChanged) {
+ this.selection.fromJSON(this.lastFileJumpPos);
+ return
+ }
+ }
+ this.endOperation(e);
+ }.bind(this), true);
+
+ this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this));
+
+ this.on("change", function() {
+ this.curOp || this.startOperation();
+ this.curOp.docChanged = true;
+ }.bind(this), true);
+
+ this.on("changeSelection", function() {
+ this.curOp || this.startOperation();
+ this.curOp.selectionChanged = true;
+ }.bind(this), true);
+ }
+
+ this.curOp = null;
+ this.prevOp = {};
+ this.startOperation = function(commadEvent) {
+ if (this.curOp) {
+ if (!commadEvent || this.curOp.command)
+ return;
+ this.prevOp = this.curOp;
+ }
+ if (!commadEvent) {
+ this.previousCommand = null;
+ commadEvent = {};
+ }
+
+ this.$opResetTimer.schedule();
+ this.curOp = {
+ command: commadEvent.command || {},
+ args: commadEvent.args
+ };
+
+ this.selections.push(this.selection.toJSON());
+ };
+
+ this.endOperation = function() {
+ if (this.curOp) {
+ this.prevOp = this.curOp;
+ this.curOp = null;
+ }
+ };
+
+ this.$historyTracker = function(e) {
+ if (!this.$mergeUndoDeltas)
+ return;
+
+
+ var prev = this.prevOp;
+ var mergeableCommands = ["backspace", "del", "insertstring"];
+ var shouldMerge = prev.command && (e.command.name == prev.command.name);
+ if (e.command.name == "insertstring") {
+ var text = e.args;
+ if (this.mergeNextCommand === undefined)
+ this.mergeNextCommand = true;
+
+ shouldMerge = shouldMerge
+ && this.mergeNextCommand // previous command allows to coalesce with
+ && (!/\s/.test(text) || /\s/.test(prev.args)) // previous insertion was of same type
+
+ this.mergeNextCommand = true;
+ } else {
+ shouldMerge = shouldMerge
+ && mergeableCommands.indexOf(e.command.name) !== -1// the command is mergeable
+ }
+
+ if (
+ this.$mergeUndoDeltas != "always"
+ && Date.now() - this.sequenceStartTime > 2000
+ ) {
+ shouldMerge = false; // the sequence is too long
+ }
+
+ if (shouldMerge)
+ this.session.mergeUndoDeltas = true;
+ else if (mergeableCommands.indexOf(e.command.name) !== -1)
+ this.sequenceStartTime = Date.now();
+ };
this.setKeyboardHandler = function(keyboardHandler) {
if (!keyboardHandler) {
this.keyBinding.setKeyboardHandler(null);
@@ -1995,6 +2150,8 @@ var Editor = function(renderer, session) {
if (this.$highlightActiveLine) {
if ((this.$selectionStyle != "line" || !this.selection.isMultiLine()))
highlight = this.getCursorPosition();
+ if (this.renderer.$maxLines && this.session.getLength() === 1)
+ highlight = false;
}
if (session.$highlightLineMarker && !highlight) {
@@ -2135,13 +2292,21 @@ var Editor = function(renderer, session) {
if (this.getBehavioursEnabled()) {
var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text);
- if (transform)
+ if (transform) {
+ if (text !== transform.text) {
+ this.session.mergeUndoDeltas = false;
+ this.$mergeNextCommand = false;
+ }
text = transform.text;
- }
- text = text.replace("\t", this.session.getTabString());
+ }
+ }
+
+ if (text == "\t")
+ text = this.session.getTabString();
if (!this.selection.isEmpty()) {
- cursor = this.session.remove(this.getSelectionRange());
+ var range = this.getSelectionRange();
+ cursor = this.session.remove(range);
this.clearSelection();
}
else if (this.session.getOverwrite()) {
@@ -2150,6 +2315,13 @@ var Editor = function(renderer, session) {
this.session.remove(range);
}
+ if (text == "\n" || text == "\r\n") {
+ var line = session.getLine(cursor.row)
+ if (cursor.column > line.search(/\S|$/)) {
+ var d = line.substr(cursor.column).search(/\S|$/);
+ session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d);
+ }
+ }
this.clearSelection();
var start = cursor.column;
@@ -2171,41 +2343,11 @@ var Editor = function(renderer, session) {
transform.selection[3]));
}
}
+
if (session.getDocument().isNewLine(text)) {
var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString());
- this.moveCursorTo(cursor.row+1, 0);
-
- var size = session.getTabSize();
- var minIndent = Number.MAX_VALUE;
-
- for (var row = cursor.row + 1; row <= end.row; ++row) {
- var indent = 0;
-
- line = session.getLine(row);
- for (var i = 0; i < line.length; ++i)
- if (line.charAt(i) == '\t')
- indent += size;
- else if (line.charAt(i) == ' ')
- indent += 1;
- else
- break;
- if (/[^\s]/.test(line))
- minIndent = Math.min(indent, minIndent);
- }
-
- for (var row = cursor.row + 1; row <= end.row; ++row) {
- var outdent = minIndent;
-
- line = session.getLine(row);
- for (var i = 0; i < line.length && outdent > 0; ++i)
- if (line.charAt(i) == '\t')
- outdent -= size;
- else if (line.charAt(i) == ' ')
- outdent -= 1;
- session.remove(new Range(row, 0, row, i));
- }
- session.indentRows(cursor.row + 1, end.row, lineIndent);
+ session.insert({row: cursor.row+1, column: 0}, lineIndent);
}
if (shouldOutdent)
mode.autoOutdent(lineState, session, cursor.row);
@@ -2344,6 +2486,16 @@ var Editor = function(renderer, session) {
var session = this.session;
var state = session.getState(range.start.row);
var new_range = session.getMode().transformAction(state, 'deletion', this, session, range);
+
+ if (range.end.column == 0) {
+ var text = session.getTextRange(range);
+ if (text[text.length - 1] == "\n") {
+ var line = session.getLine(range.end.row)
+ if (/^\s+$/.test(line)) {
+ range.end.column = line.length
+ }
+ }
+ }
if (new_range)
range = new_range;
}
@@ -2443,23 +2595,37 @@ var Editor = function(renderer, session) {
var session = this.session;
var range = this.getSelectionRange();
- if (range.start.row < range.end.row || range.start.column < range.end.column) {
+ if (range.start.row < range.end.row) {
var rows = this.$getSelectedRows();
session.indentRows(rows.first, rows.last, "\t");
- } else {
- var indentString;
-
- if (this.session.getUseSoftTabs()) {
- var size = session.getTabSize(),
- position = this.getCursorPosition(),
- column = session.documentToScreenColumn(position.row, position.column),
- count = (size - column % size);
-
- indentString = lang.stringRepeat(" ", count);
- } else
- indentString = "\t";
- return this.insert(indentString);
+ return;
+ } else if (range.start.column < range.end.column) {
+ var text = session.getTextRange(range)
+ if (!/^\s+$/.test(text)) {
+ var rows = this.$getSelectedRows();
+ session.indentRows(rows.first, rows.last, "\t");
+ return;
+ }
}
+
+ var line = session.getLine(range.start.row)
+ var position = range.start;
+ var size = session.getTabSize();
+ var column = session.documentToScreenColumn(position.row, position.column);
+
+ if (this.session.getUseSoftTabs()) {
+ var count = (size - column % size);
+ var indentString = lang.stringRepeat(" ", count);
+ } else {
+ var count = column % size;
+ while (line[range.start.column] == " " && count) {
+ range.start.column--;
+ count--;
+ }
+ this.selection.setSelectionRange(range);
+ indentString = "\t";
+ }
+ return this.insert(indentString);
};
this.blockIndent = function() {
var rows = this.$getSelectedRows();
@@ -3099,6 +3265,10 @@ config.defineOptions(Editor.prototype, "editor", {
values: ["ace", "slim", "smooth", "wide"],
initialValue: "ace"
},
+ mergeUndoDeltas: {
+ values: [false, true, "always"],
+ initialValue: true
+ },
behavioursEnabled: {initialValue: true},
wrapBehavioursEnabled: {initialValue: true},
@@ -3115,6 +3285,9 @@ config.defineOptions(Editor.prototype, "editor", {
displayIndentGuides: "renderer",
fontSize: "renderer",
fontFamily: "renderer",
+ maxLines: "renderer",
+ minLines: "renderer",
+ scrollPastEnd: "renderer",
scrollSpeed: "$mouseHandler",
dragDelay: "$mouseHandler",
@@ -3133,7 +3306,7 @@ config.defineOptions(Editor.prototype, "editor", {
exports.Editor = Editor;
});
-define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
exports.stringReverse = function(string) {
@@ -3310,7 +3483,7 @@ exports.delayedCall = function(fcn, defaultTimeout) {
};
});
-define('ace/keyboard/textinput', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent', 'ace/lib/dom', 'ace/lib/lang'], function(require, exports, module) {
+ace.define('ace/keyboard/textinput', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent', 'ace/lib/dom', 'ace/lib/lang'], function(require, exports, module) {
var event = require("../lib/event");
@@ -3445,10 +3618,13 @@ var TextInput = function(parentNode, host) {
if (inComposition && (!text.value || keytable[e.keyCode]))
setTimeout(onCompositionEnd, 0);
if ((text.value.charCodeAt(0)||0) < 129) {
- return;
+ return syncProperty.call();
}
inComposition ? onCompositionUpdate() : onCompositionStart();
});
+ event.addListener(text, "keydown", function (e) {
+ syncProperty.schedule(50);
+ });
}
var onSelect = function(e) {
@@ -3692,7 +3868,7 @@ var TextInput = function(parentNode, host) {
text.style.cssText = "z-index:100000;" + (useragent.isIE ? "opacity:0.1;" : "");
resetSelection(host.selection.isEmpty());
- host._emit("nativecontextmenu", {target: host});
+ host._emit("nativecontextmenu", {target: host, domEvent: e});
var rect = host.container.getBoundingClientRect();
var style = dom.computedStyle(host.container);
var top = rect.top + (parseInt(style.borderTopWidth) || 0);
@@ -3726,7 +3902,7 @@ var TextInput = function(parentNode, host) {
}
}, 0);
}
- if (!useragent.isGecko) {
+ if (!useragent.isGecko || useragent.isMac) {
event.addListener(text, "contextmenu", function(e) {
host.textInput.onContextMenu(e);
onContextMenuClose();
@@ -3737,7 +3913,7 @@ var TextInput = function(parentNode, host) {
exports.TextInput = TextInput;
});
-define('ace/mouse/mouse_handler', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent', 'ace/mouse/default_handlers', 'ace/mouse/default_gutter_handler', 'ace/mouse/mouse_event', 'ace/mouse/dragdrop', 'ace/config'], function(require, exports, module) {
+ace.define('ace/mouse/mouse_handler', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent', 'ace/mouse/default_handlers', 'ace/mouse/default_gutter_handler', 'ace/mouse/mouse_event', 'ace/mouse/dragdrop', 'ace/config'], function(require, exports, module) {
var event = require("../lib/event");
@@ -3755,11 +3931,6 @@ var MouseHandler = function(editor) {
new DefaultGutterHandler(this);
new DragdropHandler(this);
- event.addListener(editor.container, "mousedown", function(e) {
- editor.focus();
- return event.preventDefault(e);
- });
-
var mouseTarget = editor.renderer.getMouseEventTarget();
event.addListener(mouseTarget, "click", this.onMouseEvent.bind(this, "click"));
event.addListener(mouseTarget, "mousemove", this.onMouseMove.bind(this, "mousemove"));
@@ -3771,6 +3942,16 @@ var MouseHandler = function(editor) {
event.addListener(gutterEl, "click", this.onMouseEvent.bind(this, "gutterclick"));
event.addListener(gutterEl, "dblclick", this.onMouseEvent.bind(this, "gutterdblclick"));
event.addListener(gutterEl, "mousemove", this.onMouseEvent.bind(this, "guttermousemove"));
+
+ event.addListener(mouseTarget, "mousedown", function(e) {
+ editor.focus();
+ return event.preventDefault(e);
+ });
+
+ event.addListener(gutterEl, "mousedown", function(e) {
+ editor.focus();
+ return event.preventDefault(e);
+ });
};
(function() {
@@ -3835,7 +4016,7 @@ var MouseHandler = function(editor) {
};
if (useragent.isOldIE && ev.domEvent.type == "dblclick") {
- return setTimeout(function() {onCaptureEnd(ev.domEvent);});
+ return setTimeout(function() {onCaptureEnd(ev);});
}
event.capture(this.editor.container, onMouseMove, onCaptureEnd);
@@ -3853,7 +4034,7 @@ config.defineOptions(MouseHandler.prototype, "mouseHandler", {
exports.MouseHandler = MouseHandler;
});
-define('ace/mouse/default_handlers', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/useragent'], function(require, exports, module) {
+ace.define('ace/mouse/default_handlers', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/useragent'], function(require, exports, module) {
var dom = require("../lib/dom");
@@ -4153,7 +4334,7 @@ function calcRangeOrientation(range, cursor) {
});
-define('ace/mouse/default_gutter_handler', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/event'], function(require, exports, module) {
+ace.define('ace/mouse/default_gutter_handler', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/event'], function(require, exports, module) {
var dom = require("../lib/dom");
var event = require("../lib/event");
@@ -4163,7 +4344,7 @@ function GutterHandler(mouseHandler) {
var gutter = editor.renderer.$gutterLayer;
mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) {
- if (!editor.isFocused())
+ if (!editor.isFocused() || e.getButton() != 0)
return;
var gutterRegion = gutter.getRegion(e);
@@ -4275,14 +4456,15 @@ function GutterHandler(mouseHandler) {
hideTooltip();
}, 50);
});
-
+
+ editor.on("changeSession", hideTooltip);
}
exports.GutterHandler = GutterHandler;
});
-define('ace/mouse/mouse_event', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent'], function(require, exports, module) {
+ace.define('ace/mouse/mouse_event', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent'], function(require, exports, module) {
var event = require("../lib/event");
@@ -4359,7 +4541,7 @@ var MouseEvent = exports.MouseEvent = function(domEvent, editor) {
});
-define('ace/mouse/dragdrop', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
+ace.define('ace/mouse/dragdrop', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
var event = require("../lib/event");
@@ -4451,7 +4633,7 @@ var DragdropHandler = function(mouseHandler) {
exports.DragdropHandler = DragdropHandler;
});
-define('ace/config', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/lib/net', 'ace/lib/event_emitter'], function(require, exports, module) {
+ace.define('ace/config', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/lib/net', 'ace/lib/event_emitter'], function(require, exports, module) {
"no use strict";
var lang = require("./lib/lang");
@@ -4498,16 +4680,24 @@ exports.moduleUrl = function(name, component) {
var parts = name.split("/");
component = component || parts[parts.length - 2] || "";
- var base = parts[parts.length - 1].replace(component, "").replace(/(^[\-_])|([\-_]$)/, "");
+ var sep = component == "snippets" ? "/" : "-";
+ var base = parts[parts.length - 1];
+ if (sep == "-") {
+ var re = new RegExp("^" + component + "[\-_]|[\-_]" + component + "$", "g");
+ base = base.replace(re, "");
+ }
- if (!base && parts.length > 1)
+ if ((!base || base == component) && parts.length > 1)
base = parts[parts.length - 2];
var path = options[component + "Path"];
- if (path == null)
+ if (path == null) {
path = options.basePath;
+ } else if (sep == "/") {
+ component = sep = "";
+ }
if (path && path.slice(-1) != "/")
path += "/";
- return path + component + "-" + base + this.get("suffix");
+ return path + component + sep + base + this.get("suffix");
};
exports.setModuleUrl = function(name, subst) {
@@ -4689,7 +4879,7 @@ exports.setDefaultValues = function(path, optionHash) {
};
});
-define('ace/lib/net', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
+ace.define('ace/lib/net', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
var dom = require("./dom");
@@ -4722,7 +4912,7 @@ exports.loadScript = function(path, callback) {
});
-define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) {
var EventEmitter = {};
@@ -4847,7 +5037,7 @@ exports.EventEmitter = EventEmitter;
});
-define('ace/mouse/fold_handler', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/mouse/fold_handler', ['require', 'exports', 'module' ], function(require, exports, module) {
function FoldHandler(editor) {
@@ -4909,7 +5099,7 @@ exports.FoldHandler = FoldHandler;
});
-define('ace/keyboard/keybinding', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/event'], function(require, exports, module) {
+ace.define('ace/keyboard/keybinding', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/event'], function(require, exports, module) {
var keyUtil = require("../lib/keys");
@@ -5010,7 +5200,7 @@ var KeyBinding = function(editor) {
exports.KeyBinding = KeyBinding;
});
-define('ace/edit_session', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/config', 'ace/lib/event_emitter', 'ace/selection', 'ace/mode/text', 'ace/range', 'ace/document', 'ace/background_tokenizer', 'ace/search_highlight', 'ace/edit_session/folding', 'ace/edit_session/bracket_match'], function(require, exports, module) {
+ace.define('ace/edit_session', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/config', 'ace/lib/event_emitter', 'ace/selection', 'ace/mode/text', 'ace/range', 'ace/document', 'ace/background_tokenizer', 'ace/search_highlight', 'ace/edit_session/folding', 'ace/edit_session/bracket_match'], function(require, exports, module) {
var oop = require("./lib/oop");
@@ -5216,10 +5406,11 @@ var EditSession = function(text, mode) {
if (self.$deltas.length > 0) {
undoManager.execute({
action: "aceupdate",
- args: [self.$deltas, self]
+ args: [self.$deltas, self],
+ merge: self.mergeUndoDeltas
});
}
-
+ self.mergeUndoDeltas = false;
self.$deltas = [];
}
this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager);
@@ -5249,7 +5440,7 @@ var EditSession = function(text, mode) {
this.setOption("useSoftTabs", val);
};
this.getUseSoftTabs = function() {
- return this.$useSoftTabs;
+ return this.$useSoftTabs && !this.$mode.$indentWithTabs;
};
this.setTabSize = function(tabSize) {
this.setOption("tabSize", tabSize)
@@ -5458,7 +5649,7 @@ var EditSession = function(text, mode) {
this.$modes = {};
this.$mode = null;
this.$modeId = null;
- this.setMode = function(mode) {
+ this.setMode = function(mode, cb) {
if (mode && typeof mode === "object") {
if (mode.getTokenizer)
return this.$onChangeMode(mode);
@@ -5475,7 +5666,7 @@ var EditSession = function(text, mode) {
this.$modeId = path;
config.loadModule(["mode", path], function(m) {
if (this.$modeId !== path)
- return;
+ return cb && cb();
if (this.$modes[path] && !options)
return this.$onChangeMode(this.$modes[path]);
if (m && m.Mode) {
@@ -5484,7 +5675,8 @@ var EditSession = function(text, mode) {
this.$modes[path] = m;
m.$id = path;
}
- this.$onChangeMode(m)
+ this.$onChangeMode(m);
+ cb && cb(this.mode);
}
}.bind(this));
if (!this.$mode)
@@ -5492,7 +5684,11 @@ var EditSession = function(text, mode) {
};
this.$onChangeMode = function(mode, $isPlaceholder) {
- if (this.$mode === mode) return;
+ if (!$isPlaceholder)
+ this.$modeId = mode.$id;
+ if (this.$mode === mode)
+ return;
+
this.$mode = mode;
this.$stopWorker();
@@ -5524,7 +5720,6 @@ var EditSession = function(text, mode) {
if (!$isPlaceholder) {
- this.$modeId = mode.$id;
this.$setFolding(mode.foldingRules);
this._emit("changeMode");
this.bgTokenizer.start(0);
@@ -5558,7 +5753,7 @@ var EditSession = function(text, mode) {
this.$scrollTop = 0;
this.setScrollTop = function(scrollTop) {
- scrollTop = Math.round(Math.max(0, scrollTop));
+ scrollTop = Math.round(scrollTop);
if (this.$scrollTop === scrollTop || isNaN(scrollTop))
return;
@@ -5571,7 +5766,7 @@ var EditSession = function(text, mode) {
this.$scrollLeft = 0;
this.setScrollLeft = function(scrollLeft) {
- scrollLeft = Math.round(Math.max(0, scrollLeft));
+ scrollLeft = Math.round(scrollLeft);
if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft))
return;
@@ -5698,7 +5893,7 @@ var EditSession = function(text, mode) {
var range, point;
var lastDeltaIsInsert = false;
if (isInsert(delta)) {
- range = delta.range.clone();
+ range = Range.fromPoints(delta.range.start, delta.range.end);
lastDeltaIsInsert = true;
} else {
range = Range.fromPoints(delta.range.start, delta.range.start);
@@ -5727,6 +5922,11 @@ var EditSession = function(text, mode) {
}
}
if (lastUndoRange != null) {
+ if (Range.comparePoints(lastUndoRange.start, range.start) == 0) {
+ lastUndoRange.start.column += range.end.column - range.start.column;
+ lastUndoRange.end.column += range.end.column - range.start.column;
+ }
+
var cmp = lastUndoRange.compareRange(range);
if (cmp == 1) {
range.setStart(lastUndoRange.start);
@@ -6631,7 +6831,7 @@ config.defineOptions(EditSession.prototype, "session", {
exports.EditSession = EditSession;
});
-define('ace/selection', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/event_emitter', 'ace/range'], function(require, exports, module) {
+ace.define('ace/selection', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/event_emitter', 'ace/range'], function(require, exports, module) {
var oop = require("./lib/oop");
@@ -6756,6 +6956,8 @@ var Selection = function(session) {
this.setSelectionAnchor(range.start.row, range.start.column);
this.selectTo(range.end.row, range.end.column);
}
+ if (this.getRange().isEmpty())
+ this.$isEmpty = true;
this.$desiredColumn = null;
};
@@ -7007,7 +7209,7 @@ var Selection = function(session) {
while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch))
index ++;
- if (index <= 1) {
+ if (index < 1) {
tokenRe.lastIndex = 0;
while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) {
tokenRe.lastIndex = 0;
@@ -7043,11 +7245,11 @@ var Selection = function(session) {
if (column == line.length) {
var l = this.doc.getLength();
- do {
+ do {
row++;
rightOfCursor = this.doc.getLine(row)
} while (row < l && /^\s*$/.test(rightOfCursor))
-
+
if (!/^\s+/.test(rightOfCursor))
rightOfCursor = ""
column = 0;
@@ -7068,11 +7270,11 @@ var Selection = function(session) {
var line = this.session.getLine(row).substring(0, column);
if (column == 0) {
- do {
+ do {
row--;
line = this.doc.getLine(row);
} while (row > 0 && /^\s*$/.test(line))
-
+
column = line.length;
if (!/\s+$/.test(line))
line = ""
@@ -7161,12 +7363,58 @@ var Selection = function(session) {
return range;
}
+ this.toJSON = function() {
+ if (this.rangeCount) {
+ var data = this.ranges.map(function(r) {
+ var r1 = r.clone();
+ r1.isBackwards = r.cursor == r.start;
+ return r1;
+ });
+ } else {
+ var data = this.getRange();
+ data.isBackwards = this.isBackwards();
+ }
+ return data;
+ };
+
+ this.fromJSON = function(data) {
+ if (data.start == undefined) {
+ if (this.rangeList) {
+ this.toSingleRange(data[0]);
+ for (var i = data.length; i--; ) {
+ var r = Range.fromPoints(data[i].start, data[i].end);
+ if (data.isBackwards)
+ r.cursor = r.start;
+ this.addRange(r, true);
+ }
+ return;
+ } else
+ data = data[0];
+ }
+ if (this.rangeList)
+ this.toSingleRange(data);
+ this.setSelectionRange(data, data.isBackwards);
+ };
+
+ this.isEqual = function(data) {
+ if ((data.length || this.rangeCount) && data.length != this.rangeCount)
+ return false;
+ if (!data.length || !this.ranges)
+ return this.getRange().isEqual(data);
+
+ for (var i = this.ranges.length; i--; ) {
+ if (!this.ranges[i].isEqual(data[i]))
+ return false
+ }
+ return true;
+ }
+
}).call(Selection.prototype);
exports.Selection = Selection;
});
-define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) {
var comparePoints = function(p1, p2) {
return p1.row - p2.row || p1.column - p2.column;
@@ -7405,7 +7653,7 @@ Range.comparePoints = function(p1, p2) {
exports.Range = Range;
});
-define('ace/mode/text', ['require', 'exports', 'module' , 'ace/tokenizer', 'ace/mode/text_highlight_rules', 'ace/mode/behaviour', 'ace/unicode', 'ace/lib/lang', 'ace/token_iterator', 'ace/range'], function(require, exports, module) {
+ace.define('ace/mode/text', ['require', 'exports', 'module' , 'ace/tokenizer', 'ace/mode/text_highlight_rules', 'ace/mode/behaviour', 'ace/unicode', 'ace/lib/lang', 'ace/token_iterator', 'ace/range'], function(require, exports, module) {
var Tokenizer = require("../tokenizer").Tokenizer;
@@ -7701,13 +7949,41 @@ var Mode = function() {
}
}
};
-
+
+ this.getKeywords = function(append) {
+ if (!this.completionKeywords) {
+ var rules = this.$tokenizer.rules;
+ var completionKeywords = [];
+ for (var rule in rules) {
+ var ruleItr = rules[rule];
+ for (var r = 0, l = ruleItr.length; r < l; r++) {
+ if (typeof ruleItr[r].token === "string") {
+ if (/keyword|support|storage/.test(ruleItr[r].token))
+ completionKeywords.push(ruleItr[r].regex);
+ }
+ else if (typeof ruleItr[r].token === "object") {
+ for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) {
+ if (/keyword|support|storage/.test(ruleItr[r].token[a])) {
+ var rule = ruleItr[r].regex.match(/\(.+?\)/g)[a];
+ completionKeywords.push(rule.substr(1, rule.length - 2));
+ }
+ }
+ }
+ }
+ }
+ this.completionKeywords = completionKeywords;
+ }
+ if (!append)
+ return this.$keywordList;
+ return completionKeywords.concat(this.$keywordList || []);
+ };
+
}).call(Mode.prototype);
exports.Mode = Mode;
});
-define('ace/tokenizer', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/tokenizer', ['require', 'exports', 'module' ], function(require, exports, module) {
var MAX_TOKEN_COUNT = 1000;
var Tokenizer = function(rules) {
this.states = rules;
@@ -7979,7 +8255,7 @@ var Tokenizer = function(rules) {
exports.Tokenizer = Tokenizer;
});
-define('ace/mode/text_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) {
+ace.define('ace/mode/text_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) {
var lang = require("../lib/lang");
@@ -7999,15 +8275,23 @@ var TextHighlightRules = function() {
(function() {
this.addRules = function(rules, prefix) {
+ if (!prefix) {
+ for (var key in rules)
+ this.$rules[key] = rules[key];
+ return;
+ }
for (var key in rules) {
var state = rules[key];
for (var i = 0; i < state.length; i++) {
var rule = state[i];
if (rule.next) {
- if (typeof rule.next != "string")
- rule.nextState = prefix + rule.nextState;
- else
- rule.next = prefix + rule.next;
+ if (typeof rule.next != "string") {
+ if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)
+ rule.nextState = prefix + rule.nextState;
+ } else {
+ if (rule.next.indexOf(prefix) !== 0)
+ rule.next = prefix + rule.next;
+ }
}
}
@@ -8041,7 +8325,7 @@ var TextHighlightRules = function() {
if (!this.$embeds)
this.$embeds = [];
this.$embeds.push(prefix);
- }
+ };
this.getEmbeds = function() {
return this.$embeds;
@@ -8150,6 +8434,7 @@ var TextHighlightRules = function() {
for (var i = list.length; i--; )
keywords[list[i]] = className;
});
+ this.$keywordList = Object.keys(keywords);
map = null;
return ignoreCase
? function(value) {return keywords[value.toLowerCase()] || defaultToken }
@@ -8165,7 +8450,7 @@ var TextHighlightRules = function() {
exports.TextHighlightRules = TextHighlightRules;
});
-define('ace/mode/behaviour', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/mode/behaviour', ['require', 'exports', 'module' ], function(require, exports, module) {
var Behaviour = function() {
@@ -8225,7 +8510,7 @@ var Behaviour = function() {
exports.Behaviour = Behaviour;
});
-define('ace/unicode', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/unicode', ['require', 'exports', 'module' ], function(require, exports, module) {
exports.packages = {};
addUnicodePackage({
@@ -8276,7 +8561,7 @@ function addUnicodePackage (pack) {
});
-define('ace/token_iterator', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/token_iterator', ['require', 'exports', 'module' ], function(require, exports, module) {
var TokenIterator = function(session, initialRow, initialColumn) {
this.$session = session;
this.$row = initialRow;
@@ -8348,7 +8633,7 @@ var TokenIterator = function(session, initialRow, initialColumn) {
exports.TokenIterator = TokenIterator;
});
-define('ace/document', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/range', 'ace/anchor'], function(require, exports, module) {
+ace.define('ace/document', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/range', 'ace/anchor'], function(require, exports, module) {
var oop = require("./lib/oop");
@@ -8434,7 +8719,7 @@ var Document = function(text) {
};
this.getTextRange = function(range) {
if (range.start.row == range.end.row) {
- return this.$lines[range.start.row]
+ return this.getLine(range.start.row)
.substring(range.start.column, range.end.column);
}
var lines = this.getLines(range.start.row, range.end.row);
@@ -8700,36 +8985,31 @@ var Document = function(text) {
exports.Document = Document;
});
-define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
+ace.define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
var oop = require("./lib/oop");
var EventEmitter = require("./lib/event_emitter").EventEmitter;
var Anchor = exports.Anchor = function(doc, row, column) {
- this.document = doc;
-
+ this.$onChange = this.onChange.bind(this);
+ this.attach(doc);
+
if (typeof column == "undefined")
this.setPosition(row.row, row.column);
else
this.setPosition(row, column);
-
- this.$onChange = this.onChange.bind(this);
- doc.on("change", this.$onChange);
};
(function() {
oop.implement(this, EventEmitter);
-
this.getPosition = function() {
return this.$clipPositionToDocument(this.row, this.column);
};
-
this.getDocument = function() {
return this.document;
};
-
this.onChange = function(e) {
var delta = e.data;
var range = delta.range;
@@ -8791,7 +9071,6 @@ var Anchor = exports.Anchor = function(doc, row, column) {
this.setPosition(row, column, true);
};
-
this.setPosition = function(row, column, noClip) {
var pos;
if (noClip) {
@@ -8818,10 +9097,13 @@ var Anchor = exports.Anchor = function(doc, row, column) {
value: pos
});
};
-
this.detach = function() {
this.document.removeEventListener("change", this.$onChange);
};
+ this.attach = function(doc) {
+ this.document = doc || this.document;
+ this.document.on("change", this.$onChange);
+ };
this.$clipPositionToDocument = function(row, column) {
var pos = {};
@@ -8848,7 +9130,7 @@ var Anchor = exports.Anchor = function(doc, row, column) {
});
-define('ace/background_tokenizer', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
+ace.define('ace/background_tokenizer', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
var oop = require("./lib/oop");
@@ -8867,27 +9149,35 @@ var BackgroundTokenizer = function(tokenizer, editor) {
if (!self.running) { return; }
var workerStart = new Date();
- var startLine = self.currentLine;
+ var currentLine = self.currentLine;
+ var endLine = -1;
var doc = self.doc;
- var processedLines = 0;
+ while (self.lines[currentLine])
+ currentLine++;
+
+ var startLine = currentLine;
var len = doc.getLength();
- while (self.currentLine < len) {
- self.$tokenizeRow(self.currentLine);
- while (self.lines[self.currentLine])
- self.currentLine++;
+ var processedLines = 0;
+ self.running = false;
+ while (currentLine < len) {
+ self.$tokenizeRow(currentLine);
+ endLine = currentLine;
+ do {
+ currentLine++;
+ } while (self.lines[currentLine]);
processedLines ++;
- if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {
- self.fireUpdateEvent(startLine, self.currentLine-1);
+ if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {
self.running = setTimeout(self.$worker, 20);
+ self.currentLine = currentLine;
return;
}
}
-
- self.running = false;
-
- self.fireUpdateEvent(startLine, len - 1);
+ self.currentLine = currentLine;
+
+ if (startLine <= endLine)
+ self.fireUpdateEvent(startLine, endLine);
};
};
@@ -8983,7 +9273,7 @@ var BackgroundTokenizer = function(tokenizer, editor) {
exports.BackgroundTokenizer = BackgroundTokenizer;
});
-define('ace/search_highlight', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/range'], function(require, exports, module) {
+ace.define('ace/search_highlight', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/range'], function(require, exports, module) {
var lang = require("./lib/lang");
@@ -9035,7 +9325,7 @@ var SearchHighlight = function(regExp, clazz, type) {
exports.SearchHighlight = SearchHighlight;
});
-define('ace/edit_session/folding', ['require', 'exports', 'module' , 'ace/range', 'ace/edit_session/fold_line', 'ace/edit_session/fold', 'ace/token_iterator'], function(require, exports, module) {
+ace.define('ace/edit_session/folding', ['require', 'exports', 'module' , 'ace/range', 'ace/edit_session/fold_line', 'ace/edit_session/fold', 'ace/token_iterator'], function(require, exports, module) {
var Range = require("../range").Range;
@@ -9562,8 +9852,8 @@ function Folding() {
if (range && range.end.row <= endRow) try {
var fold = this.addFold("...", range);
fold.collapseChildren = depth;
+ row = range.end.row;
} catch(e) {}
- row = range.end.row;
}
};
this.$foldStyles = {
@@ -9709,7 +9999,7 @@ exports.Folding = Folding;
});
-define('ace/edit_session/fold_line', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
+ace.define('ace/edit_session/fold_line', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
var Range = require("../range").Range;
@@ -9927,7 +10217,7 @@ function FoldLine(foldData, folds) {
exports.FoldLine = FoldLine;
});
-define('ace/edit_session/fold', ['require', 'exports', 'module' , 'ace/range', 'ace/range_list', 'ace/lib/oop'], function(require, exports, module) {
+ace.define('ace/edit_session/fold', ['require', 'exports', 'module' , 'ace/range', 'ace/range_list', 'ace/lib/oop'], function(require, exports, module) {
var Range = require("../range").Range;
@@ -10031,7 +10321,7 @@ function restoreRange(range, anchor) {
});
-define('ace/range_list', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
+ace.define('ace/range_list', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
var Range = require("./range").Range;
var comparePoints = Range.comparePoints;
@@ -10233,7 +10523,7 @@ var RangeList = function() {
exports.RangeList = RangeList;
});
-define('ace/edit_session/bracket_match', ['require', 'exports', 'module' , 'ace/token_iterator', 'ace/range'], function(require, exports, module) {
+ace.define('ace/edit_session/bracket_match', ['require', 'exports', 'module' , 'ace/token_iterator', 'ace/range'], function(require, exports, module) {
var TokenIterator = require("../token_iterator").TokenIterator;
@@ -10413,7 +10703,7 @@ exports.BracketMatch = BracketMatch;
});
-define('ace/search', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/range'], function(require, exports, module) {
+ace.define('ace/search', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/lib/oop', 'ace/range'], function(require, exports, module) {
var lang = require("./lib/lang");
@@ -10702,7 +10992,7 @@ var Search = function() {
exports.Search = Search;
});
-define('ace/commands/command_manager', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/keyboard/hash_handler', 'ace/lib/event_emitter'], function(require, exports, module) {
+ace.define('ace/commands/command_manager', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/keyboard/hash_handler', 'ace/lib/event_emitter'], function(require, exports, module) {
var oop = require("../lib/oop");
@@ -10806,7 +11096,7 @@ exports.CommandManager = CommandManager;
});
-define('ace/keyboard/hash_handler', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/useragent'], function(require, exports, module) {
+ace.define('ace/keyboard/hash_handler', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/useragent'], function(require, exports, module) {
var keyUtil = require("../lib/keys");
@@ -10941,7 +11231,7 @@ function HashHandler(config, platform) {
exports.HashHandler = HashHandler;
});
-define('ace/commands/default_commands', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/config'], function(require, exports, module) {
+ace.define('ace/commands/default_commands', ['require', 'exports', 'module' , 'ace/lib/lang', 'ace/config'], function(require, exports, module) {
var lang = require("../lib/lang");
@@ -11031,13 +11321,15 @@ exports.commands = [{
bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"),
exec: function(editor) { editor.getSelection().selectFileStart(); },
multiSelectAction: "forEach",
- readOnly: true
+ readOnly: true,
+ group: "fileJump"
}, {
name: "gotostart",
bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"),
exec: function(editor) { editor.navigateFileStart(); },
multiSelectAction: "forEach",
- readOnly: true
+ readOnly: true,
+ group: "fileJump"
}, {
name: "selectup",
bindKey: bindKey("Shift-Up", "Shift-Up"),
@@ -11055,13 +11347,15 @@ exports.commands = [{
bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-Down"),
exec: function(editor) { editor.getSelection().selectFileEnd(); },
multiSelectAction: "forEach",
- readOnly: true
+ readOnly: true,
+ group: "fileJump"
}, {
name: "gotoend",
bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"),
exec: function(editor) { editor.navigateFileEnd(); },
multiSelectAction: "forEach",
- readOnly: true
+ readOnly: true,
+ group: "fileJump"
}, {
name: "selectdown",
bindKey: bindKey("Shift-Down", "Shift-Down"),
@@ -11306,8 +11600,8 @@ exports.commands = [{
}, {
name: "backspace",
bindKey: bindKey(
- "Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
- "Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"
+ "Shift-Backspace|Backspace",
+ "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"
),
exec: function(editor) { editor.remove("left"); },
multiSelectAction: "forEach"
@@ -11385,7 +11679,7 @@ exports.commands = [{
});
-define('ace/undomanager', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/undomanager', ['require', 'exports', 'module' ], function(require, exports, module) {
var UndoManager = function() {
this.reset();
};
@@ -11394,6 +11688,9 @@ var UndoManager = function() {
this.execute = function(options) {
var deltas = options.args[0];
this.$doc = options.args[1];
+ if (options.merge && this.hasUndo()){
+ deltas = this.$undoStack.pop().concat(deltas);
+ }
this.$undoStack.push(deltas);
this.$redoStack = [];
@@ -11449,19 +11746,19 @@ var UndoManager = function() {
exports.UndoManager = UndoManager;
});
-define('ace/virtual_renderer', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/event', 'ace/lib/useragent', 'ace/config', 'ace/layer/gutter', 'ace/layer/marker', 'ace/layer/text', 'ace/layer/cursor', 'ace/scrollbar', 'ace/renderloop', 'ace/lib/event_emitter'], function(require, exports, module) {
+ace.define('ace/virtual_renderer', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/useragent', 'ace/config', 'ace/layer/gutter', 'ace/layer/marker', 'ace/layer/text', 'ace/layer/cursor', 'ace/scrollbar', 'ace/renderloop', 'ace/lib/event_emitter'], function(require, exports, module) {
var oop = require("./lib/oop");
var dom = require("./lib/dom");
-var event = require("./lib/event");
var useragent = require("./lib/useragent");
var config = require("./config");
var GutterLayer = require("./layer/gutter").Gutter;
var MarkerLayer = require("./layer/marker").Marker;
var TextLayer = require("./layer/text").Text;
var CursorLayer = require("./layer/cursor").Cursor;
-var ScrollBar = require("./scrollbar").ScrollBar;
+var ScrollBarH = require("./scrollbar").ScrollBarH;
+var ScrollBarV = require("./scrollbar").ScrollBarV;
var RenderLoop = require("./renderloop").RenderLoop;
var EventEmitter = require("./lib/event_emitter").EventEmitter;
var editorCss = ".ace_editor {\
@@ -11527,8 +11824,8 @@ background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCA
}\
.ace_scrollbar {\
position: absolute;\
-overflow-x: hidden;\
-overflow-y: scroll;\
+overflow: hidden;\
+overflow-y: auto;\
right: 0;\
top: 0;\
bottom: 0;\
@@ -11538,6 +11835,19 @@ position: absolute;\
width: 1px;\
left: 0;\
}\
+.ace_scrollbar-h {\
+position: absolute;\
+overflow-x: auto;\
+overflow-y: hidden;\
+right: 0;\
+left: 0;\
+bottom: 0;\
+}\
+.ace_scrollbar-inner {\
+position: absolute;\
+height: 1px;\
+left: 0;\
+}\
.ace_print-margin {\
position: absolute;\
height: 100%;\
@@ -11621,7 +11931,7 @@ border-left-width: 1px;\
.ace_line {\
white-space: nowrap;\
}\
-.ace_marker-layer .ace_step {\
+.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\
position: absolute;\
z-index: 3;\
}\
@@ -11795,6 +12105,16 @@ font-weight: normal;\
.ace_italic {\
font-style: italic;\
}\
+.ace_error-marker {\
+background-color: rgba(255, 0, 0,0.2);\
+position: absolute;\
+z-index: 9;\
+}\
+.ace_highlight-marker {\
+background-color: rgba(255, 255, 0,0.2);\
+position: absolute;\
+z-index: 8;\
+}\
";
dom.importCssString(editorCss, "ace_editor");
@@ -11833,22 +12153,23 @@ var VirtualRenderer = function(container, theme) {
this.$cursorLayer = new CursorLayer(this.content);
this.$horizScroll = false;
+ this.$vScroll = false;
- this.scrollBar = new ScrollBar(this.container);
- this.scrollBar.addEventListener("scroll", function(e) {
+ this.scrollBar =
+ this.scrollBarV = new ScrollBarV(this.container, this);
+ this.scrollBarH = new ScrollBarH(this.container, this);
+ this.scrollBarV.addEventListener("scroll", function(e) {
if (!_self.$scrollAnimation)
- _self.session.setScrollTop(e.data);
+ _self.session.setScrollTop(e.data - _self.scrollMargin.top);
+ });
+ this.scrollBarH.addEventListener("scroll", function(e) {
+ if (!_self.$scrollAnimation)
+ _self.session.setScrollLeft(e.data - _self.scrollMargin.left);
});
this.scrollTop = 0;
this.scrollLeft = 0;
- event.addListener(this.scroller, "scroll", function() {
- var scrollLeft = _self.scroller.scrollLeft;
- _self.scrollLeft = scrollLeft;
- _self.session.setScrollLeft(scrollLeft);
- });
-
this.cursorPos = {
row : 0,
column : 0
@@ -11857,6 +12178,7 @@ var VirtualRenderer = function(container, theme) {
this.$textLayer.addEventListener("changeCharacterSize", function() {
_self.updateCharacterSize();
_self.onResize(true);
+ _self._signal("changeCharacterSize");
});
this.$size = {
@@ -11879,6 +12201,15 @@ var VirtualRenderer = function(container, theme) {
offset : 0,
height : 1
};
+
+ this.scrollMargin = {
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0,
+ v: 0,
+ h: 0
+ };
this.$loop = new RenderLoop(
this.$renderChanges.bind(this),
@@ -11914,7 +12245,9 @@ var VirtualRenderer = function(container, theme) {
this.setStyle("ace_nobold", !this.$allowBoldFonts);
}
+ this.layerConfig.characterWidth =
this.characterWidth = this.$textLayer.getCharacterWidth();
+ this.layerConfig.lineHeight =
this.lineHeight = this.$textLayer.getLineHeight();
this.$updatePrintMargin();
};
@@ -11971,78 +12304,94 @@ var VirtualRenderer = function(container, theme) {
this.updateFontSize = function() {
this.$textLayer.checkForSizeChanges();
};
- this.onResize = function(force, gutterWidth, width, height) {
- var changes = 0;
- var size = this.$size;
+ this.$changes = 0;
+ this.onResize = function(force, gutterWidth, width, height) {
if (this.resizing > 2)
return;
- else if (this.resizing > 1)
+ else if (this.resizing > 0)
this.resizing++;
else
this.resizing = force ? 1 : 0;
+ var el = this.container;
if (!height)
- height = dom.getInnerHeight(this.container);
-
- if (height && (force || size.height != height)) {
- size.height = height;
- changes = this.CHANGE_SIZE;
-
- size.scrollerHeight = this.scroller.clientHeight;
- if (force || !size.scrollerHeight) {
- size.scrollerHeight = size.height;
- if (this.$horizScroll)
- size.scrollerHeight -= this.scrollBar.getWidth();
- }
- this.scrollBar.setHeight(size.scrollerHeight);
-
- if (this.session) {
- this.session.setScrollTop(this.getScrollTop());
- changes = changes | this.CHANGE_FULL;
- }
- }
-
+ height = el.clientHeight || el.scrollHeight;
if (!width)
- width = dom.getInnerWidth(this.container);
+ width = el.clientWidth || el.scrollWidth;
- if (width && (force || this.resizing > 1 || size.width != width)) {
- changes = this.CHANGE_SIZE;
- size.width = width;
-
- var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;
- this.scroller.style.left = gutterWidth + "px";
- size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBar.getWidth());
- this.scroller.style.right = this.scrollBar.getWidth() + "px";
-
- if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force)
- changes = changes | this.CHANGE_FULL;
- }
-
- if (!this.$size.scrollerHeight)
- return;
-
- if (force)
- this.$renderChanges(changes, true);
- else
- this.$loop.schedule(changes);
+ var changes = this.$updateCachedSize(force, gutterWidth, width, height);
+
+ if (!this.$size.scrollerHeight || (!width && !height))
+ return this.resizing = 0;
if (force)
this.$gutterLayer.$padding = null;
if (force)
- delete this.resizing;
+ this.$renderChanges(changes, true);
+ else
+ this.$loop.schedule(changes || this.$changes);
+
+ if (this.resizing)
+ this.resizing = 0;
+ };
+
+ this.$updateCachedSize = function(force, gutterWidth, width, height) {
+ var changes = 0;
+ var size = this.$size;
+ if (height && (force || size.height != height)) {
+ size.height = height;
+ changes = this.CHANGE_SIZE;
+
+ size.scrollerHeight = size.height;
+ if (this.$horizScroll)
+ size.scrollerHeight -= this.scrollBarH.getHeight();
+ this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + "px";
+
+ if (this.session) {
+ this.session.setScrollTop(this.getScrollTop());
+ changes = changes | this.CHANGE_SCROLL;
+ }
+ }
+
+ if (width && (force || size.width != width)) {
+ changes = this.CHANGE_SIZE;
+ size.width = width;
+
+ if (gutterWidth == null)
+ gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;
+
+ this.gutterWidth = gutterWidth;
+
+ this.scrollBarH.element.style.left =
+ this.scroller.style.left = gutterWidth + "px";
+ size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth());
+
+ this.scrollBarH.element.style.right =
+ this.scroller.style.right = this.scrollBarV.getWidth() + "px";
+ this.scroller.style.bottom = this.scrollBarH.getHeight() + "px";
+
+ if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force)
+ changes = changes | this.CHANGE_FULL;
+ }
+
+ if (changes)
+ this._signal("resize");
+
+ return changes;
};
this.onGutterResize = function() {
- var width = this.$size.width;
var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;
- this.scroller.style.left = gutterWidth + "px";
- this.$size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBar.getWidth());
+ if (gutterWidth != this.gutterWidth)
+ this.$changes != this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height);
if (this.session.getUseWrapMode() && this.adjustWrapLimit())
this.$loop.schedule(this.CHANGE_FULL);
- else
+ else {
+ this.$computeLayerConfig();
this.$loop.schedule(this.CHANGE_MARKER);
+ }
};
this.adjustWrapLimit = function() {
var availableWidth = this.$size.scrollerWidth - this.$padding * 2;
@@ -12199,41 +12548,69 @@ var VirtualRenderer = function(container, theme) {
this.$loop.schedule(this.CHANGE_FULL);
this.$updatePrintMargin();
};
+
+ this.setScrollMargin = function(top, bottom, left, right) {
+ var sm = this.scrollMargin;
+ sm.top = top|0;
+ sm.bottom = bottom|0;
+ sm.right = right|0;
+ sm.left = left|0;
+ sm.v = sm.top + sm.bottom;
+ sm.h = sm.left + sm.right;
+ this.updateFull();
+ };
this.getHScrollBarAlwaysVisible = function() {
return this.$hScrollBarAlwaysVisible;
};
this.setHScrollBarAlwaysVisible = function(alwaysVisible) {
this.setOption("hScrollBarAlwaysVisible", alwaysVisible);
};
+ this.getVScrollBarAlwaysVisible = function() {
+ return this.$hScrollBarAlwaysVisible;
+ };
+ this.setVScrollBarAlwaysVisible = function(alwaysVisible) {
+ this.setOption("vScrollBarAlwaysVisible", alwaysVisible);
+ };
- this.$updateScrollBar = function() {
- this.scrollBar.setInnerHeight(this.layerConfig.maxHeight);
- this.scrollBar.setScrollTop(this.scrollTop);
+ this.$updateScrollBarV = function() {
+ this.scrollBarV.setInnerHeight(this.layerConfig.maxHeight + this.scrollMargin.v);
+ this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top);
+ };
+ this.$updateScrollBarH = function() {
+ this.scrollBarH.setInnerWidth(this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h);
+ this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left);
};
this.$renderChanges = function(changes, force) {
- if (!force && (!changes || !this.session || !this.container.offsetWidth))
- return;
-
+ if (this.$changes) {
+ changes |= this.$changes;
+ this.$changes = 0;
+ }
+ if ((!this.session || !this.container.offsetWidth) || (!changes && !force)) {
+ this.$changes |= changes;
+ return;
+ }
+ if (!this.$size.width)
+ return this.onResize(true);
+
this._signal("beforeRender");
if (changes & this.CHANGE_FULL ||
changes & this.CHANGE_SIZE ||
changes & this.CHANGE_TEXT ||
changes & this.CHANGE_LINES ||
- changes & this.CHANGE_SCROLL
+ changes & this.CHANGE_SCROLL ||
+ changes & this.CHANGE_H_SCROLL
)
- this.$computeLayerConfig();
+ changes |= this.$computeLayerConfig();
if (changes & this.CHANGE_H_SCROLL) {
- this.scroller.scrollLeft = this.scrollLeft;
- var scrollLeft = this.scroller.scrollLeft;
- this.scrollLeft = scrollLeft;
- this.session.setScrollLeft(scrollLeft);
-
- this.scroller.className = this.scrollLeft == 0 ? "ace_scroller" : "ace_scroller ace_scroll-left";
+ this.$updateScrollBarH();
+ this.content.style.marginLeft = -this.scrollLeft + "px";
+ this.scroller.className = this.scrollLeft <= 0 ? "ace_scroller" : "ace_scroller ace_scroll-left";
}
if (changes & this.CHANGE_FULL) {
this.$textLayer.checkForSizeChanges();
- this.$updateScrollBar();
+ this.$updateScrollBarV();
+ this.$updateScrollBarH();
this.$textLayer.update(this.layerConfig);
if (this.$showGutter)
this.$gutterLayer.update(this.layerConfig);
@@ -12246,6 +12623,7 @@ var VirtualRenderer = function(container, theme) {
return;
}
if (changes & this.CHANGE_SCROLL) {
+ this.$updateScrollBarV();
if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES)
this.$textLayer.update(this.layerConfig);
else
@@ -12258,7 +12636,6 @@ var VirtualRenderer = function(container, theme) {
this.$cursorLayer.update(this.layerConfig);
this.$highlightGutterLine && this.$updateGutterLineHighlight();
this.$moveTextAreaToCursor();
- this.$updateScrollBar();
this._signal("afterRender");
return;
}
@@ -12291,33 +12668,83 @@ var VirtualRenderer = function(container, theme) {
this.$markerBack.update(this.layerConfig);
}
- if (changes & this.CHANGE_SIZE)
- this.$updateScrollBar();
+ if (changes & this.CHANGE_SIZE || changes & this.CHANGE_LINES) {
+ this.$updateScrollBarV();
+ this.$updateScrollBarH();
+ }
this._signal("afterRender");
};
+
+ this.$autosize = function(height, width) {
+ var height = this.session.getScreenLength() * this.lineHeight;
+ var maxHeight = this.$maxLines * this.lineHeight;
+ var desiredHeight = Math.max(
+ (this.$minLines||1) * this.lineHeight,
+ Math.min(maxHeight, height)
+ );
+ var vScroll = height > maxHeight;
+
+ if (desiredHeight != this.desiredHeight ||
+ this.$size.height != this.desiredHeight || vScroll != this.$vScroll) {
+ if (vScroll != this.$vScroll) {
+ this.$vScroll = vScroll;
+ this.scrollBarV.setVisible(vScroll);
+ }
+
+ var w = this.container.clientWidth;
+ this.container.style.height = desiredHeight + "px";
+ this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight);
+ this.desiredHeight = desiredHeight;
+ }
+ };
+
this.$computeLayerConfig = function() {
- if (!this.$size.scrollerHeight)
- return this.onResize(true);
+ if (this.$maxLines && this.lineHeight > 1)
+ this.$autosize();
var session = this.session;
+
+ var hideScrollbars = this.$size.height <= 2 * this.lineHeight;
+ var screenLines = this.session.getScreenLength()
+ var maxHeight = screenLines * this.lineHeight;
var offset = this.scrollTop % this.lineHeight;
var minHeight = this.$size.scrollerHeight + this.lineHeight;
var longestLine = this.$getLongestLine();
+
+ var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible ||
+ this.$size.scrollerWidth - longestLine - 2 * this.$padding < 0);
- var horizScroll = this.$hScrollBarAlwaysVisible || this.$size.scrollerWidth - longestLine < 0;
- var horizScrollChanged = this.$horizScroll !== horizScroll;
- this.$horizScroll = horizScroll;
- if (horizScrollChanged) {
- this.scroller.style.overflowX = horizScroll ? "scroll" : "hidden";
- if (!horizScroll)
- this.session.setScrollLeft(0);
+ var hScrollChanged = this.$horizScroll !== horizScroll;
+ if (hScrollChanged) {
+ this.$horizScroll = horizScroll;
+ this.scrollBarH.setVisible(horizScroll);
}
- var maxHeight = this.session.getScreenLength() * this.lineHeight;
- this.session.setScrollTop(Math.max(0, Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight)));
+
+ if (!this.$maxLines && this.$scrollPastEnd) {
+ if (this.scrollTop > maxHeight - this.$size.scrollerHeight)
+ maxHeight += Math.min(
+ (this.$size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd,
+ this.scrollTop - maxHeight + this.$size.scrollerHeight
+ );
+ }
+
+ var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible ||
+ this.$size.scrollerHeight - maxHeight < 0);
+ var vScrollChanged = this.$vScroll !== vScroll;
+ if (vScrollChanged) {
+ this.$vScroll = vScroll;
+ this.scrollBarV.setVisible(vScroll);
+ }
+
+ this.session.setScrollTop(Math.max(-this.scrollMargin.top,
+ Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight + this.scrollMargin.v)));
+
+ this.session.setScrollLeft(Math.max(-this.scrollMargin.left, Math.min(this.scrollLeft,
+ longestLine + 2 * this.$padding - this.$size.scrollerWidth + this.scrollMargin.h)));
var lineCount = Math.ceil(minHeight / this.lineHeight) - 1;
var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));
@@ -12339,6 +12766,14 @@ var VirtualRenderer = function(container, theme) {
offset = this.scrollTop - firstRowScreen * lineHeight;
+ var changes = 0;
+ if (hScrollChanged || vScrollChanged) {
+ changes = this.$updateCachedSize(true, this.gutterWidth, this.$size.width, this.$size.height);
+ this._signal("scrollbarVisibilityChanged");
+ if (vScrollChanged)
+ longestLine = this.$getLongestLine();
+ }
+
this.layerConfig = {
width : longestLine,
padding : this.$padding,
@@ -12357,8 +12792,8 @@ var VirtualRenderer = function(container, theme) {
this.content.style.marginTop = (-offset) + "px";
this.content.style.width = longestLine + 2 * this.$padding + "px";
this.content.style.height = minHeight + "px";
- if (horizScrollChanged)
- this.onResize(true);
+
+ return changes;
};
this.$updateLines = function() {
@@ -12430,12 +12865,18 @@ var VirtualRenderer = function(container, theme) {
var left = pos.left;
var top = pos.top;
+
+ var scrollTop = this.$scrollAnimation ? this.session.getScrollTop() : this.scrollTop;
- if (this.scrollTop > top) {
+ if (scrollTop > top) {
if (offset)
top -= offset * this.$size.scrollerHeight;
+ if (top == 0)
+ top = - this.scrollMargin.top;
+ else if (top == 0)
+ top = + this.scrollMargin.bottom;
this.session.setScrollTop(top);
- } else if (this.scrollTop + this.$size.scrollerHeight < top + this.lineHeight) {
+ } else if (scrollTop + this.$size.scrollerHeight < top + this.lineHeight) {
if (offset)
top += offset * this.$size.scrollerHeight;
this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight);
@@ -12445,10 +12886,12 @@ var VirtualRenderer = function(container, theme) {
if (scrollLeft > left) {
if (left < this.$padding + 2 * this.layerConfig.characterWidth)
- left = 0;
+ left = -this.scrollMargin.left;
this.session.setScrollLeft(left);
} else if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) {
this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth));
+ } else if (scrollLeft <= this.$padding && left - scrollLeft < this.characterWidth) {
+ this.session.setScrollLeft(0);
}
};
this.getScrollTop = function() {
@@ -12508,29 +12951,42 @@ var VirtualRenderer = function(container, theme) {
this.animateScrolling = function(fromValue, callback) {
var toValue = this.scrollTop;
- if (this.$animatedScroll) {
- var _self = this;
- var steps = _self.$calcSteps(fromValue, toValue);
- this.$scrollAnimation = {from: fromValue, to: toValue};
-
- clearInterval(this.$timer);
-
- _self.session.setScrollTop(steps.shift());
- this.$timer = setInterval(function() {
- if (steps.length) {
- _self.session.setScrollTop(steps.shift());
- _self.session.$scrollTop = toValue;
- } else if (toValue != null) {
- _self.session.$scrollTop = -1;
- _self.session.setScrollTop(toValue);
- toValue = null;
- } else {
- _self.$timer = clearInterval(_self.$timer);
- _self.$scrollAnimation = null;
- callback && callback();
- }
- }, 10);
+ if (!this.$animatedScroll)
+ return;
+ var _self = this;
+
+ if (fromValue == toValue)
+ return;
+
+ if (this.$scrollAnimation) {
+ var oldSteps = this.$scrollAnimation.steps;
+ if (oldSteps.length) {
+ fromValue = oldSteps[0];
+ if (fromValue == toValue)
+ return;
+ }
}
+
+ var steps = _self.$calcSteps(fromValue, toValue);
+ this.$scrollAnimation = {from: fromValue, to: toValue, steps: steps};
+
+ clearInterval(this.$timer);
+
+ _self.session.setScrollTop(steps.shift());
+ this.$timer = setInterval(function() {
+ if (steps.length) {
+ _self.session.setScrollTop(steps.shift());
+ _self.session.$scrollTop = toValue;
+ } else if (toValue != null) {
+ _self.session.$scrollTop = -1;
+ _self.session.setScrollTop(toValue);
+ toValue = null;
+ } else {
+ _self.$timer = clearInterval(_self.$timer);
+ _self.$scrollAnimation = null;
+ callback && callback();
+ }
+ }, 10);
};
this.scrollToY = function(scrollTop) {
if (this.scrollTop !== scrollTop) {
@@ -12539,9 +12995,6 @@ var VirtualRenderer = function(container, theme) {
}
};
this.scrollToX = function(scrollLeft) {
- if (scrollLeft < 0)
- scrollLeft = 0;
-
if (this.scrollLeft !== scrollLeft)
this.scrollLeft = scrollLeft;
this.$loop.schedule(this.CHANGE_H_SCROLL);
@@ -12551,9 +13004,13 @@ var VirtualRenderer = function(container, theme) {
deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX);
};
this.isScrollableBy = function(deltaX, deltaY) {
- if (deltaY < 0 && this.session.getScrollTop() >= 1)
+ if (deltaY < 0 && this.session.getScrollTop() >= 1 - this.scrollMargin.top)
return true;
- if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight - this.layerConfig.maxHeight < -1)
+ if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight
+ - this.layerConfig.maxHeight - (this.$size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd
+ < -1 + this.scrollMargin.bottom)
+ return true;
+ if (deltaX)
return true;
};
@@ -12621,7 +13078,7 @@ var VirtualRenderer = function(container, theme) {
this.textarea.style.cssText = this.$composition.cssText;
this.$composition = null;
};
- this.setTheme = function(theme) {
+ this.setTheme = function(theme, cb) {
var _self = this;
this.$themeValue = theme;
_self._dispatchEvent('themeChange',{theme:theme});
@@ -12635,7 +13092,7 @@ var VirtualRenderer = function(container, theme) {
function afterLoad(module) {
if (_self.$themeValue != theme)
- return;
+ return cb && cb();
if (!module.cssClass)
return;
dom.importCssString(
@@ -12660,7 +13117,8 @@ var VirtualRenderer = function(container, theme) {
_self.onResize();
}
- _self._dispatchEvent('themeLoaded',{theme:module});
+ _self._dispatchEvent('themeLoaded', {theme:module});
+ cb && cb();
}
};
this.getTheme = function() {
@@ -12749,13 +13207,19 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", {
value: true
},
hScrollBarAlwaysVisible: {
- set: function(alwaysVisible) {
- this.$hScrollBarAlwaysVisible = alwaysVisible;
+ set: function(val) {
if (!this.$hScrollBarAlwaysVisible || !this.$horizScroll)
this.$loop.schedule(this.CHANGE_SCROLL);
},
initialValue: false
},
+ vScrollBarAlwaysVisible: {
+ set: function(val) {
+ if (!this.$vScrollBarAlwaysVisible || !this.$vScroll)
+ this.$loop.schedule(this.CHANGE_SCROLL);
+ },
+ initialValue: false
+ },
fontSize: {
set: function(size) {
if (typeof size == "number")
@@ -12770,13 +13234,34 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", {
this.container.style.fontFamily = name;
this.updateFontSize();
}
+ },
+ maxLines: {
+ set: function(val) {
+ this.updateFull();
+ }
+ },
+ minLines: {
+ set: function(val) {
+ this.updateFull();
+ }
+ },
+ scrollPastEnd: {
+ set: function(val) {
+ val = +val || 0;
+ if (this.$scrollPastEnd == val)
+ return;
+ this.$scrollPastEnd = val;
+ this.$loop.schedule(this.CHANGE_SCROLL);
+ },
+ initialValue: 0,
+ handlesSet: true
}
});
exports.VirtualRenderer = VirtualRenderer;
});
-define('ace/layer/gutter', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/event_emitter'], function(require, exports, module) {
+ace.define('ace/layer/gutter', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/event_emitter'], function(require, exports, module) {
var dom = require("../lib/dom");
@@ -12919,7 +13404,7 @@ var Gutter = function(parentEl) {
var gutterWidth = ("" + lastLineNumber).length * config.characterWidth;
var padding = this.$padding || this.$computePadding();
gutterWidth += padding.left + padding.right;
- if (gutterWidth !== this.gutterWidth) {
+ if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) {
this.gutterWidth = gutterWidth;
this.element.style.width = Math.ceil(this.gutterWidth) + "px";
this._emit("changeGutterWidth", gutterWidth);
@@ -12945,9 +13430,9 @@ var Gutter = function(parentEl) {
if (!this.element.firstChild)
return {left: 0, right: 0};
var style = dom.computedStyle(this.element.firstChild);
- this.$padding = {}
- this.$padding.left = parseInt(style.paddingLeft) + 1;
- this.$padding.right = parseInt(style.paddingRight);
+ this.$padding = {};
+ this.$padding.left = parseInt(style.paddingLeft) + 1 || 0;
+ this.$padding.right = parseInt(style.paddingRight) || 0;
return this.$padding;
};
@@ -12966,7 +13451,7 @@ exports.Gutter = Gutter;
});
-define('ace/layer/marker', ['require', 'exports', 'module' , 'ace/range', 'ace/lib/dom'], function(require, exports, module) {
+ace.define('ace/layer/marker', ['require', 'exports', 'module' , 'ace/range', 'ace/lib/dom'], function(require, exports, module) {
var Range = require("../range").Range;
@@ -13141,7 +13626,7 @@ exports.Marker = Marker;
});
-define('ace/layer/text', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/lang', 'ace/lib/useragent', 'ace/lib/event_emitter'], function(require, exports, module) {
+ace.define('ace/layer/text', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/lang', 'ace/lib/useragent', 'ace/lib/event_emitter'], function(require, exports, module) {
var oop = require("../lib/oop");
@@ -13744,7 +14229,7 @@ exports.Text = Text;
});
-define('ace/layer/cursor', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
+ace.define('ace/layer/cursor', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
var dom = require("../lib/dom");
@@ -13930,14 +14415,14 @@ exports.Cursor = Cursor;
});
-define('ace/scrollbar', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/event', 'ace/lib/event_emitter'], function(require, exports, module) {
+ace.define('ace/scrollbar', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/event', 'ace/lib/event_emitter'], function(require, exports, module) {
var oop = require("./lib/oop");
var dom = require("./lib/dom");
var event = require("./lib/event");
var EventEmitter = require("./lib/event_emitter").EventEmitter;
-var ScrollBar = function(parent) {
+var ScrollBarV = function(parent, renderer) {
this.element = dom.createElement("div");
this.element.className = "ace_scrollbar";
@@ -13946,43 +14431,108 @@ var ScrollBar = function(parent) {
this.element.appendChild(this.inner);
parent.appendChild(this.element);
+ renderer.$scrollbarWidth =
this.width = dom.scrollbarWidth(parent.ownerDocument);
+ this.fullWidth = this.width;
this.element.style.width = (this.width || 15) + 5 + "px";
+ this.setVisible(false);
+ this.element.style.overflowY = "scroll";
+
+ event.addListener(this.element, "scroll", this.onScrollV.bind(this));
+};
- event.addListener(this.element, "scroll", this.onScroll.bind(this));
+var ScrollBarH = function(parent, renderer) {
+ this.element = dom.createElement("div");
+ this.element.className = "ace_scrollbar-h";
+
+ this.inner = dom.createElement("div");
+ this.inner.className = "ace_scrollbar-inner";
+ this.element.appendChild(this.inner);
+
+ parent.appendChild(this.element);
+ this.height = renderer.$scrollbarWidth;
+ this.fullHeight = this.height;
+ this.element.style.height = (this.height || 15) + 5 + "px";
+ this.setVisible(false);
+ this.element.style.overflowX = "scroll";
+
+ event.addListener(this.element, "scroll", this.onScrollH.bind(this));
};
(function() {
oop.implement(this, EventEmitter);
- this.onScroll = function() {
+
+ this.setVisible = function(show) {
+ if (show) {
+ this.element.style.display = "";
+ if (this.fullWidth)
+ this.width = this.fullWidth;
+ if (this.fullHeight)
+ this.height = this.fullHeight;
+ } else {
+ this.element.style.display = "none";
+ this.height = this.width = 0;
+ }
+ };
+ this.onScrollV = function() {
if (!this.skipEvent) {
this.scrollTop = this.element.scrollTop;
this._emit("scroll", {data: this.scrollTop});
}
this.skipEvent = false;
};
+ this.onScrollH = function() {
+ if (!this.skipEvent) {
+ this.scrollLeft = this.element.scrollLeft;
+ this._emit("scroll", {data: this.scrollLeft});
+ }
+ this.skipEvent = false;
+ };
this.getWidth = function() {
return this.width;
};
+
+ this.getHeight = function() {
+ return this.height;
+ };
this.setHeight = function(height) {
this.element.style.height = height + "px";
};
+
+ this.setWidth = function(width) {
+ this.element.style.width = width + "px";
+ };
this.setInnerHeight = function(height) {
this.inner.style.height = height + "px";
};
+
+ this.setInnerWidth = function(width) {
+ this.inner.style.width = width + "px";
+ };
this.setScrollTop = function(scrollTop) {
if (this.scrollTop != scrollTop) {
this.skipEvent = true;
this.scrollTop = this.element.scrollTop = scrollTop;
}
};
+ this.setScrollLeft = function(scrollLeft) {
+ if (this.scrollLeft != scrollLeft) {
+ this.skipEvent = true;
+ this.scrollLeft = this.element.scrollLeft = scrollLeft;
+ }
+ };
-}).call(ScrollBar.prototype);
+}).call(ScrollBarV.prototype);
+ScrollBarH.prototype = ScrollBarV.prototype;
-exports.ScrollBar = ScrollBar;
+
+
+exports.ScrollBar = ScrollBarV; // backward compatibility
+exports.ScrollBarV = ScrollBarV;
+exports.ScrollBarH = ScrollBarH;
});
-define('ace/renderloop', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
+ace.define('ace/renderloop', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
var event = require("./lib/event");
@@ -14019,7 +14569,7 @@ var RenderLoop = function(onRender, win) {
exports.RenderLoop = RenderLoop;
});
-define('ace/multi_select', ['require', 'exports', 'module' , 'ace/range_list', 'ace/range', 'ace/selection', 'ace/mouse/multi_select_handler', 'ace/lib/event', 'ace/lib/lang', 'ace/commands/multi_select_commands', 'ace/search', 'ace/edit_session', 'ace/editor'], function(require, exports, module) {
+ace.define('ace/multi_select', ['require', 'exports', 'module' , 'ace/range_list', 'ace/range', 'ace/selection', 'ace/mouse/multi_select_handler', 'ace/lib/event', 'ace/lib/lang', 'ace/commands/multi_select_commands', 'ace/search', 'ace/edit_session', 'ace/editor', 'ace/config'], function(require, exports, module) {
var RangeList = require("./range_list").RangeList;
var Range = require("./range").Range;
@@ -14716,13 +15266,16 @@ exports.onSessionChange = function(e) {
}
};
function MultiSelect(editor) {
+ if (editor.$multiselectOnSessionChange)
+ return;
editor.$onAddRange = editor.$onAddRange.bind(editor);
editor.$onRemoveRange = editor.$onRemoveRange.bind(editor);
editor.$onMultiSelect = editor.$onMultiSelect.bind(editor);
editor.$onSingleSelect = editor.$onSingleSelect.bind(editor);
+ editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor);
- exports.onSessionChange.call(editor, editor);
- editor.on("changeSession", exports.onSessionChange.bind(editor));
+ editor.$multiselectOnSessionChange(editor);
+ editor.on("changeSession", editor.$multiselectOnSessionChange);
editor.on("mousedown", onMouseDown);
editor.commands.addCommands(commands.defaultCommands);
@@ -14757,9 +15310,28 @@ function addAltCursorListeners(editor){
exports.MultiSelect = MultiSelect;
+
+require("./config").defineOptions(Editor.prototype, "editor", {
+ enableMultiselect: {
+ set: function(val) {
+ MultiSelect(this);
+ if (val) {
+ this.on("changeSession", this.$multiselectOnSessionChange);
+ this.on("mousedown", onMouseDown);
+ } else {
+ this.off("changeSession", this.$multiselectOnSessionChange);
+ this.off("mousedown", onMouseDown);
+ }
+ },
+ value: true
+ }
+})
+
+
+
});
-define('ace/mouse/multi_select_handler', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
+ace.define('ace/mouse/multi_select_handler', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
var event = require("../lib/event");
function isSamePoint(p1, p2) {
@@ -14887,7 +15459,7 @@ exports.onMouseDown = onMouseDown;
});
-define('ace/commands/multi_select_commands', ['require', 'exports', 'module' , 'ace/keyboard/hash_handler'], function(require, exports, module) {
+ace.define('ace/commands/multi_select_commands', ['require', 'exports', 'module' , 'ace/keyboard/hash_handler'], function(require, exports, module) {
exports.defaultCommands = [{
name: "addCursorAbove",
exec: function(editor) { editor.selectMoreLines(-1); },
@@ -14951,7 +15523,7 @@ exports.keyboardHandler = new HashHandler(exports.multiSelectCommands);
});
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/config'], function(require, exports, module) {
+ace.define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/config'], function(require, exports, module) {
var oop = require("../lib/oop");
@@ -15036,6 +15608,7 @@ var WorkerClient = function(topLevelNamespaces, mod, classname) {
this.terminate = function() {
this._emit("terminate", {});
+ this.deltaQueue = null;
this.$worker.terminate();
this.$worker = null;
this.$doc.removeEventListener("change", this.changeListener);
@@ -15141,7 +15714,7 @@ exports.UIWorkerClient = UIWorkerClient;
exports.WorkerClient = WorkerClient;
});
-define('ace/placeholder', ['require', 'exports', 'module' , 'ace/range', 'ace/lib/event_emitter', 'ace/lib/oop'], function(require, exports, module) {
+ace.define('ace/placeholder', ['require', 'exports', 'module' , 'ace/range', 'ace/lib/event_emitter', 'ace/lib/oop'], function(require, exports, module) {
var Range = require("./range").Range;
@@ -15313,7 +15886,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
exports.PlaceHolder = PlaceHolder;
});
-define('ace/mode/folding/fold_mode', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
+ace.define('ace/mode/folding/fold_mode', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
var Range = require("../../range").Range;
@@ -15402,7 +15975,7 @@ var FoldMode = exports.FoldMode = function() {};
});
-define('ace/theme/textmate', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
+ace.define('ace/theme/textmate', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
exports.isDark = false;
@@ -15488,10 +16061,10 @@ color: rgb(104, 104, 91);\
.ace-tm .ace_entity.ace_name.ace_function {\
color: #0000A2;\
}\
-.ace-tm .ace_markup.ace_heading {\
+.ace-tm .ace_heading {\
color: rgb(12, 7, 255);\
}\
-.ace-tm .ace_markup.ace_list {\
+.ace-tm .ace_list {\
color:rgb(185, 6, 144);\
}\
.ace-tm .ace_meta.ace_tag {\
@@ -15537,7 +16110,7 @@ dom.importCssString(exports.cssText, exports.cssClass);
});
;
(function() {
- window.require(["ace/ace"], function(a) {
+ ace.require(["ace/ace"], function(a) {
a && a.config.init();
if (!window.ace)
window.ace = {};
diff --git a/lib/client/edit/ext-searchbox.js b/lib/client/edit/ext-searchbox.js
index 81c5b74f..f2990d59 100644
--- a/lib/client/edit/ext-searchbox.js
+++ b/lib/client/edit/ext-searchbox.js
@@ -28,7 +28,7 @@
*
* ***** END LICENSE BLOCK ***** */
-define('ace/ext/searchbox', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/lang', 'ace/lib/event', 'ace/keyboard/hash_handler', 'ace/lib/keys'], function(require, exports, module) {
+ace.define('ace/ext/searchbox', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/lang', 'ace/lib/event', 'ace/keyboard/hash_handler', 'ace/lib/keys'], function(require, exports, module) {
var dom = require("../lib/dom");
@@ -198,7 +198,7 @@ var html = '
\
\
\
\
- \
+ \
\
\
\
@@ -244,7 +244,7 @@ var SearchBox = function(editor, range, showReplaceForm) {
event.stopPropagation(e);
});
event.addListener(sb, "click", function(e) {
- var t = e.target;
+ var t = e.target || e.srcElement;
var action = t.getAttribute("action");
if (action && _this[action])
_this[action]();
@@ -369,10 +369,18 @@ var SearchBox = function(editor, range, showReplaceForm) {
this.find(true, true);
};
this.replace = function() {
- this.editor.replace(this.replaceInput.value);
+ if (!this.editor.getReadOnly())
+ this.editor.replace(this.replaceInput.value);
+ };
+ this.replaceAndFindNext = function() {
+ if (!this.editor.getReadOnly()) {
+ this.editor.replace(this.replaceInput.value);
+ this.findNext()
+ }
};
this.replaceAll = function() {
- this.editor.replaceAll(this.replaceInput.value);
+ if (!this.editor.getReadOnly())
+ this.editor.replaceAll(this.replaceInput.value);
};
this.hide = function() {
@@ -403,45 +411,4 @@ exports.Search = function(editor, isReplace) {
sb.show(editor.session.getTextRange(), isReplace);
};
-
-exports.ISearch = function(session, options) {
- this.$changeListener = this.$changeListener.bind(this);
- this.startRange = session.selection.toOrientedRange();
- this.options = options || {};
-};
-
-(function(){
- this.setSession = function(session) {
- if (this.session) {
- this.session.removeListener(this.$changeListener);
- }
- this.session = session;
- this.session.addListener(this.$changeListener);
- };
- this.setSearchString = function() {
-
- };
- this.getValue = function() {
- if (this.value == null)
- this.value = this.session.getValue();
- return this.value;
- };
- this.$changeListener = function() {
- this.value = null;
- };
- this.find = function() {
-
- };
- this.$edgeBefore = function() {
- this.cursor = this.startRange[this.options.backwards ? "start" : "end"];
- };
- this.$edgeAfter = function() {
-
- };
- this.next = function(dir) {
-
- };
-}).call(exports.ISearch.prototype);
-
-
});
diff --git a/lib/client/edit/mode-javascript.js b/lib/client/edit/mode-javascript.js
index 5bfc25dd..bf541754 100644
--- a/lib/client/edit/mode-javascript.js
+++ b/lib/client/edit/mode-javascript.js
@@ -28,7 +28,7 @@
*
* ***** END LICENSE BLOCK ***** */
-define('ace/mode/javascript', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/javascript_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/range', 'ace/worker/worker_client', 'ace/mode/behaviour/cstyle', 'ace/mode/folding/cstyle'], function(require, exports, module) {
+ace.define('ace/mode/javascript', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/javascript_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/range', 'ace/worker/worker_client', 'ace/mode/behaviour/cstyle', 'ace/mode/folding/cstyle'], function(require, exports, module) {
var oop = require("../lib/oop");
@@ -42,9 +42,12 @@ var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
var CStyleFoldMode = require("./folding/cstyle").FoldMode;
var Mode = function() {
- this.$tokenizer = new Tokenizer(new JavaScriptHighlightRules().getRules());
+ var highlighter = new JavaScriptHighlightRules();
+
+ this.$tokenizer = new Tokenizer(highlighter.getRules());
this.$outdent = new MatchingBraceOutdent();
this.$behaviour = new CstyleBehaviour();
+ this.$keywordList = highlighter.$keywordList;
this.foldingRules = new CStyleFoldMode();
};
oop.inherits(Mode, TextMode);
@@ -114,7 +117,7 @@ oop.inherits(Mode, TextMode);
exports.Mode = Mode;
});
-define('ace/mode/javascript_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/doc_comment_highlight_rules', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+ace.define('ace/mode/javascript_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/doc_comment_highlight_rules', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
var oop = require("../lib/oop");
@@ -163,7 +166,8 @@ var JavaScriptHighlightRules = function() {
"no_regex" : [
{
token : "comment",
- regex : /\/\/.*$/
+ regex : "\\/\\/",
+ next : "line_comment"
},
DocCommentHighlightRules.getStartRule("doc-start"),
{
@@ -238,7 +242,7 @@ var JavaScriptHighlightRules = function() {
next : "start"
}, {
token : ["punctuation.operator", "support.function"],
- regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+ regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
}, {
token : ["punctuation.operator", "support.function.dom"],
regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
@@ -283,8 +287,8 @@ var JavaScriptHighlightRules = function() {
next : "comment_regex_allowed"
}, {
token : "comment",
- regex : "\\/\\/.*$",
- next : "start"
+ regex : "\\/\\/",
+ next : "line_comment_regex_allowed"
}, {
token: "string.regexp",
regex: "\\/",
@@ -371,6 +375,14 @@ var JavaScriptHighlightRules = function() {
{token : "comment", regex : "\\*\\/", next : "no_regex"},
{defaultToken : "comment"}
],
+ "line_comment_regex_allowed" : [
+ {token : "comment", regex : "$|^", next : "start"},
+ {defaultToken : "comment"}
+ ],
+ "line_comment" : [
+ {token : "comment", regex : "$|^", next : "no_regex"},
+ {defaultToken : "comment"}
+ ],
"qqstring" : [
{
token : "constant.language.escape",
@@ -414,7 +426,7 @@ oop.inherits(JavaScriptHighlightRules, TextHighlightRules);
exports.JavaScriptHighlightRules = JavaScriptHighlightRules;
});
-define('ace/mode/doc_comment_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+ace.define('ace/mode/doc_comment_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
var oop = require("../lib/oop");
@@ -458,7 +470,7 @@ exports.DocCommentHighlightRules = DocCommentHighlightRules;
});
-define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
+ace.define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
var Range = require("../range").Range;
@@ -498,7 +510,7 @@ var MatchingBraceOutdent = function() {};
exports.MatchingBraceOutdent = MatchingBraceOutdent;
});
-define('ace/mode/behaviour/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour', 'ace/token_iterator', 'ace/lib/lang'], function(require, exports, module) {
+ace.define('ace/mode/behaviour/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour', 'ace/token_iterator', 'ace/lib/lang'], function(require, exports, module) {
var oop = require("../../lib/oop");
@@ -821,7 +833,7 @@ oop.inherits(CstyleBehaviour, Behaviour);
exports.CstyleBehaviour = CstyleBehaviour;
});
-define('ace/mode/folding/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/range', 'ace/mode/folding/fold_mode'], function(require, exports, module) {
+ace.define('ace/mode/folding/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/range', 'ace/mode/folding/fold_mode'], function(require, exports, module) {
var oop = require("../../lib/oop");
@@ -873,4 +885,4 @@ oop.inherits(FoldMode, BaseFoldMode);
}).call(FoldMode.prototype);
-});
\ No newline at end of file
+});
diff --git a/lib/client/edit/theme-tomorrow_night_blue.js b/lib/client/edit/theme-tomorrow_night_blue.js
index 86c6e45f..30e1146e 100644
--- a/lib/client/edit/theme-tomorrow_night_blue.js
+++ b/lib/client/edit/theme-tomorrow_night_blue.js
@@ -28,7 +28,7 @@
*
* ***** END LICENSE BLOCK ***** */
-define('ace/theme/tomorrow_night_blue', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
+ace.define('ace/theme/tomorrow_night_blue', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
exports.isDark = true;
exports.cssClass = "ace-tomorrow-night-blue";
@@ -119,7 +119,7 @@ color: #BBDAFF\
.ace-tomorrow-night-blue .ace_support.ace_type {\
color: #FFEEAD\
}\
-.ace-tomorrow-night-blue .ace_markup.ace_heading,\
+.ace-tomorrow-night-blue .ace_heading,\
.ace-tomorrow-night-blue .ace_string {\
color: #D1F1A9\
}\
@@ -133,13 +133,10 @@ color: #FF9DA4\
.ace-tomorrow-night-blue .ace_comment {\
color: #7285B7\
}\
-.ace-tomorrow-night-blue .ace_markup.ace_underline {\
-text-decoration: underline\
-}\
.ace-tomorrow-night-blue .ace_indent-guide {\
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYJDzqfwPAANXAeNsiA+ZAAAAAElFTkSuQmCC) right repeat-y;\
}";
var dom = require("../lib/dom");
dom.importCssString(exports.cssText, exports.cssClass);
-});
\ No newline at end of file
+});
diff --git a/lib/client/edit/worker-javascript.js b/lib/client/edit/worker-javascript.js
index 95aee706..8beac737 100644
--- a/lib/client/edit/worker-javascript.js
+++ b/lib/client/edit/worker-javascript.js
@@ -4,16 +4,15 @@ if (typeof window.window != "undefined" && window.document) {
return;
}
-window.console = {
- log: function() {
- var msgs = Array.prototype.slice.call(arguments, 0);
- postMessage({type: "log", data: msgs});
- },
- error: function() {
- var msgs = Array.prototype.slice.call(arguments, 0);
- postMessage({type: "log", data: msgs});
- }
+window.console = function() {
+ var msgs = Array.prototype.slice.call(arguments, 0);
+ postMessage({type: "log", data: msgs});
};
+window.console.error =
+window.console.warn =
+window.console.log =
+window.console.trace = window.console;
+
window.window = window;
window.ace = window;
@@ -86,10 +85,9 @@ window.define = function(id, deps, factory) {
};
require.modules[id] = {
+ exports: {},
factory: function() {
- var module = {
- exports: {}
- };
+ var module = this;
var returnExports = factory(req, module.exports, module);
if (returnExports)
module.exports = returnExports;
@@ -158,7 +156,7 @@ window.onmessage = function(e) {
};
})(this);
-define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) {
var EventEmitter = {};
@@ -283,7 +281,7 @@ exports.EventEmitter = EventEmitter;
});
-define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
exports.inherits = (function() {
@@ -309,7 +307,7 @@ exports.implement = function(proto, mixin) {
});
-define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) {
function Empty() {}
@@ -1006,7 +1004,7 @@ var toObject = function (o) {
});
-define('ace/mode/javascript_worker', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/worker/mirror', 'ace/mode/javascript/jshint'], function(require, exports, module) {
+ace.define('ace/mode/javascript_worker', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/worker/mirror', 'ace/mode/javascript/jshint'], function(require, exports, module) {
var oop = require("../lib/oop");
@@ -1055,8 +1053,8 @@ oop.inherits(JavaScriptWorker, Mirror);
(function() {
this.setOptions = function(options) {
this.options = options || {
- es5: true,
esnext: true,
+ moz: true,
devel: true,
browser: true,
node: true,
@@ -1153,7 +1151,7 @@ oop.inherits(JavaScriptWorker, Mirror);
}).call(JavaScriptWorker.prototype);
});
-define('ace/worker/mirror', ['require', 'exports', 'module' , 'ace/document', 'ace/lib/lang'], function(require, exports, module) {
+ace.define('ace/worker/mirror', ['require', 'exports', 'module' , 'ace/document', 'ace/lib/lang'], function(require, exports, module) {
var Document = require("../document").Document;
@@ -1196,7 +1194,7 @@ var Mirror = exports.Mirror = function(sender) {
});
-define('ace/document', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/range', 'ace/anchor'], function(require, exports, module) {
+ace.define('ace/document', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/range', 'ace/anchor'], function(require, exports, module) {
var oop = require("./lib/oop");
@@ -1282,7 +1280,7 @@ var Document = function(text) {
};
this.getTextRange = function(range) {
if (range.start.row == range.end.row) {
- return this.$lines[range.start.row]
+ return this.getLine(range.start.row)
.substring(range.start.column, range.end.column);
}
var lines = this.getLines(range.start.row, range.end.row);
@@ -1548,7 +1546,7 @@ var Document = function(text) {
exports.Document = Document;
});
-define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) {
var comparePoints = function(p1, p2) {
return p1.row - p2.row || p1.column - p2.column;
@@ -1787,36 +1785,31 @@ Range.comparePoints = function(p1, p2) {
exports.Range = Range;
});
-define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
+ace.define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
var oop = require("./lib/oop");
var EventEmitter = require("./lib/event_emitter").EventEmitter;
var Anchor = exports.Anchor = function(doc, row, column) {
- this.document = doc;
-
+ this.$onChange = this.onChange.bind(this);
+ this.attach(doc);
+
if (typeof column == "undefined")
this.setPosition(row.row, row.column);
else
this.setPosition(row, column);
-
- this.$onChange = this.onChange.bind(this);
- doc.on("change", this.$onChange);
};
(function() {
oop.implement(this, EventEmitter);
-
this.getPosition = function() {
return this.$clipPositionToDocument(this.row, this.column);
};
-
this.getDocument = function() {
return this.document;
};
-
this.onChange = function(e) {
var delta = e.data;
var range = delta.range;
@@ -1878,7 +1871,6 @@ var Anchor = exports.Anchor = function(doc, row, column) {
this.setPosition(row, column, true);
};
-
this.setPosition = function(row, column, noClip) {
var pos;
if (noClip) {
@@ -1905,10 +1897,13 @@ var Anchor = exports.Anchor = function(doc, row, column) {
value: pos
});
};
-
this.detach = function() {
this.document.removeEventListener("change", this.$onChange);
};
+ this.attach = function(doc) {
+ this.document = doc || this.document;
+ this.document.on("change", this.$onChange);
+ };
this.$clipPositionToDocument = function(row, column) {
var pos = {};
@@ -1935,7 +1930,7 @@ var Anchor = exports.Anchor = function(doc, row, column) {
});
-define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
exports.stringReverse = function(string) {
@@ -2111,13 +2106,1089 @@ exports.delayedCall = function(fcn, defaultTimeout) {
return _self;
};
});
-define('ace/mode/javascript/jshint', ['require', 'exports', 'module' ], function(require, exports, module) {
+ace.define('ace/mode/javascript/jshint', ['require', 'exports', 'module' ], function(require, exports, module) {
+var require;
+require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s 0) {
+ var fn = queue.shift();
+ fn();
+ }
+ }
+ }, true);
+
+ return function nextTick(fn) {
+ queue.push(fn);
+ window.postMessage('process-tick', '*');
+ };
+ }
+
+ return function nextTick(fn) {
+ setTimeout(fn, 0);
+ };
+})();
+
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+}
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+
+},
+{}],
+2:[function(req,module,exports){
+(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
+
+var EventEmitter = exports.EventEmitter = process.EventEmitter;
+var isArray = typeof Array.isArray === 'function'
+ ? Array.isArray
+ : function (xs) {
+ return Object.prototype.toString.call(xs) === '[object Array]'
+ }
+;
+function indexOf (xs, x) {
+ if (xs.indexOf) return xs.indexOf(x);
+ for (var i = 0; i < xs.length; i++) {
+ if (x === xs[i]) return i;
+ }
+ return -1;
+}
+var defaultMaxListeners = 200;
+EventEmitter.prototype.setMaxListeners = function(n) {
+ if (!this._events) this._events = {};
+ this._events.maxListeners = n;
+};
+
+
+EventEmitter.prototype.emit = function(type) {
+ if (type === 'error') {
+ if (!this._events || !this._events.error ||
+ (isArray(this._events.error) && !this._events.error.length))
+ {
+ if (arguments[1] instanceof Error) {
+ throw arguments[1]; // Unhandled 'error' event
+ } else {
+ throw new Error("Uncaught, unspecified 'error' event.");
+ }
+ return false;
+ }
+ }
+
+ if (!this._events) return false;
+ var handler = this._events[type];
+ if (!handler) return false;
+
+ if (typeof handler == 'function') {
+ switch (arguments.length) {
+ case 1:
+ handler.call(this);
+ break;
+ case 2:
+ handler.call(this, arguments[1]);
+ break;
+ case 3:
+ handler.call(this, arguments[1], arguments[2]);
+ break;
+ default:
+ var args = Array.prototype.slice.call(arguments, 1);
+ handler.apply(this, args);
+ }
+ return true;
+
+ } else if (isArray(handler)) {
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ var listeners = handler.slice();
+ for (var i = 0, l = listeners.length; i < l; i++) {
+ listeners[i].apply(this, args);
+ }
+ return true;
+
+ } else {
+ return false;
+ }
+};
+EventEmitter.prototype.addListener = function(type, listener) {
+ if ('function' !== typeof listener) {
+ throw new Error('addListener only takes instances of Function');
+ }
+
+ if (!this._events) this._events = {};
+ this.emit('newListener', type, listener);
+
+ if (!this._events[type]) {
+ this._events[type] = listener;
+ } else if (isArray(this._events[type])) {
+ if (!this._events[type].warned) {
+ var m;
+ if (this._events.maxListeners !== undefined) {
+ m = this._events.maxListeners;
+ } else {
+ m = defaultMaxListeners;
+ }
+
+ if (m && m > 0 && this._events[type].length > m) {
+ this._events[type].warned = true;
+ console.error('(node) warning: possible EventEmitter memory ' +
+ 'leak detected. %d listeners added. ' +
+ 'Use emitter.setMaxListeners() to increase limit.',
+ this._events[type].length);
+ console.trace();
+ }
+ }
+ this._events[type].push(listener);
+ } else {
+ this._events[type] = [this._events[type], listener];
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;
+
+EventEmitter.prototype.once = function(type, listener) {
+ var self = this;
+ self.on(type, function g() {
+ self.removeListener(type, g);
+ listener.apply(this, arguments);
+ });
+
+ return this;
+};
+
+EventEmitter.prototype.removeListener = function(type, listener) {
+ if ('function' !== typeof listener) {
+ throw new Error('removeListener only takes instances of Function');
+ }
+ if (!this._events || !this._events[type]) return this;
+
+ var list = this._events[type];
+
+ if (isArray(list)) {
+ var i = indexOf(list, listener);
+ if (i < 0) return this;
+ list.splice(i, 1);
+ if (list.length == 0)
+ delete this._events[type];
+ } else if (this._events[type] === listener) {
+ delete this._events[type];
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.removeAllListeners = function(type) {
+ if (arguments.length === 0) {
+ this._events = {};
+ return this;
+ }
+ if (type && this._events && this._events[type]) this._events[type] = null;
+ return this;
+};
+
+EventEmitter.prototype.listeners = function(type) {
+ if (!this._events) this._events = {};
+ if (!this._events[type]) this._events[type] = [];
+ if (!isArray(this._events[type])) {
+ this._events[type] = [this._events[type]];
+ }
+ return this._events[type];
+};
+
+})(req("__browserify_process"))
+},
+{"__browserify_process":1}],
+3:[function(req,module,exports){
+(function(){// jshint -W001
+
+exports.reservedVars = {
+ arguments : false,
+ NaN : false
+};
+
+exports.ecmaIdentifiers = {
+ Array : false,
+ Boolean : false,
+ Date : false,
+ decodeURI : false,
+ decodeURIComponent : false,
+ encodeURI : false,
+ encodeURIComponent : false,
+ Error : false,
+ "eval" : false,
+ EvalError : false,
+ Function : false,
+ hasOwnProperty : false,
+ isFinite : false,
+ isNaN : false,
+ JSON : false,
+ Math : false,
+ Map : false,
+ Number : false,
+ Object : false,
+ parseInt : false,
+ parseFloat : false,
+ RangeError : false,
+ ReferenceError : false,
+ RegExp : false,
+ Set : false,
+ String : false,
+ SyntaxError : false,
+ TypeError : false,
+ URIError : false,
+ WeakMap : false
+};
+
+exports.browser = {
+ ArrayBuffer : false,
+ ArrayBufferView : false,
+ Audio : false,
+ Blob : false,
+ addEventListener : false,
+ applicationCache : false,
+ atob : false,
+ blur : false,
+ btoa : false,
+ clearInterval : false,
+ clearTimeout : false,
+ close : false,
+ closed : false,
+ DataView : false,
+ DOMParser : false,
+ defaultStatus : false,
+ document : false,
+ Element : false,
+ ElementTimeControl : false,
+ event : false,
+ FileReader : false,
+ Float32Array : false,
+ Float64Array : false,
+ FormData : false,
+ focus : false,
+ frames : false,
+ getComputedStyle : false,
+ HTMLElement : false,
+ HTMLAnchorElement : false,
+ HTMLBaseElement : false,
+ HTMLBlockquoteElement: false,
+ HTMLBodyElement : false,
+ HTMLBRElement : false,
+ HTMLButtonElement : false,
+ HTMLCanvasElement : false,
+ HTMLDirectoryElement : false,
+ HTMLDivElement : false,
+ HTMLDListElement : false,
+ HTMLFieldSetElement : false,
+ HTMLFontElement : false,
+ HTMLFormElement : false,
+ HTMLFrameElement : false,
+ HTMLFrameSetElement : false,
+ HTMLHeadElement : false,
+ HTMLHeadingElement : false,
+ HTMLHRElement : false,
+ HTMLHtmlElement : false,
+ HTMLIFrameElement : false,
+ HTMLImageElement : false,
+ HTMLInputElement : false,
+ HTMLIsIndexElement : false,
+ HTMLLabelElement : false,
+ HTMLLayerElement : false,
+ HTMLLegendElement : false,
+ HTMLLIElement : false,
+ HTMLLinkElement : false,
+ HTMLMapElement : false,
+ HTMLMenuElement : false,
+ HTMLMetaElement : false,
+ HTMLModElement : false,
+ HTMLObjectElement : false,
+ HTMLOListElement : false,
+ HTMLOptGroupElement : false,
+ HTMLOptionElement : false,
+ HTMLParagraphElement : false,
+ HTMLParamElement : false,
+ HTMLPreElement : false,
+ HTMLQuoteElement : false,
+ HTMLScriptElement : false,
+ HTMLSelectElement : false,
+ HTMLStyleElement : false,
+ HTMLTableCaptionElement: false,
+ HTMLTableCellElement : false,
+ HTMLTableColElement : false,
+ HTMLTableElement : false,
+ HTMLTableRowElement : false,
+ HTMLTableSectionElement: false,
+ HTMLTextAreaElement : false,
+ HTMLTitleElement : false,
+ HTMLUListElement : false,
+ HTMLVideoElement : false,
+ history : false,
+ Int16Array : false,
+ Int32Array : false,
+ Int8Array : false,
+ Image : false,
+ length : false,
+ localStorage : false,
+ location : false,
+ MessageChannel : false,
+ MessageEvent : false,
+ MessagePort : false,
+ moveBy : false,
+ moveTo : false,
+ MutationObserver : false,
+ name : false,
+ Node : false,
+ NodeFilter : false,
+ navigator : false,
+ onbeforeunload : true,
+ onblur : true,
+ onerror : true,
+ onfocus : true,
+ onload : true,
+ onresize : true,
+ onunload : true,
+ open : false,
+ openDatabase : false,
+ opener : false,
+ Option : false,
+ parent : false,
+ print : false,
+ removeEventListener : false,
+ resizeBy : false,
+ resizeTo : false,
+ screen : false,
+ scroll : false,
+ scrollBy : false,
+ scrollTo : false,
+ sessionStorage : false,
+ setInterval : false,
+ setTimeout : false,
+ SharedWorker : false,
+ status : false,
+ SVGAElement : false,
+ SVGAltGlyphDefElement: false,
+ SVGAltGlyphElement : false,
+ SVGAltGlyphItemElement: false,
+ SVGAngle : false,
+ SVGAnimateColorElement: false,
+ SVGAnimateElement : false,
+ SVGAnimateMotionElement: false,
+ SVGAnimateTransformElement: false,
+ SVGAnimatedAngle : false,
+ SVGAnimatedBoolean : false,
+ SVGAnimatedEnumeration: false,
+ SVGAnimatedInteger : false,
+ SVGAnimatedLength : false,
+ SVGAnimatedLengthList: false,
+ SVGAnimatedNumber : false,
+ SVGAnimatedNumberList: false,
+ SVGAnimatedPathData : false,
+ SVGAnimatedPoints : false,
+ SVGAnimatedPreserveAspectRatio: false,
+ SVGAnimatedRect : false,
+ SVGAnimatedString : false,
+ SVGAnimatedTransformList: false,
+ SVGAnimationElement : false,
+ SVGCSSRule : false,
+ SVGCircleElement : false,
+ SVGClipPathElement : false,
+ SVGColor : false,
+ SVGColorProfileElement: false,
+ SVGColorProfileRule : false,
+ SVGComponentTransferFunctionElement: false,
+ SVGCursorElement : false,
+ SVGDefsElement : false,
+ SVGDescElement : false,
+ SVGDocument : false,
+ SVGElement : false,
+ SVGElementInstance : false,
+ SVGElementInstanceList: false,
+ SVGEllipseElement : false,
+ SVGExternalResourcesRequired: false,
+ SVGFEBlendElement : false,
+ SVGFEColorMatrixElement: false,
+ SVGFEComponentTransferElement: false,
+ SVGFECompositeElement: false,
+ SVGFEConvolveMatrixElement: false,
+ SVGFEDiffuseLightingElement: false,
+ SVGFEDisplacementMapElement: false,
+ SVGFEDistantLightElement: false,
+ SVGFEFloodElement : false,
+ SVGFEFuncAElement : false,
+ SVGFEFuncBElement : false,
+ SVGFEFuncGElement : false,
+ SVGFEFuncRElement : false,
+ SVGFEGaussianBlurElement: false,
+ SVGFEImageElement : false,
+ SVGFEMergeElement : false,
+ SVGFEMergeNodeElement: false,
+ SVGFEMorphologyElement: false,
+ SVGFEOffsetElement : false,
+ SVGFEPointLightElement: false,
+ SVGFESpecularLightingElement: false,
+ SVGFESpotLightElement: false,
+ SVGFETileElement : false,
+ SVGFETurbulenceElement: false,
+ SVGFilterElement : false,
+ SVGFilterPrimitiveStandardAttributes: false,
+ SVGFitToViewBox : false,
+ SVGFontElement : false,
+ SVGFontFaceElement : false,
+ SVGFontFaceFormatElement: false,
+ SVGFontFaceNameElement: false,
+ SVGFontFaceSrcElement: false,
+ SVGFontFaceUriElement: false,
+ SVGForeignObjectElement: false,
+ SVGGElement : false,
+ SVGGlyphElement : false,
+ SVGGlyphRefElement : false,
+ SVGGradientElement : false,
+ SVGHKernElement : false,
+ SVGICCColor : false,
+ SVGImageElement : false,
+ SVGLangSpace : false,
+ SVGLength : false,
+ SVGLengthList : false,
+ SVGLineElement : false,
+ SVGLinearGradientElement: false,
+ SVGLocatable : false,
+ SVGMPathElement : false,
+ SVGMarkerElement : false,
+ SVGMaskElement : false,
+ SVGMatrix : false,
+ SVGMetadataElement : false,
+ SVGMissingGlyphElement: false,
+ SVGNumber : false,
+ SVGNumberList : false,
+ SVGPaint : false,
+ SVGPathElement : false,
+ SVGPathSeg : false,
+ SVGPathSegArcAbs : false,
+ SVGPathSegArcRel : false,
+ SVGPathSegClosePath : false,
+ SVGPathSegCurvetoCubicAbs: false,
+ SVGPathSegCurvetoCubicRel: false,
+ SVGPathSegCurvetoCubicSmoothAbs: false,
+ SVGPathSegCurvetoCubicSmoothRel: false,
+ SVGPathSegCurvetoQuadraticAbs: false,
+ SVGPathSegCurvetoQuadraticRel: false,
+ SVGPathSegCurvetoQuadraticSmoothAbs: false,
+ SVGPathSegCurvetoQuadraticSmoothRel: false,
+ SVGPathSegLinetoAbs : false,
+ SVGPathSegLinetoHorizontalAbs: false,
+ SVGPathSegLinetoHorizontalRel: false,
+ SVGPathSegLinetoRel : false,
+ SVGPathSegLinetoVerticalAbs: false,
+ SVGPathSegLinetoVerticalRel: false,
+ SVGPathSegList : false,
+ SVGPathSegMovetoAbs : false,
+ SVGPathSegMovetoRel : false,
+ SVGPatternElement : false,
+ SVGPoint : false,
+ SVGPointList : false,
+ SVGPolygonElement : false,
+ SVGPolylineElement : false,
+ SVGPreserveAspectRatio: false,
+ SVGRadialGradientElement: false,
+ SVGRect : false,
+ SVGRectElement : false,
+ SVGRenderingIntent : false,
+ SVGSVGElement : false,
+ SVGScriptElement : false,
+ SVGSetElement : false,
+ SVGStopElement : false,
+ SVGStringList : false,
+ SVGStylable : false,
+ SVGStyleElement : false,
+ SVGSwitchElement : false,
+ SVGSymbolElement : false,
+ SVGTRefElement : false,
+ SVGTSpanElement : false,
+ SVGTests : false,
+ SVGTextContentElement: false,
+ SVGTextElement : false,
+ SVGTextPathElement : false,
+ SVGTextPositioningElement: false,
+ SVGTitleElement : false,
+ SVGTransform : false,
+ SVGTransformList : false,
+ SVGTransformable : false,
+ SVGURIReference : false,
+ SVGUnitTypes : false,
+ SVGUseElement : false,
+ SVGVKernElement : false,
+ SVGViewElement : false,
+ SVGViewSpec : false,
+ SVGZoomAndPan : false,
+ TimeEvent : false,
+ top : false,
+ Uint16Array : false,
+ Uint32Array : false,
+ Uint8Array : false,
+ Uint8ClampedArray : false,
+ WebSocket : false,
+ window : false,
+ Worker : false,
+ XMLHttpRequest : false,
+ XMLSerializer : false,
+ XPathEvaluator : false,
+ XPathException : false,
+ XPathExpression : false,
+ XPathNamespace : false,
+ XPathNSResolver : false,
+ XPathResult : false
+};
+
+exports.devel = {
+ alert : false,
+ confirm: false,
+ console: false,
+ Debug : false,
+ opera : false,
+ prompt : false
+};
+
+exports.worker = {
+ importScripts: true,
+ postMessage : true,
+ self : true
+};
+exports.nonstandard = {
+ escape : false,
+ unescape: false
+};
+
+exports.couch = {
+ "require" : false,
+ respond : false,
+ getRow : false,
+ emit : false,
+ send : false,
+ start : false,
+ sum : false,
+ log : false,
+ exports : false,
+ module : false,
+ provides : false
+};
+
+exports.node = {
+ __filename : false,
+ __dirname : false,
+ Buffer : false,
+ DataView : false,
+ console : false,
+ exports : true, // In Node it is ok to exports = module.exports = foo();
+ GLOBAL : false,
+ global : false,
+ module : false,
+ process : false,
+ require : false,
+ setTimeout : false,
+ clearTimeout : false,
+ setInterval : false,
+ clearInterval : false,
+ setImmediate : false, // v0.9.1+
+ clearImmediate: false // v0.9.1+
+};
+
+exports.phantom = {
+ phantom : true,
+ require : true,
+ WebPage : true
+};
+
+exports.rhino = {
+ defineClass : false,
+ deserialize : false,
+ gc : false,
+ help : false,
+ importPackage: false,
+ "java" : false,
+ load : false,
+ loadClass : false,
+ print : false,
+ quit : false,
+ readFile : false,
+ readUrl : false,
+ runCommand : false,
+ seal : false,
+ serialize : false,
+ spawn : false,
+ sync : false,
+ toint32 : false,
+ version : false
+};
+
+exports.shelljs = {
+ target : false,
+ echo : false,
+ exit : false,
+ cd : false,
+ pwd : false,
+ ls : false,
+ find : false,
+ cp : false,
+ rm : false,
+ mv : false,
+ mkdir : false,
+ test : false,
+ cat : false,
+ sed : false,
+ grep : false,
+ which : false,
+ dirs : false,
+ pushd : false,
+ popd : false,
+ env : false,
+ exec : false,
+ chmod : false,
+ config : false,
+ error : false,
+ tempdir : false
+};
+
+exports.wsh = {
+ ActiveXObject : true,
+ Enumerator : true,
+ GetObject : true,
+ ScriptEngine : true,
+ ScriptEngineBuildVersion : true,
+ ScriptEngineMajorVersion : true,
+ ScriptEngineMinorVersion : true,
+ VBArray : true,
+ WSH : true,
+ WScript : true,
+ XDomainRequest : true
+};
+
+exports.dojo = {
+ dojo : false,
+ dijit : false,
+ dojox : false,
+ define : false,
+ "require": false
+};
+
+exports.jquery = {
+ "$" : false,
+ jQuery : false
+};
+
+exports.mootools = {
+ "$" : false,
+ "$$" : false,
+ Asset : false,
+ Browser : false,
+ Chain : false,
+ Class : false,
+ Color : false,
+ Cookie : false,
+ Core : false,
+ Document : false,
+ DomReady : false,
+ DOMEvent : false,
+ DOMReady : false,
+ Drag : false,
+ Element : false,
+ Elements : false,
+ Event : false,
+ Events : false,
+ Fx : false,
+ Group : false,
+ Hash : false,
+ HtmlTable : false,
+ Iframe : false,
+ IframeShim : false,
+ InputValidator: false,
+ instanceOf : false,
+ Keyboard : false,
+ Locale : false,
+ Mask : false,
+ MooTools : false,
+ Native : false,
+ Options : false,
+ OverText : false,
+ Request : false,
+ Scroller : false,
+ Slick : false,
+ Slider : false,
+ Sortables : false,
+ Spinner : false,
+ Swiff : false,
+ Tips : false,
+ Type : false,
+ typeOf : false,
+ URI : false,
+ Window : false
+};
+
+exports.prototypejs = {
+ "$" : false,
+ "$$" : false,
+ "$A" : false,
+ "$F" : false,
+ "$H" : false,
+ "$R" : false,
+ "$break" : false,
+ "$continue" : false,
+ "$w" : false,
+ Abstract : false,
+ Ajax : false,
+ Class : false,
+ Enumerable : false,
+ Element : false,
+ Event : false,
+ Field : false,
+ Form : false,
+ Hash : false,
+ Insertion : false,
+ ObjectRange : false,
+ PeriodicalExecuter: false,
+ Position : false,
+ Prototype : false,
+ Selector : false,
+ Template : false,
+ Toggle : false,
+ Try : false,
+ Autocompleter : false,
+ Builder : false,
+ Control : false,
+ Draggable : false,
+ Draggables : false,
+ Droppables : false,
+ Effect : false,
+ Sortable : false,
+ SortableObserver : false,
+ Sound : false,
+ Scriptaculous : false
+};
+
+exports.yui = {
+ YUI : false,
+ Y : false,
+ YUI_config: false
+};
+
+
+})()
+},
+{}],
+4:[function(req,module,exports){
+
+"use string";
+exports.unsafeString =
+ /@cc|<\/?|script|\]\s*\]|<\s*!|</i;
+exports.unsafeChars =
+ /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+exports.needEsc =
+ /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+
+exports.needEscGlobal =
+ /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
+exports.starSlash = /\*\//;
+exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
+exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
+exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
+
+},
+{}],
+5:[function(req,module,exports){
+
+
+var state = {
+ syntax: {},
+
+ reset: function () {
+ this.tokens = {
+ prev: null,
+ next: null,
+ curr: null
+ };
+
+ this.option = {};
+ this.ignored = {};
+ this.directive = {};
+ this.jsonMode = false;
+ this.jsonWarnings = [];
+ this.lines = [];
+ this.tab = "";
+ this.cache = {}; // Node.JS doesn't have Map. Sniff.
+ }
+};
+
+exports.state = state;
+
+},
+{}],
+6:[function(req,module,exports){
+(function(){
+
+exports.register = function (linter) {
+
+ linter.on("Identifier", function style_scanProto(data) {
+ if (linter.getOption("proto")) {
+ return;
+ }
+
+ if (data.name === "__proto__") {
+ linter.warn("W103", {
+ line: data.line,
+ char: data.char,
+ data: [ data.name ]
+ });
+ }
+ });
+
+ linter.on("Identifier", function style_scanIterator(data) {
+ if (linter.getOption("iterator")) {
+ return;
+ }
+
+ if (data.name === "__iterator__") {
+ linter.warn("W104", {
+ line: data.line,
+ char: data.char,
+ data: [ data.name ]
+ });
+ }
+ });
+
+ linter.on("Identifier", function style_scanDangling(data) {
+ if (!linter.getOption("nomen")) {
+ return;
+ }
+ if (data.name === "_") {
+ return;
+ }
+ if (linter.getOption("node")) {
+ if (/^(__dirname|__filename)$/.test(data.name) && !data.isProperty) {
+ return;
+ }
+ }
+
+ if (/^(_+.*|.*_+)$/.test(data.name)) {
+ linter.warn("W105", {
+ line: data.line,
+ char: data.from,
+ data: [ "dangling '_'", data.name ]
+ });
+ }
+ });
+
+ linter.on("Identifier", function style_scanCamelCase(data) {
+ if (!linter.getOption("camelcase")) {
+ return;
+ }
+
+ if (data.name.replace(/^_+/, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
+ linter.warn("W106", {
+ line: data.line,
+ char: data.from,
+ data: [ data.name ]
+ });
+ }
+ });
+
+ linter.on("String", function style_scanQuotes(data) {
+ var quotmark = linter.getOption("quotmark");
+ var code;
+
+ if (!quotmark) {
+ return;
+ }
+
+ if (quotmark === "single" && data.quote !== "'") {
+ code = "W109";
+ }
+
+ if (quotmark === "double" && data.quote !== "\"") {
+ code = "W108";
+ }
+
+ if (quotmark === true) {
+ if (!linter.getCache("quotmark")) {
+ linter.setCache("quotmark", data.quote);
+ }
+
+ if (linter.getCache("quotmark") !== data.quote) {
+ code = "W110";
+ }
+ }
+
+ if (code) {
+ linter.warn(code, {
+ line: data.line,
+ char: data.char,
+ });
+ }
+ });
+
+ linter.on("Number", function style_scanNumbers(data) {
+ if (data.value.charAt(0) === ".") {
+ linter.warn("W008", {
+ line: data.line,
+ char: data.char,
+ data: [ data.value ]
+ });
+ }
+
+ if (data.value.substr(data.value.length - 1) === ".") {
+ linter.warn("W047", {
+ line: data.line,
+ char: data.char,
+ data: [ data.value ]
+ });
+ }
+
+ if (/^00+/.test(data.value)) {
+ linter.warn("W046", {
+ line: data.line,
+ char: data.char,
+ data: [ data.value ]
+ });
+ }
+ });
+
+ linter.on("String", function style_scanJavaScriptURLs(data) {
+ var re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
+
+ if (linter.getOption("scripturl")) {
+ return;
+ }
+
+ if (re.test(data.value)) {
+ linter.warn("W107", {
+ line: data.line,
+ char: data.char
+ });
+ }
+ });
+};
+})()
+},
+{}],
+7:[function(req,module,exports){
+(function(global){/*global window, global*/
+var functions = [
+ [log, "log"]
+ , [info, "info"]
+ , [warn, "warn"]
+ , [error, "error"]
+ , [time, "time"]
+ , [timeEnd, "timeEnd"]
+ , [trace, "trace"]
+ , [dir, "dir"]
+ , [assert, "assert"]
+]
+
+for (var i = 0; i < functions.length; i++) {
+ var tuple = functions[i]
+ var f = tuple[0]
+ var name = tuple[1]
+
+ if (!console[name]) {
+ console[name] = f
+ }
+}
+
+module.exports = console
+
+function log() {}
+
+function info() {}
+
+function warn() {}
+
+function error() {}
+
+function time(label) {}
+
+function timeEnd(label) {}
+
+function trace() {}
+
+function dir(object) {}
+
+function assert(expression) {}
+
+})(window)
+},
+{}],
+"jshint":[function(req,module,exports){
+module.exports=req('E/GbHF');
+},
+{}],"E/GbHF":[function(req,module,exports){
+(function(){/*!
+ * JSHint, by JSHint Community.
+ *
+ * This file (and this file only) is licensed under the same slightly modified
+ * MIT license that JSLint is. It stops evil-doers everywhere:
+ *
+ * Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * The Software shall be used for Good, not Evil.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+var _ = req("underscore");
+var events = req("events");
+var vars = req("../shared/vars.js");
+var messages = req("../shared/messages.js");
+var Lexer = req("./lex.js").Lexer;
+var reg = req("./reg.js");
+var state = req("./state.js").state;
+var style = req("./style.js");
+var console = req("console-browserify");
var JSHINT = (function () {
-
-
- var anonname, // The guessed name for anonymous functions.
+
+ var anonname, // The guessed name for anonymous functions.
+ api, // Extension API
bang = {
"<" : true,
"<=" : true,
@@ -2134,627 +3205,189 @@ var JSHINT = (function () {
"%" : true
},
boolOptions = {
- asi : true, // if automatic semicolon insertion should be tolerated
- bitwise : true, // if bitwise operators should not be allowed
- boss : true, // if advanced usage of assignments should be allowed
- browser : true, // if the standard browser globals should be predefined
- camelcase : true, // if identifiers should be required in camel case
- couch : true, // if CouchDB globals should be predefined
- curly : true, // if curly braces around all blocks should be required
- debug : true, // if debugger statements should be allowed
- devel : true, // if logging globals should be predefined (console,
- dojo : true, // if Dojo Toolkit globals should be predefined
- eqeqeq : true, // if === should be required
- eqnull : true, // if == null comparisons should be tolerated
- es5 : true, // if ES5 syntax should be allowed
- esnext : true, // if es.next specific syntax should be allowed
- evil : true, // if eval should be allowed
- expr : true, // if ExpressionStatement should be allowed as Programs
- forin : true, // if for in statements must filter
- funcscope : true, // if only function scope should be used for scope tests
- globalstrict: true, // if global should be allowed (also
- immed : true, // if immediate invocations must be wrapped in parens
- iterator : true, // if the `__iterator__` property should be allowed
- jquery : true, // if jQuery globals should be predefined
- lastsemic : true, // if semicolons may be ommitted for the trailing
- latedef : true, // if the use before definition should not be tolerated
- laxbreak : true, // if line breaks should not be checked
- laxcomma : true, // if line breaks should not be checked around commas
- loopfunc : true, // if functions should be allowed to be defined within
- mootools : true, // if MooTools globals should be predefined
- multistr : true, // allow multiline strings
- newcap : true, // if constructor names must be capitalized
- noarg : true, // if arguments.caller and arguments.callee should be
- node : true, // if the Node.js environment globals should be
- noempty : true, // if empty blocks should be disallowed
- nonew : true, // if using `new` for side-effects should be disallowed
+ asi : true, // if automatic semicolon insertion should be tolerated
+ bitwise : true, // if bitwise operators should not be allowed
+ boss : true, // if advanced usage of assignments should be allowed
+ browser : true, // if the standard browser globals should be predefined
+ camelcase : true, // if identifiers should be required in camel case
+ couch : true, // if CouchDB globals should be predefined
+ curly : true, // if curly braces around all blocks should be required
+ debug : true, // if debugger statements should be allowed
+ devel : true, // if logging globals should be predefined (console, alert, etc.)
+ dojo : true, // if Dojo Toolkit globals should be predefined
+ eqeqeq : true, // if === should be required
+ eqnull : true, // if == null comparisons should be tolerated
+ es3 : true, // if ES3 syntax should be allowed
+ es5 : true, // if ES5 syntax should be allowed (is now set per default)
+ esnext : true, // if es.next specific syntax should be allowed
+ moz : true, // if mozilla specific syntax should be allowed
+ evil : true, // if eval should be allowed
+ expr : true, // if ExpressionStatement should be allowed as Programs
+ forin : true, // if for in statements must filter
+ funcscope : true, // if only function scope should be used for scope tests
+ gcl : true, // if JSHint should be compatible with Google Closure Linter
+ globalstrict: true, // if global should be allowed (also enables 'strict')
+ immed : true, // if immediate invocations must be wrapped in parens
+ iterator : true, // if the `__iterator__` property should be allowed
+ jquery : true, // if jQuery globals should be predefined
+ lastsemic : true, // if semicolons may be ommitted for the trailing
+ laxbreak : true, // if line breaks should not be checked
+ laxcomma : true, // if line breaks should not be checked around commas
+ loopfunc : true, // if functions should be allowed to be defined within
+ mootools : true, // if MooTools globals should be predefined
+ multistr : true, // allow multiline strings
+ newcap : true, // if constructor names must be capitalized
+ noarg : true, // if arguments.caller and arguments.callee should be
+ node : true, // if the Node.js environment globals should be
+ noempty : true, // if empty blocks should be disallowed
+ nonew : true, // if using `new` for side-effects should be disallowed
nonstandard : true, // if non-standard (but widely adopted) globals should
- nomen : true, // if names should be checked
- onevar : true, // if only one var statement per function should be
- onecase : true, // if one case switch statements should be allowed
- passfail : true, // if the scan should stop on first error
- plusplus : true, // if increment/decrement should not be allowed
- proto : true, // if the `__proto__` property should be allowed
+ nomen : true, // if names should be checked
+ onevar : true, // if only one var statement per function should be
+ passfail : true, // if the scan should stop on first error
+ phantom : true, // if PhantomJS symbols should be allowed
+ plusplus : true, // if increment/decrement should not be allowed
+ proto : true, // if the `__proto__` property should be allowed
prototypejs : true, // if Prototype and Scriptaculous globals should be
- regexdash : true, // if unescaped first/last dash (-) inside brackets
- regexp : true, // if the . should not be allowed in regexp literals
- rhino : true, // if the Rhino environment globals should be predefined
- undef : true, // if variables should be declared before used
- unused : true, // if variables should be always used
- scripturl : true, // if script-targeted URLs should be tolerated
- shadow : true, // if variable shadowing should be tolerated
- smarttabs : true, // if smarttabs should be tolerated
- strict : true, // require the pragma
- sub : true, // if all forms of subscript notation are tolerated
- supernew : true, // if `new function () { ... };` and `new Object;`
- trailing : true, // if trailing whitespace rules apply
- validthis : true, // if 'this' inside a non-constructor function is valid.
- withstmt : true, // if with statements should be allowed
- white : true, // if strict whitespace rules apply
- worker : true, // if Web Worker script symbols should be allowed
- wsh : true, // if the Windows Scripting Host environment globals
- yui : true // YUI variables should be predefined
+ rhino : true, // if the Rhino environment globals should be predefined
+ shelljs : true, // if ShellJS globals should be predefined
+ undef : true, // if variables should be declared before used
+ scripturl : true, // if script-targeted URLs should be tolerated
+ shadow : true, // if variable shadowing should be tolerated
+ smarttabs : true, // if smarttabs should be tolerated
+ strict : true, // require the pragma
+ sub : true, // if all forms of subscript notation are tolerated
+ supernew : true, // if `new function () { ... };` and `new Object;`
+ trailing : true, // if trailing whitespace rules apply
+ validthis : true, // if 'this' inside a non-constructor function is valid.
+ withstmt : true, // if with statements should be allowed
+ white : true, // if strict whitespace rules apply
+ worker : true, // if Web Worker script symbols should be allowed
+ wsh : true, // if the Windows Scripting Host environment globals
+ yui : true, // YUI variables should be predefined
+ onecase : true, // if one case switch statements should be allowed
+ regexp : true, // if the . should not be allowed in regexp literals
+ regexdash : true // if unescaped first/last dash (-) inside brackets
},
valOptions = {
- maxlen : false,
- indent : false,
- maxerr : false,
- predef : false,
- quotmark : false, //'single'|'double'|true
- scope : false,
+ maxlen : false,
+ indent : false,
+ maxerr : false,
+ predef : false,
+ quotmark : false, //'single'|'double'|true
+ scope : false,
maxstatements: false, // {int} max statements per function
- maxdepth : false, // {int} max nested block depth per function
- maxparams : false, // {int} max params per function
- maxcomplexity: false // {int} max cyclomatic complexity per function
+ maxdepth : false, // {int} max nested block depth per function
+ maxparams : false, // {int} max params per function
+ maxcomplexity: false, // {int} max cyclomatic complexity per function
+ unused : true, // warn if variables are unused. Available options:
+ latedef : false // warn if the variable is used before its definition
},
invertedOptions = {
- bitwise : true,
- forin : true,
- newcap : true,
- nomen : true,
- plusplus : true,
- regexp : true,
- undef : true,
- white : true,
- eqeqeq : true,
- onevar : true
+ bitwise : true,
+ forin : true,
+ newcap : true,
+ nomen : true,
+ plusplus: true,
+ regexp : true,
+ undef : true,
+ white : true,
+ eqeqeq : true,
+ onevar : true,
+ strict : true
},
renamedOptions = {
- eqeq : "eqeqeq",
- vars : "onevar",
- windows : "wsh"
- },
- browser = {
- ArrayBuffer : false,
- ArrayBufferView : false,
- Audio : false,
- Blob : false,
- addEventListener : false,
- applicationCache : false,
- atob : false,
- blur : false,
- btoa : false,
- clearInterval : false,
- clearTimeout : false,
- close : false,
- closed : false,
- DataView : false,
- DOMParser : false,
- defaultStatus : false,
- document : false,
- event : false,
- FileReader : false,
- Float32Array : false,
- Float64Array : false,
- FormData : false,
- focus : false,
- frames : false,
- getComputedStyle : false,
- HTMLElement : false,
- HTMLAnchorElement : false,
- HTMLBaseElement : false,
- HTMLBlockquoteElement : false,
- HTMLBodyElement : false,
- HTMLBRElement : false,
- HTMLButtonElement : false,
- HTMLCanvasElement : false,
- HTMLDirectoryElement : false,
- HTMLDivElement : false,
- HTMLDListElement : false,
- HTMLFieldSetElement : false,
- HTMLFontElement : false,
- HTMLFormElement : false,
- HTMLFrameElement : false,
- HTMLFrameSetElement : false,
- HTMLHeadElement : false,
- HTMLHeadingElement : false,
- HTMLHRElement : false,
- HTMLHtmlElement : false,
- HTMLIFrameElement : false,
- HTMLImageElement : false,
- HTMLInputElement : false,
- HTMLIsIndexElement : false,
- HTMLLabelElement : false,
- HTMLLayerElement : false,
- HTMLLegendElement : false,
- HTMLLIElement : false,
- HTMLLinkElement : false,
- HTMLMapElement : false,
- HTMLMenuElement : false,
- HTMLMetaElement : false,
- HTMLModElement : false,
- HTMLObjectElement : false,
- HTMLOListElement : false,
- HTMLOptGroupElement : false,
- HTMLOptionElement : false,
- HTMLParagraphElement : false,
- HTMLParamElement : false,
- HTMLPreElement : false,
- HTMLQuoteElement : false,
- HTMLScriptElement : false,
- HTMLSelectElement : false,
- HTMLStyleElement : false,
- HTMLTableCaptionElement : false,
- HTMLTableCellElement : false,
- HTMLTableColElement : false,
- HTMLTableElement : false,
- HTMLTableRowElement : false,
- HTMLTableSectionElement : false,
- HTMLTextAreaElement : false,
- HTMLTitleElement : false,
- HTMLUListElement : false,
- HTMLVideoElement : false,
- history : false,
- Int16Array : false,
- Int32Array : false,
- Int8Array : false,
- Image : false,
- length : false,
- localStorage : false,
- location : false,
- MessageChannel : false,
- MessageEvent : false,
- MessagePort : false,
- moveBy : false,
- moveTo : false,
- MutationObserver : false,
- name : false,
- Node : false,
- NodeFilter : false,
- navigator : false,
- onbeforeunload : true,
- onblur : true,
- onerror : true,
- onfocus : true,
- onload : true,
- onresize : true,
- onunload : true,
- open : false,
- openDatabase : false,
- opener : false,
- Option : false,
- parent : false,
- print : false,
- removeEventListener : false,
- resizeBy : false,
- resizeTo : false,
- screen : false,
- scroll : false,
- scrollBy : false,
- scrollTo : false,
- sessionStorage : false,
- setInterval : false,
- setTimeout : false,
- SharedWorker : false,
- status : false,
- top : false,
- Uint16Array : false,
- Uint32Array : false,
- Uint8Array : false,
- WebSocket : false,
- window : false,
- Worker : false,
- XMLHttpRequest : false,
- XMLSerializer : false,
- XPathEvaluator : false,
- XPathException : false,
- XPathExpression : false,
- XPathNamespace : false,
- XPathNSResolver : false,
- XPathResult : false
- },
-
- couch = {
- "require" : false,
- respond : false,
- getRow : false,
- emit : false,
- send : false,
- start : false,
- sum : false,
- log : false,
- exports : false,
- module : false,
- provides : false
+ eqeq : "eqeqeq",
+ vars : "onevar",
+ windows: "wsh",
+ sloppy : "strict"
},
declared, // Globals that were declared using /*global ... */ syntax.
-
- devel = {
- alert : false,
- confirm : false,
- console : false,
- Debug : false,
- opera : false,
- prompt : false
- },
-
- dojo = {
- dojo : false,
- dijit : false,
- dojox : false,
- define : false,
- "require" : false
- },
-
- funct, // The current function
+ exported, // Variables that are used outside of the current file.
functionicity = [
"closure", "exception", "global", "label",
"outer", "unused", "var"
],
- functions, // All of the functions
+ funct, // The current function
+ functions, // All of the functions
- global, // The global scope
- implied, // Implied globals
+ global, // The global scope
+ implied, // Implied globals
inblock,
indent,
- jsonmode,
-
- jquery = {
- "$" : false,
- jQuery : false
- },
-
- lines,
lookahead,
+ lex,
member,
membersOnly,
-
- mootools = {
- "$" : false,
- "$$" : false,
- Asset : false,
- Browser : false,
- Chain : false,
- Class : false,
- Color : false,
- Cookie : false,
- Core : false,
- Document : false,
- DomReady : false,
- DOMEvent : false,
- DOMReady : false,
- Drag : false,
- Element : false,
- Elements : false,
- Event : false,
- Events : false,
- Fx : false,
- Group : false,
- Hash : false,
- HtmlTable : false,
- Iframe : false,
- IframeShim : false,
- InputValidator : false,
- instanceOf : false,
- Keyboard : false,
- Locale : false,
- Mask : false,
- MooTools : false,
- Native : false,
- Options : false,
- OverText : false,
- Request : false,
- Scroller : false,
- Slick : false,
- Slider : false,
- Sortables : false,
- Spinner : false,
- Swiff : false,
- Tips : false,
- Type : false,
- typeOf : false,
- URI : false,
- Window : false
- },
-
- nexttoken,
-
- node = {
- __filename : false,
- __dirname : false,
- Buffer : false,
- console : false,
- exports : true, // In Node it is ok to exports = module.exports = foo();
- GLOBAL : false,
- global : false,
- module : false,
- process : false,
- require : false,
- setTimeout : false,
- clearTimeout : false,
- setInterval : false,
- clearInterval : false
- },
-
noreach,
- option,
predefined, // Global variables defined by option
- prereg,
- prevtoken,
- prototypejs = {
- "$" : false,
- "$$" : false,
- "$A" : false,
- "$F" : false,
- "$H" : false,
- "$R" : false,
- "$break" : false,
- "$continue" : false,
- "$w" : false,
- Abstract : false,
- Ajax : false,
- Class : false,
- Enumerable : false,
- Element : false,
- Event : false,
- Field : false,
- Form : false,
- Hash : false,
- Insertion : false,
- ObjectRange : false,
- PeriodicalExecuter: false,
- Position : false,
- Prototype : false,
- Selector : false,
- Template : false,
- Toggle : false,
- Try : false,
- Autocompleter : false,
- Builder : false,
- Control : false,
- Draggable : false,
- Draggables : false,
- Droppables : false,
- Effect : false,
- Sortable : false,
- SortableObserver : false,
- Sound : false,
- Scriptaculous : false
- },
-
- quotmark,
-
- rhino = {
- defineClass : false,
- deserialize : false,
- gc : false,
- help : false,
- importPackage: false,
- "java" : false,
- load : false,
- loadClass : false,
- print : false,
- quit : false,
- readFile : false,
- readUrl : false,
- runCommand : false,
- seal : false,
- serialize : false,
- spawn : false,
- sync : false,
- toint32 : false,
- version : false
- },
-
- scope, // The current scope
+ scope, // The current scope
stack,
- standard = {
- Array : false,
- Boolean : false,
- Date : false,
- decodeURI : false,
- decodeURIComponent : false,
- encodeURI : false,
- encodeURIComponent : false,
- Error : false,
- "eval" : false,
- EvalError : false,
- Function : false,
- hasOwnProperty : false,
- isFinite : false,
- isNaN : false,
- JSON : false,
- Map : false,
- Math : false,
- NaN : false,
- Number : false,
- Object : false,
- parseInt : false,
- parseFloat : false,
- RangeError : false,
- ReferenceError : false,
- RegExp : false,
- Set : false,
- String : false,
- SyntaxError : false,
- TypeError : false,
- URIError : false,
- WeakMap : false
- },
- nonstandard = {
- escape : false,
- unescape : false
- },
-
- directive,
- syntax = {},
- tab,
- token,
unuseds,
urls,
- useESNextSyntax,
warnings,
- worker = {
- importScripts : true,
- postMessage : true,
- self : true
- },
-
- wsh = {
- ActiveXObject : true,
- Enumerator : true,
- GetObject : true,
- ScriptEngine : true,
- ScriptEngineBuildVersion : true,
- ScriptEngineMajorVersion : true,
- ScriptEngineMinorVersion : true,
- VBArray : true,
- WSH : true,
- WScript : true,
- XDomainRequest : true
- },
-
- yui = {
- YUI : false,
- Y : false,
- YUI_config : false
- };
- var ax, cx, tx, nx, nxg, lx, ix, jx, ft;
- (function () {
- ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i;
- cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
- tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/=(?!(\S*\/[gim]?))|\/(\*(jshint|jslint|members?|global)?|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/;
- nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
- nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
- lx = /\*\//;
- ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
- jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
- ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/;
- }());
-
- function F() {} // Used by Object.create
-
- function is_own(object, name) {
- return Object.prototype.hasOwnProperty.call(object, name);
- }
+ extraModules = [],
+ emitter = new events.EventEmitter();
function checkOption(name, t) {
- if (valOptions[name] === undefined && boolOptions[name] === undefined) {
- warning("Bad option: '" + name + "'.", t);
+ name = name.trim();
+
+ if (/^[+-]W\d{3}$/g.test(name)) {
+ return true;
}
+
+ if (valOptions[name] === undefined && boolOptions[name] === undefined) {
+ if (t.type !== "jslint") {
+ error("E001", t, name);
+ return false;
+ }
+ }
+
+ return true;
}
function isString(obj) {
return Object.prototype.toString.call(obj) === "[object String]";
}
- if (typeof Array.isArray !== "function") {
- Array.isArray = function (o) {
- return Object.prototype.toString.apply(o) === "[object Array]";
- };
- }
-
- if (!Array.prototype.forEach) {
- Array.prototype.forEach = function (fn, scope) {
- var len = this.length;
-
- for (var i = 0; i < len; i++) {
- fn.call(scope || this, this[i], i, this);
- }
- };
- }
-
- if (!Array.prototype.indexOf) {
- Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
- if (this === null || this === undefined) {
- throw new TypeError();
- }
-
- var t = new Object(this);
- var len = t.length >>> 0;
-
- if (len === 0) {
- return -1;
- }
-
- var n = 0;
- if (arguments.length > 0) {
- n = Number(arguments[1]);
- if (n != n) { // shortcut for verifying if it's NaN
- n = 0;
- } else if (n !== 0 && n != Infinity && n != -Infinity) {
- n = (n > 0 || -1) * Math.floor(Math.abs(n));
- }
- }
-
- if (n >= len) {
- return -1;
- }
-
- var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
- for (; k < len; k++) {
- if (k in t && t[k] === searchElement) {
- return k;
- }
- }
-
- return -1;
- };
- }
-
- if (typeof Object.create !== "function") {
- Object.create = function (o) {
- F.prototype = o;
- return new F();
- };
- }
-
- if (typeof Object.keys !== "function") {
- Object.keys = function (o) {
- var a = [], k;
- for (k in o) {
- if (is_own(o, k)) {
- a.push(k);
- }
- }
- return a;
- };
- }
-
- function isAlpha(str) {
- return (str >= "a" && str <= "z\uffff") ||
- (str >= "A" && str <= "Z\uffff");
- }
-
- function isDigit(str) {
- return (str >= "0" && str <= "9");
- }
-
- function isIdentifier(token, value) {
- if (!token)
+ function isIdentifier(tkn, value) {
+ if (!tkn)
return false;
- if (!token.identifier || token.value !== value)
+ if (!tkn.identifier || tkn.value !== value)
return false;
return true;
}
+ function isReserved(token) {
+ if (!token.reserved) {
+ return false;
+ }
+
+ if (token.meta && token.meta.isFutureReservedWord) {
+ if (state.option.inES5(true) && !token.meta.es5) {
+ return false;
+ }
+ if (token.meta.strictOnly) {
+ if (!state.option.strict && !state.directive["use strict"]) {
+ return false;
+ }
+ }
+
+ if (token.isProperty) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
function supplant(str, data) {
return str.replace(/\{([^{}]*)\}/g, function (a, b) {
var r = data[b];
@@ -2765,7 +3398,7 @@ var JSHINT = (function () {
function combine(t, o) {
var n;
for (n in o) {
- if (is_own(o, n) && !is_own(JSHINT.blacklist, n)) {
+ if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) {
t[n] = o[n];
}
}
@@ -2778,69 +3411,92 @@ var JSHINT = (function () {
}
function assume() {
- if (option.couch) {
- combine(predefined, couch);
+ if (state.option.couch) {
+ combine(predefined, vars.couch);
}
- if (option.rhino) {
- combine(predefined, rhino);
+ if (state.option.rhino) {
+ combine(predefined, vars.rhino);
}
- if (option.prototypejs) {
- combine(predefined, prototypejs);
+ if (state.option.shelljs) {
+ combine(predefined, vars.shelljs);
}
- if (option.node) {
- combine(predefined, node);
- option.globalstrict = true;
+ if (state.option.phantom) {
+ combine(predefined, vars.phantom);
}
- if (option.devel) {
- combine(predefined, devel);
+ if (state.option.prototypejs) {
+ combine(predefined, vars.prototypejs);
}
- if (option.dojo) {
- combine(predefined, dojo);
+ if (state.option.node) {
+ combine(predefined, vars.node);
}
- if (option.browser) {
- combine(predefined, browser);
+ if (state.option.devel) {
+ combine(predefined, vars.devel);
}
- if (option.nonstandard) {
- combine(predefined, nonstandard);
+ if (state.option.dojo) {
+ combine(predefined, vars.dojo);
}
- if (option.jquery) {
- combine(predefined, jquery);
+ if (state.option.browser) {
+ combine(predefined, vars.browser);
}
- if (option.mootools) {
- combine(predefined, mootools);
+ if (state.option.nonstandard) {
+ combine(predefined, vars.nonstandard);
}
- if (option.worker) {
- combine(predefined, worker);
+ if (state.option.jquery) {
+ combine(predefined, vars.jquery);
}
- if (option.wsh) {
- combine(predefined, wsh);
+ if (state.option.mootools) {
+ combine(predefined, vars.mootools);
}
- if (option.esnext) {
- useESNextSyntax();
+ if (state.option.worker) {
+ combine(predefined, vars.worker);
}
- if (option.globalstrict && option.strict !== false) {
- option.strict = true;
+ if (state.option.wsh) {
+ combine(predefined, vars.wsh);
}
- if (option.yui) {
- combine(predefined, yui);
+ if (state.option.globalstrict && state.option.strict !== false) {
+ state.option.strict = true;
}
+
+ if (state.option.yui) {
+ combine(predefined, vars.yui);
+ }
+
+ state.option.inMoz = function (strict) {
+ return state.option.moz;
+ };
+
+ state.option.inESNext = function (strict) {
+ return state.option.moz || state.option.esnext;
+ };
+
+ state.option.inES5 = function (/* strict */) {
+ return !state.option.es3;
+ };
+
+ state.option.inES3 = function (strict) {
+ if (strict) {
+ return !state.option.moz && !state.option.esnext && state.option.es3;
+ }
+ return state.option.es3;
+ };
}
- function quit(message, line, chr) {
- var percentage = Math.floor((line / lines.length) * 100);
+ function quit(code, line, chr) {
+ var percentage = Math.floor((line / state.lines.length) * 100);
+ var message = messages.errors[code].desc;
throw {
name: "JSHintError",
@@ -2851,22 +3507,37 @@ var JSHINT = (function () {
};
}
- function isundef(scope, m, t, a) {
- return JSHINT.undefs.push([scope, m, t, a]);
+ function isundef(scope, code, token, a) {
+ return JSHINT.undefs.push([scope, code, token, a]);
}
- function warning(m, t, a, b, c, d) {
- var ch, l, w;
- t = t || nexttoken;
- if (t.id === "(end)") { // `~
- t = token;
+ function warning(code, t, a, b, c, d) {
+ var ch, l, w, msg;
+
+ if (/^W\d{3}$/.test(code)) {
+ if (state.ignored[code])
+ return;
+
+ msg = messages.warnings[code];
+ } else if (/E\d{3}/.test(code)) {
+ msg = messages.errors[code];
+ } else if (/I\d{3}/.test(code)) {
+ msg = messages.info[code];
}
+
+ t = t || state.tokens.next;
+ if (t.id === "(end)") { // `~
+ t = state.tokens.curr;
+ }
+
l = t.line || 0;
ch = t.from || 0;
+
w = {
id: "(error)",
- raw: m,
- evidence: lines[l - 1] || "",
+ raw: msg.desc,
+ code: msg.code,
+ evidence: state.lines[l - 1] || "",
line: l,
character: ch,
scope: JSHINT.scope,
@@ -2875,15 +3546,19 @@ var JSHINT = (function () {
c: c,
d: d
};
- w.reason = supplant(m, w);
+
+ w.reason = supplant(msg.desc, w);
JSHINT.errors.push(w);
- if (option.passfail) {
- quit("Stopping. ", l, ch);
+
+ if (state.option.passfail) {
+ quit("E042", l, ch);
}
+
warnings += 1;
- if (warnings >= option.maxerr) {
- quit("Too many errors.", l, ch);
+ if (warnings >= state.option.maxerr) {
+ quit("E043", l, ch);
}
+
return w;
}
@@ -2915,905 +3590,258 @@ var JSHINT = (function () {
return i;
}
- var lex = (function lex() {
- var character, from, line, s;
-
- function nextLine() {
- var at,
- match,
- tw; // trailing whitespace check
-
- if (line >= lines.length)
- return false;
-
- character = 1;
- s = lines[line];
- line += 1;
- if (option.smarttabs) {
- match = s.match(/(\/\/)? \t/);
- at = match && !match[1] ? 0 : -1;
- } else {
- at = s.search(/ \t|\t [^\*]/);
- }
-
- if (at >= 0)
- warningAt("Mixed spaces and tabs.", line, at + 1);
-
- s = s.replace(/\t/g, tab);
- at = s.search(cx);
-
- if (at >= 0)
- warningAt("Unsafe character.", line, at);
-
- if (option.maxlen && option.maxlen < s.length)
- warningAt("Line too long.", line, s.length);
- tw = option.trailing && s.match(/^(.*?)\s+$/);
- if (tw && !/^\s+$/.test(s)) {
- warningAt("Trailing whitespace.", line, tw[1].length + 1);
- }
- return true;
- }
-
- function it(type, value) {
- var i, t;
-
- function checkName(name) {
- if (!option.proto && name === "__proto__") {
- warningAt("The '{a}' property is deprecated.", line, from, name);
- return;
- }
-
- if (!option.iterator && name === "__iterator__") {
- warningAt("'{a}' is only available in JavaScript 1.7.", line, from, name);
- return;
- }
-
- var hasDangling = /^(_+.*|.*_+)$/.test(name);
-
- if (option.nomen && hasDangling && name !== "_") {
- if (option.node && token.id !== "." && /^(__dirname|__filename)$/.test(name))
- return;
-
- warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", name);
- return;
- }
-
- if (option.camelcase) {
- if (name.replace(/^_+/, "").indexOf("_") > -1 && !name.match(/^[A-Z0-9_]*$/)) {
- warningAt("Identifier '{a}' is not in camel case.", line, from, value);
- }
- }
- }
-
- if (type === "(color)" || type === "(range)") {
- t = {type: type};
- } else if (type === "(punctuator)" ||
- (type === "(identifier)" && is_own(syntax, value))) {
- t = syntax[value] || syntax["(error)"];
- } else {
- t = syntax[type];
- }
-
- t = Object.create(t);
-
- if (type === "(string)" || type === "(range)") {
- if (!option.scripturl && jx.test(value)) {
- warningAt("Script URL.", line, from);
- }
- }
-
- if (type === "(identifier)") {
- t.identifier = true;
- checkName(value);
- }
-
- t.value = value;
- t.line = line;
- t.character = character;
- t.from = from;
- i = t.id;
- if (i !== "(endline)") {
- prereg = i &&
- (("(,=:[!&|?{};".indexOf(i.charAt(i.length - 1)) >= 0) ||
- i === "return" ||
- i === "case");
- }
- return t;
- }
- return {
- init: function (source) {
- if (typeof source === "string") {
- lines = source
- .replace(/\r\n/g, "\n")
- .replace(/\r/g, "\n")
- .split("\n");
- } else {
- lines = source;
- }
- if (lines[0] && lines[0].substr(0, 2) === "#!")
- lines[0] = "";
-
- line = 0;
- nextLine();
- from = 1;
- },
-
- range: function (begin, end) {
- var c, value = "";
- from = character;
- if (s.charAt(0) !== begin) {
- errorAt("Expected '{a}' and instead saw '{b}'.",
- line, character, begin, s.charAt(0));
- }
- for (;;) {
- s = s.slice(1);
- character += 1;
- c = s.charAt(0);
- switch (c) {
- case "":
- errorAt("Missing '{a}'.", line, character, c);
- break;
- case end:
- s = s.slice(1);
- character += 1;
- return it("(range)", value);
- case "\\":
- warningAt("Unexpected '{a}'.", line, character, c);
- }
- value += c;
- }
-
- },
- token: function () {
- var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n;
-
- function match(x) {
- var r = x.exec(s), r1;
-
- if (r) {
- l = r[0].length;
- r1 = r[1];
- c = r1.charAt(0);
- s = s.substr(l);
- from = character + l - r1.length;
- character += l;
- return r1;
- }
- }
-
- function string(x) {
- var c, j, r = "", allowNewLine = false;
-
- if (jsonmode && x !== "\"") {
- warningAt("Strings must use doublequote.",
- line, character);
- }
-
- if (option.quotmark) {
- if (option.quotmark === "single" && x !== "'") {
- warningAt("Strings must use singlequote.",
- line, character);
- } else if (option.quotmark === "double" && x !== "\"") {
- warningAt("Strings must use doublequote.",
- line, character);
- } else if (option.quotmark === true) {
- quotmark = quotmark || x;
- if (quotmark !== x) {
- warningAt("Mixed double and single quotes.",
- line, character);
- }
- }
- }
-
- function esc(n) {
- var i = parseInt(s.substr(j + 1, n), 16);
- j += n;
- if (i >= 32 && i <= 126 &&
- i !== 34 && i !== 92 && i !== 39) {
- warningAt("Unnecessary escapement.", line, character);
- }
- character += n;
- c = String.fromCharCode(i);
- }
-
- j = 0;
-
-unclosedString:
- for (;;) {
- while (j >= s.length) {
- j = 0;
-
- var cl = line, cf = from;
- if (!nextLine()) {
- errorAt("Unclosed string.", cl, cf);
- break unclosedString;
- }
-
- if (allowNewLine) {
- allowNewLine = false;
- } else {
- warningAt("Unclosed string.", cl, cf);
- }
- }
-
- c = s.charAt(j);
- if (c === x) {
- character += 1;
- s = s.substr(j + 1);
- return it("(string)", r, x);
- }
-
- if (c < " ") {
- if (c === "\n" || c === "\r") {
- break;
- }
- warningAt("Control character in string: {a}.",
- line, character + j, s.slice(0, j));
- } else if (c === "\\") {
- j += 1;
- character += 1;
- c = s.charAt(j);
- n = s.charAt(j + 1);
- switch (c) {
- case "\\":
- case "\"":
- case "/":
- break;
- case "\'":
- if (jsonmode) {
- warningAt("Avoid \\'.", line, character);
- }
- break;
- case "b":
- c = "\b";
- break;
- case "f":
- c = "\f";
- break;
- case "n":
- c = "\n";
- break;
- case "r":
- c = "\r";
- break;
- case "t":
- c = "\t";
- break;
- case "0":
- c = "\0";
- if (n >= 0 && n <= 7 && directive["use strict"]) {
- warningAt(
- "Octal literals are not allowed in strict mode.",
- line, character);
- }
- break;
- case "u":
- esc(4);
- break;
- case "v":
- if (jsonmode) {
- warningAt("Avoid \\v.", line, character);
- }
- c = "\v";
- break;
- case "x":
- if (jsonmode) {
- warningAt("Avoid \\x-.", line, character);
- }
- esc(2);
- break;
- case "":
- allowNewLine = true;
- if (option.multistr) {
- if (jsonmode) {
- warningAt("Avoid EOL escapement.", line, character);
- }
- c = "";
- character -= 1;
- break;
- }
- warningAt("Bad escapement of EOL. Use option multistr if needed.",
- line, character);
- break;
- case "!":
- if (s.charAt(j - 2) === "<")
- break;
- default:
- warningAt("Bad escapement.", line, character);
- }
- }
- r += c;
- character += 1;
- j += 1;
- }
- }
-
- for (;;) {
- if (!s) {
- return it(nextLine() ? "(endline)" : "(end)", "");
- }
-
- t = match(tx);
-
- if (!t) {
- t = "";
- c = "";
- while (s && s < "!") {
- s = s.substr(1);
- }
- if (s) {
- errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1));
- s = "";
- }
- } else {
-
- if (isAlpha(c) || c === "_" || c === "$") {
- return it("(identifier)", t);
- }
-
- if (isDigit(c)) {
- if (!isFinite(Number(t))) {
- warningAt("Bad number '{a}'.",
- line, character, t);
- }
- if (isAlpha(s.substr(0, 1))) {
- warningAt("Missing space after '{a}'.",
- line, character, t);
- }
- if (c === "0") {
- d = t.substr(1, 1);
- if (isDigit(d)) {
- if (token.id !== ".") {
- warningAt("Don't use extra leading zeros '{a}'.",
- line, character, t);
- }
- } else if (jsonmode && (d === "x" || d === "X")) {
- warningAt("Avoid 0x-. '{a}'.",
- line, character, t);
- }
- }
- if (t.substr(t.length - 1) === ".") {
- warningAt(
-"A trailing decimal point can be confused with a dot '{a}'.", line, character, t);
- }
- return it("(number)", t);
- }
- switch (t) {
-
- case "\"":
- case "'":
- return string(t);
-
- case "//":
- s = "";
- token.comment = true;
- break;
-
- case "/*":
- for (;;) {
- i = s.search(lx);
- if (i >= 0) {
- break;
- }
- if (!nextLine()) {
- errorAt("Unclosed comment.", line, character);
- }
- }
- s = s.substr(i + 2);
- token.comment = true;
- break;
-
- case "/*members":
- case "/*member":
- case "/*jshint":
- case "/*jslint":
- case "/*global":
- case "*/":
- return {
- value: t,
- type: "special",
- line: line,
- character: character,
- from: from
- };
-
- case "":
- break;
- case "/":
- if (s.charAt(0) === "=") {
- errorAt("A regular expression literal can be confused with '/='.",
- line, from);
- }
-
- if (prereg) {
- depth = 0;
- captures = 0;
- l = 0;
- for (;;) {
- b = true;
- c = s.charAt(l);
- l += 1;
- switch (c) {
- case "":
- errorAt("Unclosed regular expression.", line, from);
- return quit("Stopping.", line, from);
- case "/":
- if (depth > 0) {
- warningAt("{a} unterminated regular expression " +
- "group(s).", line, from + l, depth);
- }
- c = s.substr(0, l - 1);
- q = {
- g: true,
- i: true,
- m: true
- };
- while (q[s.charAt(l)] === true) {
- q[s.charAt(l)] = false;
- l += 1;
- }
- character += l;
- s = s.substr(l);
- q = s.charAt(0);
- if (q === "/" || q === "*") {
- errorAt("Confusing regular expression.",
- line, from);
- }
- return it("(regexp)", c);
- case "\\":
- c = s.charAt(l);
- if (c < " ") {
- warningAt(
-"Unexpected control character in regular expression.", line, from + l);
- } else if (c === "<") {
- warningAt(
-"Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
- }
- l += 1;
- break;
- case "(":
- depth += 1;
- b = false;
- if (s.charAt(l) === "?") {
- l += 1;
- switch (s.charAt(l)) {
- case ":":
- case "=":
- case "!":
- l += 1;
- break;
- default:
- warningAt(
-"Expected '{a}' and instead saw '{b}'.", line, from + l, ":", s.charAt(l));
- }
- } else {
- captures += 1;
- }
- break;
- case "|":
- b = false;
- break;
- case ")":
- if (depth === 0) {
- warningAt("Unescaped '{a}'.",
- line, from + l, ")");
- } else {
- depth -= 1;
- }
- break;
- case " ":
- q = 1;
- while (s.charAt(l) === " ") {
- l += 1;
- q += 1;
- }
- if (q > 1) {
- warningAt(
-"Spaces are hard to count. Use {{a}}.", line, from + l, q);
- }
- break;
- case "[":
- c = s.charAt(l);
- if (c === "^") {
- l += 1;
- if (s.charAt(l) === "]") {
- errorAt("Unescaped '{a}'.",
- line, from + l, "^");
- }
- }
- if (c === "]") {
- warningAt("Empty class.", line,
- from + l - 1);
- }
- isLiteral = false;
- isInRange = false;
-klass:
- do {
- c = s.charAt(l);
- l += 1;
- switch (c) {
- case "[":
- case "^":
- warningAt("Unescaped '{a}'.",
- line, from + l, c);
- if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = true;
- }
- break;
- case "-":
- if (isLiteral && !isInRange) {
- isLiteral = false;
- isInRange = true;
- } else if (isInRange) {
- isInRange = false;
- } else if (s.charAt(l) === "]") {
- isInRange = true;
- } else {
- if (option.regexdash !== (l === 2 || (l === 3 &&
- s.charAt(1) === "^"))) {
- warningAt("Unescaped '{a}'.",
- line, from + l - 1, "-");
- }
- isLiteral = true;
- }
- break;
- case "]":
- if (isInRange && !option.regexdash) {
- warningAt("Unescaped '{a}'.",
- line, from + l - 1, "-");
- }
- break klass;
- case "\\":
- c = s.charAt(l);
- if (c < " ") {
- warningAt(
-"Unexpected control character in regular expression.", line, from + l);
- } else if (c === "<") {
- warningAt(
-"Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
- }
- l += 1;
- if (/[wsd]/i.test(c)) {
- if (isInRange) {
- warningAt("Unescaped '{a}'.",
- line, from + l, "-");
- isInRange = false;
- }
- isLiteral = false;
- } else if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = true;
- }
- break;
- case "/":
- warningAt("Unescaped '{a}'.",
- line, from + l - 1, "/");
-
- if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = true;
- }
- break;
- case "<":
- if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = true;
- }
- break;
- default:
- if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = true;
- }
- }
- } while (c);
- break;
- case ".":
- if (option.regexp) {
- warningAt("Insecure '{a}'.", line,
- from + l, c);
- }
- break;
- case "]":
- case "?":
- case "{":
- case "}":
- case "+":
- case "*":
- warningAt("Unescaped '{a}'.", line,
- from + l, c);
- }
- if (b) {
- switch (s.charAt(l)) {
- case "?":
- case "+":
- case "*":
- l += 1;
- if (s.charAt(l) === "?") {
- l += 1;
- }
- break;
- case "{":
- l += 1;
- c = s.charAt(l);
- if (c < "0" || c > "9") {
- warningAt(
-"Expected a number and instead saw '{a}'.", line, from + l, c);
- break; // No reason to continue checking numbers.
- }
- l += 1;
- low = +c;
- for (;;) {
- c = s.charAt(l);
- if (c < "0" || c > "9") {
- break;
- }
- l += 1;
- low = +c + (low * 10);
- }
- high = low;
- if (c === ",") {
- l += 1;
- high = Infinity;
- c = s.charAt(l);
- if (c >= "0" && c <= "9") {
- l += 1;
- high = +c;
- for (;;) {
- c = s.charAt(l);
- if (c < "0" || c > "9") {
- break;
- }
- l += 1;
- high = +c + (high * 10);
- }
- }
- }
- if (s.charAt(l) !== "}") {
- warningAt(
-"Expected '{a}' and instead saw '{b}'.", line, from + l, "}", c);
- } else {
- l += 1;
- }
- if (s.charAt(l) === "?") {
- l += 1;
- }
- if (low > high) {
- warningAt(
-"'{a}' should not be greater than '{b}'.", line, from + l, low, high);
- }
- }
- }
- }
- c = s.substr(0, l - 1);
- character += l;
- s = s.substr(l);
- return it("(regexp)", c);
- }
- return it("(punctuator)", t);
-
- case "#":
- return it("(punctuator)", t);
- default:
- return it("(punctuator)", t);
- }
- }
- }
- }
- };
- }());
-
-
- function addlabel(t, type, token) {
- if (t === "hasOwnProperty") {
- warning("'hasOwnProperty' is a really bad name.");
- }
+ function addlabel(t, type, tkn, islet) {
if (type === "exception") {
- if (is_own(funct["(context)"], t)) {
- if (funct[t] !== true && !option.node) {
- warning("Value of '{a}' may be overwritten in IE.", nexttoken, t);
+ if (_.has(funct["(context)"], t)) {
+ if (funct[t] !== true && !state.option.node) {
+ warning("W002", state.tokens.next, t);
}
}
}
- if (is_own(funct, t) && !funct["(global)"]) {
+ if (_.has(funct, t) && !funct["(global)"]) {
if (funct[t] === true) {
- if (option.latedef)
- warning("'{a}' was used before it was defined.", nexttoken, t);
+ if (state.option.latedef) {
+ if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
+ !_.contains([funct[t], type], "unction")) {
+ warning("W003", state.tokens.next, t);
+ }
+ }
} else {
- if (!option.shadow && type !== "exception") {
- warning("'{a}' is already defined.", nexttoken, t);
+ if (!state.option.shadow && type !== "exception" ||
+ (funct["(blockscope)"].getlabel(t))) {
+ warning("W004", state.tokens.next, t);
}
}
}
-
- funct[t] = type;
-
- if (token) {
- funct["(tokens)"][t] = token;
+ if (funct["(blockscope)"] && funct["(blockscope)"].current.has(t)) {
+ error("E044", state.tokens.next, t);
}
-
- if (funct["(global)"]) {
- global[t] = funct;
- if (is_own(implied, t)) {
- if (option.latedef)
- warning("'{a}' was used before it was defined.", nexttoken, t);
- delete implied[t];
- }
+ if (islet) {
+ funct["(blockscope)"].current.add(t, type, state.tokens.curr);
} else {
- scope[t] = funct;
+
+ funct[t] = type;
+
+ if (tkn) {
+ funct["(tokens)"][t] = tkn;
+ }
+
+ if (funct["(global)"]) {
+ global[t] = funct;
+ if (_.has(implied, t)) {
+ if (state.option.latedef) {
+ if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
+ !_.contains([funct[t], type], "unction")) {
+ warning("W003", state.tokens.next, t);
+ }
+ }
+
+ delete implied[t];
+ }
+ } else {
+ scope[t] = funct;
+ }
}
}
-
function doOption() {
- var nt = nexttoken;
- var o = nt.value;
- var quotmarkValue = option.quotmark;
+ var nt = state.tokens.next;
+ var body = nt.body.split(",").map(function (s) { return s.trim(); });
var predef = {};
- var b, obj, filter, t, tn, v, minus;
- switch (o) {
- case "*/":
- error("Unbegun comment.");
- break;
- case "/*members":
- case "/*member":
- o = "/*members";
- if (!membersOnly) {
- membersOnly = {};
+ if (nt.type === "globals") {
+ body.forEach(function (g) {
+ g = g.split(":");
+ var key = g[0];
+ var val = g[1];
+
+ if (key.charAt(0) === "-") {
+ key = key.slice(1);
+ val = false;
+
+ JSHINT.blacklist[key] = key;
+ updatePredefined();
+ } else {
+ predef[key] = (val === "true");
+ }
+ });
+
+ combine(predefined, predef);
+
+ for (var key in predef) {
+ if (_.has(predef, key)) {
+ declared[key] = nt;
+ }
}
- obj = membersOnly;
- option.quotmark = false;
- break;
- case "/*jshint":
- case "/*jslint":
- obj = option;
- filter = boolOptions;
- break;
- case "/*global":
- obj = predef;
- break;
- default:
- error("What?");
}
- t = lex.token();
+ if (nt.type === "exported") {
+ body.forEach(function (e) {
+ exported[e] = true;
+ });
+ }
- for (;;) {
- minus = false;
- var breakOuterLoop;
- for (;;) {
- if (t.type === "special" && t.value === "*/") {
- breakOuterLoop = true;
- break;
- }
- if (t.id !== "(endline)" && t.id !== ",") {
- break;
- }
- t = lex.token();
- }
- if (breakOuterLoop)
- break;
+ if (nt.type === "members") {
+ membersOnly = membersOnly || {};
- if (o === "/*global" && t.value === "-") {
- minus = true;
- t = lex.token();
- }
+ body.forEach(function (m) {
+ var ch1 = m.charAt(0);
+ var ch2 = m.charAt(m.length - 1);
- if (t.type !== "(string)" && t.type !== "(identifier)" && o !== "/*members") {
- error("Bad option.", t);
- }
-
- v = lex.token();
- if (v.id === ":") {
- v = lex.token();
-
- if (obj === membersOnly) {
- error("Expected '{a}' and instead saw '{b}'.", t, "*/", ":");
+ if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
+ m = m
+ .substr(1, m.length - 2)
+ .replace("\\b", "\b")
+ .replace("\\t", "\t")
+ .replace("\\n", "\n")
+ .replace("\\v", "\v")
+ .replace("\\f", "\f")
+ .replace("\\r", "\r")
+ .replace("\\\\", "\\")
+ .replace("\\\"", "\"");
}
- if (o === "/*jshint") {
- checkOption(t.value, t);
+ membersOnly[m] = false;
+ });
+ }
+
+ var numvals = [
+ "maxstatements",
+ "maxparams",
+ "maxdepth",
+ "maxcomplexity",
+ "maxerr",
+ "maxlen",
+ "indent"
+ ];
+
+ if (nt.type === "jshint" || nt.type === "jslint") {
+ body.forEach(function (g) {
+ g = g.split(":");
+ var key = (g[0] || "").trim();
+ var val = (g[1] || "").trim();
+
+ if (!checkOption(key, nt)) {
+ return;
}
- var numericVals = [
- "maxstatements",
- "maxparams",
- "maxdepth",
- "maxcomplexity",
- "maxerr",
- "maxlen",
- "indent"
- ];
+ if (numvals.indexOf(key) >= 0) {
+ if (val !== "false") {
+ val = +val;
- if (numericVals.indexOf(t.value) > -1 && (o === "/*jshint" || o === "/*jslint")) {
- b = +v.value;
+ if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
+ error("E032", nt, g[1].trim());
+ return;
+ }
- if (typeof b !== "number" || !isFinite(b) || b <= 0 || Math.floor(b) !== b) {
- error("Expected a small integer and instead saw '{a}'.", v, v.value);
- }
-
- if (t.value === "indent")
- obj.white = true;
-
- obj[t.value] = b;
- } else if (t.value === "validthis") {
- if (funct["(global)"]) {
- error("Option 'validthis' can't be used in a global scope.");
+ if (key === "indent") {
+ state.option["(explicitIndent)"] = true;
+ }
+ state.option[key] = val;
} else {
- if (v.value === "true" || v.value === "false")
- obj[t.value] = v.value === "true";
- else
- error("Bad option value.", v);
+ if (key === "indent") {
+ state.option["(explicitIndent)"] = false;
+ } else {
+ state.option[key] = false;
+ }
}
- } else if (t.value === "quotmark" && (o === "/*jshint")) {
- switch (v.value) {
+
+ return;
+ }
+
+ if (key === "validthis") {
+ if (funct["(global)"]) {
+ error("E009");
+ } else {
+ if (val === "true" || val === "false") {
+ state.option.validthis = (val === "true");
+ } else {
+ error("E002", nt);
+ }
+ }
+ return;
+ }
+
+ if (key === "quotmark") {
+ switch (val) {
case "true":
- obj.quotmark = true;
- break;
case "false":
- obj.quotmark = false;
+ state.option.quotmark = (val === "true");
break;
case "double":
case "single":
- obj.quotmark = v.value;
+ state.option.quotmark = val;
break;
default:
- error("Bad option value.", v);
+ error("E002", nt);
}
- } else if (v.value === "true" || v.value === "false") {
- if (o === "/*jslint") {
- tn = renamedOptions[t.value] || t.value;
- obj[tn] = v.value === "true";
+ return;
+ }
+
+ if (key === "unused") {
+ switch (val) {
+ case "true":
+ state.option.unused = true;
+ break;
+ case "false":
+ state.option.unused = false;
+ break;
+ case "vars":
+ case "strict":
+ state.option.unused = val;
+ break;
+ default:
+ error("E002", nt);
+ }
+ return;
+ }
+
+ if (key === "latedef") {
+ switch (val) {
+ case "true":
+ state.option.latedef = true;
+ break;
+ case "false":
+ state.option.latedef = false;
+ break;
+ case "nofunc":
+ state.option.latedef = "nofunc";
+ break;
+ default:
+ error("E002", nt);
+ }
+ return;
+ }
+
+ var match = /^([+-])(W\d{3})$/g.exec(key);
+ if (match) {
+ state.ignored[match[2]] = (match[1] === "-");
+ return;
+ }
+
+ var tn;
+ if (val === "true" || val === "false") {
+ if (nt.type === "jslint") {
+ tn = renamedOptions[key] || key;
+ state.option[tn] = (val === "true");
+
if (invertedOptions[tn] !== undefined) {
- obj[tn] = !obj[tn];
+ state.option[tn] = !state.option[tn];
}
} else {
- obj[t.value] = v.value === "true";
+ state.option[key] = (val === "true");
}
- if (t.value === "newcap")
- obj["(explicitNewcap)"] = true;
- } else {
- error("Bad option value.", v);
- }
- t = lex.token();
- } else {
- if (o === "/*jshint" || o === "/*jslint") {
- error("Missing option value.", t);
+ if (key === "newcap") {
+ state.option["(explicitNewcap)"] = true;
+ }
+ return;
}
- obj[t.value] = false;
+ error("E002", nt);
+ });
- if (o === "/*global" && minus === true) {
- JSHINT.blacklist[t.value] = t.value;
- updatePredefined();
- }
-
- t = v;
- }
- }
-
- if (o === "/*members") {
- option.quotmark = quotmarkValue;
- }
-
- combine(predefined, predef);
-
- for (var key in predef) {
- if (is_own(predef, key)) {
- declared[key] = nt;
- }
- }
-
- if (filter) {
assume();
}
}
@@ -3832,54 +3860,61 @@ klass:
}
function advance(id, t) {
- switch (token.id) {
+ switch (state.tokens.curr.id) {
case "(number)":
- if (nexttoken.id === ".") {
- warning("A dot following a number can be confused with a decimal point.", token);
+ if (state.tokens.next.id === ".") {
+ warning("W005", state.tokens.curr);
}
break;
case "-":
- if (nexttoken.id === "-" || nexttoken.id === "--") {
- warning("Confusing minusses.");
+ if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
+ warning("W006");
}
break;
case "+":
- if (nexttoken.id === "+" || nexttoken.id === "++") {
- warning("Confusing plusses.");
+ if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
+ warning("W007");
}
break;
}
- if (token.type === "(string)" || token.identifier) {
- anonname = token.value;
+ if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
+ anonname = state.tokens.curr.value;
}
- if (id && nexttoken.id !== id) {
+ if (id && state.tokens.next.id !== id) {
if (t) {
- if (nexttoken.id === "(end)") {
- warning("Unmatched '{a}'.", t, t.id);
+ if (state.tokens.next.id === "(end)") {
+ error("E019", t, t.id);
} else {
- warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
- nexttoken, id, t.id, t.line, nexttoken.value);
+ error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
}
- } else if (nexttoken.type !== "(identifier)" ||
- nexttoken.value !== id) {
- warning("Expected '{a}' and instead saw '{b}'.",
- nexttoken, id, nexttoken.value);
+ } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
+ warning("W116", state.tokens.next, id, state.tokens.next.value);
}
}
- prevtoken = token;
- token = nexttoken;
+ state.tokens.prev = state.tokens.curr;
+ state.tokens.curr = state.tokens.next;
for (;;) {
- nexttoken = lookahead.shift() || lex.token();
- if (nexttoken.id === "(end)" || nexttoken.id === "(error)") {
+ state.tokens.next = lookahead.shift() || lex.token();
+
+ if (!state.tokens.next) { // No more tokens left, give up
+ quit("E041", state.tokens.curr.line);
+ }
+
+ if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
return;
}
- if (nexttoken.type === "special") {
+
+ if (state.tokens.next.check) {
+ state.tokens.next.check();
+ }
+
+ if (state.tokens.next.isSpecial) {
doOption();
} else {
- if (nexttoken.id !== "(endline)") {
+ if (state.tokens.next.id !== "(endline)") {
break;
}
}
@@ -3887,84 +3922,100 @@ klass:
}
function expression(rbp, initial) {
- var left, isArray = false, isObject = false;
+ var left, isArray = false, isObject = false, isLetExpr = false;
+ if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.next, "let expressions");
+ }
+ isLetExpr = true;
+ funct["(blockscope)"].stack();
+ advance("let");
+ advance("(");
+ state.syntax["let"].fud.call(state.syntax["let"].fud, false);
+ advance(")");
+ }
- if (nexttoken.id === "(end)")
- error("Unexpected early end of program.", token);
+ if (state.tokens.next.id === "(end)")
+ error("E006", state.tokens.curr);
advance();
+
if (initial) {
anonname = "anonymous";
- funct["(verb)"] = token.value;
+ funct["(verb)"] = state.tokens.curr.value;
}
- if (initial === true && token.fud) {
- left = token.fud();
+
+ if (initial === true && state.tokens.curr.fud) {
+ left = state.tokens.curr.fud();
} else {
- if (token.nud) {
- left = token.nud();
+ if (state.tokens.curr.nud) {
+ left = state.tokens.curr.nud();
} else {
- if (nexttoken.type === "(number)" && token.id === ".") {
- warning("A leading decimal point can be confused with a dot: '.{a}'.",
- token, nexttoken.value);
- advance();
- return token;
- } else {
- error("Expected an identifier and instead saw '{a}'.",
- token, token.id);
- }
+ error("E030", state.tokens.curr, state.tokens.curr.id);
}
- while (rbp < nexttoken.lbp) {
- isArray = token.value === "Array";
- isObject = token.value === "Object";
+
+ var end_of_expr = state.tokens.next.identifier &&
+ !state.tokens.curr.led &&
+ state.tokens.curr.line !== state.tokens.next.line;
+ while (rbp < state.tokens.next.lbp && !end_of_expr) {
+ isArray = state.tokens.curr.value === "Array";
+ isObject = state.tokens.curr.value === "Object";
if (left && (left.value || (left.first && left.first.value))) {
if (left.value !== "new" ||
(left.first && left.first.value && left.first.value === ".")) {
isArray = false;
- if (left.value !== token.value) {
+ if (left.value !== state.tokens.curr.value) {
isObject = false;
}
}
}
advance();
- if (isArray && token.id === "(" && nexttoken.id === ")")
- warning("Use the array literal notation [].", token);
- if (isObject && token.id === "(" && nexttoken.id === ")")
- warning("Use the object literal notation {}.", token);
- if (token.led) {
- left = token.led(left);
+
+ if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+ warning("W009", state.tokens.curr);
+ }
+
+ if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+ warning("W010", state.tokens.curr);
+ }
+
+ if (left && state.tokens.curr.led) {
+ left = state.tokens.curr.led(left);
} else {
- error("Expected an operator and instead saw '{a}'.",
- token, token.id);
+ error("E033", state.tokens.curr, state.tokens.curr.id);
}
}
}
+ if (isLetExpr) {
+ funct["(blockscope)"].unstack();
+ }
return left;
}
function adjacent(left, right) {
- left = left || token;
- right = right || nexttoken;
- if (option.white) {
+ left = left || state.tokens.curr;
+ right = right || state.tokens.next;
+ if (state.option.white) {
if (left.character !== right.from && left.line === right.line) {
left.from += (left.character - left.from);
- warning("Unexpected space after '{a}'.", left, left.value);
+ warning("W011", left, left.value);
}
}
}
function nobreak(left, right) {
- left = left || token;
- right = right || nexttoken;
- if (option.white && (left.character !== right.from || left.line !== right.line)) {
- warning("Unexpected space before '{a}'.", right, right.value);
+ left = left || state.tokens.curr;
+ right = right || state.tokens.next;
+ if (state.option.white && (left.character !== right.from || left.line !== right.line)) {
+ warning("W012", right, right.value);
}
}
function nospace(left, right) {
- left = left || token;
- right = right || nexttoken;
- if (option.white && !left.comment) {
+ left = left || state.tokens.curr;
+ right = right || state.tokens.next;
+ if (state.option.white && !left.comment) {
if (left.line === right.line) {
adjacent(left, right);
}
@@ -3972,77 +4023,132 @@ klass:
}
function nonadjacent(left, right) {
- if (option.white) {
- left = left || token;
- right = right || nexttoken;
+ if (state.option.white) {
+ left = left || state.tokens.curr;
+ right = right || state.tokens.next;
+
if (left.value === ";" && right.value === ";") {
return;
}
+
if (left.line === right.line && left.character === right.from) {
left.from += (left.character - left.from);
- warning("Missing space after '{a}'.",
- left, left.value);
+ warning("W013", left, left.value);
}
}
}
function nobreaknonadjacent(left, right) {
- left = left || token;
- right = right || nexttoken;
- if (!option.laxbreak && left.line !== right.line) {
- warning("Bad line breaking before '{a}'.", right, right.id);
- } else if (option.white) {
- left = left || token;
- right = right || nexttoken;
+ left = left || state.tokens.curr;
+ right = right || state.tokens.next;
+ if (!state.option.laxbreak && left.line !== right.line) {
+ warning("W014", right, right.id);
+ } else if (state.option.white) {
+ left = left || state.tokens.curr;
+ right = right || state.tokens.next;
if (left.character === right.from) {
left.from += (left.character - left.from);
- warning("Missing space after '{a}'.",
- left, left.value);
+ warning("W013", left, left.value);
}
}
}
function indentation(bias) {
- var i;
- if (option.white && nexttoken.id !== "(end)") {
- i = indent + (bias || 0);
- if (nexttoken.from !== i) {
- warning(
-"Expected '{a}' to have an indentation at {b} instead at {c}.",
- nexttoken, nexttoken.value, i, nexttoken.from);
- }
+ if (!state.option.white && !state.option["(explicitIndent)"]) {
+ return;
+ }
+
+ if (state.tokens.next.id === "(end)") {
+ return;
+ }
+
+ var i = indent + (bias || 0);
+ if (state.tokens.next.from !== i) {
+ warning("W015", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from);
}
}
function nolinebreak(t) {
- t = t || token;
- if (t.line !== nexttoken.line) {
- warning("Line breaking error '{a}'.", t, t.value);
+ t = t || state.tokens.curr;
+ if (t.line !== state.tokens.next.line) {
+ warning("E022", t, t.value);
}
}
- function comma() {
- if (token.line !== nexttoken.line) {
- if (!option.laxcomma) {
- if (comma.first) {
- warning("Comma warnings can be turned off with 'laxcomma'");
- comma.first = false;
+ function comma(opts) {
+ opts = opts || {};
+
+ if (!opts.peek) {
+ if (state.tokens.curr.line !== state.tokens.next.line) {
+ if (!state.option.laxcomma) {
+ if (comma.first) {
+ warning("I001");
+ comma.first = false;
+ }
+ warning("W014", state.tokens.curr, state.tokens.next.value);
}
- warning("Bad line breaking before '{a}'.", token, nexttoken.id);
+ } else if (!state.tokens.curr.comment &&
+ state.tokens.curr.character !== state.tokens.next.from && state.option.white) {
+ state.tokens.curr.from += (state.tokens.curr.character - state.tokens.curr.from);
+ warning("W011", state.tokens.curr, state.tokens.curr.value);
}
- } else if (!token.comment && token.character !== nexttoken.from && option.white) {
- token.from += (token.character - token.from);
- warning("Unexpected space after '{a}'.", token, token.value);
+
+ advance(",");
}
- advance(",");
- nonadjacent(token, nexttoken);
+
+ if (state.tokens.next.value !== "]" && state.tokens.next.value !== "}") {
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ }
+
+ if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) {
+ switch (state.tokens.next.value) {
+ case "break":
+ case "case":
+ case "catch":
+ case "continue":
+ case "default":
+ case "do":
+ case "else":
+ case "finally":
+ case "for":
+ case "if":
+ case "in":
+ case "instanceof":
+ case "return":
+ case "yield":
+ case "switch":
+ case "throw":
+ case "try":
+ case "var":
+ case "let":
+ case "while":
+ case "with":
+ error("E024", state.tokens.next, state.tokens.next.value);
+ return false;
+ }
+ }
+
+ if (state.tokens.next.type === "(punctuator)") {
+ switch (state.tokens.next.value) {
+ case "}":
+ case "]":
+ case ",":
+ if (opts.allowTrailing) {
+ return true;
+ }
+ case ")":
+ error("E024", state.tokens.next, state.tokens.next.value);
+ return false;
+ }
+ }
+ return true;
}
function symbol(s, p) {
- var x = syntax[s];
+ var x = state.syntax[s];
if (!x || typeof x !== "object") {
- syntax[s] = x = {
+ state.syntax[s] = x = {
id: s,
lbp: p,
value: s
@@ -4051,12 +4157,10 @@ klass:
return x;
}
-
function delim(s) {
return symbol(s, 0);
}
-
function stmt(s, f) {
var x = delim(s);
x.identifier = x.reserved = true;
@@ -4064,14 +4168,12 @@ klass:
return x;
}
-
function blockstmt(s, f) {
var x = stmt(s, f);
x.block = true;
return x;
}
-
function reserveName(x) {
var c = x.id.charAt(0);
if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
@@ -4080,7 +4182,6 @@ klass:
return x;
}
-
function prefix(s, f) {
var x = symbol(s, 150);
reserveName(x);
@@ -4088,11 +4189,11 @@ klass:
this.right = expression(150);
this.arity = "unary";
if (this.id === "++" || this.id === "--") {
- if (option.plusplus) {
- warning("Unexpected use of '{a}'.", this, this.id);
- } else if ((!this.right.identifier || this.right.reserved) &&
+ if (state.option.plusplus) {
+ warning("W016", this, this.id);
+ } else if ((!this.right.identifier || isReserved(this.right)) &&
this.right.id !== "." && this.right.id !== "[") {
- warning("Bad operand.", this);
+ warning("W017", this);
}
}
return this;
@@ -4100,7 +4201,6 @@ klass:
return x;
}
-
function type(s, f) {
var x = delim(s);
x.type = s;
@@ -4108,13 +4208,28 @@ klass:
return x;
}
-
- function reserve(s, f) {
- var x = type(s, f);
- x.identifier = x.reserved = true;
+ function reserve(name, func) {
+ var x = type(name, func);
+ x.identifier = true;
+ x.reserved = true;
return x;
}
+ function FutureReservedWord(name, meta) {
+ var x = type(name, (meta && meta.nud) || function () {
+ return this;
+ });
+
+ meta = meta || {};
+ meta.isFutureReservedWord = true;
+
+ x.value = name;
+ x.identifier = true;
+ x.reserved = true;
+ x.meta = meta;
+
+ return x;
+ }
function reservevar(s, v) {
return reserve(s, function () {
@@ -4125,17 +4240,16 @@ klass:
});
}
-
function infix(s, f, p, w) {
var x = symbol(s, p);
reserveName(x);
x.led = function (left) {
if (!w) {
- nobreaknonadjacent(prevtoken, token);
- nonadjacent(token, nexttoken);
+ nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+ nonadjacent(state.tokens.curr, state.tokens.next);
}
if (s === "in" && left.id === "!") {
- warning("Confusing use of '{a}'.", left, "!");
+ warning("W018", left, "!");
}
if (typeof f === "function") {
return f(left, this);
@@ -4149,24 +4263,50 @@ klass:
}
+ function application(s) {
+ var x = symbol(s, 42);
+
+ x.led = function (left) {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "arrow function syntax (=>)");
+ }
+
+ nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+ nonadjacent(state.tokens.curr, state.tokens.next);
+
+ this.left = left;
+ this.right = doFunction(undefined, undefined, false, left);
+ return this;
+ };
+ return x;
+ }
+
function relation(s, f) {
var x = symbol(s, 100);
+
x.led = function (left) {
- nobreaknonadjacent(prevtoken, token);
- nonadjacent(token, nexttoken);
+ nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+ nonadjacent(state.tokens.curr, state.tokens.next);
var right = expression(100);
if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
- warning("Use the isNaN function to compare with NaN.", this);
+ warning("W019", this);
} else if (f) {
f.apply(this, [left, right]);
}
+
+ if (!left || !right) {
+ quit("E041", state.tokens.curr.line);
+ }
+
if (left.id === "!") {
- warning("Confusing use of '{a}'.", left, "!");
+ warning("W018", left, "!");
}
+
if (right.id === "!") {
- warning("Confusing use of '{a}'.", right, "!");
+ warning("W018", right, "!");
}
+
this.left = left;
this.right = right;
return this;
@@ -4174,58 +4314,71 @@ klass:
return x;
}
-
function isPoorRelation(node) {
return node &&
((node.type === "(number)" && +node.value === 0) ||
(node.type === "(string)" && node.value === "") ||
- (node.type === "null" && !option.eqnull) ||
+ (node.type === "null" && !state.option.eqnull) ||
node.type === "true" ||
node.type === "false" ||
node.type === "undefined");
}
-
function assignop(s) {
symbol(s, 20).exps = true;
return infix(s, function (left, that) {
that.left = left;
- if (predefined[left.value] === false &&
- scope[left.value]["(global)"] === true) {
- warning("Read only.", left);
- } else if (left["function"]) {
- warning("'{a}' is a function.", left, left.value);
- }
-
if (left) {
- if (option.esnext && funct[left.value] === "const") {
- warning("Attempting to override '{a}' which is a constant", left, left.value);
+ if (predefined[left.value] === false &&
+ scope[left.value]["(global)"] === true) {
+ warning("W020", left);
+ } else if (left["function"]) {
+ warning("W021", left, left.value);
}
- if (left.id === "." || left.id === "[") {
- if (!left.left || left.left.value === "arguments") {
- warning("Bad assignment.", that);
+ if (funct[left.value] === "const") {
+ error("E013", left, left.value);
+ }
+
+ if (left.id === ".") {
+ if (!left.left) {
+ warning("E031", that);
+ } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
+ warning("E031", that);
+ }
+
+ that.right = expression(19);
+ return that;
+ } else if (left.id === "[") {
+ if (state.tokens.curr.left.first) {
+ state.tokens.curr.left.first.forEach(function (t) {
+ if (funct[t.value] === "const") {
+ error("E013", t, t.value);
+ }
+ });
+ } else if (!left.left) {
+ warning("E031", that);
+ } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
+ warning("E031", that);
}
that.right = expression(19);
return that;
- } else if (left.identifier && !left.reserved) {
+ } else if (left.identifier && !isReserved(left)) {
if (funct[left.value] === "exception") {
- warning("Do not assign to the exception parameter.", left);
+ warning("W022", left);
}
that.right = expression(19);
return that;
}
- if (left === syntax["function"]) {
- warning(
-"Expected an identifier in an assignment and instead saw a function invocation.",
- token);
+ if (left === state.syntax["function"]) {
+ warning("W023", state.tokens.curr);
}
}
- error("Bad assignment.", that);
+ error("E031", that);
}, 20);
}
@@ -4234,8 +4387,8 @@ klass:
var x = symbol(s, p);
reserveName(x);
x.led = (typeof f === "function") ? f : function (left) {
- if (option.bitwise) {
- warning("Unexpected use of '{a}'.", this, this.id);
+ if (state.option.bitwise) {
+ warning("W016", this, this.id);
}
this.left = left;
this.right = expression(p);
@@ -4248,72 +4401,91 @@ klass:
function bitwiseassignop(s) {
symbol(s, 20).exps = true;
return infix(s, function (left, that) {
- if (option.bitwise) {
- warning("Unexpected use of '{a}'.", that, that.id);
+ if (state.option.bitwise) {
+ warning("W016", that, that.id);
}
- nonadjacent(prevtoken, token);
- nonadjacent(token, nexttoken);
+ nonadjacent(state.tokens.prev, state.tokens.curr);
+ nonadjacent(state.tokens.curr, state.tokens.next);
if (left) {
if (left.id === "." || left.id === "[" ||
- (left.identifier && !left.reserved)) {
+ (left.identifier && !isReserved(left))) {
expression(19);
return that;
}
- if (left === syntax["function"]) {
- warning(
-"Expected an identifier in an assignment, and instead saw a function invocation.",
- token);
+ if (left === state.syntax["function"]) {
+ warning("W023", state.tokens.curr);
}
return that;
}
- error("Bad assignment.", that);
+ error("E031", that);
}, 20);
}
function suffix(s) {
var x = symbol(s, 150);
+
x.led = function (left) {
- if (option.plusplus) {
- warning("Unexpected use of '{a}'.", this, this.id);
- } else if ((!left.identifier || left.reserved) &&
- left.id !== "." && left.id !== "[") {
- warning("Bad operand.", this);
+ if (state.option.plusplus) {
+ warning("W016", this, this.id);
+ } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
+ warning("W017", this);
}
+
this.left = left;
return this;
};
return x;
}
- function optionalidentifier(fnparam) {
- if (nexttoken.identifier) {
- advance();
- if (token.reserved && !option.es5) {
- if (!fnparam || token.value !== "undefined") {
- warning("Expected an identifier and instead saw '{a}' (a reserved word).",
- token, token.id);
- }
- }
- return token.value;
+
+ function optionalidentifier(fnparam, prop) {
+ if (!state.tokens.next.identifier) {
+ return;
}
+
+ advance();
+
+ var curr = state.tokens.curr;
+ var meta = curr.meta || {};
+ var val = state.tokens.curr.value;
+
+ if (!isReserved(curr)) {
+ return val;
+ }
+
+ if (prop) {
+ if (state.option.inES5() || meta.isFutureReservedWord) {
+ return val;
+ }
+ }
+
+ if (fnparam && val === "undefined") {
+ return val;
+ }
+ if (prop && !api.getCache("displayed:I002")) {
+ api.setCache("displayed:I002", true);
+ warning("I002");
+ }
+
+ warning("W024", state.tokens.curr, state.tokens.curr.id);
+ return val;
}
- function identifier(fnparam) {
- var i = optionalidentifier(fnparam);
+ function identifier(fnparam, prop) {
+ var i = optionalidentifier(fnparam, prop);
if (i) {
return i;
}
- if (token.id === "function" && nexttoken.id === "(") {
- warning("Missing name in function declaration.");
+ if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") {
+ warning("W025");
} else {
- error("Expected an identifier and instead saw '{a}'.",
- nexttoken, nexttoken.value);
+ error("E030", state.tokens.next, state.tokens.next.value);
}
}
function reachable(s) {
var i = 0, t;
- if (nexttoken.id !== ";" || noreach) {
+ if (state.tokens.next.id !== ";" || noreach) {
return;
}
for (;;) {
@@ -4323,14 +4495,15 @@ klass:
}
if (t.id !== "(endline)") {
if (t.id === "function") {
- if (!option.latedef) {
+ if (!state.option.latedef) {
break;
}
- warning(
-"Inner functions should be listed at the top of the outer function.", t);
+
+ warning("W026", t);
break;
}
- warning("Unreachable '{a}' after '{b}'.", t, t.value, s);
+
+ warning("W027", t, t.value, s);
break;
}
i += 1;
@@ -4339,29 +4512,46 @@ klass:
function statement(noindent) {
- var i = indent, r, s = scope, t = nexttoken;
+ var values;
+ var i = indent, r, s = scope, t = state.tokens.next;
if (t.id === ";") {
advance(";");
return;
}
+ var res = isReserved(t);
- if (t.identifier && !t.reserved && peek().id === ":") {
+ if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
+ warning("W024", t, t.id);
+ res = false;
+ }
+ if (_.has(["[", "{"], t.value)) {
+ if (lookupBlockType().isDestAssign) {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "destructuring expression");
+ }
+ values = destructuringExpression();
+ values.forEach(function (tok) {
+ isundef(funct, "W117", tok.token, tok.id);
+ });
+ advance("=");
+ destructuringExpressionMatch(values, expression(5, true));
+ advance(";");
+ return;
+ }
+ }
+ if (t.identifier && !res && peek().id === ":") {
advance();
advance(":");
scope = Object.create(s);
addlabel(t.value, "label");
- if (!nexttoken.labelled && nexttoken.value !== "{") {
- warning("Label '{a}' on {b} statement.", nexttoken, t.value, nexttoken.value);
+ if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
+ warning("W028", state.tokens.next, t.value, state.tokens.next.value);
}
- if (jx.test(t.value + ":")) {
- warning("Label '{a}' looks like a javascript url.", t, t.value);
- }
-
- nexttoken.label = t.value;
- t = nexttoken;
+ state.tokens.next.label = t.value;
+ t = state.tokens.next;
}
if (t.id === "{") {
@@ -4375,28 +4565,23 @@ klass:
r = expression(0, true);
if (!t.block) {
- if (!option.expr && (!r || !r.exps)) {
- warning("Expected an assignment or function call and instead saw an expression.",
- token);
- } else if (option.nonew && r.id === "(" && r.left.id === "new") {
- warning("Do not use 'new' for side effects.", t);
+ if (!state.option.expr && (!r || !r.exps)) {
+ warning("W030", state.tokens.curr);
+ } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
+ warning("W031", t);
}
- if (nexttoken.id === ",") {
- return comma();
- }
-
- if (nexttoken.id !== ";") {
- if (!option.asi) {
- if (!option.lastsemic || nexttoken.id !== "}" ||
- nexttoken.line !== token.line) {
- warningAt("Missing semicolon.", token.line, token.character);
+ if (state.tokens.next.id !== ";") {
+ if (!state.option.asi) {
+ if (!state.option.lastsemic || state.tokens.next.id !== "}" ||
+ state.tokens.next.line !== state.tokens.curr.line) {
+ warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
}
}
} else {
- adjacent(token, nexttoken);
+ adjacent(state.tokens.curr, state.tokens.next);
advance(";");
- nonadjacent(token, nexttoken);
+ nonadjacent(state.tokens.curr, state.tokens.next);
}
}
@@ -4409,15 +4594,17 @@ klass:
function statements(startLine) {
var a = [], p;
- while (!nexttoken.reach && nexttoken.id !== "(end)") {
- if (nexttoken.id === ";") {
+ while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
+ if (state.tokens.next.id === ";") {
p = peek();
- if (!p || p.id !== "(") {
- warning("Unnecessary semicolon.");
+
+ if (!p || (p.id !== "(" && p.id !== "[")) {
+ warning("W032");
}
+
advance(";");
} else {
- a.push(statement(startLine === nexttoken.line));
+ a.push(statement(startLine === state.tokens.next.line));
}
}
return a;
@@ -4426,7 +4613,7 @@ klass:
var i, p, pn;
for (;;) {
- if (nexttoken.id === "(string)") {
+ if (state.tokens.next.id === "(string)") {
p = peek(0);
if (p.id === "(endline)") {
i = 1;
@@ -4441,28 +4628,28 @@ klass:
pn.id !== "}") {
break;
}
- warning("Missing semicolon.", nexttoken);
+ warning("W033", state.tokens.next);
} else {
p = pn;
}
} else if (p.id === "}") {
- warning("Missing semicolon.", p);
+ warning("W033", p);
} else if (p.id !== ";") {
break;
}
indentation();
advance();
- if (directive[token.value]) {
- warning("Unnecessary directive \"{a}\".", token, token.value);
+ if (state.directive[state.tokens.curr.value]) {
+ warning("W034", state.tokens.curr, state.tokens.curr.value);
}
- if (token.value === "use strict") {
- if (!option["(explicitNewcap)"])
- option.newcap = true;
- option.undef = true;
+ if (state.tokens.curr.value === "use strict") {
+ if (!state.option["(explicitNewcap)"])
+ state.option.newcap = true;
+ state.option.undef = true;
}
- directive[token.value] = true;
+ state.directive[state.tokens.curr.value] = true;
if (p.id === ";") {
advance(";");
@@ -4472,7 +4659,7 @@ klass:
break;
}
}
- function block(ordinary, stmt, isfunc) {
+ function block(ordinary, stmt, isfunc, isfatarrow) {
var a,
b = inblock,
old_indent = indent,
@@ -4484,37 +4671,39 @@ klass:
inblock = ordinary;
- if (!ordinary || !option.funcscope)
+ if (!ordinary || !state.option.funcscope)
scope = Object.create(scope);
- nonadjacent(token, nexttoken);
- t = nexttoken;
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ t = state.tokens.next;
var metrics = funct["(metrics)"];
metrics.nestedBlockDepth += 1;
metrics.verifyMaxNestedBlockDepthPerFunction();
- if (nexttoken.id === "{") {
+ if (state.tokens.next.id === "{") {
advance("{");
- line = token.line;
- if (nexttoken.id !== "}") {
- indent += option.indent;
- while (!ordinary && nexttoken.from > indent) {
- indent += option.indent;
+ funct["(blockscope)"].stack();
+
+ line = state.tokens.curr.line;
+ if (state.tokens.next.id !== "}") {
+ indent += state.option.indent;
+ while (!ordinary && state.tokens.next.from > indent) {
+ indent += state.option.indent;
}
if (isfunc) {
m = {};
- for (d in directive) {
- if (is_own(directive, d)) {
- m[d] = directive[d];
+ for (d in state.directive) {
+ if (_.has(state.directive, d)) {
+ m[d] = state.directive[d];
}
}
directives();
- if (option.strict && funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !directive["use strict"]) {
- warning("Missing \"use strict\" statement.");
+ if (state.option.strict && funct["(context)"]["(global)"]) {
+ if (!m["use strict"] && !state.directive["use strict"]) {
+ warning("E007");
}
}
}
@@ -4524,37 +4713,65 @@ klass:
metrics.statementCount += a.length;
if (isfunc) {
- directive = m;
+ state.directive = m;
}
- indent -= option.indent;
- if (line !== nexttoken.line) {
+ indent -= state.option.indent;
+ if (line !== state.tokens.next.line) {
indentation();
}
- } else if (line !== nexttoken.line) {
+ } else if (line !== state.tokens.next.line) {
indentation();
}
advance("}", t);
+
+ funct["(blockscope)"].unstack();
+
indent = old_indent;
} else if (!ordinary) {
- error("Expected '{a}' and instead saw '{b}'.",
- nexttoken, "{", nexttoken.value);
+ if (isfunc) {
+ m = {};
+ if (stmt && !isfatarrow && !state.option.inMoz(true)) {
+ error("W118", state.tokens.curr, "function closure expressions");
+ }
+
+ if (!stmt) {
+ for (d in state.directive) {
+ if (_.has(state.directive, d)) {
+ m[d] = state.directive[d];
+ }
+ }
+ }
+ expression(5);
+
+ if (state.option.strict && funct["(context)"]["(global)"]) {
+ if (!m["use strict"] && !state.directive["use strict"]) {
+ warning("E007");
+ }
+ }
+ } else {
+ error("E021", state.tokens.next, "{", state.tokens.next.value);
+ }
} else {
- if (!stmt || option.curly)
- warning("Expected '{a}' and instead saw '{b}'.",
- nexttoken, "{", nexttoken.value);
+ funct["(nolet)"] = true;
+
+ if (!stmt || state.option.curly) {
+ warning("W116", state.tokens.next, "{", state.tokens.next.value);
+ }
noreach = true;
- indent += option.indent;
- a = [statement(nexttoken.line === token.line)];
- indent -= option.indent;
+ indent += state.option.indent;
+ a = [statement(state.tokens.next.line === state.tokens.curr.line)];
+ indent -= state.option.indent;
noreach = false;
+
+ delete funct["(nolet)"];
}
funct["(verb)"] = null;
- if (!ordinary || !option.funcscope) scope = s;
+ if (!ordinary || !state.option.funcscope) scope = s;
inblock = b;
- if (ordinary && option.noempty && (!a || a.length === 0)) {
- warning("Empty block.");
+ if (ordinary && state.option.noempty && (!a || a.length === 0)) {
+ warning("W035");
}
metrics.nestedBlockDepth -= 1;
return a;
@@ -4563,7 +4780,7 @@ klass:
function countMember(m) {
if (membersOnly && typeof membersOnly[m] !== "boolean") {
- warning("Unexpected /*member '{a}'.", token, m);
+ warning("W036", state.tokens.curr, m);
}
if (typeof member[m] === "number") {
member[m] += 1;
@@ -4573,8 +4790,8 @@ klass:
}
- function note_implied(token) {
- var name = token.value, line = token.line, a = implied[name];
+ function note_implied(tkn) {
+ var name = tkn.value, line = tkn.line, a = implied[name];
if (typeof a === "function") {
a = false;
}
@@ -4595,7 +4812,7 @@ klass:
return this;
});
- syntax["(identifier)"] = {
+ state.syntax["(identifier)"] = {
type: "(identifier)",
lbp: 0,
identifier: true,
@@ -4613,33 +4830,42 @@ klass:
s = funct;
funct = f;
}
- if (funct === s) {
- switch (funct[v]) {
+ var block;
+ if (_.has(funct, "(blockscope)")) {
+ block = funct["(blockscope)"].getlabel(v);
+ }
+ if (funct === s || block) {
+ switch (block ? block[v]["(type)"] : funct[v]) {
case "unused":
- funct[v] = "var";
+ if (block) block[v]["(type)"] = "var";
+ else funct[v] = "var";
break;
case "unction":
- funct[v] = "function";
+ if (block) block[v]["(type)"] = "function";
+ else funct[v] = "function";
this["function"] = true;
break;
case "function":
this["function"] = true;
break;
case "label":
- warning("'{a}' is a statement label.", token, v);
+ warning("W037", state.tokens.curr, v);
break;
}
} else if (funct["(global)"]) {
- if (option.undef && typeof predefined[v] !== "boolean") {
+ if (typeof predefined[v] !== "boolean") {
if (!(anonname === "typeof" || anonname === "delete") ||
- (nexttoken && (nexttoken.value === "." || nexttoken.value === "["))) {
+ (state.tokens.next && (state.tokens.next.value === "." ||
+ state.tokens.next.value === "["))) {
- isundef(funct, "'{a}' is not defined.", token, v);
+ if (!funct["(comparray)"].check(v)) {
+ isundef(funct, "W117", state.tokens.curr, v);
+ }
}
}
- note_implied(token);
+ note_implied(state.tokens.curr);
} else {
switch (funct[v]) {
@@ -4647,10 +4873,10 @@ klass:
case "function":
case "var":
case "unused":
- warning("'{a}' used out of scope.", token, v);
+ warning("W038", state.tokens.curr, v);
break;
case "label":
- warning("'{a}' is a statement label.", token, v);
+ warning("W037", state.tokens.curr, v);
break;
case "outer":
case "global":
@@ -4659,19 +4885,17 @@ klass:
if (s === true) {
funct[v] = true;
} else if (s === null) {
- warning("'{a}' is not allowed.", token, v);
- note_implied(token);
+ warning("W039", state.tokens.curr, v);
+ note_implied(state.tokens.curr);
} else if (typeof s !== "object") {
- if (option.undef) {
- if (!(anonname === "typeof" || anonname === "delete") ||
- (nexttoken &&
- (nexttoken.value === "." || nexttoken.value === "["))) {
+ if (!(anonname === "typeof" || anonname === "delete") ||
+ (state.tokens.next &&
+ (state.tokens.next.value === "." || state.tokens.next.value === "["))) {
- isundef(funct, "'{a}' is not defined.", token, v);
- }
+ isundef(funct, "W117", state.tokens.curr, v);
}
funct[v] = true;
- note_implied(token);
+ note_implied(state.tokens.curr);
} else {
switch (s[v]) {
case "function":
@@ -4689,7 +4913,7 @@ klass:
funct[v] = s["(global)"] ? "global" : "outer";
break;
case "label":
- warning("'{a}' is a statement label.", token, v);
+ warning("W037", state.tokens.curr, v);
}
}
}
@@ -4697,8 +4921,7 @@ klass:
return this;
},
led: function () {
- error("Expected an operator and instead saw '{a}'.",
- nexttoken, nexttoken.value);
+ error("E033", state.tokens.next, state.tokens.next.value);
}
};
@@ -4709,10 +4932,6 @@ klass:
delim("(endline)");
delim("(begin)");
delim("(end)").reach = true;
- delim("").reach = true;
- delim("");
delim("(error)").reach = true;
delim("}").reach = true;
delim(")");
@@ -4721,17 +4940,16 @@ klass:
delim("'").reach = true;
delim(";");
delim(":").reach = true;
- delim(",");
delim("#");
- delim("@");
+
reserve("else");
reserve("case").reach = true;
reserve("catch");
reserve("default").reach = true;
reserve("finally");
reservevar("arguments", function (x) {
- if (directive["use strict"] && funct["(global)"]) {
- warning("Strict violation.", x);
+ if (state.directive["use strict"] && funct["(global)"]) {
+ warning("E008", x);
}
});
reservevar("eval");
@@ -4739,27 +4957,46 @@ klass:
reservevar("Infinity");
reservevar("null");
reservevar("this", function (x) {
- if (directive["use strict"] && !option.validthis && ((funct["(statement)"] &&
+ if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] &&
funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
- warning("Possible strict violation.", x);
+ warning("W040", x);
}
});
reservevar("true");
reservevar("undefined");
+
assignop("=", "assign", 20);
assignop("+=", "assignadd", 20);
assignop("-=", "assignsub", 20);
assignop("*=", "assignmult", 20);
assignop("/=", "assigndiv", 20).nud = function () {
- error("A regular expression literal can be confused with '/='.");
+ error("E014");
};
assignop("%=", "assignmod", 20);
+
bitwiseassignop("&=", "assignbitand", 20);
bitwiseassignop("|=", "assignbitor", 20);
bitwiseassignop("^=", "assignbitxor", 20);
bitwiseassignop("<<=", "assignshiftleft", 20);
bitwiseassignop(">>=", "assignshiftright", 20);
bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
+ infix(",", function (left, that) {
+ var expr;
+ that.exprs = [left];
+ if (!comma({peek: true})) {
+ return that;
+ }
+ while (true) {
+ if (!(expr = expression(5))) {
+ break;
+ }
+ that.exprs.push(expr);
+ if (state.tokens.next.value !== "," || !comma()) {
+ break;
+ }
+ }
+ return that;
+ }, 5, true);
infix("?", function (left, that) {
that.left = left;
that.right = expression(10);
@@ -4774,31 +5011,28 @@ klass:
bitwise("^", "bitxor", 80);
bitwise("&", "bitand", 90);
relation("==", function (left, right) {
- var eqnull = option.eqnull && (left.value === "null" || right.value === "null");
+ var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null");
- if (!eqnull && option.eqeqeq)
- warning("Expected '{a}' and instead saw '{b}'.", this, "===", "==");
+ if (!eqnull && state.option.eqeqeq)
+ warning("W116", this, "===", "==");
else if (isPoorRelation(left))
- warning("Use '{a}' to compare with '{b}'.", this, "===", left.value);
+ warning("W041", this, "===", left.value);
else if (isPoorRelation(right))
- warning("Use '{a}' to compare with '{b}'.", this, "===", right.value);
+ warning("W041", this, "===", right.value);
return this;
});
relation("===");
relation("!=", function (left, right) {
- var eqnull = option.eqnull &&
+ var eqnull = state.option.eqnull &&
(left.value === "null" || right.value === "null");
- if (!eqnull && option.eqeqeq) {
- warning("Expected '{a}' and instead saw '{b}'.",
- this, "!==", "!=");
+ if (!eqnull && state.option.eqeqeq) {
+ warning("W116", this, "!==", "!=");
} else if (isPoorRelation(left)) {
- warning("Use '{a}' to compare with '{b}'.",
- this, "!==", left.value);
+ warning("W041", this, "!==", left.value);
} else if (isPoorRelation(right)) {
- warning("Use '{a}' to compare with '{b}'.",
- this, "!==", right.value);
+ warning("W041", this, "!==", right.value);
}
return this;
});
@@ -4817,8 +5051,8 @@ klass:
if (left && right && left.id === "(string)" && right.id === "(string)") {
left.value += right.value;
left.character = right.character;
- if (!option.scripturl && jx.test(left.value)) {
- warning("JavaScript URL.", left);
+ if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
+ warning("W050", left);
}
return left;
}
@@ -4828,13 +5062,13 @@ klass:
}, 130);
prefix("+", "num");
prefix("+++", function () {
- warning("Confusing pluses.");
+ warning("W007");
this.right = expression(150);
this.arity = "unary";
return this;
});
infix("+++", function (left) {
- warning("Confusing pluses.");
+ warning("W007");
this.left = left;
this.right = expression(130);
return this;
@@ -4842,13 +5076,13 @@ klass:
infix("-", "sub", 130);
prefix("-", "neg");
prefix("---", function () {
- warning("Confusing minuses.");
+ warning("W006");
this.right = expression(150);
this.arity = "unary";
return this;
});
infix("---", function (left) {
- warning("Confusing minuses.");
+ warning("W006");
this.left = left;
this.right = expression(130);
return this;
@@ -4859,23 +5093,34 @@ klass:
suffix("++", "postinc");
prefix("++", "preinc");
- syntax["++"].exps = true;
+ state.syntax["++"].exps = true;
suffix("--", "postdec");
prefix("--", "predec");
- syntax["--"].exps = true;
+ state.syntax["--"].exps = true;
prefix("delete", function () {
- var p = expression(0);
+ var p = expression(5);
if (!p || (p.id !== "." && p.id !== "[")) {
- warning("Variables should not be deleted.");
+ warning("W051");
}
this.first = p;
return this;
}).exps = true;
prefix("~", function () {
- if (option.bitwise) {
- warning("Unexpected '{a}'.", this, "~");
+ if (state.option.bitwise) {
+ warning("W052", this, "~");
+ }
+ expression(150);
+ return this;
+ });
+
+ prefix("...", function () {
+ if (!state.option.inESNext()) {
+ warning("W104", this, "spread/rest operator");
+ }
+ if (!state.tokens.next.identifier) {
+ error("E030", state.tokens.next, state.tokens.next.value);
}
expression(150);
return this;
@@ -4884,11 +5129,17 @@ klass:
prefix("!", function () {
this.right = expression(150);
this.arity = "unary";
+
+ if (!this.right) { // '!' followed by nothing? Give up.
+ quit("E041", this.line || 0);
+ }
+
if (bang[this.right.id] === true) {
- warning("Confusing use of '{a}'.", this, "!");
+ warning("W018", this, "!");
}
return this;
});
+
prefix("typeof", "typeof");
prefix("new", function () {
var c = expression(155), i;
@@ -4901,11 +5152,11 @@ klass:
case "Boolean":
case "Math":
case "JSON":
- warning("Do not use {a} as a constructor.", prevtoken, c.value);
+ warning("W053", state.tokens.prev, c.value);
break;
case "Function":
- if (!option.evil) {
- warning("The Function constructor is eval.");
+ if (!state.option.evil) {
+ warning("W054");
}
break;
case "Date":
@@ -4914,102 +5165,113 @@ klass:
default:
if (c.id !== "function") {
i = c.value.substr(0, 1);
- if (option.newcap && (i < "A" || i > "Z") && !is_own(global, c.value)) {
- warning("A constructor name should start with an uppercase letter.",
- token);
+ if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) {
+ warning("W055", state.tokens.curr);
}
}
}
} else {
if (c.id !== "." && c.id !== "[" && c.id !== "(") {
- warning("Bad constructor.", token);
+ warning("W056", state.tokens.curr);
}
}
} else {
- if (!option.supernew)
- warning("Weird construction. Delete 'new'.", this);
+ if (!state.option.supernew)
+ warning("W057", this);
}
- adjacent(token, nexttoken);
- if (nexttoken.id !== "(" && !option.supernew) {
- warning("Missing '()' invoking a constructor.",
- token, token.value);
+ adjacent(state.tokens.curr, state.tokens.next);
+ if (state.tokens.next.id !== "(" && !state.option.supernew) {
+ warning("W058", state.tokens.curr, state.tokens.curr.value);
}
this.first = c;
return this;
});
- syntax["new"].exps = true;
+ state.syntax["new"].exps = true;
prefix("void").exps = true;
infix(".", function (left, that) {
- adjacent(prevtoken, token);
+ adjacent(state.tokens.prev, state.tokens.curr);
nobreak();
- var m = identifier();
+ var m = identifier(false, true);
+
if (typeof m === "string") {
countMember(m);
}
+
that.left = left;
that.right = m;
+
+ if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
+ warning("W001");
+ }
+
if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
- if (option.noarg)
- warning("Avoid arguments.{a}.", left, m);
- else if (directive["use strict"])
- error("Strict violation.");
- } else if (!option.evil && left && left.value === "document" &&
+ if (state.option.noarg)
+ warning("W059", left, m);
+ else if (state.directive["use strict"])
+ error("E008");
+ } else if (!state.option.evil && left && left.value === "document" &&
(m === "write" || m === "writeln")) {
- warning("document.write can be a form of eval.", left);
+ warning("W060", left);
}
- if (!option.evil && (m === "eval" || m === "execScript")) {
- warning("eval is evil.");
+
+ if (!state.option.evil && (m === "eval" || m === "execScript")) {
+ warning("W061");
}
+
return that;
}, 160, true);
infix("(", function (left, that) {
- if (prevtoken.id !== "}" && prevtoken.id !== ")") {
- nobreak(prevtoken, token);
+ if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") {
+ nobreak(state.tokens.prev, state.tokens.curr);
}
+
nospace();
- if (option.immed && !left.immed && left.id === "function") {
- warning("Wrap an immediate function invocation in parentheses " +
- "to assist the reader in understanding that the expression " +
- "is the result of a function, and not the function itself.");
+ if (state.option.immed && left && !left.immed && left.id === "function") {
+ warning("W062");
}
- var n = 0,
- p = [];
+
+ var n = 0;
+ var p = [];
+
if (left) {
if (left.type === "(identifier)") {
if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
if ("Number String Boolean Date Object".indexOf(left.value) === -1) {
if (left.value === "Math") {
- warning("Math is not a function.", left);
- } else if (option.newcap) {
- warning("Missing 'new' prefix when invoking a constructor.", left);
+ warning("W063", left);
+ } else if (state.option.newcap) {
+ warning("W064", left);
}
}
}
}
}
- if (nexttoken.id !== ")") {
+
+ if (state.tokens.next.id !== ")") {
for (;;) {
p[p.length] = expression(10);
n += 1;
- if (nexttoken.id !== ",") {
+ if (state.tokens.next.id !== ",") {
break;
}
comma();
}
}
+
advance(")");
- nospace(prevtoken, token);
+ nospace(state.tokens.prev, state.tokens.curr);
+
if (typeof left === "object") {
if (left.value === "parseInt" && n === 1) {
- warning("Missing radix parameter.", token);
+ warning("W065", state.tokens.curr);
}
- if (!option.evil) {
+ if (!state.option.evil) {
if (left.value === "eval" || left.value === "Function" ||
left.value === "execScript") {
- warning("eval is evil.", left);
+ warning("W061", left);
if (p[0] && [0].id === "(string)") {
addInternalSrc(left, p[0].value);
@@ -5017,99 +5279,188 @@ klass:
} else if (p[0] && p[0].id === "(string)" &&
(left.value === "setTimeout" ||
left.value === "setInterval")) {
- warning(
- "Implied eval is evil. Pass a function instead of a string.", left);
+ warning("W066", left);
addInternalSrc(left, p[0].value);
} else if (p[0] && p[0].id === "(string)" &&
left.value === "." &&
left.left.value === "window" &&
(left.right === "setTimeout" ||
left.right === "setInterval")) {
- warning(
- "Implied eval is evil. Pass a function instead of a string.", left);
+ warning("W066", left);
addInternalSrc(left, p[0].value);
}
}
if (!left.identifier && left.id !== "." && left.id !== "[" &&
left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
left.id !== "?") {
- warning("Bad invocation.", left);
+ warning("W067", left);
}
}
+
that.left = left;
return that;
}, 155, true).exps = true;
prefix("(", function () {
nospace();
- if (nexttoken.id === "function") {
- nexttoken.immed = true;
+ var bracket, brackets = [];
+ var pn, pn1, i = 0;
+ var ret;
+
+ do {
+ pn = peek(i);
+ i += 1;
+ pn1 = peek(i);
+ i += 1;
+ } while (pn.value !== ")" && pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)");
+
+ if (state.tokens.next.id === "function") {
+ state.tokens.next.immed = true;
}
- var v = expression(0);
- advance(")", this);
- nospace(prevtoken, token);
- if (option.immed && v.id === "function") {
- if (nexttoken.id !== "(" &&
- (nexttoken.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
- warning(
-"Do not wrap function literals in parens unless they are to be immediately invoked.",
- this);
+
+ var exprs = [];
+
+ if (state.tokens.next.id !== ")") {
+ for (;;) {
+ if (pn1.value === "=>" && state.tokens.next.value === "{") {
+ bracket = state.tokens.next;
+ bracket.left = destructuringExpression();
+ brackets.push(bracket);
+ for (var t in bracket.left) {
+ exprs.push(bracket.left[t].token);
+ }
+ } else {
+ exprs.push(expression(5));
+ }
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
}
}
- return v;
+ advance(")", this);
+ nospace(state.tokens.prev, state.tokens.curr);
+ if (state.option.immed && exprs[0] && exprs[0].id === "function") {
+ if (state.tokens.next.id !== "(" &&
+ (state.tokens.next.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
+ warning("W068", this);
+ }
+ }
+
+ if (state.tokens.next.value === "=>") {
+ return exprs;
+ }
+ if (!exprs.length) {
+ return;
+ }
+ if (exprs.length > 1) {
+ ret = Object.create(state.syntax[","]);
+ ret.exprs = exprs;
+ } else {
+ ret = exprs[0];
+ }
+ if (ret) {
+ ret.paren = true;
+ }
+ return ret;
});
+ application("=>");
+
infix("[", function (left, that) {
- nobreak(prevtoken, token);
+ nobreak(state.tokens.prev, state.tokens.curr);
nospace();
- var e = expression(0), s;
+ var e = expression(5), s;
if (e && e.type === "(string)") {
- if (!option.evil && (e.value === "eval" || e.value === "execScript")) {
- warning("eval is evil.", that);
+ if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
+ warning("W061", that);
}
+
countMember(e.value);
- if (!option.sub && ix.test(e.value)) {
- s = syntax[e.value];
- if (!s || !s.reserved) {
- warning("['{a}'] is better written in dot notation.",
- prevtoken, e.value);
+ if (!state.option.sub && reg.identifier.test(e.value)) {
+ s = state.syntax[e.value];
+ if (!s || !isReserved(s)) {
+ warning("W069", state.tokens.prev, e.value);
}
}
}
advance("]", that);
- nospace(prevtoken, token);
+
+ if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
+ warning("W001");
+ }
+
+ nospace(state.tokens.prev, state.tokens.curr);
that.left = left;
that.right = e;
return that;
}, 160, true);
- prefix("[", function () {
- var b = token.line !== nexttoken.line;
- this.first = [];
- if (b) {
- indent += option.indent;
- if (nexttoken.from === indent + option.indent) {
- indent += option.indent;
+ function comprehensiveArrayExpression() {
+ var res = {};
+ res.exps = true;
+ funct["(comparray)"].stack();
+
+ res.right = expression(5);
+ advance("for");
+ if (state.tokens.next.value === "each") {
+ advance("each");
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.curr, "for each");
}
}
- while (nexttoken.id !== "(end)") {
- while (nexttoken.id === ",") {
- if (!option.es5)
- warning("Extra comma.");
+ advance("(");
+ funct["(comparray)"].setState("define");
+ res.left = expression(5);
+ advance(")");
+ if (state.tokens.next.value === "if") {
+ advance("if");
+ advance("(");
+ funct["(comparray)"].setState("filter");
+ res.filter = expression(5);
+ advance(")");
+ }
+ advance("]");
+ funct["(comparray)"].unstack();
+ return res;
+ }
+
+ prefix("[", function () {
+ var blocktype = lookupBlockType(true);
+ if (blocktype.isCompArray) {
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.curr, "array comprehension");
+ }
+ return comprehensiveArrayExpression();
+ } else if (blocktype.isDestAssign && !state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "destructuring assignment");
+ }
+ var b = state.tokens.curr.line !== state.tokens.next.line;
+ this.first = [];
+ if (b) {
+ indent += state.option.indent;
+ if (state.tokens.next.from === indent + state.option.indent) {
+ indent += state.option.indent;
+ }
+ }
+ while (state.tokens.next.id !== "(end)") {
+ while (state.tokens.next.id === ",") {
+ if (!state.option.inES5())
+ warning("W070");
advance(",");
}
- if (nexttoken.id === "]") {
+ if (state.tokens.next.id === "]") {
break;
}
- if (b && token.line !== nexttoken.line) {
+ if (b && state.tokens.curr.line !== state.tokens.next.line) {
indentation();
}
this.first.push(expression(10));
- if (nexttoken.id === ",") {
- comma();
- if (nexttoken.id === "]" && !option.es5) {
- warning("Extra comma.", token);
+ if (state.tokens.next.id === ",") {
+ comma({ allowTrailing: true });
+ if (state.tokens.next.id === "]" && !state.option.inES5(true)) {
+ warning("W070", state.tokens.curr);
break;
}
} else {
@@ -5117,7 +5468,7 @@ klass:
}
}
if (b) {
- indent -= option.indent;
+ indent -= state.option.indent;
indentation();
}
advance("]", this);
@@ -5126,71 +5477,139 @@ klass:
function property_name() {
- var id = optionalidentifier(true);
+ var id = optionalidentifier(false, true);
+
if (!id) {
- if (nexttoken.id === "(string)") {
- id = nexttoken.value;
+ if (state.tokens.next.id === "(string)") {
+ id = state.tokens.next.value;
advance();
- } else if (nexttoken.id === "(number)") {
- id = nexttoken.value.toString();
+ } else if (state.tokens.next.id === "(number)") {
+ id = state.tokens.next.value.toString();
advance();
}
}
+
+ if (id === "hasOwnProperty") {
+ warning("W001");
+ }
+
return id;
}
- function functionparams() {
- var next = nexttoken;
+ function functionparams(parsed) {
+ var curr, next;
var params = [];
var ident;
+ var tokens = [];
+ var t;
+
+ if (parsed) {
+ if (parsed instanceof Array) {
+ for (var i in parsed) {
+ curr = parsed[i];
+ if (_.contains(["{", "["], curr.id)) {
+ for (t in curr.left) {
+ t = tokens[t];
+ if (t.id) {
+ params.push(t.id);
+ addlabel(t.id, "unused", t.token);
+ }
+ }
+ } else if (curr.value === "...") {
+ if (!state.option.inESNext()) {
+ warning("W104", curr, "spread/rest operator");
+ }
+ continue;
+ } else {
+ addlabel(curr.value, "unused", curr);
+ }
+ }
+ return params;
+ } else {
+ if (parsed.identifier === true) {
+ addlabel(parsed.value, "unused", parsed);
+ return [parsed];
+ }
+ }
+ }
+
+ next = state.tokens.next;
advance("(");
nospace();
- if (nexttoken.id === ")") {
+ if (state.tokens.next.id === ")") {
advance(")");
return;
}
for (;;) {
- ident = identifier(true);
- params.push(ident);
- addlabel(ident, "unused", token);
- if (nexttoken.id === ",") {
+ if (_.contains(["{", "["], state.tokens.next.id)) {
+ tokens = destructuringExpression();
+ for (t in tokens) {
+ t = tokens[t];
+ if (t.id) {
+ params.push(t.id);
+ addlabel(t.id, "unused", t.token);
+ }
+ }
+ } else if (state.tokens.next.value === "...") {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.next, "spread/rest operator");
+ }
+ advance("...");
+ nospace();
+ ident = identifier(true);
+ params.push(ident);
+ addlabel(ident, "unused", state.tokens.curr);
+ } else {
+ ident = identifier(true);
+ params.push(ident);
+ addlabel(ident, "unused", state.tokens.curr);
+ }
+ if (state.tokens.next.id === ",") {
comma();
} else {
advance(")", next);
- nospace(prevtoken, token);
+ nospace(state.tokens.prev, state.tokens.curr);
return params;
}
}
}
- function doFunction(name, statement) {
+ function doFunction(name, statement, generator, fatarrowparams) {
var f;
- var oldOption = option;
+ var oldOption = state.option;
+ var oldIgnored = state.ignored;
var oldScope = scope;
- option = Object.create(option);
+ state.option = Object.create(state.option);
+ state.ignored = Object.create(state.ignored);
scope = Object.create(scope);
funct = {
- "(name)" : name || "\"" + anonname + "\"",
- "(line)" : nexttoken.line,
- "(character)": nexttoken.character,
- "(context)" : funct,
- "(breakage)" : 0,
- "(loopage)" : 0,
- "(metrics)" : createMetrics(nexttoken),
- "(scope)" : scope,
- "(statement)": statement,
- "(tokens)" : {}
+ "(name)" : name || "\"" + anonname + "\"",
+ "(line)" : state.tokens.next.line,
+ "(character)" : state.tokens.next.character,
+ "(context)" : funct,
+ "(breakage)" : 0,
+ "(loopage)" : 0,
+ "(metrics)" : createMetrics(state.tokens.next),
+ "(scope)" : scope,
+ "(statement)" : statement,
+ "(tokens)" : {},
+ "(blockscope)": funct["(blockscope)"],
+ "(comparray)" : funct["(comparray)"]
};
+ if (generator) {
+ funct["(generator)"] = true;
+ }
+
f = funct;
- token.funct = funct;
+ state.tokens.curr.funct = funct;
functions.push(funct);
@@ -5198,18 +5617,25 @@ klass:
addlabel(name, "function");
}
- funct["(params)"] = functionparams();
+ funct["(params)"] = functionparams(fatarrowparams);
+
funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
- block(false, false, true);
+ block(false, true, true, fatarrowparams ? true:false);
+
+ if (generator && funct["(generator)"] !== "yielded") {
+ error("E047", state.tokens.curr);
+ }
funct["(metrics)"].verifyMaxStatementsPerFunction();
funct["(metrics)"].verifyMaxComplexityPerFunction();
+ funct["(unusedOption)"] = state.option.unused;
scope = oldScope;
- option = oldOption;
- funct["(last)"] = token.line;
- funct["(lastcharacter)"] = token.character;
+ state.option = oldOption;
+ state.ignored = oldIgnored;
+ funct["(last)"] = state.tokens.curr.line;
+ funct["(lastcharacter)"] = state.tokens.curr.character;
funct = funct["(context)"];
return f;
@@ -5221,37 +5647,33 @@ klass:
nestedBlockDepth: -1,
ComplexityCount: 1,
verifyMaxStatementsPerFunction: function () {
- if (option.maxstatements &&
- this.statementCount > option.maxstatements) {
- var message = "Too many statements per function (" + this.statementCount + ").";
- warning(message, functionStartToken);
+ if (state.option.maxstatements &&
+ this.statementCount > state.option.maxstatements) {
+ warning("W071", functionStartToken, this.statementCount);
}
},
verifyMaxParametersPerFunction: function (params) {
params = params || [];
- if (option.maxparams && params.length > option.maxparams) {
- var message = "Too many parameters per function (" + params.length + ").";
- warning(message, functionStartToken);
+ if (state.option.maxparams && params.length > state.option.maxparams) {
+ warning("W072", functionStartToken, params.length);
}
},
verifyMaxNestedBlockDepthPerFunction: function () {
- if (option.maxdepth &&
+ if (state.option.maxdepth &&
this.nestedBlockDepth > 0 &&
- this.nestedBlockDepth === option.maxdepth + 1) {
- var message = "Blocks are nested too deeply (" + this.nestedBlockDepth + ").";
- warning(message);
+ this.nestedBlockDepth === state.option.maxdepth + 1) {
+ warning("W073", null, this.nestedBlockDepth);
}
},
verifyMaxComplexityPerFunction: function () {
- var max = option.maxcomplexity;
+ var max = state.option.maxcomplexity;
var cc = this.ComplexityCount;
if (max && cc > max) {
- var message = "Cyclomatic complexity is too high per function (" + cc + ").";
- warning(message, functionStartToken);
+ warning("W074", functionStartToken, cc);
}
}
};
@@ -5261,236 +5683,406 @@ klass:
funct["(metrics)"].ComplexityCount += 1;
}
+ function checkCondAssignment(expr) {
+ var id, paren;
+ if (expr) {
+ id = expr.id;
+ paren = expr.paren;
+ if (id === "," && (expr = expr.exprs[expr.exprs.length - 1])) {
+ id = expr.id;
+ paren = paren || expr.paren;
+ }
+ }
+ switch (id) {
+ case "=":
+ case "+=":
+ case "-=":
+ case "*=":
+ case "%=":
+ case "&=":
+ case "|=":
+ case "^=":
+ case "/=":
+ if (!paren && !state.option.boss) {
+ warning("W084");
+ }
+ }
+ }
+
(function (x) {
- x.nud = function () {
- var b, f, i, p, t;
+ x.nud = function (isclassdef) {
+ var b, f, i, p, t, g;
var props = {}; // All properties, including accessors
+ var tag = "";
- function saveProperty(name, token) {
- if (props[name] && is_own(props, name))
- warning("Duplicate member '{a}'.", nexttoken, i);
+ function saveProperty(name, tkn) {
+ if (props[name] && _.has(props, name))
+ warning("W075", state.tokens.next, i);
else
props[name] = {};
props[name].basic = true;
- props[name].basicToken = token;
+ props[name].basictkn = tkn;
}
- function saveSetter(name, token) {
- if (props[name] && is_own(props, name)) {
+ function saveSetter(name, tkn) {
+ if (props[name] && _.has(props, name)) {
if (props[name].basic || props[name].setter)
- warning("Duplicate member '{a}'.", nexttoken, i);
+ warning("W075", state.tokens.next, i);
} else {
props[name] = {};
}
props[name].setter = true;
- props[name].setterToken = token;
+ props[name].setterToken = tkn;
}
function saveGetter(name) {
- if (props[name] && is_own(props, name)) {
+ if (props[name] && _.has(props, name)) {
if (props[name].basic || props[name].getter)
- warning("Duplicate member '{a}'.", nexttoken, i);
+ warning("W075", state.tokens.next, i);
} else {
props[name] = {};
}
props[name].getter = true;
- props[name].getterToken = token;
+ props[name].getterToken = state.tokens.curr;
}
- b = token.line !== nexttoken.line;
+ b = state.tokens.curr.line !== state.tokens.next.line;
if (b) {
- indent += option.indent;
- if (nexttoken.from === indent + option.indent) {
- indent += option.indent;
+ indent += state.option.indent;
+ if (state.tokens.next.from === indent + state.option.indent) {
+ indent += state.option.indent;
}
}
+
for (;;) {
- if (nexttoken.id === "}") {
+ if (state.tokens.next.id === "}") {
break;
}
+
if (b) {
indentation();
}
- if (nexttoken.value === "get" && peek().id !== ":") {
+
+ if (isclassdef && state.tokens.next.value === "static") {
+ advance("static");
+ tag = "static ";
+ }
+
+ if (state.tokens.next.value === "get" && peek().id !== ":") {
advance("get");
- if (!option.es5) {
- error("get/set are ES5 features.");
+
+ if (!state.option.inES5(!isclassdef)) {
+ error("E034");
}
+
i = property_name();
if (!i) {
- error("Missing property name.");
+ error("E035");
}
- saveGetter(i);
- t = nexttoken;
- adjacent(token, nexttoken);
+ if (isclassdef && i === "constructor") {
+ error("E049", state.tokens.next, "class getter method", i);
+ }
+
+ saveGetter(tag + i);
+ t = state.tokens.next;
+ adjacent(state.tokens.curr, state.tokens.next);
f = doFunction();
p = f["(params)"];
+
if (p) {
- warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i);
+ warning("W076", t, p[0], i);
}
- adjacent(token, nexttoken);
- } else if (nexttoken.value === "set" && peek().id !== ":") {
+
+ adjacent(state.tokens.curr, state.tokens.next);
+ } else if (state.tokens.next.value === "set" && peek().id !== ":") {
advance("set");
- if (!option.es5) {
- error("get/set are ES5 features.");
+
+ if (!state.option.inES5(!isclassdef)) {
+ error("E034");
}
+
i = property_name();
if (!i) {
- error("Missing property name.");
+ error("E035");
}
- saveSetter(i, nexttoken);
- t = nexttoken;
- adjacent(token, nexttoken);
+ if (isclassdef && i === "constructor") {
+ error("E049", state.tokens.next, "class setter method", i);
+ }
+
+ saveSetter(tag + i, state.tokens.next);
+ t = state.tokens.next;
+ adjacent(state.tokens.curr, state.tokens.next);
f = doFunction();
p = f["(params)"];
+
if (!p || p.length !== 1) {
- warning("Expected a single parameter in set {a} function.", t, i);
+ warning("W077", t, i);
}
} else {
+ g = false;
+ if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.next, "generator functions");
+ }
+ advance("*");
+ g = true;
+ }
i = property_name();
- saveProperty(i, nexttoken);
+ saveProperty(tag + i, state.tokens.next);
+
if (typeof i !== "string") {
break;
}
- advance(":");
- nonadjacent(token, nexttoken);
- expression(10);
+
+ if (state.tokens.next.value === "(") {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "concise methods");
+ }
+ doFunction(i, undefined, g);
+ } else if (!isclassdef) {
+ advance(":");
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ expression(10);
+ }
+ }
+ if (isclassdef && i === "prototype") {
+ error("E049", state.tokens.next, "class method", i);
}
countMember(i);
- if (nexttoken.id === ",") {
- comma();
- if (nexttoken.id === ",") {
- warning("Extra comma.", token);
- } else if (nexttoken.id === "}" && !option.es5) {
- warning("Extra comma.", token);
+ if (isclassdef) {
+ tag = "";
+ continue;
+ }
+ if (state.tokens.next.id === ",") {
+ comma({ allowTrailing: true, property: true });
+ if (state.tokens.next.id === ",") {
+ warning("W070", state.tokens.curr);
+ } else if (state.tokens.next.id === "}" && !state.option.inES5(true)) {
+ warning("W070", state.tokens.curr);
}
} else {
break;
}
}
if (b) {
- indent -= option.indent;
+ indent -= state.option.indent;
indentation();
}
advance("}", this);
- if (option.es5) {
+ if (state.option.inES5()) {
for (var name in props) {
- if (is_own(props, name) && props[name].setter && !props[name].getter) {
- warning("Setter is defined without getter.", props[name].setterToken);
+ if (_.has(props, name) && props[name].setter && !props[name].getter) {
+ warning("W078", props[name].setterToken);
}
}
}
return this;
};
x.fud = function () {
- error("Expected to see a statement and instead saw a block.", token);
+ error("E036", state.tokens.curr);
};
}(delim("{")));
- useESNextSyntax = function () {
- var conststatement = stmt("const", function (prefix) {
- var id, name, value;
-
- this.first = [];
- for (;;) {
- nonadjacent(token, nexttoken);
- id = identifier();
- if (funct[id] === "const") {
- warning("const '" + id + "' has already been declared");
+ function destructuringExpression() {
+ var id, ids;
+ var identifiers = [];
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "destructuring expression");
+ }
+ var nextInnerDE = function () {
+ var ident;
+ if (_.contains(["[", "{"], state.tokens.next.value)) {
+ ids = destructuringExpression();
+ for (var id in ids) {
+ id = ids[id];
+ identifiers.push({ id: id.id, token: id.token });
}
- if (funct["(global)"] && predefined[id] === false) {
- warning("Redefinition of '{a}'.", token, id);
- }
- addlabel(id, "const");
- if (prefix) {
- break;
- }
- name = token;
- this.first.push(token);
-
- if (nexttoken.id !== "=") {
- warning("const " +
- "'{a}' is initialized to 'undefined'.", token, id);
- }
-
- if (nexttoken.id === "=") {
- nonadjacent(token, nexttoken);
- advance("=");
- nonadjacent(token, nexttoken);
- if (nexttoken.id === "undefined") {
- warning("It is not necessary to initialize " +
- "'{a}' to 'undefined'.", token, id);
- }
- if (peek(0).id === "=" && nexttoken.identifier) {
- error("Constant {a} was not declared correctly.",
- nexttoken, nexttoken.value);
- }
- value = expression(0);
- name.first = value;
- }
-
- if (nexttoken.id !== ",") {
- break;
- }
- comma();
+ } else if (state.tokens.next.value === ",") {
+ identifiers.push({ id: null, token: state.tokens.curr });
+ } else {
+ ident = identifier();
+ if (ident)
+ identifiers.push({ id: ident, token: state.tokens.curr });
}
- return this;
- });
- conststatement.exps = true;
- };
+ };
+ if (state.tokens.next.value === "[") {
+ advance("[");
+ nextInnerDE();
+ while (state.tokens.next.value !== "]") {
+ advance(",");
+ nextInnerDE();
+ }
+ advance("]");
+ } else if (state.tokens.next.value === "{") {
+ advance("{");
+ id = identifier();
+ if (state.tokens.next.value === ":") {
+ advance(":");
+ nextInnerDE();
+ } else {
+ identifiers.push({ id: id, token: state.tokens.curr });
+ }
+ while (state.tokens.next.value !== "}") {
+ advance(",");
+ id = identifier();
+ if (state.tokens.next.value === ":") {
+ advance(":");
+ nextInnerDE();
+ } else {
+ identifiers.push({ id: id, token: state.tokens.curr });
+ }
+ }
+ advance("}");
+ }
+ return identifiers;
+ }
+ function destructuringExpressionMatch(tokens, value) {
+ if (value.first) {
+ _.zip(tokens, value.first).forEach(function (val) {
+ var token = val[0];
+ var value = val[1];
+ if (token && value) {
+ token.first = value;
+ } else if (token && token.first && !value) {
+ warning("W080", token.first, token.first.value);
+ } /* else {
+ XXX value is discarded: wouldn't it need a warning ?
+ } */
+ });
+ }
+ }
+ var conststatement = stmt("const", function (prefix) {
+ var tokens, value;
+ var lone;
+
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "const");
+ }
+
+ this.first = [];
+ for (;;) {
+ var names = [];
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ if (_.contains(["{", "["], state.tokens.next.value)) {
+ tokens = destructuringExpression();
+ lone = false;
+ } else {
+ tokens = [ { id: identifier(), token: state.tokens.curr } ];
+ lone = true;
+ }
+ for (var t in tokens) {
+ t = tokens[t];
+ if (funct[t.id] === "const") {
+ warning("E011", null, t.id);
+ }
+ if (funct["(global)"] && predefined[t.id] === false) {
+ warning("W079", t.token, t.id);
+ }
+ if (t.id) {
+ addlabel(t.id, "const");
+ names.push(t.token);
+ }
+ }
+ if (prefix) {
+ break;
+ }
+
+ this.first = this.first.concat(names);
+
+ if (state.tokens.next.id !== "=") {
+ warning("E012", state.tokens.curr, state.tokens.curr.value);
+ }
+
+ if (state.tokens.next.id === "=") {
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ advance("=");
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ if (state.tokens.next.id === "undefined") {
+ warning("W080", state.tokens.prev, state.tokens.prev.value);
+ }
+ if (peek(0).id === "=" && state.tokens.next.identifier) {
+ error("E037", state.tokens.next, state.tokens.next.value);
+ }
+ value = expression(5);
+ if (lone) {
+ tokens[0].first = value;
+ } else {
+ destructuringExpressionMatch(names, value);
+ }
+ }
+
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
+ }
+ return this;
+ });
+ conststatement.exps = true;
var varstatement = stmt("var", function (prefix) {
- var id, name, value;
+ var tokens, lone, value;
- if (funct["(onevar)"] && option.onevar) {
- warning("Too many var statements.");
+ if (funct["(onevar)"] && state.option.onevar) {
+ warning("W081");
} else if (!funct["(global)"]) {
funct["(onevar)"] = true;
}
this.first = [];
-
for (;;) {
- nonadjacent(token, nexttoken);
- id = identifier();
-
- if (option.esnext && funct[id] === "const") {
- warning("const '" + id + "' has already been declared");
+ var names = [];
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ if (_.contains(["{", "["], state.tokens.next.value)) {
+ tokens = destructuringExpression();
+ lone = false;
+ } else {
+ tokens = [ { id: identifier(), token: state.tokens.curr } ];
+ lone = true;
}
-
- if (funct["(global)"] && predefined[id] === false) {
- warning("Redefinition of '{a}'.", token, id);
+ for (var t in tokens) {
+ t = tokens[t];
+ if (state.option.inESNext() && funct[t.id] === "const") {
+ warning("E011", null, t.id);
+ }
+ if (funct["(global)"] && predefined[t.id] === false) {
+ warning("W079", t.token, t.id);
+ }
+ if (t.id) {
+ addlabel(t.id, "unused", t.token);
+ names.push(t.token);
+ }
}
-
- addlabel(id, "unused", token);
-
if (prefix) {
break;
}
- name = token;
- this.first.push(token);
+ this.first = this.first.concat(names);
- if (nexttoken.id === "=") {
- nonadjacent(token, nexttoken);
+ if (state.tokens.next.id === "=") {
+ nonadjacent(state.tokens.curr, state.tokens.next);
advance("=");
- nonadjacent(token, nexttoken);
- if (nexttoken.id === "undefined") {
- warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id);
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ if (state.tokens.next.id === "undefined") {
+ warning("W080", state.tokens.prev, state.tokens.prev.value);
}
- if (peek(0).id === "=" && nexttoken.identifier) {
- error("Variable {a} was not declared correctly.",
- nexttoken, nexttoken.value);
+ if (peek(0).id === "=" && state.tokens.next.identifier) {
+ error("E038", state.tokens.next, state.tokens.next.value);
+ }
+ value = expression(5);
+ if (lone) {
+ tokens[0].first = value;
+ } else {
+ destructuringExpressionMatch(names, value);
}
- value = expression(0);
- name.first = value;
}
- if (nexttoken.id !== ",") {
+
+ if (state.tokens.next.id !== ",") {
break;
}
comma();
@@ -5498,63 +6090,190 @@ klass:
return this;
});
varstatement.exps = true;
+ var letstatement = stmt("let", function (prefix) {
+ var tokens, lone, value, letblock;
+
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "let");
+ }
+
+ if (state.tokens.next.value === "(") {
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.next, "let block");
+ }
+ advance("(");
+ funct["(blockscope)"].stack();
+ letblock = true;
+ } else if (funct["(nolet)"]) {
+ error("E048", state.tokens.curr);
+ }
+
+ if (funct["(onevar)"] && state.option.onevar) {
+ warning("W081");
+ } else if (!funct["(global)"]) {
+ funct["(onevar)"] = true;
+ }
+
+ this.first = [];
+ for (;;) {
+ var names = [];
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ if (_.contains(["{", "["], state.tokens.next.value)) {
+ tokens = destructuringExpression();
+ lone = false;
+ } else {
+ tokens = [ { id: identifier(), token: state.tokens.curr.value } ];
+ lone = true;
+ }
+ for (var t in tokens) {
+ t = tokens[t];
+ if (state.option.inESNext() && funct[t.id] === "const") {
+ warning("E011", null, t.id);
+ }
+ if (funct["(global)"] && predefined[t.id] === false) {
+ warning("W079", t.token, t.id);
+ }
+ if (t.id && !funct["(nolet)"]) {
+ addlabel(t.id, "unused", t.token, true);
+ names.push(t.token);
+ }
+ }
+ if (prefix) {
+ break;
+ }
+
+ this.first = this.first.concat(names);
+
+ if (state.tokens.next.id === "=") {
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ advance("=");
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ if (state.tokens.next.id === "undefined") {
+ warning("W080", state.tokens.prev, state.tokens.prev.value);
+ }
+ if (peek(0).id === "=" && state.tokens.next.identifier) {
+ error("E037", state.tokens.next, state.tokens.next.value);
+ }
+ value = expression(5);
+ if (lone) {
+ tokens[0].first = value;
+ } else {
+ destructuringExpressionMatch(names, value);
+ }
+ }
+
+ if (state.tokens.next.id !== ",") {
+ break;
+ }
+ comma();
+ }
+ if (letblock) {
+ advance(")");
+ block(true, true);
+ this.block = true;
+ funct["(blockscope)"].unstack();
+ }
+
+ return this;
+ });
+ letstatement.exps = true;
+
+ blockstmt("class", function () {
+ return classdef.call(this, true);
+ });
+
+ function classdef(stmt) {
+ if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "class");
+ }
+ if (stmt) {
+ this.name = identifier();
+ addlabel(this.name, "unused", state.tokens.curr);
+ } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
+ this.name = identifier();
+ }
+ classtail(this);
+ return this;
+ }
+
+ function classtail(c) {
+ var strictness = state.directive["use strict"];
+ if (state.tokens.next.value === "extends") {
+ advance("extends");
+ c.heritage = expression(10);
+ }
+ state.directive["use strict"] = true;
+ advance("{");
+ c.body = state.syntax["{"].nud(true);
+ state.directive["use strict"] = strictness;
+ }
blockstmt("function", function () {
+ var generator = false;
+ if (state.tokens.next.value === "*") {
+ advance("*");
+ if (state.option.inESNext(true)) {
+ generator = true;
+ } else {
+ warning("W119", state.tokens.curr, "function*");
+ }
+ }
if (inblock) {
- warning("Function declarations should not be placed in blocks. " +
- "Use a function expression or move the statement to the top of " +
- "the outer function.", token);
+ warning("W082", state.tokens.curr);
}
var i = identifier();
- if (option.esnext && funct[i] === "const") {
- warning("const '" + i + "' has already been declared");
+ if (funct[i] === "const") {
+ warning("E011", null, i);
}
- adjacent(token, nexttoken);
- addlabel(i, "unction", token);
+ adjacent(state.tokens.curr, state.tokens.next);
+ addlabel(i, "unction", state.tokens.curr);
- doFunction(i, { statement: true });
- if (nexttoken.id === "(" && nexttoken.line === token.line) {
- error(
-"Function declarations are not invocable. Wrap the whole function invocation in parens.");
+ doFunction(i, { statement: true }, generator);
+ if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) {
+ error("E039");
}
return this;
});
prefix("function", function () {
- var i = optionalidentifier();
- if (i) {
- adjacent(token, nexttoken);
- } else {
- nonadjacent(token, nexttoken);
+ var generator = false;
+ if (state.tokens.next.value === "*") {
+ if (!state.option.inESNext()) {
+ warning("W119", state.tokens.curr, "function*");
+ }
+ advance("*");
+ generator = true;
}
- doFunction(i);
- if (!option.loopfunc && funct["(loopage)"]) {
- warning("Don't make functions within a loop.");
+ var i = optionalidentifier();
+ if (i || state.option.gcl) {
+ adjacent(state.tokens.curr, state.tokens.next);
+ } else {
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ }
+ doFunction(i, undefined, generator);
+ if (!state.option.loopfunc && funct["(loopage)"]) {
+ warning("W083");
}
return this;
});
blockstmt("if", function () {
- var t = nexttoken;
+ var t = state.tokens.next;
increaseComplexityCount();
+ state.condition = true;
advance("(");
nonadjacent(this, t);
nospace();
- expression(20);
- if (nexttoken.id === "=") {
- if (!option.boss)
- warning("Assignment in conditional expression");
- advance("=");
- expression(20);
- }
+ checkCondAssignment(expression(0));
advance(")", t);
- nospace(prevtoken, token);
+ state.condition = false;
+ nospace(state.tokens.prev, state.tokens.curr);
block(true, true);
- if (nexttoken.id === "else") {
- nonadjacent(token, nexttoken);
+ if (state.tokens.next.id === "else") {
+ nonadjacent(state.tokens.curr, state.tokens.next);
advance("else");
- if (nexttoken.id === "if" || nexttoken.id === "switch") {
+ if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
statement(true);
} else {
block(true, true);
@@ -5571,87 +6290,96 @@ klass:
var e;
advance("catch");
- nonadjacent(token, nexttoken);
+ nonadjacent(state.tokens.curr, state.tokens.next);
advance("(");
scope = Object.create(oldScope);
- e = nexttoken.value;
- if (nexttoken.type !== "(identifier)") {
+ e = state.tokens.next.value;
+ if (state.tokens.next.type !== "(identifier)") {
e = null;
- warning("Expected an identifier and instead saw '{a}'.", nexttoken, e);
+ warning("E030", state.tokens.next, e);
}
advance();
- advance(")");
funct = {
- "(name)" : "(catch)",
- "(line)" : nexttoken.line,
- "(character)": nexttoken.character,
+ "(name)" : "(catch)",
+ "(line)" : state.tokens.next.line,
+ "(character)": state.tokens.next.character,
"(context)" : funct,
"(breakage)" : funct["(breakage)"],
"(loopage)" : funct["(loopage)"],
- "(scope)" : scope,
+ "(scope)" : scope,
"(statement)": false,
- "(metrics)" : createMetrics(nexttoken),
- "(catch)" : true,
- "(tokens)" : {}
+ "(metrics)" : createMetrics(state.tokens.next),
+ "(catch)" : true,
+ "(tokens)" : {},
+ "(blockscope)": funct["(blockscope)"],
+ "(comparray)": funct["(comparray)"]
};
if (e) {
addlabel(e, "exception");
}
- token.funct = funct;
+ if (state.tokens.next.value === "if") {
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.curr, "catch filter");
+ }
+ advance("if");
+ expression(0);
+ }
+
+ advance(")");
+
+ state.tokens.curr.funct = funct;
functions.push(funct);
block(false);
scope = oldScope;
- funct["(last)"] = token.line;
- funct["(lastcharacter)"] = token.character;
+ funct["(last)"] = state.tokens.curr.line;
+ funct["(lastcharacter)"] = state.tokens.curr.character;
funct = funct["(context)"];
}
block(false);
- if (nexttoken.id === "catch") {
+ while (state.tokens.next.id === "catch") {
increaseComplexityCount();
+ if (b && (!state.option.inMoz(true))) {
+ warning("W118", state.tokens.next, "multiple catch blocks");
+ }
doCatch();
b = true;
}
- if (nexttoken.id === "finally") {
+ if (state.tokens.next.id === "finally") {
advance("finally");
block(false);
return;
- } else if (!b) {
- error("Expected '{a}' and instead saw '{b}'.",
- nexttoken, "catch", nexttoken.value);
+ }
+
+ if (!b) {
+ error("E021", state.tokens.next, "catch", state.tokens.next.value);
}
return this;
});
blockstmt("while", function () {
- var t = nexttoken;
+ var t = state.tokens.next;
funct["(breakage)"] += 1;
funct["(loopage)"] += 1;
increaseComplexityCount();
advance("(");
nonadjacent(this, t);
nospace();
- expression(20);
- if (nexttoken.id === "=") {
- if (!option.boss)
- warning("Assignment in conditional expression");
- advance("=");
- expression(20);
- }
+ checkCondAssignment(expression(0));
advance(")", t);
- nospace(prevtoken, token);
+ nospace(state.tokens.prev, state.tokens.curr);
block(true, true);
funct["(breakage)"] -= 1;
funct["(loopage)"] -= 1;
@@ -5659,11 +6387,11 @@ klass:
}).labelled = true;
blockstmt("with", function () {
- var t = nexttoken;
- if (directive["use strict"]) {
- error("'with' is not allowed in strict mode.", token);
- } else if (!option.withstmt) {
- warning("Don't use 'with'.", token);
+ var t = state.tokens.next;
+ if (state.directive["use strict"]) {
+ error("E010", state.tokens.curr);
+ } else if (!state.option.withstmt) {
+ warning("W085", state.tokens.curr);
}
advance("(");
@@ -5671,32 +6399,34 @@ klass:
nospace();
expression(0);
advance(")", t);
- nospace(prevtoken, token);
+ nospace(state.tokens.prev, state.tokens.curr);
block(true, true);
return this;
});
blockstmt("switch", function () {
- var t = nexttoken,
+ var t = state.tokens.next,
g = false;
funct["(breakage)"] += 1;
advance("(");
nonadjacent(this, t);
nospace();
- this.condition = expression(20);
+ checkCondAssignment(expression(0));
advance(")", t);
- nospace(prevtoken, token);
- nonadjacent(token, nexttoken);
- t = nexttoken;
+ nospace(state.tokens.prev, state.tokens.curr);
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ t = state.tokens.next;
advance("{");
- nonadjacent(token, nexttoken);
- indent += option.indent;
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ indent += state.option.indent;
this.cases = [];
+
for (;;) {
- switch (nexttoken.id) {
+ switch (state.tokens.next.id) {
case "case":
switch (funct["(verb)"]) {
+ case "yield":
case "break":
case "case":
case "continue":
@@ -5705,13 +6435,11 @@ klass:
case "throw":
break;
default:
- if (!ft.test(lines[nexttoken.line - 2])) {
- warning(
- "Expected a 'break' statement before 'case'.",
- token);
+ if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
+ warning("W086", state.tokens.curr, "case");
}
}
- indentation(-option.indent);
+ indentation(-state.option.indent);
advance("case");
this.cases.push(expression(20));
increaseComplexityCount();
@@ -5721,60 +6449,55 @@ klass:
break;
case "default":
switch (funct["(verb)"]) {
+ case "yield":
case "break":
case "continue":
case "return":
case "throw":
break;
default:
- if (!ft.test(lines[nexttoken.line - 2])) {
- warning(
- "Expected a 'break' statement before 'default'.",
- token);
+ if (this.cases.length) {
+ if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
+ warning("W086", state.tokens.curr, "default");
+ }
}
}
- indentation(-option.indent);
+ indentation(-state.option.indent);
advance("default");
g = true;
advance(":");
break;
case "}":
- indent -= option.indent;
+ indent -= state.option.indent;
indentation();
advance("}", t);
- if (this.cases.length === 1 || this.condition.id === "true" ||
- this.condition.id === "false") {
- if (!option.onecase)
- warning("This 'switch' should be an 'if'.", this);
- }
funct["(breakage)"] -= 1;
funct["(verb)"] = undefined;
return;
case "(end)":
- error("Missing '{a}'.", nexttoken, "}");
+ error("E023", state.tokens.next, "}");
return;
default:
if (g) {
- switch (token.id) {
+ switch (state.tokens.curr.id) {
case ",":
- error("Each value should have its own case label.");
+ error("E040");
return;
case ":":
g = false;
statements();
break;
default:
- error("Missing ':' on a case clause.", token);
+ error("E025", state.tokens.curr);
return;
}
} else {
- if (token.id === ":") {
+ if (state.tokens.curr.id === ":") {
advance(":");
- error("Unexpected '{a}'.", token, ":");
+ error("E024", state.tokens.curr, ":");
statements();
} else {
- error("Expected '{a}' and instead saw '{b}'.",
- nexttoken, "case", nexttoken.value);
+ error("E021", state.tokens.next, "case", state.tokens.next.value);
return;
}
}
@@ -5783,8 +6506,8 @@ klass:
}).labelled = true;
stmt("debugger", function () {
- if (!option.debug) {
- warning("All 'debugger' statements should be removed.");
+ if (!state.option.debug) {
+ warning("W087");
}
return this;
}).exps = true;
@@ -5795,21 +6518,15 @@ klass:
funct["(loopage)"] += 1;
increaseComplexityCount();
- this.first = block(true);
+ this.first = block(true, true);
advance("while");
- var t = nexttoken;
- nonadjacent(token, t);
+ var t = state.tokens.next;
+ nonadjacent(state.tokens.curr, t);
advance("(");
nospace();
- expression(20);
- if (nexttoken.id === "=") {
- if (!option.boss)
- warning("Assignment in conditional expression");
- advance("=");
- expression(20);
- }
+ checkCondAssignment(expression(0));
advance(")", t);
- nospace(prevtoken, token);
+ nospace(state.tokens.prev, state.tokens.curr);
funct["(breakage)"] -= 1;
funct["(loopage)"] -= 1;
return this;
@@ -5819,110 +6536,140 @@ klass:
}());
blockstmt("for", function () {
- var s, t = nexttoken;
+ var s, t = state.tokens.next;
+ var letscope = false;
+ var foreachtok = null;
+
+ if (t.value === "each") {
+ foreachtok = t;
+ advance("each");
+ if (!state.option.inMoz(true)) {
+ warning("W118", state.tokens.curr, "for each");
+ }
+ }
+
funct["(breakage)"] += 1;
funct["(loopage)"] += 1;
increaseComplexityCount();
advance("(");
nonadjacent(this, t);
nospace();
- if (peek(nexttoken.id === "var" ? 1 : 0).id === "in") {
- if (nexttoken.id === "var") {
+ var nextop; // contains the token of the "in" or "of" operator
+ var i = 0;
+ var inof = ["in", "of"];
+ do {
+ nextop = peek(i);
+ ++i;
+ } while (!_.contains(inof, nextop.value) && nextop.value !== ";" &&
+ nextop.type !== "(end)");
+ if (_.contains(inof, nextop.value)) {
+ if (!state.option.inESNext() && nextop.value === "of") {
+ error("W104", nextop, "for of");
+ }
+ if (state.tokens.next.id === "var") {
advance("var");
- varstatement.fud.call(varstatement, true);
+ state.syntax["var"].fud.call(state.syntax["var"].fud, true);
+ } else if (state.tokens.next.id === "let") {
+ advance("let");
+ letscope = true;
+ funct["(blockscope)"].stack();
+ state.syntax["let"].fud.call(state.syntax["let"].fud, true);
} else {
- switch (funct[nexttoken.value]) {
+ switch (funct[state.tokens.next.value]) {
case "unused":
- funct[nexttoken.value] = "var";
+ funct[state.tokens.next.value] = "var";
break;
case "var":
break;
default:
- warning("Bad for in variable '{a}'.",
- nexttoken, nexttoken.value);
+ if (!funct["(blockscope)"].getlabel(state.tokens.next.value))
+ warning("W088", state.tokens.next, state.tokens.next.value);
}
advance();
}
- advance("in");
+ advance(nextop.value);
expression(20);
advance(")", t);
s = block(true, true);
- if (option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
+ if (state.option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
s[0].value !== "if")) {
- warning("The body of a for in should be wrapped in an if statement to filter " +
- "unwanted properties from the prototype.", this);
+ warning("W089", this);
}
funct["(breakage)"] -= 1;
funct["(loopage)"] -= 1;
- return this;
} else {
- if (nexttoken.id !== ";") {
- if (nexttoken.id === "var") {
+ if (foreachtok) {
+ error("E045", foreachtok);
+ }
+ if (state.tokens.next.id !== ";") {
+ if (state.tokens.next.id === "var") {
advance("var");
- varstatement.fud.call(varstatement);
+ state.syntax["var"].fud.call(state.syntax["var"].fud);
+ } else if (state.tokens.next.id === "let") {
+ advance("let");
+ letscope = true;
+ funct["(blockscope)"].stack();
+ state.syntax["let"].fud.call(state.syntax["let"].fud);
} else {
for (;;) {
expression(0, "for");
- if (nexttoken.id !== ",") {
+ if (state.tokens.next.id !== ",") {
break;
}
comma();
}
}
}
- nolinebreak(token);
+ nolinebreak(state.tokens.curr);
advance(";");
- if (nexttoken.id !== ";") {
- expression(20);
- if (nexttoken.id === "=") {
- if (!option.boss)
- warning("Assignment in conditional expression");
- advance("=");
- expression(20);
- }
+ if (state.tokens.next.id !== ";") {
+ checkCondAssignment(expression(0));
}
- nolinebreak(token);
+ nolinebreak(state.tokens.curr);
advance(";");
- if (nexttoken.id === ";") {
- error("Expected '{a}' and instead saw '{b}'.",
- nexttoken, ")", ";");
+ if (state.tokens.next.id === ";") {
+ error("E021", state.tokens.next, ")", ";");
}
- if (nexttoken.id !== ")") {
+ if (state.tokens.next.id !== ")") {
for (;;) {
expression(0, "for");
- if (nexttoken.id !== ",") {
+ if (state.tokens.next.id !== ",") {
break;
}
comma();
}
}
advance(")", t);
- nospace(prevtoken, token);
+ nospace(state.tokens.prev, state.tokens.curr);
block(true, true);
funct["(breakage)"] -= 1;
funct["(loopage)"] -= 1;
- return this;
+
}
+ if (letscope) {
+ funct["(blockscope)"].unstack();
+ }
+ return this;
}).labelled = true;
stmt("break", function () {
- var v = nexttoken.value;
+ var v = state.tokens.next.value;
if (funct["(breakage)"] === 0)
- warning("Unexpected '{a}'.", nexttoken, this.value);
+ warning("W052", state.tokens.next, this.value);
- if (!option.asi)
+ if (!state.option.asi)
nolinebreak(this);
- if (nexttoken.id !== ";") {
- if (token.line === nexttoken.line) {
+ if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
+ if (state.tokens.curr.line === state.tokens.next.line) {
if (funct[v] !== "label") {
- warning("'{a}' is not a statement label.", nexttoken, v);
+ warning("W090", state.tokens.next, v);
} else if (scope[v] !== funct) {
- warning("'{a}' is out of scope.", nexttoken, v);
+ warning("W091", state.tokens.next, v);
}
- this.first = nexttoken;
+ this.first = state.tokens.next;
advance();
}
}
@@ -5932,26 +6679,26 @@ klass:
stmt("continue", function () {
- var v = nexttoken.value;
+ var v = state.tokens.next.value;
if (funct["(breakage)"] === 0)
- warning("Unexpected '{a}'.", nexttoken, this.value);
+ warning("W052", state.tokens.next, this.value);
- if (!option.asi)
+ if (!state.option.asi)
nolinebreak(this);
- if (nexttoken.id !== ";") {
- if (token.line === nexttoken.line) {
+ if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
+ if (state.tokens.curr.line === state.tokens.next.line) {
if (funct[v] !== "label") {
- warning("'{a}' is not a statement label.", nexttoken, v);
+ warning("W090", state.tokens.next, v);
} else if (scope[v] !== funct) {
- warning("'{a}' is out of scope.", nexttoken, v);
+ warning("W091", state.tokens.next, v);
}
- this.first = nexttoken;
+ this.first = state.tokens.next;
advance();
}
} else if (!funct["(loopage)"]) {
- warning("Unexpected '{a}'.", nexttoken, this.value);
+ warning("W052", state.tokens.next, this.value);
}
reachable("continue");
return this;
@@ -5959,86 +6706,248 @@ klass:
stmt("return", function () {
- if (this.line === nexttoken.line) {
- if (nexttoken.id === "(regexp)")
- warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");
+ if (this.line === state.tokens.next.line) {
+ if (state.tokens.next.id === "(regexp)")
+ warning("W092");
- if (nexttoken.id !== ";" && !nexttoken.reach) {
- nonadjacent(token, nexttoken);
- if (peek().value === "=" && !option.boss) {
- warningAt("Did you mean to return a conditional instead of an assignment?",
- token.line, token.character + 1);
- }
+ if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
+ nonadjacent(state.tokens.curr, state.tokens.next);
this.first = expression(0);
+
+ if (this.first &&
+ this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
+ warningAt("W093", this.first.line, this.first.character);
+ }
+ }
+ } else {
+ if (state.tokens.next.type === "(punctuator)" &&
+ ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) {
+ nolinebreak(this); // always warn (Line breaking error)
}
- } else if (!option.asi) {
- nolinebreak(this); // always warn (Line breaking error)
}
reachable("return");
return this;
}).exps = true;
+ stmt("yield", function () {
+ if (state.option.inESNext(true) && funct["(generator)"] !== true) {
+ error("E046", state.tokens.curr, "yield");
+ } else if (!state.option.inESNext()) {
+ warning("W104", state.tokens.curr, "yield");
+ }
+ funct["(generator)"] = "yielded";
+ if (this.line === state.tokens.next.line) {
+ if (state.tokens.next.id === "(regexp)")
+ warning("W092");
+
+ if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
+ nonadjacent(state.tokens.curr, state.tokens.next);
+ this.first = expression(0);
+
+ if (this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
+ warningAt("W093", this.first.line, this.first.character);
+ }
+ }
+ } else if (!state.option.asi) {
+ nolinebreak(this); // always warn (Line breaking error)
+ }
+ return this;
+ }).exps = true;
+
stmt("throw", function () {
nolinebreak(this);
- nonadjacent(token, nexttoken);
+ nonadjacent(state.tokens.curr, state.tokens.next);
this.first = expression(20);
reachable("throw");
return this;
}).exps = true;
- reserve("class");
- reserve("const");
- reserve("enum");
- reserve("export");
- reserve("extends");
- reserve("import");
- reserve("super");
+ FutureReservedWord("abstract");
+ FutureReservedWord("boolean");
+ FutureReservedWord("byte");
+ FutureReservedWord("char");
+ FutureReservedWord("class", { es5: true, nud: classdef });
+ FutureReservedWord("double");
+ FutureReservedWord("enum", { es5: true });
+ FutureReservedWord("export", { es5: true });
+ FutureReservedWord("extends", { es5: true });
+ FutureReservedWord("final");
+ FutureReservedWord("float");
+ FutureReservedWord("goto");
+ FutureReservedWord("implements", { es5: true, strictOnly: true });
+ FutureReservedWord("import", { es5: true });
+ FutureReservedWord("int");
+ FutureReservedWord("interface", { es5: true, strictOnly: true });
+ FutureReservedWord("long");
+ FutureReservedWord("native");
+ FutureReservedWord("package", { es5: true, strictOnly: true });
+ FutureReservedWord("private", { es5: true, strictOnly: true });
+ FutureReservedWord("protected", { es5: true, strictOnly: true });
+ FutureReservedWord("public", { es5: true, strictOnly: true });
+ FutureReservedWord("short");
+ FutureReservedWord("static", { es5: true, strictOnly: true });
+ FutureReservedWord("super", { es5: true });
+ FutureReservedWord("synchronized");
+ FutureReservedWord("throws");
+ FutureReservedWord("transient");
+ FutureReservedWord("volatile");
- reserve("let");
- reserve("yield");
- reserve("implements");
- reserve("interface");
- reserve("package");
- reserve("private");
- reserve("protected");
- reserve("public");
- reserve("static");
+ var lookupBlockType = function () {
+ var pn, pn1;
+ var i = 0;
+ var bracketStack = 0;
+ var ret = {};
+ if (_.contains(["[", "{"], state.tokens.curr.value))
+ bracketStack += 1;
+ if (_.contains(["[", "{"], state.tokens.next.value))
+ bracketStack += 1;
+ if (_.contains(["]", "}"], state.tokens.next.value))
+ bracketStack -= 1;
+ do {
+ pn = peek(i);
+ pn1 = peek(i + 1);
+ i = i + 1;
+ if (_.contains(["[", "{"], pn.value)) {
+ bracketStack += 1;
+ } else if (_.contains(["]", "}"], pn.value)) {
+ bracketStack -= 1;
+ }
+ if (pn.identifier && pn.value === "for" && bracketStack === 1) {
+ ret.isCompArray = true;
+ ret.notJson = true;
+ break;
+ }
+ if (_.contains(["}", "]"], pn.value) && pn1.value === "=") {
+ ret.isDestAssign = true;
+ ret.notJson = true;
+ break;
+ }
+ if (pn.value === ";") {
+ ret.isBlock = true;
+ ret.notJson = true;
+ }
+ } while (bracketStack > 0 && pn.id !== "(end)" && i < 15);
+ return ret;
+ };
+ function destructuringAssignOrJsonValue() {
+
+ var block = lookupBlockType();
+ if (block.notJson) {
+ if (!state.option.inESNext() && block.isDestAssign) {
+ warning("W104", state.tokens.curr, "destructuring assignment");
+ }
+ statements();
+ } else {
+ state.option.laxbreak = true;
+ state.jsonMode = true;
+ jsonValue();
+ }
+ }
+
+ var arrayComprehension = function () {
+ var CompArray = function () {
+ this.mode = "use";
+ this.variables = [];
+ };
+ var _carrays = [];
+ var _current;
+ function declare(v) {
+ var l = _current.variables.filter(function (elt) {
+ if (elt.value === v) {
+ elt.undef = false;
+ return v;
+ }
+ }).length;
+ return l !== 0;
+ }
+ function use(v) {
+ var l = _current.variables.filter(function (elt) {
+ if (elt.value === v && !elt.undef) {
+ if (elt.unused === true) {
+ elt.unused = false;
+ }
+ return v;
+ }
+ }).length;
+ return (l === 0);
+ }
+ return {stack: function () {
+ _current = new CompArray();
+ _carrays.push(_current);
+ },
+ unstack: function () {
+ _current.variables.filter(function (v) {
+ if (v.unused)
+ warning("W098", v.token, v.value);
+ if (v.undef)
+ isundef(v.funct, "W117", v.token, v.value);
+ });
+ _carrays.splice(_carrays[_carrays.length - 1], 1);
+ _current = _carrays[_carrays.length - 1];
+ },
+ setState: function (s) {
+ if (_.contains(["use", "define", "filter"], s))
+ _current.mode = s;
+ },
+ check: function (v) {
+ if (_current && _current.mode === "use") {
+ _current.variables.push({funct: funct,
+ token: state.tokens.curr,
+ value: v,
+ undef: true,
+ unused: false});
+ return true;
+ } else if (_current && _current.mode === "define") {
+ if (!declare(v)) {
+ _current.variables.push({funct: funct,
+ token: state.tokens.curr,
+ value: v,
+ undef: false,
+ unused: true});
+ }
+ return true;
+ } else if (_current && _current.mode === "filter") {
+ if (use(v)) {
+ isundef(funct, "W117", state.tokens.curr, v);
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+ };
function jsonValue() {
function jsonObject() {
- var o = {}, t = nexttoken;
+ var o = {}, t = state.tokens.next;
advance("{");
- if (nexttoken.id !== "}") {
+ if (state.tokens.next.id !== "}") {
for (;;) {
- if (nexttoken.id === "(end)") {
- error("Missing '}' to match '{' from line {a}.",
- nexttoken, t.line);
- } else if (nexttoken.id === "}") {
- warning("Unexpected comma.", token);
+ if (state.tokens.next.id === "(end)") {
+ error("E026", state.tokens.next, t.line);
+ } else if (state.tokens.next.id === "}") {
+ warning("W094", state.tokens.curr);
break;
- } else if (nexttoken.id === ",") {
- error("Unexpected comma.", nexttoken);
- } else if (nexttoken.id !== "(string)") {
- warning("Expected a string and instead saw {a}.",
- nexttoken, nexttoken.value);
+ } else if (state.tokens.next.id === ",") {
+ error("E028", state.tokens.next);
+ } else if (state.tokens.next.id !== "(string)") {
+ warning("W095", state.tokens.next, state.tokens.next.value);
}
- if (o[nexttoken.value] === true) {
- warning("Duplicate key '{a}'.",
- nexttoken, nexttoken.value);
- } else if ((nexttoken.value === "__proto__" &&
- !option.proto) || (nexttoken.value === "__iterator__" &&
- !option.iterator)) {
- warning("The '{a}' key may produce unexpected results.",
- nexttoken, nexttoken.value);
+ if (o[state.tokens.next.value] === true) {
+ warning("W075", state.tokens.next, state.tokens.next.value);
+ } else if ((state.tokens.next.value === "__proto__" &&
+ !state.option.proto) || (state.tokens.next.value === "__iterator__" &&
+ !state.option.iterator)) {
+ warning("W096", state.tokens.next, state.tokens.next.value);
} else {
- o[nexttoken.value] = true;
+ o[state.tokens.next.value] = true;
}
advance();
advance(":");
jsonValue();
- if (nexttoken.id !== ",") {
+ if (state.tokens.next.id !== ",") {
break;
}
advance(",");
@@ -6048,21 +6957,20 @@ klass:
}
function jsonArray() {
- var t = nexttoken;
+ var t = state.tokens.next;
advance("[");
- if (nexttoken.id !== "]") {
+ if (state.tokens.next.id !== "]") {
for (;;) {
- if (nexttoken.id === "(end)") {
- error("Missing ']' to match '[' from line {a}.",
- nexttoken, t.line);
- } else if (nexttoken.id === "]") {
- warning("Unexpected comma.", token);
+ if (state.tokens.next.id === "(end)") {
+ error("E027", state.tokens.next, t.line);
+ } else if (state.tokens.next.id === "]") {
+ warning("W094", state.tokens.curr);
break;
- } else if (nexttoken.id === ",") {
- error("Unexpected comma.", nexttoken);
+ } else if (state.tokens.next.id === ",") {
+ error("E028", state.tokens.next);
}
jsonValue();
- if (nexttoken.id !== ",") {
+ if (state.tokens.next.id !== ",") {
break;
}
advance(",");
@@ -6071,7 +6979,7 @@ klass:
advance("]");
}
- switch (nexttoken.id) {
+ switch (state.tokens.next.id) {
case "{":
jsonObject();
break;
@@ -6087,20 +6995,72 @@ klass:
break;
case "-":
advance("-");
- if (token.character !== nexttoken.from) {
- warning("Unexpected space after '-'.", token);
+ if (state.tokens.curr.character !== state.tokens.next.from) {
+ warning("W011", state.tokens.curr);
}
- adjacent(token, nexttoken);
+ adjacent(state.tokens.curr, state.tokens.next);
advance("(number)");
break;
default:
- error("Expected a JSON value.", nexttoken);
+ error("E003", state.tokens.next);
}
}
+
+ var blockScope = function () {
+ var _current = {};
+ var _variables = [_current];
+
+ function _checkBlockLabels() {
+ for (var t in _current) {
+ if (_current[t]["(type)"] === "unused") {
+ if (state.option.unused) {
+ var tkn = _current[t]["(token)"];
+ var line = tkn.line;
+ var chr = tkn.character;
+ warningAt("W098", line, chr, t);
+ }
+ }
+ }
+ }
+
+ return {
+ stack: function () {
+ _current = {};
+ _variables.push(_current);
+ },
+
+ unstack: function () {
+ _checkBlockLabels();
+ _variables.splice(_variables.length - 1, 1);
+ _current = _.last(_variables);
+ },
+
+ getlabel: function (l) {
+ for (var i = _variables.length - 1 ; i >= 0; --i) {
+ if (_.has(_variables[i], l)) {
+ return _variables[i];
+ }
+ }
+ },
+
+ current: {
+ has: function (t) {
+ return _.has(_current, t);
+ },
+ add: function (t, type, tok) {
+ _current[t] = { "(type)" : type,
+ "(token)": tok };
+ }
+ }
+ };
+ };
var itself = function (s, o, g) {
- var a, i, k, x;
+ var i, k, x;
var optionKeys;
var newOptionObj = {};
+ var newIgnoredObj = {};
+
+ state.reset();
if (o && o.scope) {
JSHINT.scope = o.scope;
@@ -6112,48 +7072,67 @@ klass:
JSHINT.scope = "(main)";
}
- predefined = Object.create(standard);
- declared = Object.create(null);
+ predefined = Object.create(null);
+ combine(predefined, vars.ecmaIdentifiers);
+ combine(predefined, vars.reservedVars);
+
combine(predefined, g || {});
+ declared = Object.create(null);
+ exported = Object.create(null);
+
+ function each(obj, cb) {
+ if (!obj)
+ return;
+
+ if (!Array.isArray(obj) && typeof obj === "object")
+ obj = Object.keys(obj);
+
+ obj.forEach(cb);
+ }
+
if (o) {
- a = o.predef;
- if (a) {
- if (!Array.isArray(a) && typeof a === "object") {
- a = Object.keys(a);
+ each(o.predef || null, function (item) {
+ var slice, prop;
+
+ if (item[0] === "-") {
+ slice = item.slice(1);
+ JSHINT.blacklist[slice] = slice;
+ } else {
+ prop = Object.getOwnPropertyDescriptor(o.predef, item);
+ predefined[item] = prop ? prop.value : false;
}
- a.forEach(function (item) {
- var slice;
- if (item[0] === "-") {
- slice = item.slice(1);
- JSHINT.blacklist[slice] = slice;
- } else {
- predefined[item] = true;
- }
- });
- }
+ });
+
+ each(o.exported || null, function (item) {
+ exported[item] = true;
+ });
+
+ delete o.predef;
+ delete o.exported;
optionKeys = Object.keys(o);
for (x = 0; x < optionKeys.length; x++) {
- newOptionObj[optionKeys[x]] = o[optionKeys[x]];
+ if (/^-W\d{3}$/g.test(optionKeys[x])) {
+ newIgnoredObj[optionKeys[x].slice(1)] = true;
+ } else {
+ newOptionObj[optionKeys[x]] = o[optionKeys[x]];
- if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
- newOptionObj["(explicitNewcap)"] = true;
+ if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
+ newOptionObj["(explicitNewcap)"] = true;
- if (optionKeys[x] === "indent")
- newOptionObj.white = true;
+ if (optionKeys[x] === "indent")
+ newOptionObj["(explicitIndent)"] = o[optionKeys[x]] === false ? false : true;
+ }
}
}
- option = newOptionObj;
+ state.option = newOptionObj;
+ state.ignored = newIgnoredObj;
- option.indent = option.indent || 4;
- option.maxerr = option.maxerr || 50;
+ state.option.indent = state.option.indent || 4;
+ state.option.maxerr = state.option.maxerr || 50;
- tab = "";
- for (i = 0; i < option.indent; i += 1) {
- tab += " ";
- }
indent = 1;
global = Object.create(predefined);
scope = global;
@@ -6164,7 +7143,9 @@ klass:
"(breakage)": 0,
"(loopage)": 0,
"(tokens)": {},
- "(metrics)": createMetrics(nexttoken)
+ "(metrics)": createMetrics(state.tokens.next),
+ "(blockscope)": blockScope(),
+ "(comparray)": arrayComprehension()
};
functions = [funct];
urls = [];
@@ -6174,61 +7155,106 @@ klass:
implied = {};
inblock = false;
lookahead = [];
- jsonmode = false;
warnings = 0;
- lines = [];
unuseds = [];
if (!isString(s) && !Array.isArray(s)) {
- errorAt("Input is neither a string nor an array of strings.", 0);
+ errorAt("E004", 0);
return false;
}
- if (isString(s) && /^\s*$/g.test(s)) {
- errorAt("Input is an empty string.", 0);
- return false;
- }
+ api = {
+ get isJSON() {
+ return state.jsonMode;
+ },
- if (s.length === 0) {
- errorAt("Input is an empty array.", 0);
- return false;
- }
+ getOption: function (name) {
+ return state.option[name] || null;
+ },
- lex.init(s);
+ getCache: function (name) {
+ return state.cache[name];
+ },
- prereg = true;
- directive = {};
+ setCache: function (name, value) {
+ state.cache[name] = value;
+ },
- prevtoken = token = nexttoken = syntax["(begin)"];
+ warn: function (code, data) {
+ warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));
+ },
+
+ on: function (names, listener) {
+ names.split(" ").forEach(function (name) {
+ emitter.on(name, listener);
+ }.bind(this));
+ }
+ };
+
+ emitter.removeAllListeners();
+ (extraModules || []).forEach(function (func) {
+ func(api);
+ });
+
+ state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];
+
+ lex = new Lexer(s);
+
+ lex.on("warning", function (ev) {
+ warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));
+ });
+
+ lex.on("error", function (ev) {
+ errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));
+ });
+
+ lex.on("fatal", function (ev) {
+ quit("E041", ev.line, ev.from);
+ });
+
+ lex.on("Identifier", function (ev) {
+ emitter.emit("Identifier", ev);
+ });
+
+ lex.on("String", function (ev) {
+ emitter.emit("String", ev);
+ });
+
+ lex.on("Number", function (ev) {
+ emitter.emit("Number", ev);
+ });
+
+ lex.start();
for (var name in o) {
- if (is_own(o, name)) {
- checkOption(name, token);
+ if (_.has(o, name)) {
+ checkOption(name, state.tokens.curr);
}
}
assume();
combine(predefined, g || {});
comma.first = true;
- quotmark = undefined;
try {
advance();
- switch (nexttoken.id) {
+ switch (state.tokens.next.id) {
case "{":
case "[":
- option.laxbreak = true;
- jsonmode = true;
- jsonValue();
+ destructuringAssignOrJsonValue();
break;
default:
directives();
- if (directive["use strict"] && !option.globalstrict) {
- warning("Use the function form of \"use strict\".", prevtoken);
+
+ if (state.directive["use strict"]) {
+ if (!state.option.globalstrict && !state.option.node) {
+ warning("W097", state.tokens.prev);
+ }
}
statements();
}
- advance((nexttoken && nexttoken.value !== ".") ? "(end)" : undefined);
+ advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined);
+ funct["(blockscope)"].unstack();
var markDefined = function (name, context) {
do {
@@ -6264,12 +7290,29 @@ klass:
implied[name] = newImplied;
};
- var warnUnused = function (name, token) {
- var line = token.line;
- var chr = token.character;
+ var warnUnused = function (name, tkn, type, unused_opt) {
+ var line = tkn.line;
+ var chr = tkn.character;
- if (option.unused)
- warningAt("'{a}' is defined but never used.", line, chr, name);
+ if (unused_opt === undefined) {
+ unused_opt = state.option.unused;
+ }
+
+ if (unused_opt === true) {
+ unused_opt = "last-param";
+ }
+
+ var warnable_types = {
+ "vars": ["var"],
+ "last-param": ["var", "param"],
+ "strict": ["var", "param", "last-param"]
+ };
+
+ if (unused_opt) {
+ if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
+ warningAt("W098", line, chr, name);
+ }
+ }
unuseds.push({
name: name,
@@ -6280,7 +7323,7 @@ klass:
var checkUnused = function (func, key) {
var type = func[key];
- var token = func["(tokens)"][key];
+ var tkn = func["(tokens)"][key];
if (key.charAt(0) === "(")
return;
@@ -6289,22 +7332,29 @@ klass:
return;
if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
return;
+ if (func["(global)"] && _.has(exported, key)) {
+ return;
+ }
- warnUnused(key, token);
+ warnUnused(key, tkn, "var");
};
for (i = 0; i < JSHINT.undefs.length; i += 1) {
k = JSHINT.undefs[i].slice(0);
if (markDefined(k[2].value, k[0])) {
clearImplied(k[2].value, k[2].line);
- } else {
+ } else if (state.option.undef) {
warning.apply(warning, k.slice(1));
}
}
functions.forEach(function (func) {
+ if (func["(unusedOption)"] === false) {
+ return;
+ }
+
for (var key in func) {
- if (is_own(func, key)) {
+ if (_.has(func, key)) {
checkUnused(func, key);
}
}
@@ -6314,36 +7364,44 @@ klass:
var params = func["(params)"].slice();
var param = params.pop();
- var type;
+ var type, unused_opt;
while (param) {
type = func[param];
+ unused_opt = func["(unusedOption)"] || state.option.unused;
+ unused_opt = unused_opt === true ? "last-param" : unused_opt;
if (param === "undefined")
return;
- if (type !== "unused" && type !== "unction")
+ if (type === "unused" || type === "unction") {
+ warnUnused(param, func["(tokens)"][param], "param", func["(unusedOption)"]);
+ } else if (unused_opt === "last-param") {
return;
+ }
- warnUnused(param, func["(tokens)"][param]);
param = params.pop();
}
});
for (var key in declared) {
- if (is_own(declared, key) && !is_own(global, key)) {
- warnUnused(key, declared[key]);
+ if (_.has(declared, key) && !_.has(global, key)) {
+ warnUnused(key, declared[key], "var");
}
}
- } catch (e) {
- if (e) {
- var nt = nexttoken || {};
+
+ } catch (err) {
+ if (err && err.name === "JSHintError") {
+ var nt = state.tokens.next || {};
JSHINT.errors.push({
- raw : e.raw,
- reason : e.message,
- line : e.line || nt.line,
- character : e.character || nt.from
+ scope : "(main)",
+ raw : err.raw,
+ reason : err.message,
+ line : err.line || nt.line,
+ character : err.character || nt.from
}, null);
+ } else {
+ throw err;
}
}
@@ -6359,10 +7417,15 @@ klass:
return JSHINT.errors.length === 0;
};
+ itself.addModule = function (func) {
+ extraModules.push(func);
+ };
+
+ itself.addModule(style.register);
itself.data = function () {
var data = {
functions: [],
- options: option
+ options: state.option
};
var implieds = [];
var members = [];
@@ -6372,12 +7435,12 @@ klass:
data.errors = itself.errors;
}
- if (jsonmode) {
+ if (state.jsonMode) {
data.json = true;
}
for (n in implied) {
- if (is_own(implied, n)) {
+ if (_.has(implied, n)) {
implieds.push({
name: n,
line: implied[n]
@@ -6444,4 +7507,2474 @@ if (typeof exports === "object" && exports) {
exports.JSHINT = JSHINT;
}
+})()
+},
+{"events":2,"../shared/vars.js":3,"../shared/messages.js":10,"./lex.js":11,"./reg.js":4,"./state.js":5,"./style.js":6,"console-browserify":7,"underscore":12}],
+10:[function(req,module,exports){
+(function(){
+
+var _ = req("underscore");
+
+var errors = {
+ E001: "Bad option: '{a}'.",
+ E002: "Bad option value.",
+ E003: "Expected a JSON value.",
+ E004: "Input is neither a string nor an array of strings.",
+ E005: "Input is empty.",
+ E006: "Unexpected early end of program.",
+ E007: "Missing \"use strict\" statement.",
+ E008: "Strict violation.",
+ E009: "Option 'validthis' can't be used in a global scope.",
+ E010: "'with' is not allowed in strict mode.",
+ E011: "const '{a}' has already been declared.",
+ E012: "const '{a}' is initialized to 'undefined'.",
+ E013: "Attempting to override '{a}' which is a constant.",
+ E014: "A regular expression literal can be confused with '/='.",
+ E015: "Unclosed regular expression.",
+ E016: "Invalid regular expression.",
+ E017: "Unclosed comment.",
+ E018: "Unbegun comment.",
+ E019: "Unmatched '{a}'.",
+ E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
+ E021: "Expected '{a}' and instead saw '{b}'.",
+ E022: "Line breaking error '{a}'.",
+ E023: "Missing '{a}'.",
+ E024: "Unexpected '{a}'.",
+ E025: "Missing ':' on a case clause.",
+ E026: "Missing '}' to match '{' from line {a}.",
+ E027: "Missing ']' to match '[' form line {a}.",
+ E028: "Illegal comma.",
+ E029: "Unclosed string.",
+ E030: "Expected an identifier and instead saw '{a}'.",
+ E031: "Bad assignment.", // FIXME: Rephrase
+ E032: "Expected a small integer or 'false' and instead saw '{a}'.",
+ E033: "Expected an operator and instead saw '{a}'.",
+ E034: "get/set are ES5 features.",
+ E035: "Missing property name.",
+ E036: "Expected to see a statement and instead saw a block.",
+ E037: "Constant {a} was not declared correctly.",
+ E038: "Variable {a} was not declared correctly.",
+ E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.",
+ E040: "Each value should have its own case label.",
+ E041: "Unrecoverable syntax error.",
+ E042: "Stopping.",
+ E043: "Too many errors.",
+ E044: "'{a}' is already defined and can't be redefined.",
+ E045: "Invalid for each loop.",
+ E046: "A yield statement shall be within a generator function (with syntax: `function*`)",
+ E047: "A generator function shall contain a yield statement.",
+ E048: "Let declaration not directly within block.",
+ E049: "A {a} cannot be named '{b}'."
+};
+
+var warnings = {
+ W001: "'hasOwnProperty' is a really bad name.",
+ W002: "Value of '{a}' may be overwritten in IE 8 and earlier.",
+ W003: "'{a}' was used before it was defined.",
+ W004: "'{a}' is already defined.",
+ W005: "A dot following a number can be confused with a decimal point.",
+ W006: "Confusing minuses.",
+ W007: "Confusing pluses.",
+ W008: "A leading decimal point can be confused with a dot: '{a}'.",
+ W009: "The array literal notation [] is preferrable.",
+ W010: "The object literal notation {} is preferrable.",
+ W011: "Unexpected space after '{a}'.",
+ W012: "Unexpected space before '{a}'.",
+ W013: "Missing space after '{a}'.",
+ W014: "Bad line breaking before '{a}'.",
+ W015: "Expected '{a}' to have an indentation at {b} instead at {c}.",
+ W016: "Unexpected use of '{a}'.",
+ W017: "Bad operand.",
+ W018: "Confusing use of '{a}'.",
+ W019: "Use the isNaN function to compare with NaN.",
+ W020: "Read only.",
+ W021: "'{a}' is a function.",
+ W022: "Do not assign to the exception parameter.",
+ W023: "Expected an identifier in an assignment and instead saw a function invocation.",
+ W024: "Expected an identifier and instead saw '{a}' (a reserved word).",
+ W025: "Missing name in function declaration.",
+ W026: "Inner functions should be listed at the top of the outer function.",
+ W027: "Unreachable '{a}' after '{b}'.",
+ W028: "Label '{a}' on {b} statement.",
+ W030: "Expected an assignment or function call and instead saw an expression.",
+ W031: "Do not use 'new' for side effects.",
+ W032: "Unnecessary semicolon.",
+ W033: "Missing semicolon.",
+ W034: "Unnecessary directive \"{a}\".",
+ W035: "Empty block.",
+ W036: "Unexpected /*member '{a}'.",
+ W037: "'{a}' is a statement label.",
+ W038: "'{a}' used out of scope.",
+ W039: "'{a}' is not allowed.",
+ W040: "Possible strict violation.",
+ W041: "Use '{a}' to compare with '{b}'.",
+ W042: "Avoid EOL escaping.",
+ W043: "Bad escaping of EOL. Use option multistr if needed.",
+ W044: "Bad or unnecessary escaping.",
+ W045: "Bad number '{a}'.",
+ W046: "Don't use extra leading zeros '{a}'.",
+ W047: "A trailing decimal point can be confused with a dot: '{a}'.",
+ W048: "Unexpected control character in regular expression.",
+ W049: "Unexpected escaped character '{a}' in regular expression.",
+ W050: "JavaScript URL.",
+ W051: "Variables should not be deleted.",
+ W052: "Unexpected '{a}'.",
+ W053: "Do not use {a} as a constructor.",
+ W054: "The Function constructor is a form of eval.",
+ W055: "A constructor name should start with an uppercase letter.",
+ W056: "Bad constructor.",
+ W057: "Weird construction. Is 'new' unnecessary?",
+ W058: "Missing '()' invoking a constructor.",
+ W059: "Avoid arguments.{a}.",
+ W060: "document.write can be a form of eval.",
+ W061: "eval can be harmful.",
+ W062: "Wrap an immediate function invocation in parens " +
+ "to assist the reader in understanding that the expression " +
+ "is the result of a function, and not the function itself.",
+ W063: "Math is not a function.",
+ W064: "Missing 'new' prefix when invoking a constructor.",
+ W065: "Missing radix parameter.",
+ W066: "Implied eval. Consider passing a function instead of a string.",
+ W067: "Bad invocation.",
+ W068: "Wrapping non-IIFE function literals in parens is unnecessary.",
+ W069: "['{a}'] is better written in dot notation.",
+ W070: "Extra comma. (it breaks older versions of IE)",
+ W071: "This function has too many statements. ({a})",
+ W072: "This function has too many parameters. ({a})",
+ W073: "Blocks are nested too deeply. ({a})",
+ W074: "This function's cyclomatic complexity is too high. ({a})",
+ W075: "Duplicate key '{a}'.",
+ W076: "Unexpected parameter '{a}' in get {b} function.",
+ W077: "Expected a single parameter in set {a} function.",
+ W078: "Setter is defined without getter.",
+ W079: "Redefinition of '{a}'.",
+ W080: "It's not necessary to initialize '{a}' to 'undefined'.",
+ W081: "Too many var statements.",
+ W082: "Function declarations should not be placed in blocks. " +
+ "Use a function expression or move the statement to the top of " +
+ "the outer function.",
+ W083: "Don't make functions within a loop.",
+ W084: "Assignment in conditional expression",
+ W085: "Don't use 'with'.",
+ W086: "Expected a 'break' statement before '{a}'.",
+ W087: "Forgotten 'debugger' statement?",
+ W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.",
+ W089: "The body of a for in should be wrapped in an if statement to filter " +
+ "unwanted properties from the prototype.",
+ W090: "'{a}' is not a statement label.",
+ W091: "'{a}' is out of scope.",
+ W092: "Wrap the /regexp/ literal in parens to disambiguate the slash operator.",
+ W093: "Did you mean to return a conditional instead of an assignment?",
+ W094: "Unexpected comma.",
+ W095: "Expected a string and instead saw {a}.",
+ W096: "The '{a}' key may produce unexpected results.",
+ W097: "Use the function form of \"use strict\".",
+ W098: "'{a}' is defined but never used.",
+ W099: "Mixed spaces and tabs.",
+ W100: "This character may get silently deleted by one or more browsers.",
+ W101: "Line is too long.",
+ W102: "Trailing whitespace.",
+ W103: "The '{a}' property is deprecated.",
+ W104: "'{a}' is only available in JavaScript 1.7.",
+ W105: "Unexpected {a} in '{b}'.",
+ W106: "Identifier '{a}' is not in camel case.",
+ W107: "Script URL.",
+ W108: "Strings must use doublequote.",
+ W109: "Strings must use singlequote.",
+ W110: "Mixed double and single quotes.",
+ W112: "Unclosed string.",
+ W113: "Control character in string: {a}.",
+ W114: "Avoid {a}.",
+ W115: "Octal literals are not allowed in strict mode.",
+ W116: "Expected '{a}' and instead saw '{b}'.",
+ W117: "'{a}' is not defined.",
+ W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
+ W119: "'{a}' is only available in ES6 (use esnext option)."
+};
+
+var info = {
+ I001: "Comma warnings can be turned off with 'laxcomma'.",
+ I002: "Reserved words as properties can be used under the 'es5' option.",
+ I003: "ES5 option is now set per default"
+};
+
+exports.errors = {};
+exports.warnings = {};
+exports.info = {};
+
+_.each(errors, function (desc, code) {
+ exports.errors[code] = { code: code, desc: desc };
+});
+
+_.each(warnings, function (desc, code) {
+ exports.warnings[code] = { code: code, desc: desc };
+});
+
+_.each(info, function (desc, code) {
+ exports.info[code] = { code: code, desc: desc };
+});
+
+})()
+},
+{"underscore":12}],
+11:[function(req,module,exports){
+(function(){/*
+ * Lexical analysis and token construction.
+ */
+
+
+
+var _ = req("underscore");
+var events = req("events");
+var reg = req("./reg.js");
+var state = req("./state.js").state;
+
+var Token = {
+ Identifier: 1,
+ Punctuator: 2,
+ NumericLiteral: 3,
+ StringLiteral: 4,
+ Comment: 5,
+ Keyword: 6,
+ NullLiteral: 7,
+ BooleanLiteral: 8,
+ RegExp: 9
+};
+
+var unicodeLetterTable = [
+ 170, 170, 181, 181, 186, 186, 192, 214,
+ 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750,
+ 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908,
+ 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366,
+ 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610,
+ 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775,
+ 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,
+ 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069,
+ 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361,
+ 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431,
+ 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482,
+ 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,
+ 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608,
+ 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654,
+ 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,
+ 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785,
+ 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,
+ 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,
+ 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970,
+ 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001,
+ 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123,
+ 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,
+ 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261,
+ 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344,
+ 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455,
+ 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526,
+ 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716,
+ 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,
+ 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760,
+ 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805,
+ 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138,
+ 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,
+ 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346,
+ 4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696,
+ 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789,
+ 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,
+ 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,
+ 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900,
+ 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000,
+ 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,
+ 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516,
+ 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823,
+ 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141,
+ 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409,
+ 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013,
+ 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061,
+ 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140,
+ 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188,
+ 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455,
+ 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486,
+ 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,
+ 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358,
+ 11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621,
+ 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,
+ 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,
+ 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,
+ 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438,
+ 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589,
+ 12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312,
+ 19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124,
+ 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539,
+ 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783,
+ 42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921,
+ 43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042,
+ 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259,
+ 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442,
+ 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595,
+ 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697,
+ 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714,
+ 43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798,
+ 43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032,
+ 55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045,
+ 64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279,
+ 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316,
+ 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,
+ 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,
+ 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370,
+ 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,
+ 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594,
+ 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786,
+ 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334,
+ 66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511,
+ 66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592,
+ 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669,
+ 67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115,
+ 68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405,
+ 68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687,
+ 69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894,
+ 92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964,
+ 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,
+ 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069,
+ 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121,
+ 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144,
+ 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570,
+ 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,
+ 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779,
+ 131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972,
+ 177984, 177984, 178205, 178205, 194560, 195101
+];
+
+var identifierStartTable = [];
+
+for (var i = 0; i < 128; i++) {
+ identifierStartTable[i] =
+ i === 36 || // $
+ i >= 65 && i <= 90 || // A-Z
+ i === 95 || // _
+ i >= 97 && i <= 122; // a-z
+}
+
+var identifierPartTable = [];
+
+for (var i = 0; i < 128; i++) {
+ identifierPartTable[i] =
+ identifierStartTable[i] || // $, _, A-Z, a-z
+ i >= 48 && i <= 57; // 0-9
+}
+
+function asyncTrigger() {
+ var _checks = [];
+
+ return {
+ push: function (fn) {
+ _checks.push(fn);
+ },
+
+ check: function () {
+ for (var check = 0; check < _checks.length; ++check) {
+ _checks[check]();
+ }
+
+ _checks.splice(0, _checks.length);
+ }
+ };
+}
+function Lexer(source) {
+ var lines = source;
+
+ if (typeof lines === "string") {
+ lines = lines
+ .replace(/\r\n/g, "\n")
+ .replace(/\r/g, "\n")
+ .split("\n");
+ }
+
+ if (lines[0] && lines[0].substr(0, 2) === "#!") {
+ lines[0] = "";
+ }
+
+ this.emitter = new events.EventEmitter();
+ this.source = source;
+ this.setLines(lines);
+ this.prereg = true;
+
+ this.line = 0;
+ this.char = 1;
+ this.from = 1;
+ this.input = "";
+
+ for (var i = 0; i < state.option.indent; i += 1) {
+ state.tab += " ";
+ }
+}
+
+Lexer.prototype = {
+ _lines: [],
+
+ getLines: function () {
+ this._lines = state.lines;
+ return this._lines;
+ },
+
+ setLines: function (val) {
+ this._lines = val;
+ state.lines = this._lines;
+ },
+ peek: function (i) {
+ return this.input.charAt(i || 0);
+ },
+ skip: function (i) {
+ i = i || 1;
+ this.char += i;
+ this.input = this.input.slice(i);
+ },
+ on: function (names, listener) {
+ names.split(" ").forEach(function (name) {
+ this.emitter.on(name, listener);
+ }.bind(this));
+ },
+ trigger: function () {
+ this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
+ },
+ triggerAsync: function (type, args, checks, fn) {
+ checks.push(function () {
+ if (fn()) {
+ this.trigger(type, args);
+ }
+ }.bind(this));
+ },
+ scanPunctuator: function () {
+ var ch1 = this.peek();
+ var ch2, ch3, ch4;
+
+ switch (ch1) {
+ case ".":
+ if ((/^[0-9]$/).test(this.peek(1))) {
+ return null;
+ }
+ if (this.peek(1) === "." && this.peek(2) === ".") {
+ return {
+ type: Token.Punctuator,
+ value: "..."
+ };
+ }
+ case "(":
+ case ")":
+ case ";":
+ case ",":
+ case "{":
+ case "}":
+ case "[":
+ case "]":
+ case ":":
+ case "~":
+ case "?":
+ return {
+ type: Token.Punctuator,
+ value: ch1
+ };
+ case "#":
+ return {
+ type: Token.Punctuator,
+ value: ch1
+ };
+ case "":
+ return null;
+ }
+
+ ch2 = this.peek(1);
+ ch3 = this.peek(2);
+ ch4 = this.peek(3);
+
+ if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: ">>>="
+ };
+ }
+
+ if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: "==="
+ };
+ }
+
+ if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: "!=="
+ };
+ }
+
+ if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
+ return {
+ type: Token.Punctuator,
+ value: ">>>"
+ };
+ }
+
+ if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: "<<="
+ };
+ }
+
+ if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: ">>="
+ };
+ }
+ if (ch1 === "=" && ch2 === ">") {
+ return {
+ type: Token.Punctuator,
+ value: ch1 + ch2
+ };
+ }
+ if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
+ return {
+ type: Token.Punctuator,
+ value: ch1 + ch2
+ };
+ }
+
+ if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
+ if (ch2 === "=") {
+ return {
+ type: Token.Punctuator,
+ value: ch1 + ch2
+ };
+ }
+
+ return {
+ type: Token.Punctuator,
+ value: ch1
+ };
+ }
+
+ if (ch1 === "/") {
+ if (ch2 === "=" && /\/=(?!(\S*\/[gim]?))/.test(this.input)) {
+ return {
+ type: Token.Punctuator,
+ value: "/="
+ };
+ }
+
+ return {
+ type: Token.Punctuator,
+ value: "/"
+ };
+ }
+
+ return null;
+ },
+ scanComments: function () {
+ var ch1 = this.peek();
+ var ch2 = this.peek(1);
+ var rest = this.input.substr(2);
+ var startLine = this.line;
+ var startChar = this.char;
+
+ function commentToken(label, body, opt) {
+ var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
+ var isSpecial = false;
+ var value = label + body;
+ var commentType = "plain";
+ opt = opt || {};
+
+ if (opt.isMultiline) {
+ value += "*/";
+ }
+
+ special.forEach(function (str) {
+ if (isSpecial) {
+ return;
+ }
+ if (label === "//" && str !== "jshint") {
+ return;
+ }
+
+ if (body.substr(0, str.length) === str) {
+ isSpecial = true;
+ label = label + str;
+ body = body.substr(str.length);
+ }
+
+ if (!isSpecial && body.charAt(0) === " " && body.substr(1, str.length) === str) {
+ isSpecial = true;
+ label = label + " " + str;
+ body = body.substr(str.length + 1);
+ }
+
+ if (!isSpecial) {
+ return;
+ }
+
+ switch (str) {
+ case "member":
+ commentType = "members";
+ break;
+ case "global":
+ commentType = "globals";
+ break;
+ default:
+ commentType = str;
+ }
+ });
+
+ return {
+ type: Token.Comment,
+ commentType: commentType,
+ value: value,
+ body: body,
+ isSpecial: isSpecial,
+ isMultiline: opt.isMultiline || false,
+ isMalformed: opt.isMalformed || false
+ };
+ }
+ if (ch1 === "*" && ch2 === "/") {
+ this.trigger("error", {
+ code: "E018",
+ line: startLine,
+ character: startChar
+ });
+
+ this.skip(2);
+ return null;
+ }
+ if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
+ return null;
+ }
+ if (ch2 === "/") {
+ this.skip(this.input.length); // Skip to the EOL.
+ return commentToken("//", rest);
+ }
+
+ var body = "";
+ if (ch2 === "*") {
+ this.skip(2);
+
+ while (this.peek() !== "*" || this.peek(1) !== "/") {
+ if (this.peek() === "") { // End of Line
+ body += "\n";
+ if (!this.nextLine()) {
+ this.trigger("error", {
+ code: "E017",
+ line: startLine,
+ character: startChar
+ });
+
+ return commentToken("/*", body, {
+ isMultiline: true,
+ isMalformed: true
+ });
+ }
+ } else {
+ body += this.peek();
+ this.skip();
+ }
+ }
+
+ this.skip(2);
+ return commentToken("/*", body, { isMultiline: true });
+ }
+ },
+ scanKeyword: function () {
+ var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);
+ var keywords = [
+ "if", "in", "do", "var", "for", "new",
+ "try", "let", "this", "else", "case",
+ "void", "with", "enum", "while", "break",
+ "catch", "throw", "const", "yield", "class",
+ "super", "return", "typeof", "delete",
+ "switch", "export", "import", "default",
+ "finally", "extends", "function", "continue",
+ "debugger", "instanceof"
+ ];
+
+ if (result && keywords.indexOf(result[0]) >= 0) {
+ return {
+ type: Token.Keyword,
+ value: result[0]
+ };
+ }
+
+ return null;
+ },
+ scanIdentifier: function () {
+ var id = "";
+ var index = 0;
+ var type, char;
+
+ function isUnicodeLetter(code) {
+ for (var i = 0; i < unicodeLetterTable.length;) {
+ if (code < unicodeLetterTable[i++]) {
+ return false;
+ }
+
+ if (code <= unicodeLetterTable[i++]) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ function isHexDigit(str) {
+ return (/^[0-9a-fA-F]$/).test(str);
+ }
+
+ var readUnicodeEscapeSequence = function () {
+ index += 1;
+
+ if (this.peek(index) !== "u") {
+ return null;
+ }
+
+ var ch1 = this.peek(index + 1);
+ var ch2 = this.peek(index + 2);
+ var ch3 = this.peek(index + 3);
+ var ch4 = this.peek(index + 4);
+ var code;
+
+ if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {
+ code = parseInt(ch1 + ch2 + ch3 + ch4, 16);
+
+ if (isUnicodeLetter(code)) {
+ index += 5;
+ return "\\u" + ch1 + ch2 + ch3 + ch4;
+ }
+
+ return null;
+ }
+
+ return null;
+ }.bind(this);
+
+ var getIdentifierStart = function () {
+ var chr = this.peek(index);
+ var code = chr.charCodeAt(0);
+
+ if (code === 92) {
+ return readUnicodeEscapeSequence();
+ }
+
+ if (code < 128) {
+ if (identifierStartTable[code]) {
+ index += 1;
+ return chr;
+ }
+
+ return null;
+ }
+
+ if (isUnicodeLetter(code)) {
+ index += 1;
+ return chr;
+ }
+
+ return null;
+ }.bind(this);
+
+ var getIdentifierPart = function () {
+ var chr = this.peek(index);
+ var code = chr.charCodeAt(0);
+
+ if (code === 92) {
+ return readUnicodeEscapeSequence();
+ }
+
+ if (code < 128) {
+ if (identifierPartTable[code]) {
+ index += 1;
+ return chr;
+ }
+
+ return null;
+ }
+
+ if (isUnicodeLetter(code)) {
+ index += 1;
+ return chr;
+ }
+
+ return null;
+ }.bind(this);
+
+ char = getIdentifierStart();
+ if (char === null) {
+ return null;
+ }
+
+ id = char;
+ for (;;) {
+ char = getIdentifierPart();
+
+ if (char === null) {
+ break;
+ }
+
+ id += char;
+ }
+
+ switch (id) {
+ case "true":
+ case "false":
+ type = Token.BooleanLiteral;
+ break;
+ case "null":
+ type = Token.NullLiteral;
+ break;
+ default:
+ type = Token.Identifier;
+ }
+
+ return {
+ type: type,
+ value: id
+ };
+ },
+ scanNumericLiteral: function () {
+ var index = 0;
+ var value = "";
+ var length = this.input.length;
+ var char = this.peek(index);
+ var bad;
+
+ function isDecimalDigit(str) {
+ return (/^[0-9]$/).test(str);
+ }
+
+ function isOctalDigit(str) {
+ return (/^[0-7]$/).test(str);
+ }
+
+ function isHexDigit(str) {
+ return (/^[0-9a-fA-F]$/).test(str);
+ }
+
+ function isIdentifierStart(ch) {
+ return (ch === "$") || (ch === "_") || (ch === "\\") ||
+ (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
+ }
+
+ if (char !== "." && !isDecimalDigit(char)) {
+ return null;
+ }
+
+ if (char !== ".") {
+ value = this.peek(index);
+ index += 1;
+ char = this.peek(index);
+
+ if (value === "0") {
+ if (char === "x" || char === "X") {
+ index += 1;
+ value += char;
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!isHexDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+
+ if (value.length <= 2) { // 0x
+ return {
+ type: Token.NumericLiteral,
+ value: value,
+ isMalformed: true
+ };
+ }
+
+ if (index < length) {
+ char = this.peek(index);
+ if (isIdentifierStart(char)) {
+ return null;
+ }
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: value,
+ base: 16,
+ isMalformed: false
+ };
+ }
+ if (isOctalDigit(char)) {
+ index += 1;
+ value += char;
+ bad = false;
+
+ while (index < length) {
+ char = this.peek(index);
+
+ if (isDecimalDigit(char)) {
+ bad = true;
+ } else if (!isOctalDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+
+ if (index < length) {
+ char = this.peek(index);
+ if (isIdentifierStart(char)) {
+ return null;
+ }
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: value,
+ base: 8,
+ isMalformed: false
+ };
+ }
+
+ if (isDecimalDigit(char)) {
+ index += 1;
+ value += char;
+ }
+ }
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!isDecimalDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+ }
+
+ if (char === ".") {
+ value += char;
+ index += 1;
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!isDecimalDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+ }
+
+ if (char === "e" || char === "E") {
+ value += char;
+ index += 1;
+ char = this.peek(index);
+
+ if (char === "+" || char === "-") {
+ value += this.peek(index);
+ index += 1;
+ }
+
+ char = this.peek(index);
+ if (isDecimalDigit(char)) {
+ value += char;
+ index += 1;
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!isDecimalDigit(char)) {
+ break;
+ }
+ value += char;
+ index += 1;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ if (index < length) {
+ char = this.peek(index);
+ if (isIdentifierStart(char)) {
+ return null;
+ }
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: value,
+ base: 10,
+ isMalformed: !isFinite(value)
+ };
+ },
+ scanStringLiteral: function (checks) {
+ var quote = this.peek();
+ if (quote !== "\"" && quote !== "'") {
+ return null;
+ }
+ this.triggerAsync("warning", {
+ code: "W108",
+ line: this.line,
+ character: this.char // +1?
+ }, checks, function () { return state.jsonMode && quote !== "\""; });
+
+ var value = "";
+ var startLine = this.line;
+ var startChar = this.char;
+ var allowNewLine = false;
+
+ this.skip();
+
+ while (this.peek() !== quote) {
+ while (this.peek() === "") { // End Of Line
+
+ if (!allowNewLine) {
+ this.trigger("warning", {
+ code: "W112",
+ line: this.line,
+ character: this.char
+ });
+ } else {
+ allowNewLine = false;
+
+ this.triggerAsync("warning", {
+ code: "W043",
+ line: this.line,
+ character: this.char
+ }, checks, function () { return !state.option.multistr; });
+
+ this.triggerAsync("warning", {
+ code: "W042",
+ line: this.line,
+ character: this.char
+ }, checks, function () { return state.jsonMode && state.option.multistr; });
+ }
+
+ if (!this.nextLine()) {
+ this.trigger("error", {
+ code: "E029",
+ line: startLine,
+ character: startChar
+ });
+
+ return {
+ type: Token.StringLiteral,
+ value: value,
+ isUnclosed: true,
+ quote: quote
+ };
+ }
+ }
+
+ allowNewLine = false;
+ var char = this.peek();
+ var jump = 1; // A length of a jump, after we're done
+
+ if (char < " ") {
+ this.trigger("warning", {
+ code: "W113",
+ line: this.line,
+ character: this.char,
+ data: [ "" ]
+ });
+ }
+
+ if (char === "\\") {
+ this.skip();
+ char = this.peek();
+
+ switch (char) {
+ case "'":
+ this.triggerAsync("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.char,
+ data: [ "\\'" ]
+ }, checks, function () {return state.jsonMode; });
+ break;
+ case "b":
+ char = "\b";
+ break;
+ case "f":
+ char = "\f";
+ break;
+ case "n":
+ char = "\n";
+ break;
+ case "r":
+ char = "\r";
+ break;
+ case "t":
+ char = "\t";
+ break;
+ case "0":
+ char = "\0";
+ var n = parseInt(this.peek(1), 10);
+ this.triggerAsync("warning", {
+ code: "W115",
+ line: this.line,
+ character: this.char
+ }, checks,
+ function () { return n >= 0 && n <= 7 && state.directive["use strict"]; });
+ break;
+ case "u":
+ char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16));
+ jump = 5;
+ break;
+ case "v":
+ this.triggerAsync("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.char,
+ data: [ "\\v" ]
+ }, checks, function () { return state.jsonMode; });
+
+ char = "\v";
+ break;
+ case "x":
+ var x = parseInt(this.input.substr(1, 2), 16);
+
+ this.triggerAsync("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.char,
+ data: [ "\\x-" ]
+ }, checks, function () { return state.jsonMode; });
+
+ char = String.fromCharCode(x);
+ jump = 3;
+ break;
+ case "\\":
+ case "\"":
+ case "/":
+ break;
+ case "":
+ allowNewLine = true;
+ char = "";
+ break;
+ case "!":
+ if (value.slice(value.length - 2) === "<") {
+ break;
+ }
+ default:
+ this.trigger("warning", {
+ code: "W044",
+ line: this.line,
+ character: this.char
+ });
+ }
+ }
+
+ value += char;
+ this.skip(jump);
+ }
+
+ this.skip();
+ return {
+ type: Token.StringLiteral,
+ value: value,
+ isUnclosed: false,
+ quote: quote
+ };
+ },
+ scanRegExp: function () {
+ var index = 0;
+ var length = this.input.length;
+ var char = this.peek();
+ var value = char;
+ var body = "";
+ var flags = [];
+ var malformed = false;
+ var isCharSet = false;
+ var terminated;
+
+ var scanUnexpectedChars = function () {
+ if (char < " ") {
+ malformed = true;
+ this.trigger("warning", {
+ code: "W048",
+ line: this.line,
+ character: this.char
+ });
+ }
+ if (char === "<") {
+ malformed = true;
+ this.trigger("warning", {
+ code: "W049",
+ line: this.line,
+ character: this.char,
+ data: [ char ]
+ });
+ }
+ }.bind(this);
+ if (!this.prereg || char !== "/") {
+ return null;
+ }
+
+ index += 1;
+ terminated = false;
+
+ while (index < length) {
+ char = this.peek(index);
+ value += char;
+ body += char;
+
+ if (isCharSet) {
+ if (char === "]") {
+ if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
+ isCharSet = false;
+ }
+ }
+
+ if (char === "\\") {
+ index += 1;
+ char = this.peek(index);
+ body += char;
+ value += char;
+
+ scanUnexpectedChars();
+ }
+
+ index += 1;
+ continue;
+ }
+
+ if (char === "\\") {
+ index += 1;
+ char = this.peek(index);
+ body += char;
+ value += char;
+
+ scanUnexpectedChars();
+
+ if (char === "/") {
+ index += 1;
+ continue;
+ }
+
+ if (char === "[") {
+ index += 1;
+ continue;
+ }
+ }
+
+ if (char === "[") {
+ isCharSet = true;
+ index += 1;
+ continue;
+ }
+
+ if (char === "/") {
+ body = body.substr(0, body.length - 1);
+ terminated = true;
+ index += 1;
+ break;
+ }
+
+ index += 1;
+ }
+
+ if (!terminated) {
+ this.trigger("error", {
+ code: "E015",
+ line: this.line,
+ character: this.from
+ });
+
+ return void this.trigger("fatal", {
+ line: this.line,
+ from: this.from
+ });
+ }
+
+ while (index < length) {
+ char = this.peek(index);
+ if (!/[gim]/.test(char)) {
+ break;
+ }
+ flags.push(char);
+ value += char;
+ index += 1;
+ }
+
+ try {
+ new RegExp(body, flags.join(""));
+ } catch (err) {
+ malformed = true;
+ this.trigger("error", {
+ code: "E016",
+ line: this.line,
+ character: this.char,
+ data: [ err.message ] // Platform dependent!
+ });
+ }
+
+ return {
+ type: Token.RegExp,
+ value: value,
+ flags: flags,
+ isMalformed: malformed
+ };
+ },
+ scanMixedSpacesAndTabs: function () {
+ var at, match;
+
+ if (state.option.smarttabs) {
+ match = this.input.match(/(\/\/|^\s?\*)? \t/);
+ at = match && !match[1] ? 0 : -1;
+ } else {
+ at = this.input.search(/ \t|\t [^\*]/);
+ }
+
+ return at;
+ },
+ scanUnsafeChars: function () {
+ return this.input.search(reg.unsafeChars);
+ },
+ next: function (checks) {
+ this.from = this.char;
+ var start;
+ if (/\s/.test(this.peek())) {
+ start = this.char;
+
+ while (/\s/.test(this.peek())) {
+ this.from += 1;
+ this.skip();
+ }
+
+ if (this.peek() === "") { // EOL
+ if (!/^\s*$/.test(this.getLines()[this.line - 1]) && state.option.trailing) {
+ this.trigger("warning", { code: "W102", line: this.line, character: start });
+ }
+ }
+ }
+
+ var match = this.scanComments() ||
+ this.scanStringLiteral(checks);
+
+ if (match) {
+ return match;
+ }
+
+ match =
+ this.scanRegExp() ||
+ this.scanPunctuator() ||
+ this.scanKeyword() ||
+ this.scanIdentifier() ||
+ this.scanNumericLiteral();
+
+ if (match) {
+ this.skip(match.value.length);
+ return match;
+ }
+
+ return null;
+ },
+ nextLine: function () {
+ var char;
+
+ if (this.line >= this.getLines().length) {
+ return false;
+ }
+
+ this.input = this.getLines()[this.line];
+ this.line += 1;
+ this.char = 1;
+ this.from = 1;
+
+ char = this.scanMixedSpacesAndTabs();
+ if (char >= 0) {
+ this.trigger("warning", { code: "W099", line: this.line, character: char + 1 });
+ }
+
+ this.input = this.input.replace(/\t/g, state.tab);
+ char = this.scanUnsafeChars();
+
+ if (char >= 0) {
+ this.trigger("warning", { code: "W100", line: this.line, character: char });
+ }
+
+ if (state.option.maxlen && state.option.maxlen < this.input.length) {
+ this.trigger("warning", { code: "W101", line: this.line, character: this.input.length });
+ }
+
+ return true;
+ },
+ start: function () {
+ this.nextLine();
+ },
+ token: function () {
+ var checks = asyncTrigger();
+ var token;
+
+
+ function isReserved(token, isProperty) {
+ if (!token.reserved) {
+ return false;
+ }
+
+ if (token.meta && token.meta.isFutureReservedWord) {
+ if (state.option.inES5(true) && !token.meta.es5) {
+ return false;
+ }
+ if (token.meta.strictOnly) {
+ if (!state.option.strict && !state.directive["use strict"]) {
+ return false;
+ }
+ }
+
+ if (isProperty) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ var create = function (type, value, isProperty) {
+ var obj;
+
+ if (type !== "(endline)" && type !== "(end)") {
+ this.prereg = false;
+ }
+
+ if (type === "(punctuator)") {
+ switch (value) {
+ case ".":
+ case ")":
+ case "~":
+ case "#":
+ case "]":
+ this.prereg = false;
+ break;
+ default:
+ this.prereg = true;
+ }
+
+ obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
+ }
+
+ if (type === "(identifier)") {
+ if (value === "return" || value === "case" || value === "typeof") {
+ this.prereg = true;
+ }
+
+ if (_.has(state.syntax, value)) {
+ obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
+ if (!isReserved(obj, isProperty && type === "(identifier)")) {
+ obj = null;
+ }
+ }
+ }
+
+ if (!obj) {
+ obj = Object.create(state.syntax[type]);
+ }
+
+ obj.identifier = (type === "(identifier)");
+ obj.type = obj.type || type;
+ obj.value = value;
+ obj.line = this.line;
+ obj.character = this.char;
+ obj.from = this.from;
+
+ if (isProperty && obj.identifier) {
+ obj.isProperty = isProperty;
+ }
+
+ obj.check = checks.check;
+
+ return obj;
+ }.bind(this);
+
+ for (;;) {
+ if (!this.input.length) {
+ return create(this.nextLine() ? "(endline)" : "(end)", "");
+ }
+
+ token = this.next(checks);
+
+ if (!token) {
+ if (this.input.length) {
+ this.trigger("error", {
+ code: "E024",
+ line: this.line,
+ character: this.char,
+ data: [ this.peek() ]
+ });
+
+ this.input = "";
+ }
+
+ continue;
+ }
+
+ switch (token.type) {
+ case Token.StringLiteral:
+ this.triggerAsync("String", {
+ line: this.line,
+ char: this.char,
+ from: this.from,
+ value: token.value,
+ quote: token.quote
+ }, checks, function () { return true; });
+
+ return create("(string)", token.value);
+ case Token.Identifier:
+ this.trigger("Identifier", {
+ line: this.line,
+ char: this.char,
+ from: this.form,
+ name: token.value,
+ isProperty: state.tokens.curr.id === "."
+ });
+ case Token.Keyword:
+ case Token.NullLiteral:
+ case Token.BooleanLiteral:
+ return create("(identifier)", token.value, state.tokens.curr.id === ".");
+
+ case Token.NumericLiteral:
+ if (token.isMalformed) {
+ this.trigger("warning", {
+ code: "W045",
+ line: this.line,
+ character: this.char,
+ data: [ token.value ]
+ });
+ }
+
+ this.triggerAsync("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.char,
+ data: [ "0x-" ]
+ }, checks, function () { return token.base === 16 && state.jsonMode; });
+
+ this.triggerAsync("warning", {
+ code: "W115",
+ line: this.line,
+ character: this.char
+ }, checks, function () {
+ return state.directive["use strict"] && token.base === 8;
+ });
+
+ this.trigger("Number", {
+ line: this.line,
+ char: this.char,
+ from: this.from,
+ value: token.value,
+ base: token.base,
+ isMalformed: token.malformed
+ });
+
+ return create("(number)", token.value);
+
+ case Token.RegExp:
+ return create("(regexp)", token.value);
+
+ case Token.Comment:
+ state.tokens.curr.comment = true;
+
+ if (token.isSpecial) {
+ return {
+ value: token.value,
+ body: token.body,
+ type: token.commentType,
+ isSpecial: token.isSpecial,
+ line: this.line,
+ character: this.char,
+ from: this.from
+ };
+ }
+
+ break;
+
+ case "":
+ break;
+
+ default:
+ return create("(punctuator)", token.value);
+ }
+ }
+ }
+};
+
+exports.Lexer = Lexer;
+
+})()
+},
+{"events":2,"./reg.js":4,"./state.js":5,"underscore":12}],
+12:[function(req,module,exports){
+(function(){// Underscore.js 1.4.4
+
+(function() {
+ var root = this;
+ var previousUnderscore = root._;
+ var breaker = {};
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+ var push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ concat = ArrayProto.concat,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+ var
+ nativeForEach = ArrayProto.forEach,
+ nativeMap = ArrayProto.map,
+ nativeReduce = ArrayProto.reduce,
+ nativeReduceRight = ArrayProto.reduceRight,
+ nativeFilter = ArrayProto.filter,
+ nativeEvery = ArrayProto.every,
+ nativeSome = ArrayProto.some,
+ nativeIndexOf = ArrayProto.indexOf,
+ nativeLastIndexOf = ArrayProto.lastIndexOf,
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind;
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+ _.VERSION = '1.4.4';
+ var each = _.each = _.forEach = function(obj, iterator, context) {
+ if (obj == null) return;
+ if (nativeForEach && obj.forEach === nativeForEach) {
+ obj.forEach(iterator, context);
+ } else if (obj.length === +obj.length) {
+ for (var i = 0, l = obj.length; i < l; i++) {
+ if (iterator.call(context, obj[i], i, obj) === breaker) return;
+ }
+ } else {
+ for (var key in obj) {
+ if (_.has(obj, key)) {
+ if (iterator.call(context, obj[key], key, obj) === breaker) return;
+ }
+ }
+ }
+ };
+ _.map = _.collect = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+ each(obj, function(value, index, list) {
+ results[results.length] = iterator.call(context, value, index, list);
+ });
+ return results;
+ };
+
+ var reduceError = 'Reduce of empty array with no initial value';
+ _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduce && obj.reduce === nativeReduce) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+ }
+ each(obj, function(value, index, list) {
+ if (!initial) {
+ memo = value;
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, value, index, list);
+ }
+ });
+ if (!initial) throw new TypeError(reduceError);
+ return memo;
+ };
+ _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+ }
+ var length = obj.length;
+ if (length !== +length) {
+ var keys = _.keys(obj);
+ length = keys.length;
+ }
+ each(obj, function(value, index, list) {
+ index = keys ? keys[--length] : --length;
+ if (!initial) {
+ memo = obj[index];
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, obj[index], index, list);
+ }
+ });
+ if (!initial) throw new TypeError(reduceError);
+ return memo;
+ };
+ _.find = _.detect = function(obj, iterator, context) {
+ var result;
+ any(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ return true;
+ }
+ });
+ return result;
+ };
+ _.filter = _.select = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+ each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+ _.reject = function(obj, iterator, context) {
+ return _.filter(obj, function(value, index, list) {
+ return !iterator.call(context, value, index, list);
+ }, context);
+ };
+ _.every = _.all = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
+ var result = true;
+ if (obj == null) return result;
+ if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+ each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+ var any = _.some = _.any = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
+ var result = false;
+ if (obj == null) return result;
+ if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+ each(obj, function(value, index, list) {
+ if (result || (result = iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+ _.contains = _.include = function(obj, target) {
+ if (obj == null) return false;
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+ return any(obj, function(value) {
+ return value === target;
+ });
+ };
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ return (isFunc ? method : value[method]).apply(value, args);
+ });
+ };
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+ _.where = function(obj, attrs, first) {
+ if (_.isEmpty(attrs)) return first ? null : [];
+ return _[first ? 'find' : 'filter'](obj, function(value) {
+ for (var key in attrs) {
+ if (attrs[key] !== value[key]) return false;
+ }
+ return true;
+ });
+ };
+ _.findWhere = function(obj, attrs) {
+ return _.where(obj, attrs, true);
+ };
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
+ return Math.max.apply(Math, obj);
+ }
+ if (!iterator && _.isEmpty(obj)) return -Infinity;
+ var result = {computed : -Infinity, value: -Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
+ return Math.min.apply(Math, obj);
+ }
+ if (!iterator && _.isEmpty(obj)) return Infinity;
+ var result = {computed : Infinity, value: Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+ _.shuffle = function(obj) {
+ var rand;
+ var index = 0;
+ var shuffled = [];
+ each(obj, function(value) {
+ rand = _.random(index++);
+ shuffled[index - 1] = shuffled[rand];
+ shuffled[rand] = value;
+ });
+ return shuffled;
+ };
+ var lookupIterator = function(value) {
+ return _.isFunction(value) ? value : function(obj){ return obj[value]; };
+ };
+ _.sortBy = function(obj, value, context) {
+ var iterator = lookupIterator(value);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ index : index,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index < right.index ? -1 : 1;
+ }), 'value');
+ };
+ var group = function(obj, value, context, behavior) {
+ var result = {};
+ var iterator = lookupIterator(value || _.identity);
+ each(obj, function(value, index) {
+ var key = iterator.call(context, value, index, obj);
+ behavior(result, key, value);
+ });
+ return result;
+ };
+ _.groupBy = function(obj, value, context) {
+ return group(obj, value, context, function(result, key, value) {
+ (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
+ });
+ };
+ _.countBy = function(obj, value, context) {
+ return group(obj, value, context, function(result, key) {
+ if (!_.has(result, key)) result[key] = 0;
+ result[key]++;
+ });
+ };
+ _.sortedIndex = function(array, obj, iterator, context) {
+ iterator = iterator == null ? _.identity : lookupIterator(iterator);
+ var value = iterator.call(context, obj);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >>> 1;
+ iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (obj.length === +obj.length) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
+ };
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+ };
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+ };
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if ((n != null) && !guard) {
+ return slice.call(array, Math.max(array.length - n, 0));
+ } else {
+ return array[array.length - 1];
+ }
+ };
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, (n == null) || guard ? 1 : n);
+ };
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+ var flatten = function(input, shallow, output) {
+ each(input, function(value) {
+ if (_.isArray(value)) {
+ shallow ? push.apply(output, value) : flatten(value, shallow, output);
+ } else {
+ output.push(value);
+ }
+ });
+ return output;
+ };
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, []);
+ };
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+ _.uniq = _.unique = function(array, isSorted, iterator, context) {
+ if (_.isFunction(isSorted)) {
+ context = iterator;
+ iterator = isSorted;
+ isSorted = false;
+ }
+ var initial = iterator ? _.map(array, iterator, context) : array;
+ var results = [];
+ var seen = [];
+ each(initial, function(value, index) {
+ if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
+ seen.push(value);
+ results.push(array[index]);
+ }
+ });
+ return results;
+ };
+ _.union = function() {
+ return _.uniq(concat.apply(ArrayProto, arguments));
+ };
+ _.intersection = function(array) {
+ var rest = slice.call(arguments, 1);
+ return _.filter(_.uniq(array), function(item) {
+ return _.every(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+ _.difference = function(array) {
+ var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
+ return _.filter(array, function(value){ return !_.contains(rest, value); });
+ };
+ _.zip = function() {
+ var args = slice.call(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i = 0; i < length; i++) {
+ results[i] = _.pluck(args, "" + i);
+ }
+ return results;
+ };
+ _.object = function(list, values) {
+ if (list == null) return {};
+ var result = {};
+ for (var i = 0, l = list.length; i < l; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+ _.indexOf = function(array, item, isSorted) {
+ if (array == null) return -1;
+ var i = 0, l = array.length;
+ if (isSorted) {
+ if (typeof isSorted == 'number') {
+ i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
+ } else {
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
+ }
+ }
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
+ for (; i < l; i++) if (array[i] === item) return i;
+ return -1;
+ };
+ _.lastIndexOf = function(array, item, from) {
+ if (array == null) return -1;
+ var hasIndex = from != null;
+ if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
+ return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
+ }
+ var i = (hasIndex ? from : array.length);
+ while (i--) if (array[i] === item) return i;
+ return -1;
+ };
+ _.range = function(start, stop, step) {
+ if (arguments.length <= 1) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = arguments[2] || 1;
+
+ var len = Math.max(Math.ceil((stop - start) / step), 0);
+ var idx = 0;
+ var range = new Array(len);
+
+ while(idx < len) {
+ range[idx++] = start;
+ start += step;
+ }
+
+ return range;
+ };
+ _.bind = function(func, context) {
+ if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ var args = slice.call(arguments, 2);
+ return function() {
+ return func.apply(context, args.concat(slice.call(arguments)));
+ };
+ };
+ _.partial = function(func) {
+ var args = slice.call(arguments, 1);
+ return function() {
+ return func.apply(this, args.concat(slice.call(arguments)));
+ };
+ };
+ _.bindAll = function(obj) {
+ var funcs = slice.call(arguments, 1);
+ if (funcs.length === 0) funcs = _.functions(obj);
+ each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ return obj;
+ };
+ _.memoize = function(func, hasher) {
+ var memo = {};
+ hasher || (hasher = _.identity);
+ return function() {
+ var key = hasher.apply(this, arguments);
+ return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+ };
+ };
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){ return func.apply(null, args); }, wait);
+ };
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+ };
+ _.throttle = function(func, wait) {
+ var context, args, timeout, result;
+ var previous = 0;
+ var later = function() {
+ previous = new Date;
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function() {
+ var now = new Date;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+ _.debounce = function(func, wait, immediate) {
+ var timeout, result;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) result = func.apply(context, args);
+ };
+ var callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) result = func.apply(context, args);
+ return result;
+ };
+ };
+ _.once = function(func) {
+ var ran = false, memo;
+ return function() {
+ if (ran) return memo;
+ ran = true;
+ memo = func.apply(this, arguments);
+ func = null;
+ return memo;
+ };
+ };
+ _.wrap = function(func, wrapper) {
+ return function() {
+ var args = [func];
+ push.apply(args, arguments);
+ return wrapper.apply(this, args);
+ };
+ };
+ _.compose = function() {
+ var funcs = arguments;
+ return function() {
+ var args = arguments;
+ for (var i = funcs.length - 1; i >= 0; i--) {
+ args = [funcs[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ };
+ _.after = function(times, func) {
+ if (times <= 0) return func();
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+ _.keys = nativeKeys || function(obj) {
+ if (obj !== Object(obj)) throw new TypeError('Invalid object');
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
+ return keys;
+ };
+ _.values = function(obj) {
+ var values = [];
+ for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
+ return values;
+ };
+ _.pairs = function(obj) {
+ var pairs = [];
+ for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
+ return pairs;
+ };
+ _.invert = function(obj) {
+ var result = {};
+ for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
+ return result;
+ };
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+ _.extend = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ if (source) {
+ for (var prop in source) {
+ obj[prop] = source[prop];
+ }
+ }
+ });
+ return obj;
+ };
+ _.pick = function(obj) {
+ var copy = {};
+ var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+ each(keys, function(key) {
+ if (key in obj) copy[key] = obj[key];
+ });
+ return copy;
+ };
+ _.omit = function(obj) {
+ var copy = {};
+ var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+ for (var key in obj) {
+ if (!_.contains(keys, key)) copy[key] = obj[key];
+ }
+ return copy;
+ };
+ _.defaults = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ if (source) {
+ for (var prop in source) {
+ if (obj[prop] == null) obj[prop] = source[prop];
+ }
+ }
+ });
+ return obj;
+ };
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+ var eq = function(a, b, aStack, bStack) {
+ if (a === b) return a !== 0 || 1 / a == 1 / b;
+ if (a == null || b == null) return a === b;
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ var className = toString.call(a);
+ if (className != toString.call(b)) return false;
+ switch (className) {
+ case '[object String]':
+ return a == String(b);
+ case '[object Number]':
+ return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+ case '[object Date]':
+ case '[object Boolean]':
+ return +a == +b;
+ case '[object RegExp]':
+ return a.source == b.source &&
+ a.global == b.global &&
+ a.multiline == b.multiline &&
+ a.ignoreCase == b.ignoreCase;
+ }
+ if (typeof a != 'object' || typeof b != 'object') return false;
+ var length = aStack.length;
+ while (length--) {
+ if (aStack[length] == a) return bStack[length] == b;
+ }
+ aStack.push(a);
+ bStack.push(b);
+ var size = 0, result = true;
+ if (className == '[object Array]') {
+ size = a.length;
+ result = size == b.length;
+ if (result) {
+ while (size--) {
+ if (!(result = eq(a[size], b[size], aStack, bStack))) break;
+ }
+ }
+ } else {
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
+ _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
+ return false;
+ }
+ for (var key in a) {
+ if (_.has(a, key)) {
+ size++;
+ if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
+ }
+ }
+ if (result) {
+ for (key in b) {
+ if (_.has(b, key) && !(size--)) break;
+ }
+ result = !size;
+ }
+ }
+ aStack.pop();
+ bStack.pop();
+ return result;
+ };
+ _.isEqual = function(a, b) {
+ return eq(a, b, [], []);
+ };
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+ for (var key in obj) if (_.has(obj, key)) return false;
+ return true;
+ };
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) == '[object Array]';
+ };
+ _.isObject = function(obj) {
+ return obj === Object(obj);
+ };
+ each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) == '[object ' + name + ']';
+ };
+ });
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return !!(obj && _.has(obj, 'callee'));
+ };
+ }
+ if (typeof (/./) !== 'function') {
+ _.isFunction = function(obj) {
+ return typeof obj === 'function';
+ };
+ }
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj != +obj;
+ };
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
+ };
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+ _.has = function(obj, key) {
+ return hasOwnProperty.call(obj, key);
+ };
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+ _.identity = function(value) {
+ return value;
+ };
+ _.times = function(n, iterator, context) {
+ var accum = Array(n);
+ for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
+ return accum;
+ };
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+ var entityMap = {
+ escape: {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/'
+ }
+ };
+ entityMap.unescape = _.invert(entityMap.escape);
+ var entityRegexes = {
+ escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
+ unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
+ };
+ _.each(['escape', 'unescape'], function(method) {
+ _[method] = function(string) {
+ if (string == null) return '';
+ return ('' + string).replace(entityRegexes[method], function(match) {
+ return entityMap[method][match];
+ });
+ };
+ });
+ _.result = function(object, property) {
+ if (object == null) return null;
+ var value = object[property];
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+ _.mixin = function(obj) {
+ each(_.functions(obj), function(name){
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result.call(this, func.apply(_, args));
+ };
+ });
+ };
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+ var noMatch = /(.)^/;
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\t': 't',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
+ _.template = function(text, data, settings) {
+ var render;
+ settings = _.defaults({}, settings, _.templateSettings);
+ var matcher = new RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset)
+ .replace(escaper, function(match) { return '\\' + escapes[match]; });
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ }
+ if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ }
+ if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+ index = offset + match.length;
+ return match;
+ });
+ source += "';\n";
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + "return __p;\n";
+
+ try {
+ render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ if (data) return render(data, _);
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+ template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
+
+ return template;
+ };
+ _.chain = function(obj) {
+ return _(obj).chain();
+ };
+ var result = function(obj) {
+ return this._chain ? _(obj).chain() : obj;
+ };
+ _.mixin(_);
+ each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
+ return result.call(this, obj);
+ };
+ });
+ each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result.call(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ _.extend(_.prototype, {
+ chain: function() {
+ this._chain = true;
+ return this;
+ },
+ value: function() {
+ return this._wrapped;
+ }
+
+ });
+
+}).call(this);
+
+})()
+},
+{}]
+},{},["E/GbHF"])
+;
+
+function req() {return require.apply(this, arguments)}
+module.exports = req("jshint");
+
});
\ No newline at end of file