mirror of
https://github.com/overte-org/overte.git
synced 2025-05-01 14:05:02 +02:00
Instead of calling glutSolidSphere, just call Application::getInstance()->getGeometryCache()->renderSphere(...) - replaced all the instances of "glutSolidSphere" - Changed the atmosphere shaders so instead of drawing a sphere of the size of the atmosphere, we draw a unit sphere, the vertices get scaled at the right radius in th vertex shader using fOuterRadius
9980 lines
No EOL
254 KiB
JavaScript
9980 lines
No EOL
254 KiB
JavaScript
"no use strict";
|
|
;(function(window) {
|
|
if (typeof window.window != "undefined" && window.document) {
|
|
return;
|
|
}
|
|
|
|
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;
|
|
|
|
window.normalizeModule = function(parentId, moduleName) {
|
|
if (moduleName.indexOf("!") !== -1) {
|
|
var chunks = moduleName.split("!");
|
|
return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]);
|
|
}
|
|
if (moduleName.charAt(0) == ".") {
|
|
var base = parentId.split("/").slice(0, -1).join("/");
|
|
moduleName = base + "/" + moduleName;
|
|
|
|
while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
|
|
var previous = moduleName;
|
|
moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
|
|
}
|
|
}
|
|
|
|
return moduleName;
|
|
};
|
|
|
|
window.require = function(parentId, id) {
|
|
if (!id) {
|
|
id = parentId
|
|
parentId = null;
|
|
}
|
|
if (!id.charAt)
|
|
throw new Error("worker.js require() accepts only (parentId, id) as arguments");
|
|
|
|
id = normalizeModule(parentId, id);
|
|
|
|
var module = require.modules[id];
|
|
if (module) {
|
|
if (!module.initialized) {
|
|
module.initialized = true;
|
|
module.exports = module.factory().exports;
|
|
}
|
|
return module.exports;
|
|
}
|
|
|
|
var chunks = id.split("/");
|
|
chunks[0] = require.tlns[chunks[0]] || chunks[0];
|
|
var path = chunks.join("/") + ".js";
|
|
|
|
require.id = id;
|
|
importScripts(path);
|
|
return require(parentId, id);
|
|
};
|
|
|
|
require.modules = {};
|
|
require.tlns = {};
|
|
|
|
window.define = function(id, deps, factory) {
|
|
if (arguments.length == 2) {
|
|
factory = deps;
|
|
if (typeof id != "string") {
|
|
deps = id;
|
|
id = require.id;
|
|
}
|
|
} else if (arguments.length == 1) {
|
|
factory = id;
|
|
id = require.id;
|
|
}
|
|
|
|
if (id.indexOf("text!") === 0)
|
|
return;
|
|
|
|
var req = function(deps, factory) {
|
|
return require(id, deps, factory);
|
|
};
|
|
|
|
require.modules[id] = {
|
|
exports: {},
|
|
factory: function() {
|
|
var module = this;
|
|
var returnExports = factory(req, module.exports, module);
|
|
if (returnExports)
|
|
module.exports = returnExports;
|
|
return module;
|
|
}
|
|
};
|
|
};
|
|
|
|
window.initBaseUrls = function initBaseUrls(topLevelNamespaces) {
|
|
require.tlns = topLevelNamespaces;
|
|
}
|
|
|
|
window.initSender = function initSender() {
|
|
|
|
var EventEmitter = require("ace/lib/event_emitter").EventEmitter;
|
|
var oop = require("ace/lib/oop");
|
|
|
|
var Sender = function() {};
|
|
|
|
(function() {
|
|
|
|
oop.implement(this, EventEmitter);
|
|
|
|
this.callback = function(data, callbackId) {
|
|
postMessage({
|
|
type: "call",
|
|
id: callbackId,
|
|
data: data
|
|
});
|
|
};
|
|
|
|
this.emit = function(name, data) {
|
|
postMessage({
|
|
type: "event",
|
|
name: name,
|
|
data: data
|
|
});
|
|
};
|
|
|
|
}).call(Sender.prototype);
|
|
|
|
return new Sender();
|
|
}
|
|
|
|
window.main = null;
|
|
window.sender = null;
|
|
|
|
window.onmessage = function(e) {
|
|
var msg = e.data;
|
|
if (msg.command) {
|
|
if (main[msg.command])
|
|
main[msg.command].apply(main, msg.args);
|
|
else
|
|
throw new Error("Unknown command:" + msg.command);
|
|
}
|
|
else if (msg.init) {
|
|
initBaseUrls(msg.tlns);
|
|
require("ace/lib/es5-shim");
|
|
sender = initSender();
|
|
var clazz = require(msg.module)[msg.classname];
|
|
main = new clazz(sender);
|
|
}
|
|
else if (msg.event && sender) {
|
|
sender._emit(msg.event, msg.data);
|
|
}
|
|
};
|
|
})(this);
|
|
|
|
ace.define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) {
|
|
|
|
|
|
var EventEmitter = {};
|
|
var stopPropagation = function() { this.propagationStopped = true; };
|
|
var preventDefault = function() { this.defaultPrevented = true; };
|
|
|
|
EventEmitter._emit =
|
|
EventEmitter._dispatchEvent = function(eventName, e) {
|
|
this._eventRegistry || (this._eventRegistry = {});
|
|
this._defaultHandlers || (this._defaultHandlers = {});
|
|
|
|
var listeners = this._eventRegistry[eventName] || [];
|
|
var defaultHandler = this._defaultHandlers[eventName];
|
|
if (!listeners.length && !defaultHandler)
|
|
return;
|
|
|
|
if (typeof e != "object" || !e)
|
|
e = {};
|
|
|
|
if (!e.type)
|
|
e.type = eventName;
|
|
if (!e.stopPropagation)
|
|
e.stopPropagation = stopPropagation;
|
|
if (!e.preventDefault)
|
|
e.preventDefault = preventDefault;
|
|
|
|
for (var i=0; i<listeners.length; i++) {
|
|
listeners[i](e, this);
|
|
if (e.propagationStopped)
|
|
break;
|
|
}
|
|
|
|
if (defaultHandler && !e.defaultPrevented)
|
|
return defaultHandler(e, this);
|
|
};
|
|
|
|
|
|
EventEmitter._signal = function(eventName, e) {
|
|
var listeners = (this._eventRegistry || {})[eventName];
|
|
if (!listeners)
|
|
return;
|
|
|
|
for (var i=0; i<listeners.length; i++)
|
|
listeners[i](e, this);
|
|
};
|
|
|
|
EventEmitter.once = function(eventName, callback) {
|
|
var _self = this;
|
|
callback && this.addEventListener(eventName, function newCallback() {
|
|
_self.removeEventListener(eventName, newCallback);
|
|
callback.apply(null, arguments);
|
|
});
|
|
};
|
|
|
|
|
|
EventEmitter.setDefaultHandler = function(eventName, callback) {
|
|
var handlers = this._defaultHandlers
|
|
if (!handlers)
|
|
handlers = this._defaultHandlers = {_disabled_: {}};
|
|
|
|
if (handlers[eventName]) {
|
|
var old = handlers[eventName];
|
|
var disabled = handlers._disabled_[eventName];
|
|
if (!disabled)
|
|
handlers._disabled_[eventName] = disabled = [];
|
|
disabled.push(old);
|
|
var i = disabled.indexOf(callback);
|
|
if (i != -1)
|
|
disabled.splice(i, 1);
|
|
}
|
|
handlers[eventName] = callback;
|
|
};
|
|
EventEmitter.removeDefaultHandler = function(eventName, callback) {
|
|
var handlers = this._defaultHandlers
|
|
if (!handlers)
|
|
return;
|
|
var disabled = handlers._disabled_[eventName];
|
|
|
|
if (handlers[eventName] == callback) {
|
|
var old = handlers[eventName];
|
|
if (disabled)
|
|
this.setDefaultHandler(eventName, disabled.pop());
|
|
} else if (disabled) {
|
|
var i = disabled.indexOf(callback);
|
|
if (i != -1)
|
|
disabled.splice(i, 1);
|
|
}
|
|
};
|
|
|
|
EventEmitter.on =
|
|
EventEmitter.addEventListener = function(eventName, callback, capturing) {
|
|
this._eventRegistry = this._eventRegistry || {};
|
|
|
|
var listeners = this._eventRegistry[eventName];
|
|
if (!listeners)
|
|
listeners = this._eventRegistry[eventName] = [];
|
|
|
|
if (listeners.indexOf(callback) == -1)
|
|
listeners[capturing ? "unshift" : "push"](callback);
|
|
return callback;
|
|
};
|
|
|
|
EventEmitter.off =
|
|
EventEmitter.removeListener =
|
|
EventEmitter.removeEventListener = function(eventName, callback) {
|
|
this._eventRegistry = this._eventRegistry || {};
|
|
|
|
var listeners = this._eventRegistry[eventName];
|
|
if (!listeners)
|
|
return;
|
|
|
|
var index = listeners.indexOf(callback);
|
|
if (index !== -1)
|
|
listeners.splice(index, 1);
|
|
};
|
|
|
|
EventEmitter.removeAllListeners = function(eventName) {
|
|
if (this._eventRegistry) this._eventRegistry[eventName] = [];
|
|
};
|
|
|
|
exports.EventEmitter = EventEmitter;
|
|
|
|
});
|
|
|
|
ace.define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
|
|
|
|
|
|
exports.inherits = (function() {
|
|
var tempCtor = function() {};
|
|
return function(ctor, superCtor) {
|
|
tempCtor.prototype = superCtor.prototype;
|
|
ctor.super_ = superCtor.prototype;
|
|
ctor.prototype = new tempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
};
|
|
}());
|
|
|
|
exports.mixin = function(obj, mixin) {
|
|
for (var key in mixin) {
|
|
obj[key] = mixin[key];
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
exports.implement = function(proto, mixin) {
|
|
exports.mixin(proto, mixin);
|
|
};
|
|
|
|
});
|
|
|
|
ace.define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) {
|
|
|
|
function Empty() {}
|
|
|
|
if (!Function.prototype.bind) {
|
|
Function.prototype.bind = function bind(that) { // .length is 1
|
|
var target = this;
|
|
if (typeof target != "function") {
|
|
throw new TypeError("Function.prototype.bind called on incompatible " + target);
|
|
}
|
|
var args = slice.call(arguments, 1); // for normal call
|
|
var bound = function () {
|
|
|
|
if (this instanceof bound) {
|
|
|
|
var result = target.apply(
|
|
this,
|
|
args.concat(slice.call(arguments))
|
|
);
|
|
if (Object(result) === result) {
|
|
return result;
|
|
}
|
|
return this;
|
|
|
|
} else {
|
|
return target.apply(
|
|
that,
|
|
args.concat(slice.call(arguments))
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
if(target.prototype) {
|
|
Empty.prototype = target.prototype;
|
|
bound.prototype = new Empty();
|
|
Empty.prototype = null;
|
|
}
|
|
return bound;
|
|
};
|
|
}
|
|
var call = Function.prototype.call;
|
|
var prototypeOfArray = Array.prototype;
|
|
var prototypeOfObject = Object.prototype;
|
|
var slice = prototypeOfArray.slice;
|
|
var _toString = call.bind(prototypeOfObject.toString);
|
|
var owns = call.bind(prototypeOfObject.hasOwnProperty);
|
|
var defineGetter;
|
|
var defineSetter;
|
|
var lookupGetter;
|
|
var lookupSetter;
|
|
var supportsAccessors;
|
|
if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
|
|
defineGetter = call.bind(prototypeOfObject.__defineGetter__);
|
|
defineSetter = call.bind(prototypeOfObject.__defineSetter__);
|
|
lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
|
|
lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
|
|
}
|
|
if ([1,2].splice(0).length != 2) {
|
|
if(function() { // test IE < 9 to splice bug - see issue #138
|
|
function makeArray(l) {
|
|
var a = new Array(l+2);
|
|
a[0] = a[1] = 0;
|
|
return a;
|
|
}
|
|
var array = [], lengthBefore;
|
|
|
|
array.splice.apply(array, makeArray(20));
|
|
array.splice.apply(array, makeArray(26));
|
|
|
|
lengthBefore = array.length; //46
|
|
array.splice(5, 0, "XXX"); // add one element
|
|
|
|
lengthBefore + 1 == array.length
|
|
|
|
if (lengthBefore + 1 == array.length) {
|
|
return true;// has right splice implementation without bugs
|
|
}
|
|
}()) {//IE 6/7
|
|
var array_splice = Array.prototype.splice;
|
|
Array.prototype.splice = function(start, deleteCount) {
|
|
if (!arguments.length) {
|
|
return [];
|
|
} else {
|
|
return array_splice.apply(this, [
|
|
start === void 0 ? 0 : start,
|
|
deleteCount === void 0 ? (this.length - start) : deleteCount
|
|
].concat(slice.call(arguments, 2)))
|
|
}
|
|
};
|
|
} else {//IE8
|
|
Array.prototype.splice = function(pos, removeCount){
|
|
var length = this.length;
|
|
if (pos > 0) {
|
|
if (pos > length)
|
|
pos = length;
|
|
} else if (pos == void 0) {
|
|
pos = 0;
|
|
} else if (pos < 0) {
|
|
pos = Math.max(length + pos, 0);
|
|
}
|
|
|
|
if (!(pos+removeCount < length))
|
|
removeCount = length - pos;
|
|
|
|
var removed = this.slice(pos, pos+removeCount);
|
|
var insert = slice.call(arguments, 2);
|
|
var add = insert.length;
|
|
if (pos === length) {
|
|
if (add) {
|
|
this.push.apply(this, insert);
|
|
}
|
|
} else {
|
|
var remove = Math.min(removeCount, length - pos);
|
|
var tailOldPos = pos + remove;
|
|
var tailNewPos = tailOldPos + add - remove;
|
|
var tailCount = length - tailOldPos;
|
|
var lengthAfterRemove = length - remove;
|
|
|
|
if (tailNewPos < tailOldPos) { // case A
|
|
for (var i = 0; i < tailCount; ++i) {
|
|
this[tailNewPos+i] = this[tailOldPos+i];
|
|
}
|
|
} else if (tailNewPos > tailOldPos) { // case B
|
|
for (i = tailCount; i--; ) {
|
|
this[tailNewPos+i] = this[tailOldPos+i];
|
|
}
|
|
} // else, add == remove (nothing to do)
|
|
|
|
if (add && pos === lengthAfterRemove) {
|
|
this.length = lengthAfterRemove; // truncate array
|
|
this.push.apply(this, insert);
|
|
} else {
|
|
this.length = lengthAfterRemove + add; // reserves space
|
|
for (i = 0; i < add; ++i) {
|
|
this[pos+i] = insert[i];
|
|
}
|
|
}
|
|
}
|
|
return removed;
|
|
};
|
|
}
|
|
}
|
|
if (!Array.isArray) {
|
|
Array.isArray = function isArray(obj) {
|
|
return _toString(obj) == "[object Array]";
|
|
};
|
|
}
|
|
var boxedString = Object("a"),
|
|
splitString = boxedString[0] != "a" || !(0 in boxedString);
|
|
|
|
if (!Array.prototype.forEach) {
|
|
Array.prototype.forEach = function forEach(fun /*, thisp*/) {
|
|
var object = toObject(this),
|
|
self = splitString && _toString(this) == "[object String]" ?
|
|
this.split("") :
|
|
object,
|
|
thisp = arguments[1],
|
|
i = -1,
|
|
length = self.length >>> 0;
|
|
if (_toString(fun) != "[object Function]") {
|
|
throw new TypeError(); // TODO message
|
|
}
|
|
|
|
while (++i < length) {
|
|
if (i in self) {
|
|
fun.call(thisp, self[i], i, object);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
if (!Array.prototype.map) {
|
|
Array.prototype.map = function map(fun /*, thisp*/) {
|
|
var object = toObject(this),
|
|
self = splitString && _toString(this) == "[object String]" ?
|
|
this.split("") :
|
|
object,
|
|
length = self.length >>> 0,
|
|
result = Array(length),
|
|
thisp = arguments[1];
|
|
if (_toString(fun) != "[object Function]") {
|
|
throw new TypeError(fun + " is not a function");
|
|
}
|
|
|
|
for (var i = 0; i < length; i++) {
|
|
if (i in self)
|
|
result[i] = fun.call(thisp, self[i], i, object);
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
if (!Array.prototype.filter) {
|
|
Array.prototype.filter = function filter(fun /*, thisp */) {
|
|
var object = toObject(this),
|
|
self = splitString && _toString(this) == "[object String]" ?
|
|
this.split("") :
|
|
object,
|
|
length = self.length >>> 0,
|
|
result = [],
|
|
value,
|
|
thisp = arguments[1];
|
|
if (_toString(fun) != "[object Function]") {
|
|
throw new TypeError(fun + " is not a function");
|
|
}
|
|
|
|
for (var i = 0; i < length; i++) {
|
|
if (i in self) {
|
|
value = self[i];
|
|
if (fun.call(thisp, value, i, object)) {
|
|
result.push(value);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
if (!Array.prototype.every) {
|
|
Array.prototype.every = function every(fun /*, thisp */) {
|
|
var object = toObject(this),
|
|
self = splitString && _toString(this) == "[object String]" ?
|
|
this.split("") :
|
|
object,
|
|
length = self.length >>> 0,
|
|
thisp = arguments[1];
|
|
if (_toString(fun) != "[object Function]") {
|
|
throw new TypeError(fun + " is not a function");
|
|
}
|
|
|
|
for (var i = 0; i < length; i++) {
|
|
if (i in self && !fun.call(thisp, self[i], i, object)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
}
|
|
if (!Array.prototype.some) {
|
|
Array.prototype.some = function some(fun /*, thisp */) {
|
|
var object = toObject(this),
|
|
self = splitString && _toString(this) == "[object String]" ?
|
|
this.split("") :
|
|
object,
|
|
length = self.length >>> 0,
|
|
thisp = arguments[1];
|
|
if (_toString(fun) != "[object Function]") {
|
|
throw new TypeError(fun + " is not a function");
|
|
}
|
|
|
|
for (var i = 0; i < length; i++) {
|
|
if (i in self && fun.call(thisp, self[i], i, object)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
}
|
|
if (!Array.prototype.reduce) {
|
|
Array.prototype.reduce = function reduce(fun /*, initial*/) {
|
|
var object = toObject(this),
|
|
self = splitString && _toString(this) == "[object String]" ?
|
|
this.split("") :
|
|
object,
|
|
length = self.length >>> 0;
|
|
if (_toString(fun) != "[object Function]") {
|
|
throw new TypeError(fun + " is not a function");
|
|
}
|
|
if (!length && arguments.length == 1) {
|
|
throw new TypeError("reduce of empty array with no initial value");
|
|
}
|
|
|
|
var i = 0;
|
|
var result;
|
|
if (arguments.length >= 2) {
|
|
result = arguments[1];
|
|
} else {
|
|
do {
|
|
if (i in self) {
|
|
result = self[i++];
|
|
break;
|
|
}
|
|
if (++i >= length) {
|
|
throw new TypeError("reduce of empty array with no initial value");
|
|
}
|
|
} while (true);
|
|
}
|
|
|
|
for (; i < length; i++) {
|
|
if (i in self) {
|
|
result = fun.call(void 0, result, self[i], i, object);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|
|
}
|
|
if (!Array.prototype.reduceRight) {
|
|
Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
|
|
var object = toObject(this),
|
|
self = splitString && _toString(this) == "[object String]" ?
|
|
this.split("") :
|
|
object,
|
|
length = self.length >>> 0;
|
|
if (_toString(fun) != "[object Function]") {
|
|
throw new TypeError(fun + " is not a function");
|
|
}
|
|
if (!length && arguments.length == 1) {
|
|
throw new TypeError("reduceRight of empty array with no initial value");
|
|
}
|
|
|
|
var result, i = length - 1;
|
|
if (arguments.length >= 2) {
|
|
result = arguments[1];
|
|
} else {
|
|
do {
|
|
if (i in self) {
|
|
result = self[i--];
|
|
break;
|
|
}
|
|
if (--i < 0) {
|
|
throw new TypeError("reduceRight of empty array with no initial value");
|
|
}
|
|
} while (true);
|
|
}
|
|
|
|
do {
|
|
if (i in this) {
|
|
result = fun.call(void 0, result, self[i], i, object);
|
|
}
|
|
} while (i--);
|
|
|
|
return result;
|
|
};
|
|
}
|
|
if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {
|
|
Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
|
|
var self = splitString && _toString(this) == "[object String]" ?
|
|
this.split("") :
|
|
toObject(this),
|
|
length = self.length >>> 0;
|
|
|
|
if (!length) {
|
|
return -1;
|
|
}
|
|
|
|
var i = 0;
|
|
if (arguments.length > 1) {
|
|
i = toInteger(arguments[1]);
|
|
}
|
|
i = i >= 0 ? i : Math.max(0, length + i);
|
|
for (; i < length; i++) {
|
|
if (i in self && self[i] === sought) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
}
|
|
if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {
|
|
Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
|
|
var self = splitString && _toString(this) == "[object String]" ?
|
|
this.split("") :
|
|
toObject(this),
|
|
length = self.length >>> 0;
|
|
|
|
if (!length) {
|
|
return -1;
|
|
}
|
|
var i = length - 1;
|
|
if (arguments.length > 1) {
|
|
i = Math.min(i, toInteger(arguments[1]));
|
|
}
|
|
i = i >= 0 ? i : length - Math.abs(i);
|
|
for (; i >= 0; i--) {
|
|
if (i in self && sought === self[i]) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
}
|
|
if (!Object.getPrototypeOf) {
|
|
Object.getPrototypeOf = function getPrototypeOf(object) {
|
|
return object.__proto__ || (
|
|
object.constructor ?
|
|
object.constructor.prototype :
|
|
prototypeOfObject
|
|
);
|
|
};
|
|
}
|
|
if (!Object.getOwnPropertyDescriptor) {
|
|
var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " +
|
|
"non-object: ";
|
|
Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
|
|
if ((typeof object != "object" && typeof object != "function") || object === null)
|
|
throw new TypeError(ERR_NON_OBJECT + object);
|
|
if (!owns(object, property))
|
|
return;
|
|
|
|
var descriptor, getter, setter;
|
|
descriptor = { enumerable: true, configurable: true };
|
|
if (supportsAccessors) {
|
|
var prototype = object.__proto__;
|
|
object.__proto__ = prototypeOfObject;
|
|
|
|
var getter = lookupGetter(object, property);
|
|
var setter = lookupSetter(object, property);
|
|
object.__proto__ = prototype;
|
|
|
|
if (getter || setter) {
|
|
if (getter) descriptor.get = getter;
|
|
if (setter) descriptor.set = setter;
|
|
return descriptor;
|
|
}
|
|
}
|
|
descriptor.value = object[property];
|
|
return descriptor;
|
|
};
|
|
}
|
|
if (!Object.getOwnPropertyNames) {
|
|
Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
|
|
return Object.keys(object);
|
|
};
|
|
}
|
|
if (!Object.create) {
|
|
var createEmpty;
|
|
if (Object.prototype.__proto__ === null) {
|
|
createEmpty = function () {
|
|
return { "__proto__": null };
|
|
};
|
|
} else {
|
|
createEmpty = function () {
|
|
var empty = {};
|
|
for (var i in empty)
|
|
empty[i] = null;
|
|
empty.constructor =
|
|
empty.hasOwnProperty =
|
|
empty.propertyIsEnumerable =
|
|
empty.isPrototypeOf =
|
|
empty.toLocaleString =
|
|
empty.toString =
|
|
empty.valueOf =
|
|
empty.__proto__ = null;
|
|
return empty;
|
|
}
|
|
}
|
|
|
|
Object.create = function create(prototype, properties) {
|
|
var object;
|
|
if (prototype === null) {
|
|
object = createEmpty();
|
|
} else {
|
|
if (typeof prototype != "object")
|
|
throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
|
|
var Type = function () {};
|
|
Type.prototype = prototype;
|
|
object = new Type();
|
|
object.__proto__ = prototype;
|
|
}
|
|
if (properties !== void 0)
|
|
Object.defineProperties(object, properties);
|
|
return object;
|
|
};
|
|
}
|
|
|
|
function doesDefinePropertyWork(object) {
|
|
try {
|
|
Object.defineProperty(object, "sentinel", {});
|
|
return "sentinel" in object;
|
|
} catch (exception) {
|
|
}
|
|
}
|
|
if (Object.defineProperty) {
|
|
var definePropertyWorksOnObject = doesDefinePropertyWork({});
|
|
var definePropertyWorksOnDom = typeof document == "undefined" ||
|
|
doesDefinePropertyWork(document.createElement("div"));
|
|
if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
|
|
var definePropertyFallback = Object.defineProperty;
|
|
}
|
|
}
|
|
|
|
if (!Object.defineProperty || definePropertyFallback) {
|
|
var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
|
|
var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
|
|
var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
|
|
"on this javascript engine";
|
|
|
|
Object.defineProperty = function defineProperty(object, property, descriptor) {
|
|
if ((typeof object != "object" && typeof object != "function") || object === null)
|
|
throw new TypeError(ERR_NON_OBJECT_TARGET + object);
|
|
if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null)
|
|
throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
|
|
if (definePropertyFallback) {
|
|
try {
|
|
return definePropertyFallback.call(Object, object, property, descriptor);
|
|
} catch (exception) {
|
|
}
|
|
}
|
|
if (owns(descriptor, "value")) {
|
|
|
|
if (supportsAccessors && (lookupGetter(object, property) ||
|
|
lookupSetter(object, property)))
|
|
{
|
|
var prototype = object.__proto__;
|
|
object.__proto__ = prototypeOfObject;
|
|
delete object[property];
|
|
object[property] = descriptor.value;
|
|
object.__proto__ = prototype;
|
|
} else {
|
|
object[property] = descriptor.value;
|
|
}
|
|
} else {
|
|
if (!supportsAccessors)
|
|
throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
|
|
if (owns(descriptor, "get"))
|
|
defineGetter(object, property, descriptor.get);
|
|
if (owns(descriptor, "set"))
|
|
defineSetter(object, property, descriptor.set);
|
|
}
|
|
|
|
return object;
|
|
};
|
|
}
|
|
if (!Object.defineProperties) {
|
|
Object.defineProperties = function defineProperties(object, properties) {
|
|
for (var property in properties) {
|
|
if (owns(properties, property))
|
|
Object.defineProperty(object, property, properties[property]);
|
|
}
|
|
return object;
|
|
};
|
|
}
|
|
if (!Object.seal) {
|
|
Object.seal = function seal(object) {
|
|
return object;
|
|
};
|
|
}
|
|
if (!Object.freeze) {
|
|
Object.freeze = function freeze(object) {
|
|
return object;
|
|
};
|
|
}
|
|
try {
|
|
Object.freeze(function () {});
|
|
} catch (exception) {
|
|
Object.freeze = (function freeze(freezeObject) {
|
|
return function freeze(object) {
|
|
if (typeof object == "function") {
|
|
return object;
|
|
} else {
|
|
return freezeObject(object);
|
|
}
|
|
};
|
|
})(Object.freeze);
|
|
}
|
|
if (!Object.preventExtensions) {
|
|
Object.preventExtensions = function preventExtensions(object) {
|
|
return object;
|
|
};
|
|
}
|
|
if (!Object.isSealed) {
|
|
Object.isSealed = function isSealed(object) {
|
|
return false;
|
|
};
|
|
}
|
|
if (!Object.isFrozen) {
|
|
Object.isFrozen = function isFrozen(object) {
|
|
return false;
|
|
};
|
|
}
|
|
if (!Object.isExtensible) {
|
|
Object.isExtensible = function isExtensible(object) {
|
|
if (Object(object) === object) {
|
|
throw new TypeError(); // TODO message
|
|
}
|
|
var name = '';
|
|
while (owns(object, name)) {
|
|
name += '?';
|
|
}
|
|
object[name] = true;
|
|
var returnValue = owns(object, name);
|
|
delete object[name];
|
|
return returnValue;
|
|
};
|
|
}
|
|
if (!Object.keys) {
|
|
var hasDontEnumBug = true,
|
|
dontEnums = [
|
|
"toString",
|
|
"toLocaleString",
|
|
"valueOf",
|
|
"hasOwnProperty",
|
|
"isPrototypeOf",
|
|
"propertyIsEnumerable",
|
|
"constructor"
|
|
],
|
|
dontEnumsLength = dontEnums.length;
|
|
|
|
for (var key in {"toString": null}) {
|
|
hasDontEnumBug = false;
|
|
}
|
|
|
|
Object.keys = function keys(object) {
|
|
|
|
if (
|
|
(typeof object != "object" && typeof object != "function") ||
|
|
object === null
|
|
) {
|
|
throw new TypeError("Object.keys called on a non-object");
|
|
}
|
|
|
|
var keys = [];
|
|
for (var name in object) {
|
|
if (owns(object, name)) {
|
|
keys.push(name);
|
|
}
|
|
}
|
|
|
|
if (hasDontEnumBug) {
|
|
for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
|
|
var dontEnum = dontEnums[i];
|
|
if (owns(object, dontEnum)) {
|
|
keys.push(dontEnum);
|
|
}
|
|
}
|
|
}
|
|
return keys;
|
|
};
|
|
|
|
}
|
|
if (!Date.now) {
|
|
Date.now = function now() {
|
|
return new Date().getTime();
|
|
};
|
|
}
|
|
var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
|
|
"\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
|
|
"\u2029\uFEFF";
|
|
if (!String.prototype.trim || ws.trim()) {
|
|
ws = "[" + ws + "]";
|
|
var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
|
|
trimEndRegexp = new RegExp(ws + ws + "*$");
|
|
String.prototype.trim = function trim() {
|
|
return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
|
|
};
|
|
}
|
|
|
|
function toInteger(n) {
|
|
n = +n;
|
|
if (n !== n) { // isNaN
|
|
n = 0;
|
|
} else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {
|
|
n = (n > 0 || -1) * Math.floor(Math.abs(n));
|
|
}
|
|
return n;
|
|
}
|
|
|
|
function isPrimitive(input) {
|
|
var type = typeof input;
|
|
return (
|
|
input === null ||
|
|
type === "undefined" ||
|
|
type === "boolean" ||
|
|
type === "number" ||
|
|
type === "string"
|
|
);
|
|
}
|
|
|
|
function toPrimitive(input) {
|
|
var val, valueOf, toString;
|
|
if (isPrimitive(input)) {
|
|
return input;
|
|
}
|
|
valueOf = input.valueOf;
|
|
if (typeof valueOf === "function") {
|
|
val = valueOf.call(input);
|
|
if (isPrimitive(val)) {
|
|
return val;
|
|
}
|
|
}
|
|
toString = input.toString;
|
|
if (typeof toString === "function") {
|
|
val = toString.call(input);
|
|
if (isPrimitive(val)) {
|
|
return val;
|
|
}
|
|
}
|
|
throw new TypeError();
|
|
}
|
|
var toObject = function (o) {
|
|
if (o == null) { // this matches both null and undefined
|
|
throw new TypeError("can't convert "+o+" to object");
|
|
}
|
|
return Object(o);
|
|
};
|
|
|
|
});
|
|
|
|
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");
|
|
var Mirror = require("../worker/mirror").Mirror;
|
|
var lint = require("./javascript/jshint").JSHINT;
|
|
|
|
function startRegex(arr) {
|
|
return RegExp("^(" + arr.join("|") + ")");
|
|
}
|
|
|
|
var disabledWarningsRe = startRegex([
|
|
"Bad for in variable '(.+)'.",
|
|
'Missing "use strict"'
|
|
]);
|
|
var errorsRe = startRegex([
|
|
"Unexpected",
|
|
"Expected ",
|
|
"Confusing (plus|minus)",
|
|
"\\{a\\} unterminated regular expression",
|
|
"Unclosed ",
|
|
"Unmatched ",
|
|
"Unbegun comment",
|
|
"Bad invocation",
|
|
"Missing space after",
|
|
"Missing operator at"
|
|
]);
|
|
var infoRe = startRegex([
|
|
"Expected an assignment",
|
|
"Bad escapement of EOL",
|
|
"Unexpected comma",
|
|
"Unexpected space",
|
|
"Missing radix parameter.",
|
|
"A leading decimal point can",
|
|
"\\['{a}'\\] is better written in dot notation.",
|
|
"'{a}' used out of scope"
|
|
]);
|
|
|
|
var JavaScriptWorker = exports.JavaScriptWorker = function(sender) {
|
|
Mirror.call(this, sender);
|
|
this.setTimeout(500);
|
|
this.setOptions();
|
|
};
|
|
|
|
oop.inherits(JavaScriptWorker, Mirror);
|
|
|
|
(function() {
|
|
this.setOptions = function(options) {
|
|
this.options = options || {
|
|
esnext: true,
|
|
moz: true,
|
|
devel: true,
|
|
browser: true,
|
|
node: true,
|
|
laxcomma: true,
|
|
laxbreak: true,
|
|
lastsemic: true,
|
|
onevar: false,
|
|
passfail: false,
|
|
maxerr: 100,
|
|
expr: true,
|
|
multistr: true,
|
|
globalstrict: true
|
|
};
|
|
this.doc.getValue() && this.deferredUpdate.schedule(100);
|
|
};
|
|
|
|
this.changeOptions = function(newOptions) {
|
|
oop.mixin(this.options, newOptions);
|
|
this.doc.getValue() && this.deferredUpdate.schedule(100);
|
|
};
|
|
|
|
this.isValidJS = function(str) {
|
|
try {
|
|
eval("throw 0;" + str);
|
|
} catch(e) {
|
|
if (e === 0)
|
|
return true;
|
|
}
|
|
return false
|
|
};
|
|
|
|
this.onUpdate = function() {
|
|
var value = this.doc.getValue();
|
|
value = value.replace(/^#!.*\n/, "\n");
|
|
if (!value) {
|
|
this.sender.emit("jslint", []);
|
|
return;
|
|
}
|
|
var errors = [];
|
|
var maxErrorLevel = this.isValidJS(value) ? "warning" : "error";
|
|
lint(value, this.options);
|
|
var results = lint.errors;
|
|
|
|
var errorAdded = false
|
|
for (var i = 0; i < results.length; i++) {
|
|
var error = results[i];
|
|
if (!error)
|
|
continue;
|
|
var raw = error.raw;
|
|
var type = "warning";
|
|
|
|
if (raw == "Missing semicolon.") {
|
|
var str = error.evidence.substr(error.character);
|
|
str = str.charAt(str.search(/\S/));
|
|
if (maxErrorLevel == "error" && str && /[\w\d{(['"]/.test(str)) {
|
|
error.reason = 'Missing ";" before statement';
|
|
type = "error";
|
|
} else {
|
|
type = "info";
|
|
}
|
|
}
|
|
else if (disabledWarningsRe.test(raw)) {
|
|
continue;
|
|
}
|
|
else if (infoRe.test(raw)) {
|
|
type = "info"
|
|
}
|
|
else if (errorsRe.test(raw)) {
|
|
errorAdded = true;
|
|
type = maxErrorLevel;
|
|
}
|
|
else if (raw == "'{a}' is not defined.") {
|
|
type = "warning";
|
|
}
|
|
else if (raw == "'{a}' is defined but never used.") {
|
|
type = "info";
|
|
}
|
|
|
|
errors.push({
|
|
row: error.line-1,
|
|
column: error.character-1,
|
|
text: error.reason,
|
|
type: type,
|
|
raw: raw
|
|
});
|
|
|
|
if (errorAdded) {
|
|
}
|
|
}
|
|
|
|
this.sender.emit("jslint", errors);
|
|
};
|
|
|
|
}).call(JavaScriptWorker.prototype);
|
|
|
|
});
|
|
ace.define('ace/worker/mirror', ['require', 'exports', 'module' , 'ace/document', 'ace/lib/lang'], function(require, exports, module) {
|
|
|
|
|
|
var Document = require("../document").Document;
|
|
var lang = require("../lib/lang");
|
|
|
|
var Mirror = exports.Mirror = function(sender) {
|
|
this.sender = sender;
|
|
var doc = this.doc = new Document("");
|
|
|
|
var deferredUpdate = this.deferredUpdate = lang.delayedCall(this.onUpdate.bind(this));
|
|
|
|
var _self = this;
|
|
sender.on("change", function(e) {
|
|
doc.applyDeltas(e.data);
|
|
deferredUpdate.schedule(_self.$timeout);
|
|
});
|
|
};
|
|
|
|
(function() {
|
|
|
|
this.$timeout = 500;
|
|
|
|
this.setTimeout = function(timeout) {
|
|
this.$timeout = timeout;
|
|
};
|
|
|
|
this.setValue = function(value) {
|
|
this.doc.setValue(value);
|
|
this.deferredUpdate.schedule(this.$timeout);
|
|
};
|
|
|
|
this.getValue = function(callbackId) {
|
|
this.sender.callback(this.doc.getValue(), callbackId);
|
|
};
|
|
|
|
this.onUpdate = function() {
|
|
};
|
|
|
|
}).call(Mirror.prototype);
|
|
|
|
});
|
|
|
|
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");
|
|
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
|
var Range = require("./range").Range;
|
|
var Anchor = require("./anchor").Anchor;
|
|
|
|
var Document = function(text) {
|
|
this.$lines = [];
|
|
if (text.length == 0) {
|
|
this.$lines = [""];
|
|
} else if (Array.isArray(text)) {
|
|
this._insertLines(0, text);
|
|
} else {
|
|
this.insert({row: 0, column:0}, text);
|
|
}
|
|
};
|
|
|
|
(function() {
|
|
|
|
oop.implement(this, EventEmitter);
|
|
this.setValue = function(text) {
|
|
var len = this.getLength();
|
|
this.remove(new Range(0, 0, len, this.getLine(len-1).length));
|
|
this.insert({row: 0, column:0}, text);
|
|
};
|
|
this.getValue = function() {
|
|
return this.getAllLines().join(this.getNewLineCharacter());
|
|
};
|
|
this.createAnchor = function(row, column) {
|
|
return new Anchor(this, row, column);
|
|
};
|
|
if ("aaa".split(/a/).length == 0)
|
|
this.$split = function(text) {
|
|
return text.replace(/\r\n|\r/g, "\n").split("\n");
|
|
}
|
|
else
|
|
this.$split = function(text) {
|
|
return text.split(/\r\n|\r|\n/);
|
|
};
|
|
|
|
|
|
this.$detectNewLine = function(text) {
|
|
var match = text.match(/^.*?(\r\n|\r|\n)/m);
|
|
this.$autoNewLine = match ? match[1] : "\n";
|
|
};
|
|
this.getNewLineCharacter = function() {
|
|
switch (this.$newLineMode) {
|
|
case "windows":
|
|
return "\r\n";
|
|
case "unix":
|
|
return "\n";
|
|
default:
|
|
return this.$autoNewLine;
|
|
}
|
|
};
|
|
|
|
this.$autoNewLine = "\n";
|
|
this.$newLineMode = "auto";
|
|
this.setNewLineMode = function(newLineMode) {
|
|
if (this.$newLineMode === newLineMode)
|
|
return;
|
|
|
|
this.$newLineMode = newLineMode;
|
|
};
|
|
this.getNewLineMode = function() {
|
|
return this.$newLineMode;
|
|
};
|
|
this.isNewLine = function(text) {
|
|
return (text == "\r\n" || text == "\r" || text == "\n");
|
|
};
|
|
this.getLine = function(row) {
|
|
return this.$lines[row] || "";
|
|
};
|
|
this.getLines = function(firstRow, lastRow) {
|
|
return this.$lines.slice(firstRow, lastRow + 1);
|
|
};
|
|
this.getAllLines = function() {
|
|
return this.getLines(0, this.getLength());
|
|
};
|
|
this.getLength = function() {
|
|
return this.$lines.length;
|
|
};
|
|
this.getTextRange = function(range) {
|
|
if (range.start.row == range.end.row) {
|
|
return this.getLine(range.start.row)
|
|
.substring(range.start.column, range.end.column);
|
|
}
|
|
var lines = this.getLines(range.start.row, range.end.row);
|
|
lines[0] = (lines[0] || "").substring(range.start.column);
|
|
var l = lines.length - 1;
|
|
if (range.end.row - range.start.row == l)
|
|
lines[l] = lines[l].substring(0, range.end.column);
|
|
return lines.join(this.getNewLineCharacter());
|
|
};
|
|
|
|
this.$clipPosition = function(position) {
|
|
var length = this.getLength();
|
|
if (position.row >= length) {
|
|
position.row = Math.max(0, length - 1);
|
|
position.column = this.getLine(length-1).length;
|
|
} else if (position.row < 0)
|
|
position.row = 0;
|
|
return position;
|
|
};
|
|
this.insert = function(position, text) {
|
|
if (!text || text.length === 0)
|
|
return position;
|
|
|
|
position = this.$clipPosition(position);
|
|
if (this.getLength() <= 1)
|
|
this.$detectNewLine(text);
|
|
|
|
var lines = this.$split(text);
|
|
var firstLine = lines.splice(0, 1)[0];
|
|
var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
|
|
|
|
position = this.insertInLine(position, firstLine);
|
|
if (lastLine !== null) {
|
|
position = this.insertNewLine(position); // terminate first line
|
|
position = this._insertLines(position.row, lines);
|
|
position = this.insertInLine(position, lastLine || "");
|
|
}
|
|
return position;
|
|
};
|
|
this.insertLines = function(row, lines) {
|
|
if (row >= this.getLength())
|
|
return this.insert({row: row, column: 0}, "\n" + lines.join("\n"));
|
|
return this._insertLines(Math.max(row, 0), lines);
|
|
};
|
|
this._insertLines = function(row, lines) {
|
|
if (lines.length == 0)
|
|
return {row: row, column: 0};
|
|
if (lines.length > 0xFFFF) {
|
|
var end = this._insertLines(row, lines.slice(0xFFFF));
|
|
lines = lines.slice(0, 0xFFFF);
|
|
}
|
|
|
|
var args = [row, 0];
|
|
args.push.apply(args, lines);
|
|
this.$lines.splice.apply(this.$lines, args);
|
|
|
|
var range = new Range(row, 0, row + lines.length, 0);
|
|
var delta = {
|
|
action: "insertLines",
|
|
range: range,
|
|
lines: lines
|
|
};
|
|
this._emit("change", { data: delta });
|
|
return end || range.end;
|
|
};
|
|
this.insertNewLine = function(position) {
|
|
position = this.$clipPosition(position);
|
|
var line = this.$lines[position.row] || "";
|
|
|
|
this.$lines[position.row] = line.substring(0, position.column);
|
|
this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
|
|
|
|
var end = {
|
|
row : position.row + 1,
|
|
column : 0
|
|
};
|
|
|
|
var delta = {
|
|
action: "insertText",
|
|
range: Range.fromPoints(position, end),
|
|
text: this.getNewLineCharacter()
|
|
};
|
|
this._emit("change", { data: delta });
|
|
|
|
return end;
|
|
};
|
|
this.insertInLine = function(position, text) {
|
|
if (text.length == 0)
|
|
return position;
|
|
|
|
var line = this.$lines[position.row] || "";
|
|
|
|
this.$lines[position.row] = line.substring(0, position.column) + text
|
|
+ line.substring(position.column);
|
|
|
|
var end = {
|
|
row : position.row,
|
|
column : position.column + text.length
|
|
};
|
|
|
|
var delta = {
|
|
action: "insertText",
|
|
range: Range.fromPoints(position, end),
|
|
text: text
|
|
};
|
|
this._emit("change", { data: delta });
|
|
|
|
return end;
|
|
};
|
|
this.remove = function(range) {
|
|
range.start = this.$clipPosition(range.start);
|
|
range.end = this.$clipPosition(range.end);
|
|
|
|
if (range.isEmpty())
|
|
return range.start;
|
|
|
|
var firstRow = range.start.row;
|
|
var lastRow = range.end.row;
|
|
|
|
if (range.isMultiLine()) {
|
|
var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
|
|
var lastFullRow = lastRow - 1;
|
|
|
|
if (range.end.column > 0)
|
|
this.removeInLine(lastRow, 0, range.end.column);
|
|
|
|
if (lastFullRow >= firstFullRow)
|
|
this._removeLines(firstFullRow, lastFullRow);
|
|
|
|
if (firstFullRow != firstRow) {
|
|
this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
|
|
this.removeNewLine(range.start.row);
|
|
}
|
|
}
|
|
else {
|
|
this.removeInLine(firstRow, range.start.column, range.end.column);
|
|
}
|
|
return range.start;
|
|
};
|
|
this.removeInLine = function(row, startColumn, endColumn) {
|
|
if (startColumn == endColumn)
|
|
return;
|
|
|
|
var range = new Range(row, startColumn, row, endColumn);
|
|
var line = this.getLine(row);
|
|
var removed = line.substring(startColumn, endColumn);
|
|
var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
|
|
this.$lines.splice(row, 1, newLine);
|
|
|
|
var delta = {
|
|
action: "removeText",
|
|
range: range,
|
|
text: removed
|
|
};
|
|
this._emit("change", { data: delta });
|
|
return range.start;
|
|
};
|
|
this.removeLines = function(firstRow, lastRow) {
|
|
if (firstRow < 0 || lastRow >= this.getLength())
|
|
return this.remove(new Range(firstRow, 0, lastRow + 1, 0));
|
|
return this._removeLines(firstRow, lastRow);
|
|
};
|
|
|
|
this._removeLines = function(firstRow, lastRow) {
|
|
var range = new Range(firstRow, 0, lastRow + 1, 0);
|
|
var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
|
|
|
|
var delta = {
|
|
action: "removeLines",
|
|
range: range,
|
|
nl: this.getNewLineCharacter(),
|
|
lines: removed
|
|
};
|
|
this._emit("change", { data: delta });
|
|
return removed;
|
|
};
|
|
this.removeNewLine = function(row) {
|
|
var firstLine = this.getLine(row);
|
|
var secondLine = this.getLine(row+1);
|
|
|
|
var range = new Range(row, firstLine.length, row+1, 0);
|
|
var line = firstLine + secondLine;
|
|
|
|
this.$lines.splice(row, 2, line);
|
|
|
|
var delta = {
|
|
action: "removeText",
|
|
range: range,
|
|
text: this.getNewLineCharacter()
|
|
};
|
|
this._emit("change", { data: delta });
|
|
};
|
|
this.replace = function(range, text) {
|
|
if (text.length == 0 && range.isEmpty())
|
|
return range.start;
|
|
if (text == this.getTextRange(range))
|
|
return range.end;
|
|
|
|
this.remove(range);
|
|
if (text) {
|
|
var end = this.insert(range.start, text);
|
|
}
|
|
else {
|
|
end = range.start;
|
|
}
|
|
|
|
return end;
|
|
};
|
|
this.applyDeltas = function(deltas) {
|
|
for (var i=0; i<deltas.length; i++) {
|
|
var delta = deltas[i];
|
|
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
|
|
|
if (delta.action == "insertLines")
|
|
this.insertLines(range.start.row, delta.lines);
|
|
else if (delta.action == "insertText")
|
|
this.insert(range.start, delta.text);
|
|
else if (delta.action == "removeLines")
|
|
this._removeLines(range.start.row, range.end.row - 1);
|
|
else if (delta.action == "removeText")
|
|
this.remove(range);
|
|
}
|
|
};
|
|
this.revertDeltas = function(deltas) {
|
|
for (var i=deltas.length-1; i>=0; i--) {
|
|
var delta = deltas[i];
|
|
|
|
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
|
|
|
if (delta.action == "insertLines")
|
|
this._removeLines(range.start.row, range.end.row - 1);
|
|
else if (delta.action == "insertText")
|
|
this.remove(range);
|
|
else if (delta.action == "removeLines")
|
|
this._insertLines(range.start.row, delta.lines);
|
|
else if (delta.action == "removeText")
|
|
this.insert(range.start, delta.text);
|
|
}
|
|
};
|
|
this.indexToPosition = function(index, startRow) {
|
|
var lines = this.$lines || this.getAllLines();
|
|
var newlineLength = this.getNewLineCharacter().length;
|
|
for (var i = startRow || 0, l = lines.length; i < l; i++) {
|
|
index -= lines[i].length + newlineLength;
|
|
if (index < 0)
|
|
return {row: i, column: index + lines[i].length + newlineLength};
|
|
}
|
|
return {row: l-1, column: lines[l-1].length};
|
|
};
|
|
this.positionToIndex = function(pos, startRow) {
|
|
var lines = this.$lines || this.getAllLines();
|
|
var newlineLength = this.getNewLineCharacter().length;
|
|
var index = 0;
|
|
var row = Math.min(pos.row, lines.length);
|
|
for (var i = startRow || 0; i < row; ++i)
|
|
index += lines[i].length + newlineLength;
|
|
|
|
return index + pos.column;
|
|
};
|
|
|
|
}).call(Document.prototype);
|
|
|
|
exports.Document = Document;
|
|
});
|
|
|
|
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;
|
|
};
|
|
var Range = function(startRow, startColumn, endRow, endColumn) {
|
|
this.start = {
|
|
row: startRow,
|
|
column: startColumn
|
|
};
|
|
|
|
this.end = {
|
|
row: endRow,
|
|
column: endColumn
|
|
};
|
|
};
|
|
|
|
(function() {
|
|
this.isEqual = function(range) {
|
|
return this.start.row === range.start.row &&
|
|
this.end.row === range.end.row &&
|
|
this.start.column === range.start.column &&
|
|
this.end.column === range.end.column;
|
|
};
|
|
this.toString = function() {
|
|
return ("Range: [" + this.start.row + "/" + this.start.column +
|
|
"] -> [" + this.end.row + "/" + this.end.column + "]");
|
|
};
|
|
|
|
this.contains = function(row, column) {
|
|
return this.compare(row, column) == 0;
|
|
};
|
|
this.compareRange = function(range) {
|
|
var cmp,
|
|
end = range.end,
|
|
start = range.start;
|
|
|
|
cmp = this.compare(end.row, end.column);
|
|
if (cmp == 1) {
|
|
cmp = this.compare(start.row, start.column);
|
|
if (cmp == 1) {
|
|
return 2;
|
|
} else if (cmp == 0) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else if (cmp == -1) {
|
|
return -2;
|
|
} else {
|
|
cmp = this.compare(start.row, start.column);
|
|
if (cmp == -1) {
|
|
return -1;
|
|
} else if (cmp == 1) {
|
|
return 42;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
};
|
|
this.comparePoint = function(p) {
|
|
return this.compare(p.row, p.column);
|
|
};
|
|
this.containsRange = function(range) {
|
|
return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
|
|
};
|
|
this.intersects = function(range) {
|
|
var cmp = this.compareRange(range);
|
|
return (cmp == -1 || cmp == 0 || cmp == 1);
|
|
};
|
|
this.isEnd = function(row, column) {
|
|
return this.end.row == row && this.end.column == column;
|
|
};
|
|
this.isStart = function(row, column) {
|
|
return this.start.row == row && this.start.column == column;
|
|
};
|
|
this.setStart = function(row, column) {
|
|
if (typeof row == "object") {
|
|
this.start.column = row.column;
|
|
this.start.row = row.row;
|
|
} else {
|
|
this.start.row = row;
|
|
this.start.column = column;
|
|
}
|
|
};
|
|
this.setEnd = function(row, column) {
|
|
if (typeof row == "object") {
|
|
this.end.column = row.column;
|
|
this.end.row = row.row;
|
|
} else {
|
|
this.end.row = row;
|
|
this.end.column = column;
|
|
}
|
|
};
|
|
this.inside = function(row, column) {
|
|
if (this.compare(row, column) == 0) {
|
|
if (this.isEnd(row, column) || this.isStart(row, column)) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
this.insideStart = function(row, column) {
|
|
if (this.compare(row, column) == 0) {
|
|
if (this.isEnd(row, column)) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
this.insideEnd = function(row, column) {
|
|
if (this.compare(row, column) == 0) {
|
|
if (this.isStart(row, column)) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
this.compare = function(row, column) {
|
|
if (!this.isMultiLine()) {
|
|
if (row === this.start.row) {
|
|
return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);
|
|
};
|
|
}
|
|
|
|
if (row < this.start.row)
|
|
return -1;
|
|
|
|
if (row > this.end.row)
|
|
return 1;
|
|
|
|
if (this.start.row === row)
|
|
return column >= this.start.column ? 0 : -1;
|
|
|
|
if (this.end.row === row)
|
|
return column <= this.end.column ? 0 : 1;
|
|
|
|
return 0;
|
|
};
|
|
this.compareStart = function(row, column) {
|
|
if (this.start.row == row && this.start.column == column) {
|
|
return -1;
|
|
} else {
|
|
return this.compare(row, column);
|
|
}
|
|
};
|
|
this.compareEnd = function(row, column) {
|
|
if (this.end.row == row && this.end.column == column) {
|
|
return 1;
|
|
} else {
|
|
return this.compare(row, column);
|
|
}
|
|
};
|
|
this.compareInside = function(row, column) {
|
|
if (this.end.row == row && this.end.column == column) {
|
|
return 1;
|
|
} else if (this.start.row == row && this.start.column == column) {
|
|
return -1;
|
|
} else {
|
|
return this.compare(row, column);
|
|
}
|
|
};
|
|
this.clipRows = function(firstRow, lastRow) {
|
|
if (this.end.row > lastRow)
|
|
var end = {row: lastRow + 1, column: 0};
|
|
else if (this.end.row < firstRow)
|
|
var end = {row: firstRow, column: 0};
|
|
|
|
if (this.start.row > lastRow)
|
|
var start = {row: lastRow + 1, column: 0};
|
|
else if (this.start.row < firstRow)
|
|
var start = {row: firstRow, column: 0};
|
|
|
|
return Range.fromPoints(start || this.start, end || this.end);
|
|
};
|
|
this.extend = function(row, column) {
|
|
var cmp = this.compare(row, column);
|
|
|
|
if (cmp == 0)
|
|
return this;
|
|
else if (cmp == -1)
|
|
var start = {row: row, column: column};
|
|
else
|
|
var end = {row: row, column: column};
|
|
|
|
return Range.fromPoints(start || this.start, end || this.end);
|
|
};
|
|
|
|
this.isEmpty = function() {
|
|
return (this.start.row === this.end.row && this.start.column === this.end.column);
|
|
};
|
|
this.isMultiLine = function() {
|
|
return (this.start.row !== this.end.row);
|
|
};
|
|
this.clone = function() {
|
|
return Range.fromPoints(this.start, this.end);
|
|
};
|
|
this.collapseRows = function() {
|
|
if (this.end.column == 0)
|
|
return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)
|
|
else
|
|
return new Range(this.start.row, 0, this.end.row, 0)
|
|
};
|
|
this.toScreenRange = function(session) {
|
|
var screenPosStart = session.documentToScreenPosition(this.start);
|
|
var screenPosEnd = session.documentToScreenPosition(this.end);
|
|
|
|
return new Range(
|
|
screenPosStart.row, screenPosStart.column,
|
|
screenPosEnd.row, screenPosEnd.column
|
|
);
|
|
};
|
|
this.moveBy = function(row, column) {
|
|
this.start.row += row;
|
|
this.start.column += column;
|
|
this.end.row += row;
|
|
this.end.column += column;
|
|
};
|
|
|
|
}).call(Range.prototype);
|
|
Range.fromPoints = function(start, end) {
|
|
return new Range(start.row, start.column, end.row, end.column);
|
|
};
|
|
Range.comparePoints = comparePoints;
|
|
|
|
Range.comparePoints = function(p1, p2) {
|
|
return p1.row - p2.row || p1.column - p2.column;
|
|
};
|
|
|
|
|
|
exports.Range = Range;
|
|
});
|
|
|
|
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.$onChange = this.onChange.bind(this);
|
|
this.attach(doc);
|
|
|
|
if (typeof column == "undefined")
|
|
this.setPosition(row.row, row.column);
|
|
else
|
|
this.setPosition(row, column);
|
|
};
|
|
|
|
(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;
|
|
|
|
if (range.start.row == range.end.row && range.start.row != this.row)
|
|
return;
|
|
|
|
if (range.start.row > this.row)
|
|
return;
|
|
|
|
if (range.start.row == this.row && range.start.column > this.column)
|
|
return;
|
|
|
|
var row = this.row;
|
|
var column = this.column;
|
|
var start = range.start;
|
|
var end = range.end;
|
|
|
|
if (delta.action === "insertText") {
|
|
if (start.row === row && start.column <= column) {
|
|
if (start.row === end.row) {
|
|
column += end.column - start.column;
|
|
} else {
|
|
column -= start.column;
|
|
row += end.row - start.row;
|
|
}
|
|
} else if (start.row !== end.row && start.row < row) {
|
|
row += end.row - start.row;
|
|
}
|
|
} else if (delta.action === "insertLines") {
|
|
if (start.row <= row) {
|
|
row += end.row - start.row;
|
|
}
|
|
} else if (delta.action === "removeText") {
|
|
if (start.row === row && start.column < column) {
|
|
if (end.column >= column)
|
|
column = start.column;
|
|
else
|
|
column = Math.max(0, column - (end.column - start.column));
|
|
|
|
} else if (start.row !== end.row && start.row < row) {
|
|
if (end.row === row)
|
|
column = Math.max(0, column - end.column) + start.column;
|
|
row -= (end.row - start.row);
|
|
} else if (end.row === row) {
|
|
row -= end.row - start.row;
|
|
column = Math.max(0, column - end.column) + start.column;
|
|
}
|
|
} else if (delta.action == "removeLines") {
|
|
if (start.row <= row) {
|
|
if (end.row <= row)
|
|
row -= end.row - start.row;
|
|
else {
|
|
row = start.row;
|
|
column = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.setPosition(row, column, true);
|
|
};
|
|
this.setPosition = function(row, column, noClip) {
|
|
var pos;
|
|
if (noClip) {
|
|
pos = {
|
|
row: row,
|
|
column: column
|
|
};
|
|
} else {
|
|
pos = this.$clipPositionToDocument(row, column);
|
|
}
|
|
|
|
if (this.row == pos.row && this.column == pos.column)
|
|
return;
|
|
|
|
var old = {
|
|
row: this.row,
|
|
column: this.column
|
|
};
|
|
|
|
this.row = pos.row;
|
|
this.column = pos.column;
|
|
this._emit("change", {
|
|
old: old,
|
|
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 = {};
|
|
|
|
if (row >= this.document.getLength()) {
|
|
pos.row = Math.max(0, this.document.getLength() - 1);
|
|
pos.column = this.document.getLine(pos.row).length;
|
|
}
|
|
else if (row < 0) {
|
|
pos.row = 0;
|
|
pos.column = 0;
|
|
}
|
|
else {
|
|
pos.row = row;
|
|
pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
|
|
}
|
|
|
|
if (column < 0)
|
|
pos.column = 0;
|
|
|
|
return pos;
|
|
};
|
|
|
|
}).call(Anchor.prototype);
|
|
|
|
});
|
|
|
|
ace.define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
|
|
|
|
|
|
exports.stringReverse = function(string) {
|
|
return string.split("").reverse().join("");
|
|
};
|
|
|
|
exports.stringRepeat = function (string, count) {
|
|
var result = '';
|
|
while (count > 0) {
|
|
if (count & 1)
|
|
result += string;
|
|
|
|
if (count >>= 1)
|
|
string += string;
|
|
}
|
|
return result;
|
|
};
|
|
|
|
var trimBeginRegexp = /^\s\s*/;
|
|
var trimEndRegexp = /\s\s*$/;
|
|
|
|
exports.stringTrimLeft = function (string) {
|
|
return string.replace(trimBeginRegexp, '');
|
|
};
|
|
|
|
exports.stringTrimRight = function (string) {
|
|
return string.replace(trimEndRegexp, '');
|
|
};
|
|
|
|
exports.copyObject = function(obj) {
|
|
var copy = {};
|
|
for (var key in obj) {
|
|
copy[key] = obj[key];
|
|
}
|
|
return copy;
|
|
};
|
|
|
|
exports.copyArray = function(array){
|
|
var copy = [];
|
|
for (var i=0, l=array.length; i<l; i++) {
|
|
if (array[i] && typeof array[i] == "object")
|
|
copy[i] = this.copyObject( array[i] );
|
|
else
|
|
copy[i] = array[i];
|
|
}
|
|
return copy;
|
|
};
|
|
|
|
exports.deepCopy = function (obj) {
|
|
if (typeof obj != "object") {
|
|
return obj;
|
|
}
|
|
|
|
var copy = obj.constructor();
|
|
for (var key in obj) {
|
|
if (typeof obj[key] == "object") {
|
|
copy[key] = this.deepCopy(obj[key]);
|
|
} else {
|
|
copy[key] = obj[key];
|
|
}
|
|
}
|
|
return copy;
|
|
};
|
|
|
|
exports.arrayToMap = function(arr) {
|
|
var map = {};
|
|
for (var i=0; i<arr.length; i++) {
|
|
map[arr[i]] = 1;
|
|
}
|
|
return map;
|
|
|
|
};
|
|
|
|
exports.createMap = function(props) {
|
|
var map = Object.create(null);
|
|
for (var i in props) {
|
|
map[i] = props[i];
|
|
}
|
|
return map;
|
|
};
|
|
exports.arrayRemove = function(array, value) {
|
|
for (var i = 0; i <= array.length; i++) {
|
|
if (value === array[i]) {
|
|
array.splice(i, 1);
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.escapeRegExp = function(str) {
|
|
return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
|
|
};
|
|
|
|
exports.escapeHTML = function(str) {
|
|
return str.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<");
|
|
};
|
|
|
|
exports.getMatchOffsets = function(string, regExp) {
|
|
var matches = [];
|
|
|
|
string.replace(regExp, function(str) {
|
|
matches.push({
|
|
offset: arguments[arguments.length-2],
|
|
length: str.length
|
|
});
|
|
});
|
|
|
|
return matches;
|
|
};
|
|
exports.deferredCall = function(fcn) {
|
|
|
|
var timer = null;
|
|
var callback = function() {
|
|
timer = null;
|
|
fcn();
|
|
};
|
|
|
|
var deferred = function(timeout) {
|
|
deferred.cancel();
|
|
timer = setTimeout(callback, timeout || 0);
|
|
return deferred;
|
|
};
|
|
|
|
deferred.schedule = deferred;
|
|
|
|
deferred.call = function() {
|
|
this.cancel();
|
|
fcn();
|
|
return deferred;
|
|
};
|
|
|
|
deferred.cancel = function() {
|
|
clearTimeout(timer);
|
|
timer = null;
|
|
return deferred;
|
|
};
|
|
|
|
return deferred;
|
|
};
|
|
|
|
|
|
exports.delayedCall = function(fcn, defaultTimeout) {
|
|
var timer = null;
|
|
var callback = function() {
|
|
timer = null;
|
|
fcn();
|
|
};
|
|
|
|
var _self = function(timeout) {
|
|
timer && clearTimeout(timer);
|
|
timer = setTimeout(callback, timeout || defaultTimeout);
|
|
};
|
|
|
|
_self.delay = _self;
|
|
_self.schedule = function(timeout) {
|
|
if (timer == null)
|
|
timer = setTimeout(callback, timeout || 0);
|
|
};
|
|
|
|
_self.call = function() {
|
|
this.cancel();
|
|
fcn();
|
|
};
|
|
|
|
_self.cancel = function() {
|
|
timer && clearTimeout(timer);
|
|
timer = null;
|
|
};
|
|
|
|
_self.isPending = function() {
|
|
return timer;
|
|
};
|
|
|
|
return _self;
|
|
};
|
|
});
|
|
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<n.length;s++)i(n[s]);return i})({
|
|
1:[function(req,module,exports){
|
|
|
|
var process = module.exports = {};
|
|
|
|
process.nextTick = (function () {
|
|
var canSetImmediate = typeof window !== 'undefined'
|
|
&& window.setImmediate;
|
|
var canPost = typeof window !== 'undefined'
|
|
&& window.postMessage && window.addEventListener
|
|
;
|
|
|
|
if (canSetImmediate) {
|
|
return function (f) { return window.setImmediate(f) };
|
|
}
|
|
|
|
if (canPost) {
|
|
var queue = [];
|
|
window.addEventListener('message', function (ev) {
|
|
if (ev.source === window && ev.data === 'process-tick') {
|
|
ev.stopPropagation();
|
|
if (queue.length > 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.
|
|
api, // Extension API
|
|
bang = {
|
|
"<" : true,
|
|
"<=" : true,
|
|
"==" : true,
|
|
"===": true,
|
|
"!==": true,
|
|
"!=" : true,
|
|
">" : true,
|
|
">=" : true,
|
|
"+" : true,
|
|
"-" : true,
|
|
"*" : true,
|
|
"/" : true,
|
|
"%" : 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, 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
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
strict : true
|
|
},
|
|
renamedOptions = {
|
|
eqeq : "eqeqeq",
|
|
vars : "onevar",
|
|
windows: "wsh",
|
|
sloppy : "strict"
|
|
},
|
|
|
|
declared, // Globals that were declared using /*global ... */ syntax.
|
|
exported, // Variables that are used outside of the current file.
|
|
|
|
functionicity = [
|
|
"closure", "exception", "global", "label",
|
|
"outer", "unused", "var"
|
|
],
|
|
|
|
funct, // The current function
|
|
functions, // All of the functions
|
|
|
|
global, // The global scope
|
|
implied, // Implied globals
|
|
inblock,
|
|
indent,
|
|
lookahead,
|
|
lex,
|
|
member,
|
|
membersOnly,
|
|
noreach,
|
|
predefined, // Global variables defined by option
|
|
|
|
scope, // The current scope
|
|
stack,
|
|
unuseds,
|
|
urls,
|
|
warnings,
|
|
|
|
extraModules = [],
|
|
emitter = new events.EventEmitter();
|
|
|
|
function checkOption(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]";
|
|
}
|
|
|
|
function isIdentifier(tkn, value) {
|
|
if (!tkn)
|
|
return false;
|
|
|
|
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];
|
|
return typeof r === "string" || typeof r === "number" ? r : a;
|
|
});
|
|
}
|
|
|
|
function combine(t, o) {
|
|
var n;
|
|
for (n in o) {
|
|
if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) {
|
|
t[n] = o[n];
|
|
}
|
|
}
|
|
}
|
|
|
|
function updatePredefined() {
|
|
Object.keys(JSHINT.blacklist).forEach(function (key) {
|
|
delete predefined[key];
|
|
});
|
|
}
|
|
|
|
function assume() {
|
|
if (state.option.couch) {
|
|
combine(predefined, vars.couch);
|
|
}
|
|
|
|
if (state.option.rhino) {
|
|
combine(predefined, vars.rhino);
|
|
}
|
|
|
|
if (state.option.shelljs) {
|
|
combine(predefined, vars.shelljs);
|
|
}
|
|
|
|
if (state.option.phantom) {
|
|
combine(predefined, vars.phantom);
|
|
}
|
|
|
|
if (state.option.prototypejs) {
|
|
combine(predefined, vars.prototypejs);
|
|
}
|
|
|
|
if (state.option.node) {
|
|
combine(predefined, vars.node);
|
|
}
|
|
|
|
if (state.option.devel) {
|
|
combine(predefined, vars.devel);
|
|
}
|
|
|
|
if (state.option.dojo) {
|
|
combine(predefined, vars.dojo);
|
|
}
|
|
|
|
if (state.option.browser) {
|
|
combine(predefined, vars.browser);
|
|
}
|
|
|
|
if (state.option.nonstandard) {
|
|
combine(predefined, vars.nonstandard);
|
|
}
|
|
|
|
if (state.option.jquery) {
|
|
combine(predefined, vars.jquery);
|
|
}
|
|
|
|
if (state.option.mootools) {
|
|
combine(predefined, vars.mootools);
|
|
}
|
|
|
|
if (state.option.worker) {
|
|
combine(predefined, vars.worker);
|
|
}
|
|
|
|
if (state.option.wsh) {
|
|
combine(predefined, vars.wsh);
|
|
}
|
|
|
|
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(code, line, chr) {
|
|
var percentage = Math.floor((line / state.lines.length) * 100);
|
|
var message = messages.errors[code].desc;
|
|
|
|
throw {
|
|
name: "JSHintError",
|
|
line: line,
|
|
character: chr,
|
|
message: message + " (" + percentage + "% scanned).",
|
|
raw: message
|
|
};
|
|
}
|
|
|
|
function isundef(scope, code, token, a) {
|
|
return JSHINT.undefs.push([scope, code, token, a]);
|
|
}
|
|
|
|
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: msg.desc,
|
|
code: msg.code,
|
|
evidence: state.lines[l - 1] || "",
|
|
line: l,
|
|
character: ch,
|
|
scope: JSHINT.scope,
|
|
a: a,
|
|
b: b,
|
|
c: c,
|
|
d: d
|
|
};
|
|
|
|
w.reason = supplant(msg.desc, w);
|
|
JSHINT.errors.push(w);
|
|
|
|
if (state.option.passfail) {
|
|
quit("E042", l, ch);
|
|
}
|
|
|
|
warnings += 1;
|
|
if (warnings >= state.option.maxerr) {
|
|
quit("E043", l, ch);
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
function warningAt(m, l, ch, a, b, c, d) {
|
|
return warning(m, {
|
|
line: l,
|
|
from: ch
|
|
}, a, b, c, d);
|
|
}
|
|
|
|
function error(m, t, a, b, c, d) {
|
|
warning(m, t, a, b, c, d);
|
|
}
|
|
|
|
function errorAt(m, l, ch, a, b, c, d) {
|
|
return error(m, {
|
|
line: l,
|
|
from: ch
|
|
}, a, b, c, d);
|
|
}
|
|
function addInternalSrc(elem, src) {
|
|
var i;
|
|
i = {
|
|
id: "(internal)",
|
|
elem: elem,
|
|
value: src
|
|
};
|
|
JSHINT.internals.push(i);
|
|
return i;
|
|
}
|
|
|
|
function addlabel(t, type, tkn, islet) {
|
|
if (type === "exception") {
|
|
if (_.has(funct["(context)"], t)) {
|
|
if (funct[t] !== true && !state.option.node) {
|
|
warning("W002", state.tokens.next, t);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_.has(funct, t) && !funct["(global)"]) {
|
|
if (funct[t] === true) {
|
|
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 (!state.option.shadow && type !== "exception" ||
|
|
(funct["(blockscope)"].getlabel(t))) {
|
|
warning("W004", state.tokens.next, t);
|
|
}
|
|
}
|
|
}
|
|
if (funct["(blockscope)"] && funct["(blockscope)"].current.has(t)) {
|
|
error("E044", state.tokens.next, t);
|
|
}
|
|
if (islet) {
|
|
funct["(blockscope)"].current.add(t, type, state.tokens.curr);
|
|
} else {
|
|
|
|
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 = state.tokens.next;
|
|
var body = nt.body.split(",").map(function (s) { return s.trim(); });
|
|
var predef = {};
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nt.type === "exported") {
|
|
body.forEach(function (e) {
|
|
exported[e] = true;
|
|
});
|
|
}
|
|
|
|
if (nt.type === "members") {
|
|
membersOnly = membersOnly || {};
|
|
|
|
body.forEach(function (m) {
|
|
var ch1 = m.charAt(0);
|
|
var ch2 = m.charAt(m.length - 1);
|
|
|
|
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("\\\"", "\"");
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if (numvals.indexOf(key) >= 0) {
|
|
if (val !== "false") {
|
|
val = +val;
|
|
|
|
if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
|
|
error("E032", nt, g[1].trim());
|
|
return;
|
|
}
|
|
|
|
if (key === "indent") {
|
|
state.option["(explicitIndent)"] = true;
|
|
}
|
|
state.option[key] = val;
|
|
} else {
|
|
if (key === "indent") {
|
|
state.option["(explicitIndent)"] = false;
|
|
} else {
|
|
state.option[key] = false;
|
|
}
|
|
}
|
|
|
|
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":
|
|
case "false":
|
|
state.option.quotmark = (val === "true");
|
|
break;
|
|
case "double":
|
|
case "single":
|
|
state.option.quotmark = val;
|
|
break;
|
|
default:
|
|
error("E002", nt);
|
|
}
|
|
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) {
|
|
state.option[tn] = !state.option[tn];
|
|
}
|
|
} else {
|
|
state.option[key] = (val === "true");
|
|
}
|
|
|
|
if (key === "newcap") {
|
|
state.option["(explicitNewcap)"] = true;
|
|
}
|
|
return;
|
|
}
|
|
|
|
error("E002", nt);
|
|
});
|
|
|
|
assume();
|
|
}
|
|
}
|
|
|
|
function peek(p) {
|
|
var i = p || 0, j = 0, t;
|
|
|
|
while (j <= i) {
|
|
t = lookahead[j];
|
|
if (!t) {
|
|
t = lookahead[j] = lex.token();
|
|
}
|
|
j += 1;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
function advance(id, t) {
|
|
switch (state.tokens.curr.id) {
|
|
case "(number)":
|
|
if (state.tokens.next.id === ".") {
|
|
warning("W005", state.tokens.curr);
|
|
}
|
|
break;
|
|
case "-":
|
|
if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
|
|
warning("W006");
|
|
}
|
|
break;
|
|
case "+":
|
|
if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
|
|
warning("W007");
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
|
|
anonname = state.tokens.curr.value;
|
|
}
|
|
|
|
if (id && state.tokens.next.id !== id) {
|
|
if (t) {
|
|
if (state.tokens.next.id === "(end)") {
|
|
error("E019", t, t.id);
|
|
} else {
|
|
error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
|
|
}
|
|
} else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
|
|
warning("W116", state.tokens.next, id, state.tokens.next.value);
|
|
}
|
|
}
|
|
|
|
state.tokens.prev = state.tokens.curr;
|
|
state.tokens.curr = state.tokens.next;
|
|
for (;;) {
|
|
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 (state.tokens.next.check) {
|
|
state.tokens.next.check();
|
|
}
|
|
|
|
if (state.tokens.next.isSpecial) {
|
|
doOption();
|
|
} else {
|
|
if (state.tokens.next.id !== "(endline)") {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function expression(rbp, initial) {
|
|
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 (state.tokens.next.id === "(end)")
|
|
error("E006", state.tokens.curr);
|
|
|
|
advance();
|
|
|
|
if (initial) {
|
|
anonname = "anonymous";
|
|
funct["(verb)"] = state.tokens.curr.value;
|
|
}
|
|
|
|
if (initial === true && state.tokens.curr.fud) {
|
|
left = state.tokens.curr.fud();
|
|
} else {
|
|
if (state.tokens.curr.nud) {
|
|
left = state.tokens.curr.nud();
|
|
} else {
|
|
error("E030", state.tokens.curr, state.tokens.curr.id);
|
|
}
|
|
|
|
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 !== state.tokens.curr.value) {
|
|
isObject = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
advance();
|
|
|
|
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("E033", state.tokens.curr, state.tokens.curr.id);
|
|
}
|
|
}
|
|
}
|
|
if (isLetExpr) {
|
|
funct["(blockscope)"].unstack();
|
|
}
|
|
return left;
|
|
}
|
|
|
|
function adjacent(left, right) {
|
|
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("W011", left, left.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
function nobreak(left, right) {
|
|
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 || state.tokens.curr;
|
|
right = right || state.tokens.next;
|
|
if (state.option.white && !left.comment) {
|
|
if (left.line === right.line) {
|
|
adjacent(left, right);
|
|
}
|
|
}
|
|
}
|
|
|
|
function nonadjacent(left, right) {
|
|
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("W013", left, left.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
function nobreaknonadjacent(left, right) {
|
|
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("W013", left, left.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
function indentation(bias) {
|
|
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 || state.tokens.curr;
|
|
if (t.line !== state.tokens.next.line) {
|
|
warning("E022", t, t.value);
|
|
}
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
} 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);
|
|
}
|
|
|
|
advance(",");
|
|
}
|
|
|
|
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 = state.syntax[s];
|
|
if (!x || typeof x !== "object") {
|
|
state.syntax[s] = x = {
|
|
id: s,
|
|
lbp: p,
|
|
value: s
|
|
};
|
|
}
|
|
return x;
|
|
}
|
|
|
|
function delim(s) {
|
|
return symbol(s, 0);
|
|
}
|
|
|
|
function stmt(s, f) {
|
|
var x = delim(s);
|
|
x.identifier = x.reserved = true;
|
|
x.fud = f;
|
|
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")) {
|
|
x.identifier = x.reserved = true;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
function prefix(s, f) {
|
|
var x = symbol(s, 150);
|
|
reserveName(x);
|
|
x.nud = (typeof f === "function") ? f : function () {
|
|
this.right = expression(150);
|
|
this.arity = "unary";
|
|
if (this.id === "++" || this.id === "--") {
|
|
if (state.option.plusplus) {
|
|
warning("W016", this, this.id);
|
|
} else if ((!this.right.identifier || isReserved(this.right)) &&
|
|
this.right.id !== "." && this.right.id !== "[") {
|
|
warning("W017", this);
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
return x;
|
|
}
|
|
|
|
function type(s, f) {
|
|
var x = delim(s);
|
|
x.type = s;
|
|
x.nud = f;
|
|
return x;
|
|
}
|
|
|
|
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 () {
|
|
if (typeof v === "function") {
|
|
v(this);
|
|
}
|
|
return this;
|
|
});
|
|
}
|
|
|
|
function infix(s, f, p, w) {
|
|
var x = symbol(s, p);
|
|
reserveName(x);
|
|
x.led = function (left) {
|
|
if (!w) {
|
|
nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
|
|
nonadjacent(state.tokens.curr, state.tokens.next);
|
|
}
|
|
if (s === "in" && left.id === "!") {
|
|
warning("W018", left, "!");
|
|
}
|
|
if (typeof f === "function") {
|
|
return f(left, this);
|
|
} else {
|
|
this.left = left;
|
|
this.right = expression(p);
|
|
return this;
|
|
}
|
|
};
|
|
return x;
|
|
}
|
|
|
|
|
|
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(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("W019", this);
|
|
} else if (f) {
|
|
f.apply(this, [left, right]);
|
|
}
|
|
|
|
if (!left || !right) {
|
|
quit("E041", state.tokens.curr.line);
|
|
}
|
|
|
|
if (left.id === "!") {
|
|
warning("W018", left, "!");
|
|
}
|
|
|
|
if (right.id === "!") {
|
|
warning("W018", right, "!");
|
|
}
|
|
|
|
this.left = left;
|
|
this.right = right;
|
|
return this;
|
|
};
|
|
return x;
|
|
}
|
|
|
|
function isPoorRelation(node) {
|
|
return node &&
|
|
((node.type === "(number)" && +node.value === 0) ||
|
|
(node.type === "(string)" && node.value === "") ||
|
|
(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 (left) {
|
|
if (predefined[left.value] === false &&
|
|
scope[left.value]["(global)"] === true) {
|
|
warning("W020", left);
|
|
} else if (left["function"]) {
|
|
warning("W021", left, left.value);
|
|
}
|
|
|
|
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 && !isReserved(left)) {
|
|
if (funct[left.value] === "exception") {
|
|
warning("W022", left);
|
|
}
|
|
that.right = expression(19);
|
|
return that;
|
|
}
|
|
|
|
if (left === state.syntax["function"]) {
|
|
warning("W023", state.tokens.curr);
|
|
}
|
|
}
|
|
|
|
error("E031", that);
|
|
}, 20);
|
|
}
|
|
|
|
|
|
function bitwise(s, f, p) {
|
|
var x = symbol(s, p);
|
|
reserveName(x);
|
|
x.led = (typeof f === "function") ? f : function (left) {
|
|
if (state.option.bitwise) {
|
|
warning("W016", this, this.id);
|
|
}
|
|
this.left = left;
|
|
this.right = expression(p);
|
|
return this;
|
|
};
|
|
return x;
|
|
}
|
|
|
|
|
|
function bitwiseassignop(s) {
|
|
symbol(s, 20).exps = true;
|
|
return infix(s, function (left, that) {
|
|
if (state.option.bitwise) {
|
|
warning("W016", that, that.id);
|
|
}
|
|
nonadjacent(state.tokens.prev, state.tokens.curr);
|
|
nonadjacent(state.tokens.curr, state.tokens.next);
|
|
if (left) {
|
|
if (left.id === "." || left.id === "[" ||
|
|
(left.identifier && !isReserved(left))) {
|
|
expression(19);
|
|
return that;
|
|
}
|
|
if (left === state.syntax["function"]) {
|
|
warning("W023", state.tokens.curr);
|
|
}
|
|
return that;
|
|
}
|
|
error("E031", that);
|
|
}, 20);
|
|
}
|
|
|
|
|
|
function suffix(s) {
|
|
var x = symbol(s, 150);
|
|
|
|
x.led = function (left) {
|
|
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, 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, prop) {
|
|
var i = optionalidentifier(fnparam, prop);
|
|
if (i) {
|
|
return i;
|
|
}
|
|
if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") {
|
|
warning("W025");
|
|
} else {
|
|
error("E030", state.tokens.next, state.tokens.next.value);
|
|
}
|
|
}
|
|
|
|
|
|
function reachable(s) {
|
|
var i = 0, t;
|
|
if (state.tokens.next.id !== ";" || noreach) {
|
|
return;
|
|
}
|
|
for (;;) {
|
|
t = peek(i);
|
|
if (t.reach) {
|
|
return;
|
|
}
|
|
if (t.id !== "(endline)") {
|
|
if (t.id === "function") {
|
|
if (!state.option.latedef) {
|
|
break;
|
|
}
|
|
|
|
warning("W026", t);
|
|
break;
|
|
}
|
|
|
|
warning("W027", t, t.value, s);
|
|
break;
|
|
}
|
|
i += 1;
|
|
}
|
|
}
|
|
|
|
|
|
function statement(noindent) {
|
|
var values;
|
|
var i = indent, r, s = scope, t = state.tokens.next;
|
|
|
|
if (t.id === ";") {
|
|
advance(";");
|
|
return;
|
|
}
|
|
var res = isReserved(t);
|
|
|
|
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 (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
|
|
warning("W028", state.tokens.next, t.value, state.tokens.next.value);
|
|
}
|
|
|
|
state.tokens.next.label = t.value;
|
|
t = state.tokens.next;
|
|
}
|
|
|
|
if (t.id === "{") {
|
|
block(true, true);
|
|
return;
|
|
}
|
|
|
|
if (!noindent) {
|
|
indentation();
|
|
}
|
|
r = expression(0, true);
|
|
|
|
if (!t.block) {
|
|
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 (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(state.tokens.curr, state.tokens.next);
|
|
advance(";");
|
|
nonadjacent(state.tokens.curr, state.tokens.next);
|
|
}
|
|
}
|
|
|
|
indent = i;
|
|
scope = s;
|
|
return r;
|
|
}
|
|
|
|
|
|
function statements(startLine) {
|
|
var a = [], p;
|
|
|
|
while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
|
|
if (state.tokens.next.id === ";") {
|
|
p = peek();
|
|
|
|
if (!p || (p.id !== "(" && p.id !== "[")) {
|
|
warning("W032");
|
|
}
|
|
|
|
advance(";");
|
|
} else {
|
|
a.push(statement(startLine === state.tokens.next.line));
|
|
}
|
|
}
|
|
return a;
|
|
}
|
|
function directives() {
|
|
var i, p, pn;
|
|
|
|
for (;;) {
|
|
if (state.tokens.next.id === "(string)") {
|
|
p = peek(0);
|
|
if (p.id === "(endline)") {
|
|
i = 1;
|
|
do {
|
|
pn = peek(i);
|
|
i = i + 1;
|
|
} while (pn.id === "(endline)");
|
|
|
|
if (pn.id !== ";") {
|
|
if (pn.id !== "(string)" && pn.id !== "(number)" &&
|
|
pn.id !== "(regexp)" && pn.identifier !== true &&
|
|
pn.id !== "}") {
|
|
break;
|
|
}
|
|
warning("W033", state.tokens.next);
|
|
} else {
|
|
p = pn;
|
|
}
|
|
} else if (p.id === "}") {
|
|
warning("W033", p);
|
|
} else if (p.id !== ";") {
|
|
break;
|
|
}
|
|
|
|
indentation();
|
|
advance();
|
|
if (state.directive[state.tokens.curr.value]) {
|
|
warning("W034", state.tokens.curr, state.tokens.curr.value);
|
|
}
|
|
|
|
if (state.tokens.curr.value === "use strict") {
|
|
if (!state.option["(explicitNewcap)"])
|
|
state.option.newcap = true;
|
|
state.option.undef = true;
|
|
}
|
|
state.directive[state.tokens.curr.value] = true;
|
|
|
|
if (p.id === ";") {
|
|
advance(";");
|
|
}
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
function block(ordinary, stmt, isfunc, isfatarrow) {
|
|
var a,
|
|
b = inblock,
|
|
old_indent = indent,
|
|
m,
|
|
s = scope,
|
|
t,
|
|
line,
|
|
d;
|
|
|
|
inblock = ordinary;
|
|
|
|
if (!ordinary || !state.option.funcscope)
|
|
scope = Object.create(scope);
|
|
|
|
nonadjacent(state.tokens.curr, state.tokens.next);
|
|
t = state.tokens.next;
|
|
|
|
var metrics = funct["(metrics)"];
|
|
metrics.nestedBlockDepth += 1;
|
|
metrics.verifyMaxNestedBlockDepthPerFunction();
|
|
|
|
if (state.tokens.next.id === "{") {
|
|
advance("{");
|
|
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 state.directive) {
|
|
if (_.has(state.directive, d)) {
|
|
m[d] = state.directive[d];
|
|
}
|
|
}
|
|
directives();
|
|
|
|
if (state.option.strict && funct["(context)"]["(global)"]) {
|
|
if (!m["use strict"] && !state.directive["use strict"]) {
|
|
warning("E007");
|
|
}
|
|
}
|
|
}
|
|
|
|
a = statements(line);
|
|
|
|
metrics.statementCount += a.length;
|
|
|
|
if (isfunc) {
|
|
state.directive = m;
|
|
}
|
|
|
|
indent -= state.option.indent;
|
|
if (line !== state.tokens.next.line) {
|
|
indentation();
|
|
}
|
|
} else if (line !== state.tokens.next.line) {
|
|
indentation();
|
|
}
|
|
advance("}", t);
|
|
|
|
funct["(blockscope)"].unstack();
|
|
|
|
indent = old_indent;
|
|
} else if (!ordinary) {
|
|
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 {
|
|
funct["(nolet)"] = true;
|
|
|
|
if (!stmt || state.option.curly) {
|
|
warning("W116", state.tokens.next, "{", state.tokens.next.value);
|
|
}
|
|
|
|
noreach = true;
|
|
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 || !state.option.funcscope) scope = s;
|
|
inblock = b;
|
|
if (ordinary && state.option.noempty && (!a || a.length === 0)) {
|
|
warning("W035");
|
|
}
|
|
metrics.nestedBlockDepth -= 1;
|
|
return a;
|
|
}
|
|
|
|
|
|
function countMember(m) {
|
|
if (membersOnly && typeof membersOnly[m] !== "boolean") {
|
|
warning("W036", state.tokens.curr, m);
|
|
}
|
|
if (typeof member[m] === "number") {
|
|
member[m] += 1;
|
|
} else {
|
|
member[m] = 1;
|
|
}
|
|
}
|
|
|
|
|
|
function note_implied(tkn) {
|
|
var name = tkn.value, line = tkn.line, a = implied[name];
|
|
if (typeof a === "function") {
|
|
a = false;
|
|
}
|
|
|
|
if (!a) {
|
|
a = [line];
|
|
implied[name] = a;
|
|
} else if (a[a.length - 1] !== line) {
|
|
a.push(line);
|
|
}
|
|
}
|
|
|
|
type("(number)", function () {
|
|
return this;
|
|
});
|
|
|
|
type("(string)", function () {
|
|
return this;
|
|
});
|
|
|
|
state.syntax["(identifier)"] = {
|
|
type: "(identifier)",
|
|
lbp: 0,
|
|
identifier: true,
|
|
nud: function () {
|
|
var v = this.value,
|
|
s = scope[v],
|
|
f;
|
|
|
|
if (typeof s === "function") {
|
|
s = undefined;
|
|
} else if (typeof s === "boolean") {
|
|
f = funct;
|
|
funct = functions[0];
|
|
addlabel(v, "var");
|
|
s = funct;
|
|
funct = f;
|
|
}
|
|
var block;
|
|
if (_.has(funct, "(blockscope)")) {
|
|
block = funct["(blockscope)"].getlabel(v);
|
|
}
|
|
if (funct === s || block) {
|
|
switch (block ? block[v]["(type)"] : funct[v]) {
|
|
case "unused":
|
|
if (block) block[v]["(type)"] = "var";
|
|
else funct[v] = "var";
|
|
break;
|
|
case "unction":
|
|
if (block) block[v]["(type)"] = "function";
|
|
else funct[v] = "function";
|
|
this["function"] = true;
|
|
break;
|
|
case "function":
|
|
this["function"] = true;
|
|
break;
|
|
case "label":
|
|
warning("W037", state.tokens.curr, v);
|
|
break;
|
|
}
|
|
} else if (funct["(global)"]) {
|
|
|
|
if (typeof predefined[v] !== "boolean") {
|
|
if (!(anonname === "typeof" || anonname === "delete") ||
|
|
(state.tokens.next && (state.tokens.next.value === "." ||
|
|
state.tokens.next.value === "["))) {
|
|
|
|
if (!funct["(comparray)"].check(v)) {
|
|
isundef(funct, "W117", state.tokens.curr, v);
|
|
}
|
|
}
|
|
}
|
|
|
|
note_implied(state.tokens.curr);
|
|
} else {
|
|
|
|
switch (funct[v]) {
|
|
case "closure":
|
|
case "function":
|
|
case "var":
|
|
case "unused":
|
|
warning("W038", state.tokens.curr, v);
|
|
break;
|
|
case "label":
|
|
warning("W037", state.tokens.curr, v);
|
|
break;
|
|
case "outer":
|
|
case "global":
|
|
break;
|
|
default:
|
|
if (s === true) {
|
|
funct[v] = true;
|
|
} else if (s === null) {
|
|
warning("W039", state.tokens.curr, v);
|
|
note_implied(state.tokens.curr);
|
|
} else if (typeof s !== "object") {
|
|
if (!(anonname === "typeof" || anonname === "delete") ||
|
|
(state.tokens.next &&
|
|
(state.tokens.next.value === "." || state.tokens.next.value === "["))) {
|
|
|
|
isundef(funct, "W117", state.tokens.curr, v);
|
|
}
|
|
funct[v] = true;
|
|
note_implied(state.tokens.curr);
|
|
} else {
|
|
switch (s[v]) {
|
|
case "function":
|
|
case "unction":
|
|
this["function"] = true;
|
|
s[v] = "closure";
|
|
funct[v] = s["(global)"] ? "global" : "outer";
|
|
break;
|
|
case "var":
|
|
case "unused":
|
|
s[v] = "closure";
|
|
funct[v] = s["(global)"] ? "global" : "outer";
|
|
break;
|
|
case "closure":
|
|
funct[v] = s["(global)"] ? "global" : "outer";
|
|
break;
|
|
case "label":
|
|
warning("W037", state.tokens.curr, v);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
led: function () {
|
|
error("E033", state.tokens.next, state.tokens.next.value);
|
|
}
|
|
};
|
|
|
|
type("(regexp)", function () {
|
|
return this;
|
|
});
|
|
|
|
delim("(endline)");
|
|
delim("(begin)");
|
|
delim("(end)").reach = true;
|
|
delim("(error)").reach = true;
|
|
delim("}").reach = true;
|
|
delim(")");
|
|
delim("]");
|
|
delim("\"").reach = true;
|
|
delim("'").reach = true;
|
|
delim(";");
|
|
delim(":").reach = true;
|
|
delim("#");
|
|
|
|
reserve("else");
|
|
reserve("case").reach = true;
|
|
reserve("catch");
|
|
reserve("default").reach = true;
|
|
reserve("finally");
|
|
reservevar("arguments", function (x) {
|
|
if (state.directive["use strict"] && funct["(global)"]) {
|
|
warning("E008", x);
|
|
}
|
|
});
|
|
reservevar("eval");
|
|
reservevar("false");
|
|
reservevar("Infinity");
|
|
reservevar("null");
|
|
reservevar("this", function (x) {
|
|
if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] &&
|
|
funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
|
|
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("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);
|
|
advance(":");
|
|
that["else"] = expression(10);
|
|
return that;
|
|
}, 30);
|
|
|
|
infix("||", "or", 40);
|
|
infix("&&", "and", 50);
|
|
bitwise("|", "bitor", 70);
|
|
bitwise("^", "bitxor", 80);
|
|
bitwise("&", "bitand", 90);
|
|
relation("==", function (left, right) {
|
|
var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null");
|
|
|
|
if (!eqnull && state.option.eqeqeq)
|
|
warning("W116", this, "===", "==");
|
|
else if (isPoorRelation(left))
|
|
warning("W041", this, "===", left.value);
|
|
else if (isPoorRelation(right))
|
|
warning("W041", this, "===", right.value);
|
|
|
|
return this;
|
|
});
|
|
relation("===");
|
|
relation("!=", function (left, right) {
|
|
var eqnull = state.option.eqnull &&
|
|
(left.value === "null" || right.value === "null");
|
|
|
|
if (!eqnull && state.option.eqeqeq) {
|
|
warning("W116", this, "!==", "!=");
|
|
} else if (isPoorRelation(left)) {
|
|
warning("W041", this, "!==", left.value);
|
|
} else if (isPoorRelation(right)) {
|
|
warning("W041", this, "!==", right.value);
|
|
}
|
|
return this;
|
|
});
|
|
relation("!==");
|
|
relation("<");
|
|
relation(">");
|
|
relation("<=");
|
|
relation(">=");
|
|
bitwise("<<", "shiftleft", 120);
|
|
bitwise(">>", "shiftright", 120);
|
|
bitwise(">>>", "shiftrightunsigned", 120);
|
|
infix("in", "in", 120);
|
|
infix("instanceof", "instanceof", 120);
|
|
infix("+", function (left, that) {
|
|
var right = expression(130);
|
|
if (left && right && left.id === "(string)" && right.id === "(string)") {
|
|
left.value += right.value;
|
|
left.character = right.character;
|
|
if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
|
|
warning("W050", left);
|
|
}
|
|
return left;
|
|
}
|
|
that.left = left;
|
|
that.right = right;
|
|
return that;
|
|
}, 130);
|
|
prefix("+", "num");
|
|
prefix("+++", function () {
|
|
warning("W007");
|
|
this.right = expression(150);
|
|
this.arity = "unary";
|
|
return this;
|
|
});
|
|
infix("+++", function (left) {
|
|
warning("W007");
|
|
this.left = left;
|
|
this.right = expression(130);
|
|
return this;
|
|
}, 130);
|
|
infix("-", "sub", 130);
|
|
prefix("-", "neg");
|
|
prefix("---", function () {
|
|
warning("W006");
|
|
this.right = expression(150);
|
|
this.arity = "unary";
|
|
return this;
|
|
});
|
|
infix("---", function (left) {
|
|
warning("W006");
|
|
this.left = left;
|
|
this.right = expression(130);
|
|
return this;
|
|
}, 130);
|
|
infix("*", "mult", 140);
|
|
infix("/", "div", 140);
|
|
infix("%", "mod", 140);
|
|
|
|
suffix("++", "postinc");
|
|
prefix("++", "preinc");
|
|
state.syntax["++"].exps = true;
|
|
|
|
suffix("--", "postdec");
|
|
prefix("--", "predec");
|
|
state.syntax["--"].exps = true;
|
|
prefix("delete", function () {
|
|
var p = expression(5);
|
|
if (!p || (p.id !== "." && p.id !== "[")) {
|
|
warning("W051");
|
|
}
|
|
this.first = p;
|
|
return this;
|
|
}).exps = true;
|
|
|
|
prefix("~", function () {
|
|
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;
|
|
});
|
|
|
|
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("W018", this, "!");
|
|
}
|
|
return this;
|
|
});
|
|
|
|
prefix("typeof", "typeof");
|
|
prefix("new", function () {
|
|
var c = expression(155), i;
|
|
if (c && c.id !== "function") {
|
|
if (c.identifier) {
|
|
c["new"] = true;
|
|
switch (c.value) {
|
|
case "Number":
|
|
case "String":
|
|
case "Boolean":
|
|
case "Math":
|
|
case "JSON":
|
|
warning("W053", state.tokens.prev, c.value);
|
|
break;
|
|
case "Function":
|
|
if (!state.option.evil) {
|
|
warning("W054");
|
|
}
|
|
break;
|
|
case "Date":
|
|
case "RegExp":
|
|
break;
|
|
default:
|
|
if (c.id !== "function") {
|
|
i = c.value.substr(0, 1);
|
|
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("W056", state.tokens.curr);
|
|
}
|
|
}
|
|
} else {
|
|
if (!state.option.supernew)
|
|
warning("W057", this);
|
|
}
|
|
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;
|
|
});
|
|
state.syntax["new"].exps = true;
|
|
|
|
prefix("void").exps = true;
|
|
|
|
infix(".", function (left, that) {
|
|
adjacent(state.tokens.prev, state.tokens.curr);
|
|
nobreak();
|
|
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 (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("W060", left);
|
|
}
|
|
|
|
if (!state.option.evil && (m === "eval" || m === "execScript")) {
|
|
warning("W061");
|
|
}
|
|
|
|
return that;
|
|
}, 160, true);
|
|
|
|
infix("(", function (left, that) {
|
|
if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") {
|
|
nobreak(state.tokens.prev, state.tokens.curr);
|
|
}
|
|
|
|
nospace();
|
|
if (state.option.immed && left && !left.immed && left.id === "function") {
|
|
warning("W062");
|
|
}
|
|
|
|
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("W063", left);
|
|
} else if (state.option.newcap) {
|
|
warning("W064", left);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (state.tokens.next.id !== ")") {
|
|
for (;;) {
|
|
p[p.length] = expression(10);
|
|
n += 1;
|
|
if (state.tokens.next.id !== ",") {
|
|
break;
|
|
}
|
|
comma();
|
|
}
|
|
}
|
|
|
|
advance(")");
|
|
nospace(state.tokens.prev, state.tokens.curr);
|
|
|
|
if (typeof left === "object") {
|
|
if (left.value === "parseInt" && n === 1) {
|
|
warning("W065", state.tokens.curr);
|
|
}
|
|
if (!state.option.evil) {
|
|
if (left.value === "eval" || left.value === "Function" ||
|
|
left.value === "execScript") {
|
|
warning("W061", left);
|
|
|
|
if (p[0] && [0].id === "(string)") {
|
|
addInternalSrc(left, p[0].value);
|
|
}
|
|
} else if (p[0] && p[0].id === "(string)" &&
|
|
(left.value === "setTimeout" ||
|
|
left.value === "setInterval")) {
|
|
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("W066", left);
|
|
addInternalSrc(left, p[0].value);
|
|
}
|
|
}
|
|
if (!left.identifier && left.id !== "." && left.id !== "[" &&
|
|
left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
|
|
left.id !== "?") {
|
|
warning("W067", left);
|
|
}
|
|
}
|
|
|
|
that.left = left;
|
|
return that;
|
|
}, 155, true).exps = true;
|
|
|
|
prefix("(", function () {
|
|
nospace();
|
|
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 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();
|
|
}
|
|
}
|
|
|
|
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(state.tokens.prev, state.tokens.curr);
|
|
nospace();
|
|
var e = expression(5), s;
|
|
if (e && e.type === "(string)") {
|
|
if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
|
|
warning("W061", that);
|
|
}
|
|
|
|
countMember(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);
|
|
|
|
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);
|
|
|
|
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");
|
|
}
|
|
}
|
|
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 (state.tokens.next.id === "]") {
|
|
break;
|
|
}
|
|
if (b && state.tokens.curr.line !== state.tokens.next.line) {
|
|
indentation();
|
|
}
|
|
this.first.push(expression(10));
|
|
if (state.tokens.next.id === ",") {
|
|
comma({ allowTrailing: true });
|
|
if (state.tokens.next.id === "]" && !state.option.inES5(true)) {
|
|
warning("W070", state.tokens.curr);
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (b) {
|
|
indent -= state.option.indent;
|
|
indentation();
|
|
}
|
|
advance("]", this);
|
|
return this;
|
|
}, 160);
|
|
|
|
|
|
function property_name() {
|
|
var id = optionalidentifier(false, true);
|
|
|
|
if (!id) {
|
|
if (state.tokens.next.id === "(string)") {
|
|
id = state.tokens.next.value;
|
|
advance();
|
|
} else if (state.tokens.next.id === "(number)") {
|
|
id = state.tokens.next.value.toString();
|
|
advance();
|
|
}
|
|
}
|
|
|
|
if (id === "hasOwnProperty") {
|
|
warning("W001");
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
|
|
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 (state.tokens.next.id === ")") {
|
|
advance(")");
|
|
return;
|
|
}
|
|
|
|
for (;;) {
|
|
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(state.tokens.prev, state.tokens.curr);
|
|
return params;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function doFunction(name, statement, generator, fatarrowparams) {
|
|
var f;
|
|
var oldOption = state.option;
|
|
var oldIgnored = state.ignored;
|
|
var oldScope = scope;
|
|
|
|
state.option = Object.create(state.option);
|
|
state.ignored = Object.create(state.ignored);
|
|
scope = Object.create(scope);
|
|
|
|
funct = {
|
|
"(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;
|
|
state.tokens.curr.funct = funct;
|
|
|
|
functions.push(funct);
|
|
|
|
if (name) {
|
|
addlabel(name, "function");
|
|
}
|
|
|
|
funct["(params)"] = functionparams(fatarrowparams);
|
|
|
|
funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
|
|
|
|
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;
|
|
state.option = oldOption;
|
|
state.ignored = oldIgnored;
|
|
funct["(last)"] = state.tokens.curr.line;
|
|
funct["(lastcharacter)"] = state.tokens.curr.character;
|
|
funct = funct["(context)"];
|
|
|
|
return f;
|
|
}
|
|
|
|
function createMetrics(functionStartToken) {
|
|
return {
|
|
statementCount: 0,
|
|
nestedBlockDepth: -1,
|
|
ComplexityCount: 1,
|
|
verifyMaxStatementsPerFunction: function () {
|
|
if (state.option.maxstatements &&
|
|
this.statementCount > state.option.maxstatements) {
|
|
warning("W071", functionStartToken, this.statementCount);
|
|
}
|
|
},
|
|
|
|
verifyMaxParametersPerFunction: function (params) {
|
|
params = params || [];
|
|
|
|
if (state.option.maxparams && params.length > state.option.maxparams) {
|
|
warning("W072", functionStartToken, params.length);
|
|
}
|
|
},
|
|
|
|
verifyMaxNestedBlockDepthPerFunction: function () {
|
|
if (state.option.maxdepth &&
|
|
this.nestedBlockDepth > 0 &&
|
|
this.nestedBlockDepth === state.option.maxdepth + 1) {
|
|
warning("W073", null, this.nestedBlockDepth);
|
|
}
|
|
},
|
|
|
|
verifyMaxComplexityPerFunction: function () {
|
|
var max = state.option.maxcomplexity;
|
|
var cc = this.ComplexityCount;
|
|
if (max && cc > max) {
|
|
warning("W074", functionStartToken, cc);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
function increaseComplexityCount() {
|
|
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 (isclassdef) {
|
|
var b, f, i, p, t, g;
|
|
var props = {}; // All properties, including accessors
|
|
var tag = "";
|
|
|
|
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].basictkn = tkn;
|
|
}
|
|
|
|
function saveSetter(name, tkn) {
|
|
if (props[name] && _.has(props, name)) {
|
|
if (props[name].basic || props[name].setter)
|
|
warning("W075", state.tokens.next, i);
|
|
} else {
|
|
props[name] = {};
|
|
}
|
|
|
|
props[name].setter = true;
|
|
props[name].setterToken = tkn;
|
|
}
|
|
|
|
function saveGetter(name) {
|
|
if (props[name] && _.has(props, name)) {
|
|
if (props[name].basic || props[name].getter)
|
|
warning("W075", state.tokens.next, i);
|
|
} else {
|
|
props[name] = {};
|
|
}
|
|
|
|
props[name].getter = true;
|
|
props[name].getterToken = state.tokens.curr;
|
|
}
|
|
|
|
b = state.tokens.curr.line !== state.tokens.next.line;
|
|
if (b) {
|
|
indent += state.option.indent;
|
|
if (state.tokens.next.from === indent + state.option.indent) {
|
|
indent += state.option.indent;
|
|
}
|
|
}
|
|
|
|
for (;;) {
|
|
if (state.tokens.next.id === "}") {
|
|
break;
|
|
}
|
|
|
|
if (b) {
|
|
indentation();
|
|
}
|
|
|
|
if (isclassdef && state.tokens.next.value === "static") {
|
|
advance("static");
|
|
tag = "static ";
|
|
}
|
|
|
|
if (state.tokens.next.value === "get" && peek().id !== ":") {
|
|
advance("get");
|
|
|
|
if (!state.option.inES5(!isclassdef)) {
|
|
error("E034");
|
|
}
|
|
|
|
i = property_name();
|
|
if (!i) {
|
|
error("E035");
|
|
}
|
|
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("W076", t, p[0], i);
|
|
}
|
|
|
|
adjacent(state.tokens.curr, state.tokens.next);
|
|
} else if (state.tokens.next.value === "set" && peek().id !== ":") {
|
|
advance("set");
|
|
|
|
if (!state.option.inES5(!isclassdef)) {
|
|
error("E034");
|
|
}
|
|
|
|
i = property_name();
|
|
if (!i) {
|
|
error("E035");
|
|
}
|
|
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("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(tag + i, state.tokens.next);
|
|
|
|
if (typeof i !== "string") {
|
|
break;
|
|
}
|
|
|
|
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 (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 -= state.option.indent;
|
|
indentation();
|
|
}
|
|
advance("}", this);
|
|
if (state.option.inES5()) {
|
|
for (var name in props) {
|
|
if (_.has(props, name) && props[name].setter && !props[name].getter) {
|
|
warning("W078", props[name].setterToken);
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
x.fud = function () {
|
|
error("E036", state.tokens.curr);
|
|
};
|
|
}(delim("{")));
|
|
|
|
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 });
|
|
}
|
|
} 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 });
|
|
}
|
|
};
|
|
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 tokens, lone, value;
|
|
|
|
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 } ];
|
|
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) {
|
|
addlabel(t.id, "unused", t.token);
|
|
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("E038", 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;
|
|
});
|
|
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("W082", state.tokens.curr);
|
|
|
|
}
|
|
var i = identifier();
|
|
if (funct[i] === "const") {
|
|
warning("E011", null, i);
|
|
}
|
|
adjacent(state.tokens.curr, state.tokens.next);
|
|
addlabel(i, "unction", state.tokens.curr);
|
|
|
|
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 generator = false;
|
|
if (state.tokens.next.value === "*") {
|
|
if (!state.option.inESNext()) {
|
|
warning("W119", state.tokens.curr, "function*");
|
|
}
|
|
advance("*");
|
|
generator = true;
|
|
}
|
|
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 = state.tokens.next;
|
|
increaseComplexityCount();
|
|
state.condition = true;
|
|
advance("(");
|
|
nonadjacent(this, t);
|
|
nospace();
|
|
checkCondAssignment(expression(0));
|
|
advance(")", t);
|
|
state.condition = false;
|
|
nospace(state.tokens.prev, state.tokens.curr);
|
|
block(true, true);
|
|
if (state.tokens.next.id === "else") {
|
|
nonadjacent(state.tokens.curr, state.tokens.next);
|
|
advance("else");
|
|
if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
|
|
statement(true);
|
|
} else {
|
|
block(true, true);
|
|
}
|
|
}
|
|
return this;
|
|
});
|
|
|
|
blockstmt("try", function () {
|
|
var b;
|
|
|
|
function doCatch() {
|
|
var oldScope = scope;
|
|
var e;
|
|
|
|
advance("catch");
|
|
nonadjacent(state.tokens.curr, state.tokens.next);
|
|
advance("(");
|
|
|
|
scope = Object.create(oldScope);
|
|
|
|
e = state.tokens.next.value;
|
|
if (state.tokens.next.type !== "(identifier)") {
|
|
e = null;
|
|
warning("E030", state.tokens.next, e);
|
|
}
|
|
|
|
advance();
|
|
|
|
funct = {
|
|
"(name)" : "(catch)",
|
|
"(line)" : state.tokens.next.line,
|
|
"(character)": state.tokens.next.character,
|
|
"(context)" : funct,
|
|
"(breakage)" : funct["(breakage)"],
|
|
"(loopage)" : funct["(loopage)"],
|
|
"(scope)" : scope,
|
|
"(statement)": false,
|
|
"(metrics)" : createMetrics(state.tokens.next),
|
|
"(catch)" : true,
|
|
"(tokens)" : {},
|
|
"(blockscope)": funct["(blockscope)"],
|
|
"(comparray)": funct["(comparray)"]
|
|
};
|
|
|
|
if (e) {
|
|
addlabel(e, "exception");
|
|
}
|
|
|
|
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)"] = state.tokens.curr.line;
|
|
funct["(lastcharacter)"] = state.tokens.curr.character;
|
|
funct = funct["(context)"];
|
|
}
|
|
|
|
block(false);
|
|
|
|
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 (state.tokens.next.id === "finally") {
|
|
advance("finally");
|
|
block(false);
|
|
return;
|
|
}
|
|
|
|
if (!b) {
|
|
error("E021", state.tokens.next, "catch", state.tokens.next.value);
|
|
}
|
|
|
|
return this;
|
|
});
|
|
|
|
blockstmt("while", function () {
|
|
var t = state.tokens.next;
|
|
funct["(breakage)"] += 1;
|
|
funct["(loopage)"] += 1;
|
|
increaseComplexityCount();
|
|
advance("(");
|
|
nonadjacent(this, t);
|
|
nospace();
|
|
checkCondAssignment(expression(0));
|
|
advance(")", t);
|
|
nospace(state.tokens.prev, state.tokens.curr);
|
|
block(true, true);
|
|
funct["(breakage)"] -= 1;
|
|
funct["(loopage)"] -= 1;
|
|
return this;
|
|
}).labelled = true;
|
|
|
|
blockstmt("with", function () {
|
|
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("(");
|
|
nonadjacent(this, t);
|
|
nospace();
|
|
expression(0);
|
|
advance(")", t);
|
|
nospace(state.tokens.prev, state.tokens.curr);
|
|
block(true, true);
|
|
|
|
return this;
|
|
});
|
|
|
|
blockstmt("switch", function () {
|
|
var t = state.tokens.next,
|
|
g = false;
|
|
funct["(breakage)"] += 1;
|
|
advance("(");
|
|
nonadjacent(this, t);
|
|
nospace();
|
|
checkCondAssignment(expression(0));
|
|
advance(")", t);
|
|
nospace(state.tokens.prev, state.tokens.curr);
|
|
nonadjacent(state.tokens.curr, state.tokens.next);
|
|
t = state.tokens.next;
|
|
advance("{");
|
|
nonadjacent(state.tokens.curr, state.tokens.next);
|
|
indent += state.option.indent;
|
|
this.cases = [];
|
|
|
|
for (;;) {
|
|
switch (state.tokens.next.id) {
|
|
case "case":
|
|
switch (funct["(verb)"]) {
|
|
case "yield":
|
|
case "break":
|
|
case "case":
|
|
case "continue":
|
|
case "return":
|
|
case "switch":
|
|
case "throw":
|
|
break;
|
|
default:
|
|
if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
|
|
warning("W086", state.tokens.curr, "case");
|
|
}
|
|
}
|
|
indentation(-state.option.indent);
|
|
advance("case");
|
|
this.cases.push(expression(20));
|
|
increaseComplexityCount();
|
|
g = true;
|
|
advance(":");
|
|
funct["(verb)"] = "case";
|
|
break;
|
|
case "default":
|
|
switch (funct["(verb)"]) {
|
|
case "yield":
|
|
case "break":
|
|
case "continue":
|
|
case "return":
|
|
case "throw":
|
|
break;
|
|
default:
|
|
if (this.cases.length) {
|
|
if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
|
|
warning("W086", state.tokens.curr, "default");
|
|
}
|
|
}
|
|
}
|
|
indentation(-state.option.indent);
|
|
advance("default");
|
|
g = true;
|
|
advance(":");
|
|
break;
|
|
case "}":
|
|
indent -= state.option.indent;
|
|
indentation();
|
|
advance("}", t);
|
|
funct["(breakage)"] -= 1;
|
|
funct["(verb)"] = undefined;
|
|
return;
|
|
case "(end)":
|
|
error("E023", state.tokens.next, "}");
|
|
return;
|
|
default:
|
|
if (g) {
|
|
switch (state.tokens.curr.id) {
|
|
case ",":
|
|
error("E040");
|
|
return;
|
|
case ":":
|
|
g = false;
|
|
statements();
|
|
break;
|
|
default:
|
|
error("E025", state.tokens.curr);
|
|
return;
|
|
}
|
|
} else {
|
|
if (state.tokens.curr.id === ":") {
|
|
advance(":");
|
|
error("E024", state.tokens.curr, ":");
|
|
statements();
|
|
} else {
|
|
error("E021", state.tokens.next, "case", state.tokens.next.value);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}).labelled = true;
|
|
|
|
stmt("debugger", function () {
|
|
if (!state.option.debug) {
|
|
warning("W087");
|
|
}
|
|
return this;
|
|
}).exps = true;
|
|
|
|
(function () {
|
|
var x = stmt("do", function () {
|
|
funct["(breakage)"] += 1;
|
|
funct["(loopage)"] += 1;
|
|
increaseComplexityCount();
|
|
|
|
this.first = block(true, true);
|
|
advance("while");
|
|
var t = state.tokens.next;
|
|
nonadjacent(state.tokens.curr, t);
|
|
advance("(");
|
|
nospace();
|
|
checkCondAssignment(expression(0));
|
|
advance(")", t);
|
|
nospace(state.tokens.prev, state.tokens.curr);
|
|
funct["(breakage)"] -= 1;
|
|
funct["(loopage)"] -= 1;
|
|
return this;
|
|
});
|
|
x.labelled = true;
|
|
x.exps = true;
|
|
}());
|
|
|
|
blockstmt("for", function () {
|
|
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();
|
|
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");
|
|
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[state.tokens.next.value]) {
|
|
case "unused":
|
|
funct[state.tokens.next.value] = "var";
|
|
break;
|
|
case "var":
|
|
break;
|
|
default:
|
|
if (!funct["(blockscope)"].getlabel(state.tokens.next.value))
|
|
warning("W088", state.tokens.next, state.tokens.next.value);
|
|
}
|
|
advance();
|
|
}
|
|
advance(nextop.value);
|
|
expression(20);
|
|
advance(")", t);
|
|
s = block(true, true);
|
|
if (state.option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
|
|
s[0].value !== "if")) {
|
|
warning("W089", this);
|
|
}
|
|
funct["(breakage)"] -= 1;
|
|
funct["(loopage)"] -= 1;
|
|
} else {
|
|
if (foreachtok) {
|
|
error("E045", foreachtok);
|
|
}
|
|
if (state.tokens.next.id !== ";") {
|
|
if (state.tokens.next.id === "var") {
|
|
advance("var");
|
|
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 (state.tokens.next.id !== ",") {
|
|
break;
|
|
}
|
|
comma();
|
|
}
|
|
}
|
|
}
|
|
nolinebreak(state.tokens.curr);
|
|
advance(";");
|
|
if (state.tokens.next.id !== ";") {
|
|
checkCondAssignment(expression(0));
|
|
}
|
|
nolinebreak(state.tokens.curr);
|
|
advance(";");
|
|
if (state.tokens.next.id === ";") {
|
|
error("E021", state.tokens.next, ")", ";");
|
|
}
|
|
if (state.tokens.next.id !== ")") {
|
|
for (;;) {
|
|
expression(0, "for");
|
|
if (state.tokens.next.id !== ",") {
|
|
break;
|
|
}
|
|
comma();
|
|
}
|
|
}
|
|
advance(")", t);
|
|
nospace(state.tokens.prev, state.tokens.curr);
|
|
block(true, true);
|
|
funct["(breakage)"] -= 1;
|
|
funct["(loopage)"] -= 1;
|
|
|
|
}
|
|
if (letscope) {
|
|
funct["(blockscope)"].unstack();
|
|
}
|
|
return this;
|
|
}).labelled = true;
|
|
|
|
|
|
stmt("break", function () {
|
|
var v = state.tokens.next.value;
|
|
|
|
if (funct["(breakage)"] === 0)
|
|
warning("W052", state.tokens.next, this.value);
|
|
|
|
if (!state.option.asi)
|
|
nolinebreak(this);
|
|
|
|
if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
|
|
if (state.tokens.curr.line === state.tokens.next.line) {
|
|
if (funct[v] !== "label") {
|
|
warning("W090", state.tokens.next, v);
|
|
} else if (scope[v] !== funct) {
|
|
warning("W091", state.tokens.next, v);
|
|
}
|
|
this.first = state.tokens.next;
|
|
advance();
|
|
}
|
|
}
|
|
reachable("break");
|
|
return this;
|
|
}).exps = true;
|
|
|
|
|
|
stmt("continue", function () {
|
|
var v = state.tokens.next.value;
|
|
|
|
if (funct["(breakage)"] === 0)
|
|
warning("W052", state.tokens.next, this.value);
|
|
|
|
if (!state.option.asi)
|
|
nolinebreak(this);
|
|
|
|
if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
|
|
if (state.tokens.curr.line === state.tokens.next.line) {
|
|
if (funct[v] !== "label") {
|
|
warning("W090", state.tokens.next, v);
|
|
} else if (scope[v] !== funct) {
|
|
warning("W091", state.tokens.next, v);
|
|
}
|
|
this.first = state.tokens.next;
|
|
advance();
|
|
}
|
|
} else if (!funct["(loopage)"]) {
|
|
warning("W052", state.tokens.next, this.value);
|
|
}
|
|
reachable("continue");
|
|
return this;
|
|
}).exps = true;
|
|
|
|
|
|
stmt("return", function () {
|
|
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 &&
|
|
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)
|
|
}
|
|
}
|
|
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(state.tokens.curr, state.tokens.next);
|
|
this.first = expression(20);
|
|
reachable("throw");
|
|
return this;
|
|
}).exps = true;
|
|
|
|
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");
|
|
|
|
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 = state.tokens.next;
|
|
advance("{");
|
|
if (state.tokens.next.id !== "}") {
|
|
for (;;) {
|
|
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 (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[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[state.tokens.next.value] = true;
|
|
}
|
|
advance();
|
|
advance(":");
|
|
jsonValue();
|
|
if (state.tokens.next.id !== ",") {
|
|
break;
|
|
}
|
|
advance(",");
|
|
}
|
|
}
|
|
advance("}");
|
|
}
|
|
|
|
function jsonArray() {
|
|
var t = state.tokens.next;
|
|
advance("[");
|
|
if (state.tokens.next.id !== "]") {
|
|
for (;;) {
|
|
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 (state.tokens.next.id === ",") {
|
|
error("E028", state.tokens.next);
|
|
}
|
|
jsonValue();
|
|
if (state.tokens.next.id !== ",") {
|
|
break;
|
|
}
|
|
advance(",");
|
|
}
|
|
}
|
|
advance("]");
|
|
}
|
|
|
|
switch (state.tokens.next.id) {
|
|
case "{":
|
|
jsonObject();
|
|
break;
|
|
case "[":
|
|
jsonArray();
|
|
break;
|
|
case "true":
|
|
case "false":
|
|
case "null":
|
|
case "(number)":
|
|
case "(string)":
|
|
advance();
|
|
break;
|
|
case "-":
|
|
advance("-");
|
|
if (state.tokens.curr.character !== state.tokens.next.from) {
|
|
warning("W011", state.tokens.curr);
|
|
}
|
|
adjacent(state.tokens.curr, state.tokens.next);
|
|
advance("(number)");
|
|
break;
|
|
default:
|
|
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 i, k, x;
|
|
var optionKeys;
|
|
var newOptionObj = {};
|
|
var newIgnoredObj = {};
|
|
|
|
state.reset();
|
|
|
|
if (o && o.scope) {
|
|
JSHINT.scope = o.scope;
|
|
} else {
|
|
JSHINT.errors = [];
|
|
JSHINT.undefs = [];
|
|
JSHINT.internals = [];
|
|
JSHINT.blacklist = {};
|
|
JSHINT.scope = "(main)";
|
|
}
|
|
|
|
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) {
|
|
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;
|
|
}
|
|
});
|
|
|
|
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++) {
|
|
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] === "indent")
|
|
newOptionObj["(explicitIndent)"] = o[optionKeys[x]] === false ? false : true;
|
|
}
|
|
}
|
|
}
|
|
|
|
state.option = newOptionObj;
|
|
state.ignored = newIgnoredObj;
|
|
|
|
state.option.indent = state.option.indent || 4;
|
|
state.option.maxerr = state.option.maxerr || 50;
|
|
|
|
indent = 1;
|
|
global = Object.create(predefined);
|
|
scope = global;
|
|
funct = {
|
|
"(global)": true,
|
|
"(name)": "(global)",
|
|
"(scope)": scope,
|
|
"(breakage)": 0,
|
|
"(loopage)": 0,
|
|
"(tokens)": {},
|
|
"(metrics)": createMetrics(state.tokens.next),
|
|
"(blockscope)": blockScope(),
|
|
"(comparray)": arrayComprehension()
|
|
};
|
|
functions = [funct];
|
|
urls = [];
|
|
stack = null;
|
|
member = {};
|
|
membersOnly = null;
|
|
implied = {};
|
|
inblock = false;
|
|
lookahead = [];
|
|
warnings = 0;
|
|
unuseds = [];
|
|
|
|
if (!isString(s) && !Array.isArray(s)) {
|
|
errorAt("E004", 0);
|
|
return false;
|
|
}
|
|
|
|
api = {
|
|
get isJSON() {
|
|
return state.jsonMode;
|
|
},
|
|
|
|
getOption: function (name) {
|
|
return state.option[name] || null;
|
|
},
|
|
|
|
getCache: function (name) {
|
|
return state.cache[name];
|
|
},
|
|
|
|
setCache: function (name, value) {
|
|
state.cache[name] = value;
|
|
},
|
|
|
|
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 (_.has(o, name)) {
|
|
checkOption(name, state.tokens.curr);
|
|
}
|
|
}
|
|
|
|
assume();
|
|
combine(predefined, g || {});
|
|
comma.first = true;
|
|
|
|
try {
|
|
advance();
|
|
switch (state.tokens.next.id) {
|
|
case "{":
|
|
case "[":
|
|
destructuringAssignOrJsonValue();
|
|
break;
|
|
default:
|
|
directives();
|
|
|
|
if (state.directive["use strict"]) {
|
|
if (!state.option.globalstrict && !state.option.node) {
|
|
warning("W097", state.tokens.prev);
|
|
}
|
|
}
|
|
|
|
statements();
|
|
}
|
|
advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined);
|
|
funct["(blockscope)"].unstack();
|
|
|
|
var markDefined = function (name, context) {
|
|
do {
|
|
if (typeof context[name] === "string") {
|
|
|
|
if (context[name] === "unused")
|
|
context[name] = "var";
|
|
else if (context[name] === "unction")
|
|
context[name] = "closure";
|
|
|
|
return true;
|
|
}
|
|
|
|
context = context["(context)"];
|
|
} while (context);
|
|
|
|
return false;
|
|
};
|
|
|
|
var clearImplied = function (name, line) {
|
|
if (!implied[name])
|
|
return;
|
|
|
|
var newImplied = [];
|
|
for (var i = 0; i < implied[name].length; i += 1) {
|
|
if (implied[name][i] !== line)
|
|
newImplied.push(implied[name][i]);
|
|
}
|
|
|
|
if (newImplied.length === 0)
|
|
delete implied[name];
|
|
else
|
|
implied[name] = newImplied;
|
|
};
|
|
|
|
var warnUnused = function (name, tkn, type, unused_opt) {
|
|
var line = tkn.line;
|
|
var chr = tkn.character;
|
|
|
|
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,
|
|
line: line,
|
|
character: chr
|
|
});
|
|
};
|
|
|
|
var checkUnused = function (func, key) {
|
|
var type = func[key];
|
|
var tkn = func["(tokens)"][key];
|
|
|
|
if (key.charAt(0) === "(")
|
|
return;
|
|
|
|
if (type !== "unused" && type !== "unction")
|
|
return;
|
|
if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
|
|
return;
|
|
if (func["(global)"] && _.has(exported, key)) {
|
|
return;
|
|
}
|
|
|
|
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 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 (_.has(func, key)) {
|
|
checkUnused(func, key);
|
|
}
|
|
}
|
|
|
|
if (!func["(params)"])
|
|
return;
|
|
|
|
var params = func["(params)"].slice();
|
|
var param = params.pop();
|
|
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") {
|
|
warnUnused(param, func["(tokens)"][param], "param", func["(unusedOption)"]);
|
|
} else if (unused_opt === "last-param") {
|
|
return;
|
|
}
|
|
|
|
param = params.pop();
|
|
}
|
|
});
|
|
|
|
for (var key in declared) {
|
|
if (_.has(declared, key) && !_.has(global, key)) {
|
|
warnUnused(key, declared[key], "var");
|
|
}
|
|
}
|
|
|
|
} catch (err) {
|
|
if (err && err.name === "JSHintError") {
|
|
var nt = state.tokens.next || {};
|
|
JSHINT.errors.push({
|
|
scope : "(main)",
|
|
raw : err.raw,
|
|
reason : err.message,
|
|
line : err.line || nt.line,
|
|
character : err.character || nt.from
|
|
}, null);
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
if (JSHINT.scope === "(main)") {
|
|
o = o || {};
|
|
|
|
for (i = 0; i < JSHINT.internals.length; i += 1) {
|
|
k = JSHINT.internals[i];
|
|
o.scope = k.elem;
|
|
itself(k.value, o, g);
|
|
}
|
|
}
|
|
|
|
return JSHINT.errors.length === 0;
|
|
};
|
|
itself.addModule = function (func) {
|
|
extraModules.push(func);
|
|
};
|
|
|
|
itself.addModule(style.register);
|
|
itself.data = function () {
|
|
var data = {
|
|
functions: [],
|
|
options: state.option
|
|
};
|
|
var implieds = [];
|
|
var members = [];
|
|
var fu, f, i, j, n, globals;
|
|
|
|
if (itself.errors.length) {
|
|
data.errors = itself.errors;
|
|
}
|
|
|
|
if (state.jsonMode) {
|
|
data.json = true;
|
|
}
|
|
|
|
for (n in implied) {
|
|
if (_.has(implied, n)) {
|
|
implieds.push({
|
|
name: n,
|
|
line: implied[n]
|
|
});
|
|
}
|
|
}
|
|
|
|
if (implieds.length > 0) {
|
|
data.implieds = implieds;
|
|
}
|
|
|
|
if (urls.length > 0) {
|
|
data.urls = urls;
|
|
}
|
|
|
|
globals = Object.keys(scope);
|
|
if (globals.length > 0) {
|
|
data.globals = globals;
|
|
}
|
|
|
|
for (i = 1; i < functions.length; i += 1) {
|
|
f = functions[i];
|
|
fu = {};
|
|
|
|
for (j = 0; j < functionicity.length; j += 1) {
|
|
fu[functionicity[j]] = [];
|
|
}
|
|
|
|
for (j = 0; j < functionicity.length; j += 1) {
|
|
if (fu[functionicity[j]].length === 0) {
|
|
delete fu[functionicity[j]];
|
|
}
|
|
}
|
|
|
|
fu.name = f["(name)"];
|
|
fu.param = f["(params)"];
|
|
fu.line = f["(line)"];
|
|
fu.character = f["(character)"];
|
|
fu.last = f["(last)"];
|
|
fu.lastcharacter = f["(lastcharacter)"];
|
|
data.functions.push(fu);
|
|
}
|
|
|
|
if (unuseds.length > 0) {
|
|
data.unused = unuseds;
|
|
}
|
|
|
|
members = [];
|
|
for (n in member) {
|
|
if (typeof member[n] === "number") {
|
|
data.member = member;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return data;
|
|
};
|
|
|
|
itself.jshint = itself;
|
|
|
|
return itself;
|
|
}());
|
|
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: [ "<non-printable>" ]
|
|
});
|
|
}
|
|
|
|
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");
|
|
|
|
}); |