diff options
Diffstat (limited to 'data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser')
4 files changed, 0 insertions, 3569 deletions
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/jsdefs.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/jsdefs.js deleted file mode 100644 index aff5c08..0000000 --- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/jsdefs.js +++ /dev/null @@ -1,751 +0,0 @@ -/* vim: set sw=4 ts=4 et tw=78: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Narcissus JavaScript engine. - * - * The Initial Developer of the Original Code is - * Brendan Eich <brendan@mozilla.org>. - * Portions created by the Initial Developer are Copyright (C) 2004 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Tom Austin <taustin@ucsc.edu> - * Brendan Eich <brendan@mozilla.org> - * Shu-Yu Guo <shu@rfrn.org> - * Dave Herman <dherman@mozilla.com> - * Dimitris Vardoulakis <dimvar@ccs.neu.edu> - * Patrick Walton <pcwalton@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Narcissus - JS implemented in JS. - * - * Well-known constants and lookup tables. Many consts are generated from the - * tokens table via eval to minimize redundancy, so consumers must be compiled - * separately to take advantage of the simple switch-case constant propagation - * done by SpiderMonkey. - */ -/** - * GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript. - * * - * Copyright (C) 2011, 2012, 2014 Loic J. Duros - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -//"use scrict"; - -var Narcissus = {}; -(function() { - - var narcissus = { - options: { - version: 185, - // Global variables to hide from the interpreter - hiddenHostGlobals: { Narcissus: true }, - // Desugar SpiderMonkey language extensions? - desugarExtensions: false - }, - hostSupportsEvalConst: (function() { - try { - return eval("(function(s) { eval(s); return x })('const x = true;')"); - } catch (e) { - return false; - } - })(), - hostGlobal: this - }; - Narcissus = narcissus; -})(); - -Narcissus.definitions = (function() { - - var tokens = [ - // End of source. - "END", - - // Operators and punctuators. Some pair-wise order matters, e.g. (+, -) - // and (UNARY_PLUS, UNARY_MINUS). - "\n", ";", - ",", - "=", - "?", ":", "CONDITIONAL", - "||", - "&&", - "|", - "^", - "&", - "==", "!=", "===", "!==", - "<", "<=", ">=", ">", - "<<", ">>", ">>>", - "+", "-", - "*", "/", "%", - "!", "~", "UNARY_PLUS", "UNARY_MINUS", - "++", "--", - ".", - "[", "]", - "{", "}", - "(", ")", - - // Nonterminal tree node type codes. - "SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX", - "ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER", - "GROUP", "LIST", "LET_BLOCK", "ARRAY_COMP", "GENERATOR", "COMP_TAIL", - - // Terminals. - "IDENTIFIER", "NUMBER", "STRING", "REGEXP", - - // Keywords. - "break", - "case", "catch", "const", "continue", - "debugger", "default", "delete", "do", - "else", "export", - "false", "finally", "for", "function", - "if", "import", "in", "instanceof", - "let", "module", - "new", "null", - "return", - "switch", - "this", "throw", "true", "try", "typeof", - "var", "void", - "yield", - "while", "with", - ]; - - var statementStartTokens = [ - "break", - "const", "continue", - "debugger", "do", - "for", - "if", - "return", - "switch", - "throw", "try", - "var", - "yield", - "while", "with", - ]; - - // Whitespace characters (see ECMA-262 7.2) - var whitespaceChars = [ - // normal whitespace: - "\u0009", "\u000B", "\u000C", "\u0020", "\u00A0", "\uFEFF", - - // high-Unicode whitespace: - "\u1680", "\u180E", - "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006", - "\u2007", "\u2008", "\u2009", "\u200A", - "\u202F", "\u205F", "\u3000" - ]; - - var whitespace = {}; - for (var i = 0; i < whitespaceChars.length; i++) { - whitespace[whitespaceChars[i]] = true; - } - - // Operator and punctuator mapping from token to tree node type name. - // NB: because the lexer doesn't backtrack, all token prefixes must themselves - // be valid tokens (e.g. !== is acceptable because its prefixes are the valid - // tokens != and !). - var opTypeNames = { - '\n': "NEWLINE", - ';': "SEMICOLON", - ',': "COMMA", - '?': "HOOK", - ':': "COLON", - '||': "OR", - '&&': "AND", - '|': "BITWISE_OR", - '^': "BITWISE_XOR", - '&': "BITWISE_AND", - '===': "STRICT_EQ", - '==': "EQ", - '=': "ASSIGN", - '!==': "STRICT_NE", - '!=': "NE", - '<<': "LSH", - '<=': "LE", - '<': "LT", - '>>>': "URSH", - '>>': "RSH", - '>=': "GE", - '>': "GT", - '++': "INCREMENT", - '--': "DECREMENT", - '+': "PLUS", - '-': "MINUS", - '*': "MUL", - '/': "DIV", - '%': "MOD", - '!': "NOT", - '~': "BITWISE_NOT", - '.': "DOT", - '[': "LEFT_BRACKET", - ']': "RIGHT_BRACKET", - '{': "LEFT_CURLY", - '}': "RIGHT_CURLY", - '(': "LEFT_PAREN", - ')': "RIGHT_PAREN" - }; - - // Hash of keyword identifier to tokens index. NB: we must null __proto__ to - // avoid toString, etc. namespace pollution. - var keywords = {__proto__: null}; - - // Define const END, etc., based on the token names. Also map name to index. - var tokenIds = {}; - - // Building up a string to be eval'd in different contexts. - var consts = Narcissus.hostSupportsEvalConst ? "const " : "var "; - for (var i = 0, j = tokens.length; i < j; i++) { - if (i > 0) - consts += ", "; - var t = tokens[i]; - var name; - if (/^[a-z]/.test(t)) { - name = t.toUpperCase(); - keywords[t] = i; - } else { - name = (/^\W/.test(t) ? opTypeNames[t] : t); - } - consts += name + " = " + i; - tokenIds[name] = i; - tokens[t] = i; - } - consts += ";"; - - var isStatementStartCode = {__proto__: null}; - for (i = 0, j = statementStartTokens.length; i < j; i++) - isStatementStartCode[keywords[statementStartTokens[i]]] = true; - - // Map assignment operators to their indexes in the tokens array. - var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%']; - - for (i = 0, j = assignOps.length; i < j; i++) { - t = assignOps[i]; - assignOps[t] = tokens[t]; - } - - function defineGetter(obj, prop, fn, dontDelete, dontEnum) { - Object.defineProperty(obj, prop, - { get: fn, configurable: !dontDelete, enumerable: !dontEnum }); - } - - function defineGetterSetter(obj, prop, getter, setter, dontDelete, dontEnum) { - Object.defineProperty(obj, prop, { - get: getter, - set: setter, - configurable: !dontDelete, - enumerable: !dontEnum - }); - } - - function defineMemoGetter(obj, prop, fn, dontDelete, dontEnum) { - Object.defineProperty(obj, prop, { - get: function() { - var val = fn(); - defineProperty(obj, prop, val, dontDelete, true, dontEnum); - return val; - }, - configurable: true, - enumerable: !dontEnum - }); - } - - function defineProperty(obj, prop, val, dontDelete, readOnly, dontEnum) { - Object.defineProperty(obj, prop, - { value: val, writable: !readOnly, configurable: !dontDelete, - enumerable: !dontEnum }); - } - - // Returns true if fn is a native function. (Note: SpiderMonkey specific.) - function isNativeCode(fn) { - // Relies on the toString method to identify native code. - return ((typeof fn) === "function") && fn.toString().match(/\[native code\]/); - } - - var Fpapply = Function.prototype.apply; - - function apply(f, o, a) { - return Fpapply.call(f, [o].concat(a)); - } - - var applyNew; - - // ES5's bind is a simpler way to implement applyNew - if (Function.prototype.bind) { - applyNew = function applyNew(f, a) { - return new (f.bind.apply(f, [,].concat(a)))(); - }; - } else { - applyNew = function applyNew(f, a) { - switch (a.length) { - case 0: - return new f(); - case 1: - return new f(a[0]); - case 2: - return new f(a[0], a[1]); - case 3: - return new f(a[0], a[1], a[2]); - default: - var argStr = "a[0]"; - for (var i = 1, n = a.length; i < n; i++) - argStr += ",a[" + i + "]"; - return eval("new f(" + argStr + ")"); - } - }; - } - - function getPropertyDescriptor(obj, name) { - while (obj) { - if (({}).hasOwnProperty.call(obj, name)) - return Object.getOwnPropertyDescriptor(obj, name); - obj = Object.getPrototypeOf(obj); - } - return undefined; - } - - function getPropertyNames(obj) { - var table = Object.create(null, {}); - while (obj) { - var names = Object.getOwnPropertyNames(obj); - for (var i = 0, n = names.length; i < n; i++) - table[names[i]] = true; - obj = Object.getPrototypeOf(obj); - } - return Object.keys(table); - } - - function getOwnProperties(obj) { - var map = {}; - for (var name in Object.getOwnPropertyNames(obj)) - map[name] = Object.getOwnPropertyDescriptor(obj, name); - return map; - } - - function blacklistHandler(target, blacklist) { - var mask = Object.create(null, {}); - var redirect = StringMap.create(blacklist).mapObject(function(name) { return mask; }); - return mixinHandler(redirect, target); - } - - function whitelistHandler(target, whitelist) { - var catchall = Object.create(null, {}); - var redirect = StringMap.create(whitelist).mapObject(function(name) { return target; }); - return mixinHandler(redirect, catchall); - } - - function mirrorHandler(target, writable) { - var handler = makePassthruHandler(target); - - var defineProperty = handler.defineProperty; - handler.defineProperty = function(name, desc) { - if (!desc.enumerable) - throw new Error("mirror property must be enumerable"); - if (!desc.configurable) - throw new Error("mirror property must be configurable"); - if (desc.writable !== writable) - throw new Error("mirror property must " + (writable ? "" : "not ") + "be writable"); - defineProperty(name, desc); - }; - - handler.fix = function() { }; - handler.getOwnPropertyDescriptor = handler.getPropertyDescriptor; - handler.getOwnPropertyNames = getPropertyNames.bind(handler, target); - handler.keys = handler.enumerate; - handler["delete"] = function() { return false; }; - handler.hasOwn = handler.has; - return handler; - } - - /* - * Mixin proxies break the single-inheritance model of prototypes, so - * the handler treats all properties as own-properties: - * - * X - * | - * +------------+------------+ - * | O | - * | | | - * | O O O | - * | | | | | - * | O O O O | - * | | | | | | - * | O O O O O | - * | | | | | | | - * +-(*)--(w)--(x)--(y)--(z)-+ - */ - - function mixinHandler(redirect, catchall) { - function targetFor(name) { - return hasOwn(redirect, name) ? redirect[name] : catchall; - } - - function getMuxPropertyDescriptor(name) { - var desc = getPropertyDescriptor(targetFor(name), name); - if (desc) - desc.configurable = true; - return desc; - } - - function getMuxPropertyNames() { - var names1 = Object.getOwnPropertyNames(redirect).filter(function(name) { - return name in redirect[name]; - }); - var names2 = getPropertyNames(catchall).filter(function(name) { - return !hasOwn(redirect, name); - }); - return names1.concat(names2); - } - - function enumerateMux() { - var result = Object.getOwnPropertyNames(redirect).filter(function(name) { - return name in redirect[name]; - }); - for (name in catchall) { - if (!hasOwn(redirect, name)) - result.push(name); - }; - return result; - } - - function hasMux(name) { - return name in targetFor(name); - } - - return { - getOwnPropertyDescriptor: getMuxPropertyDescriptor, - getPropertyDescriptor: getMuxPropertyDescriptor, - getOwnPropertyNames: getMuxPropertyNames, - defineProperty: function(name, desc) { - Object.defineProperty(targetFor(name), name, desc); - }, - "delete": function(name) { - var target = targetFor(name); - return delete target[name]; - }, - // FIXME: ha ha ha - fix: function() { }, - has: hasMux, - hasOwn: hasMux, - get: function(receiver, name) { - var target = targetFor(name); - return target[name]; - }, - set: function(receiver, name, val) { - var target = targetFor(name); - target[name] = val; - return true; - }, - enumerate: enumerateMux, - keys: enumerateMux - }; - } - - function makePassthruHandler(obj) { - // Handler copied from - // http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy - return { - getOwnPropertyDescriptor: function(name) { - var desc = Object.getOwnPropertyDescriptor(obj, name); - - // a trapping proxy's properties must always be configurable - desc.configurable = true; - return desc; - }, - getPropertyDescriptor: function(name) { - var desc = getPropertyDescriptor(obj, name); - - // a trapping proxy's properties must always be configurable - desc.configurable = true; - return desc; - }, - getOwnPropertyNames: function() { - return Object.getOwnPropertyNames(obj); - }, - defineProperty: function(name, desc) { - Object.defineProperty(obj, name, desc); - }, - "delete": function(name) { return delete obj[name]; }, - fix: function() { - if (Object.isFrozen(obj)) { - return getOwnProperties(obj); - } - - // As long as obj is not frozen, the proxy won't allow itself to be fixed. - return undefined; // will cause a TypeError to be thrown - }, - - has: function(name) { return name in obj; }, - hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); }, - get: function(receiver, name) { return obj[name]; }, - - // bad behavior when set fails in non-strict mode - set: function(receiver, name, val) { obj[name] = val; return true; }, - enumerate: function() { - var result = []; - for (name in obj) { result.push(name); }; - return result; - }, - keys: function() { return Object.keys(obj); } - }; - } - - var hasOwnProperty = ({}).hasOwnProperty; - - function hasOwn(obj, name) { - return hasOwnProperty.call(obj, name); - } - - function StringMap(table, size) { - this.table = table || Object.create(null, {}); - this.size = size || 0; - } - - StringMap.create = function(table) { - var init = Object.create(null, {}); - var size = 0; - var names = Object.getOwnPropertyNames(table); - for (var i = 0, n = names.length; i < n; i++) { - var name = names[i]; - init[name] = table[name]; - size++; - } - return new StringMap(init, size); - }; - - StringMap.prototype = { - has: function(x) { return hasOwnProperty.call(this.table, x); }, - set: function(x, v) { - if (!hasOwnProperty.call(this.table, x)) - this.size++; - this.table[x] = v; - }, - get: function(x) { return this.table[x]; }, - getDef: function(x, thunk) { - if (!hasOwnProperty.call(this.table, x)) { - this.size++; - this.table[x] = thunk(); - } - return this.table[x]; - }, - forEach: function(f) { - var table = this.table; - for (var key in table) - f.call(this, key, table[key]); - }, - map: function(f) { - var table1 = this.table; - var table2 = Object.create(null, {}); - this.forEach(function(key, val) { - table2[key] = f.call(this, val, key); - }); - return new StringMap(table2, this.size); - }, - mapObject: function(f) { - var table1 = this.table; - var table2 = Object.create(null, {}); - this.forEach(function(key, val) { - table2[key] = f.call(this, val, key); - }); - return table2; - }, - toObject: function() { - return this.mapObject(function(val) { return val; }); - }, - choose: function() { - return Object.getOwnPropertyNames(this.table)[0]; - }, - remove: function(x) { - if (hasOwnProperty.call(this.table, x)) { - this.size--; - delete this.table[x]; - } - }, - copy: function() { - var table = Object.create(null, {}); - for (var key in this.table) - table[key] = this.table[key]; - return new StringMap(table, this.size); - }, - keys: function() { - return Object.keys(this.table); - }, - toString: function() { return "[object StringMap]" } - }; - - // an object-key table with poor asymptotics (replace with WeakMap when possible) - function ObjectMap(array) { - this.array = array || []; - } - - function searchMap(map, key, found, notFound) { - var a = map.array; - for (var i = 0, n = a.length; i < n; i++) { - var pair = a[i]; - if (pair.key === key) - return found(pair, i); - } - return notFound(); - } - - ObjectMap.prototype = { - has: function(x) { - return searchMap(this, x, function() { return true }, function() { return false }); - }, - set: function(x, v) { - var a = this.array; - searchMap(this, x, - function(pair) { pair.value = v }, - function() { a.push({ key: x, value: v }) }); - }, - get: function(x) { - return searchMap(this, x, - function(pair) { return pair.value }, - function() { return null }); - }, - getDef: function(x, thunk) { - var a = this.array; - return searchMap(this, x, - function(pair) { return pair.value }, - function() { - var v = thunk(); - a.push({ key: x, value: v }); - return v; - }); - }, - forEach: function(f) { - var a = this.array; - for (var i = 0, n = a.length; i < n; i++) { - var pair = a[i]; - f.call(this, pair.key, pair.value); - } - }, - choose: function() { - return this.array[0].key; - }, - get size() { - return this.array.length; - }, - remove: function(x) { - var a = this.array; - searchMap(this, x, - function(pair, i) { a.splice(i, 1) }, - function() { }); - }, - copy: function() { - return new ObjectMap(this.array.map(function(pair) { - return { key: pair.key, value: pair.value } - })); - }, - clear: function() { - this.array = []; - }, - toString: function() { return "[object ObjectMap]" } - }; - - // non-destructive stack - function Stack(elts) { - this.elts = elts || null; - } - - Stack.prototype = { - push: function(x) { - return new Stack({ top: x, rest: this.elts }); - }, - top: function() { - if (!this.elts) - throw new Error("empty stack"); - return this.elts.top; - }, - isEmpty: function() { - return this.top === null; - }, - find: function(test) { - for (var elts = this.elts; elts; elts = elts.rest) { - if (test(elts.top)) - return elts.top; - } - return null; - }, - has: function(x) { - return Boolean(this.find(function(elt) { return elt === x })); - }, - forEach: function(f) { - for (var elts = this.elts; elts; elts = elts.rest) { - f(elts.top); - } - } - }; - - if (!Array.prototype.copy) { - Array.prototype.copy = function() { - var result = []; - for (var i = 0, n = this.length; i < n; i++) - result[i] = this[i]; - return result; - }; - } - - return { - tokens: tokens, - whitespace: whitespace, - opTypeNames: opTypeNames, - keywords: keywords, - isStatementStartCode: isStatementStartCode, - tokenIds: tokenIds, - consts: consts, - assignOps: assignOps, - defineGetter: defineGetter, - defineGetterSetter: defineGetterSetter, - defineMemoGetter: defineMemoGetter, - defineProperty: defineProperty, - isNativeCode: isNativeCode, - apply: apply, - applyNew: applyNew, - mirrorHandler: mirrorHandler, - mixinHandler: mixinHandler, - whitelistHandler: whitelistHandler, - blacklistHandler: blacklistHandler, - makePassthruHandler: makePassthruHandler, - StringMap: StringMap, - ObjectMap: ObjectMap, - Stack: Stack - }; -}()); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/jslex.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/jslex.js deleted file mode 100644 index c5c2673..0000000 --- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/jslex.js +++ /dev/null @@ -1,719 +0,0 @@ -/* vim: set sw=4 ts=4 et tw=78: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Narcissus JavaScript engine. - * - * The Initial Developer of the Original Code is - * Brendan Eich <brendan@mozilla.org>. - * Portions created by the Initial Developer are Copyright (C) 2004 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Tom Austin <taustin@ucsc.edu> - * Brendan Eich <brendan@mozilla.org> - * Shu-Yu Guo <shu@rfrn.org> - * Stephan Herhut <stephan.a.herhut@intel.com> - * Dave Herman <dherman@mozilla.com> - * Dimitris Vardoulakis <dimvar@ccs.neu.edu> - * Patrick Walton <pcwalton@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/** - * GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript. - * * - * Copyright (C) 2011, 2012, 2014 Loic J. Duros - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -/* - * Narcissus - JS implemented in JS. - * - * Lexical scanner. - */ - -"use strict"; - -Narcissus.lexer = (function() { - - var definitions = Narcissus.definitions; - - //throw Error (definitions.consts); - - // Set constants in the local scope. - //eval(definitions.consts); - const END = 0, - NEWLINE = 1, - SEMICOLON = 2, - COMMA = 3, - ASSIGN = 4, - HOOK = 5, - COLON = 6, - CONDITIONAL = 7, - OR = 8, - AND = 9, - BITWISE_OR = 10, - BITWISE_XOR = 11, - BITWISE_AND = 12, - EQ = 13, - NE = 14, - STRICT_EQ = 15, - STRICT_NE = 16, - LT = 17, - LE = 18, - GE = 19, - GT = 20, - LSH = 21, - RSH = 22, - URSH = 23, - PLUS = 24, - MINUS = 25, - MUL = 26, - DIV = 27, - MOD = 28, - NOT = 29, - BITWISE_NOT = 30, - UNARY_PLUS = 31, - UNARY_MINUS = 32, - INCREMENT = 33, - DECREMENT = 34, - DOT = 35, - LEFT_BRACKET = 36, - RIGHT_BRACKET = 37, - LEFT_CURLY = 38, - RIGHT_CURLY = 39, - LEFT_PAREN = 40, - RIGHT_PAREN = 41, - SCRIPT = 42, - BLOCK = 43, - LABEL = 44, - FOR_IN = 45, - CALL = 46, - NEW_WITH_ARGS = 47, - INDEX = 48, - ARRAY_INIT = 49, - OBJECT_INIT = 50, - PROPERTY_INIT = 51, - GETTER = 52, - SETTER = 53, - GROUP = 54, - LIST = 55, - LET_BLOCK = 56, - ARRAY_COMP = 57, - GENERATOR = 58, - COMP_TAIL = 59, - IDENTIFIER = 60, - NUMBER = 61, - STRING = 62, - REGEXP = 63, - BREAK = 64, - CASE = 65, - CATCH = 66, - CONST = 67, - CONTINUE = 68, - DEBUGGER = 69, - DEFAULT = 70, - DELETE = 71, - DO = 72, - ELSE = 73, - EXPORT = 74, - FALSE = 75, - FINALLY = 76, - FOR = 77, - FUNCTION = 78, - IF = 79, - IMPORT = 80, - IN = 81, - INSTANCEOF = 82, - LET = 83, - MODULE = 84, - NEW = 85, - NULL = 86, - RETURN = 87, - SWITCH = 88, - THIS = 89, - THROW = 90, - TRUE = 91, - TRY = 92, - TYPEOF = 93, - VAR = 94, - VOID = 95, - YIELD = 96, - WHILE = 97, - WITH = 98; - - // Banned keywords by language version - const blackLists = { 160: {}, 185: {}, harmony: {} }; -/* blackLists[160][LET] = true; - blackLists[160][MODULE] = true; - blackLists[160][YIELD] = true; - blackLists[185][MODULE] = true; -*/ - // Build up a trie of operator tokens. - var opTokens = {}; - for (var op in definitions.opTypeNames) { - if (op === '\n' || op === '.') - continue; - - var node = opTokens; - for (var i = 0; i < op.length; i++) { - var ch = op[i]; - if (!(ch in node)) - node[ch] = {}; - node = node[ch]; - node.op = op; - } - } - - /* - * Since JavaScript provides no convenient way to determine if a - * character is in a particular Unicode category, we use - * metacircularity to accomplish this (oh yeaaaah!) - */ - function isValidIdentifierChar(ch, first) { - // check directly for ASCII - if (ch <= "\u007F") { - if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '$' || ch === '_' || - (!first && (ch >= '0' && ch <= '9'))) { - return true; - } - return false; - } - - // create an object to test this in - var x = {}; - x["x"+ch] = true; - x[ch] = true; - - // then use eval to determine if it's a valid character - var valid = false; - try { - valid = (Function("x", "return (x." + (first?"":"x") + ch + ");")(x) === true); - } catch (ex) {} - - return valid; - } - - function isIdentifier(str) { - if (typeof str !== "string") - return false; - - if (str.length === 0) - return false; - - if (!isValidIdentifierChar(str[0], true)) - return false; - - for (var i = 1; i < str.length; i++) { - if (!isValidIdentifierChar(str[i], false)) - return false; - } - - return true; - } - - /* - * Tokenizer :: (source, filename, line number) -> Tokenizer - */ - function Tokenizer(s, f, l) { - this.cursor = 0; - this.source = String(s); - this.tokens = []; - this.tokenIndex = 0; - this.lookahead = 0; - this.scanNewlines = false; - this.unexpectedEOF = false; - this.filename = f || ""; - this.lineno = l || 1; - this.blackList = blackLists[Narcissus.options.version]; - this.blockComments = null; - } - - Tokenizer.prototype = { - get done() { - // We need to set scanOperand to true here because the first thing - // might be a regexp. - return this.peek(true) === END; - }, - - get token() { - return this.tokens[this.tokenIndex]; - }, - - match: function (tt, scanOperand) { - return this.get(scanOperand) === tt || this.unget(); - }, - - mustMatch: function (tt) { - if (!this.match(tt)) { - throw this.newSyntaxError("Missing " + - definitions.tokens[tt].toLowerCase()); - } - return this.token; - }, - - peek: function (scanOperand) { - var tt, next; - if (this.lookahead) { - next = this.tokens[(this.tokenIndex + this.lookahead) & 3]; - tt = (this.scanNewlines && next.lineno !== this.lineno) - ? NEWLINE - : next.type; - } else { - tt = this.get(scanOperand); - this.unget(); - } - return tt; - }, - - peekOnSameLine: function (scanOperand) { - this.scanNewlines = true; - var tt = this.peek(scanOperand); - this.scanNewlines = false; - return tt; - }, - - lastBlockComment: function() { - var length = this.blockComments.length; - return length ? this.blockComments[length - 1] : null; - }, - - // Eat comments and whitespace. - skip: function () { - var input = this.source; - this.blockComments = []; - for (;;) { - var ch = input[this.cursor++]; - var next = input[this.cursor]; - // handle \r, \r\n and (always preferable) \n - if (ch === '\r') { - // if the next character is \n, we don't care about this at all - if (next === '\n') continue; - - // otherwise, we want to consider this as a newline - ch = '\n'; - } - - if (ch === '\n' && !this.scanNewlines) { - this.lineno++; - } else if (ch === '/' && next === '*') { - var commentStart = ++this.cursor; - for (;;) { - ch = input[this.cursor++]; - if (ch === undefined) - throw this.newSyntaxError("Unterminated comment"); - - if (ch === '*') { - next = input[this.cursor]; - if (next === '/') { - var commentEnd = this.cursor - 1; - this.cursor++; - break; - } - } else if (ch === '\n') { - this.lineno++; - } - } - this.blockComments.push(input.substring(commentStart, commentEnd)); - } - else if (ch === '-' && next === '-' && - input[this.cursor + 1] === '>') { - this.cursor += 2; - } - else if ((ch === '/' && next === '/') || - (ch === '<' && next === '!' && - input[this.cursor + 1] === '-' && - input[this.cursor + 2] === '-' && - (this.cursor += 2))) { - - // capture single line comments starts. - var commentStart = ++this.cursor; - for (;;) { - ch = input[this.cursor++]; - if (ch === undefined) { - //this.lineno++; - break; - //throw this.newSyntaxError("Unterminated comment"); - } - if (ch === '\r') { - // check for \r\n - if (next !== '\n') ch = '\n'; - var commentEnd = this.cursor - 1; - } - - if (ch === '\n') { - if (this.scanNewlines) { - this.cursor--; - } else { - this.lineno++; - } - var commentEnd = this.cursor - 1; - break; - } - } - this.blockComments.push(input.substring(commentStart, commentEnd)); - // capture single line comments ends. - } else if (!(ch in definitions.whitespace)) { - this.cursor--; - return; - } - } - }, - - // Lex the exponential part of a number, if present. Return true iff an - // exponential part was found. - lexExponent: function() { - var input = this.source; - var next = input[this.cursor]; - if (next === 'e' || next === 'E') { - this.cursor++; - ch = input[this.cursor++]; - if (ch === '+' || ch === '-') - ch = input[this.cursor++]; - - if (ch < '0' || ch > '9') - throw this.newSyntaxError("Missing exponent"); - - do { - ch = input[this.cursor++]; - } while (ch >= '0' && ch <= '9'); - this.cursor--; - - return true; - } - - return false; - }, - - lexZeroNumber: function (ch) { - var token = this.token, input = this.source; - token.type = NUMBER; - - ch = input[this.cursor++]; - if (ch === '.') { - do { - ch = input[this.cursor++]; - } while (ch >= '0' && ch <= '9'); - this.cursor--; - - this.lexExponent(); - token.value = parseFloat( - input.substring(token.start, this.cursor)); - } else if (ch === 'x' || ch === 'X') { - do { - ch = input[this.cursor++]; - } while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || - (ch >= 'A' && ch <= 'F')); - this.cursor--; - - token.value = parseInt(input.substring(token.start, this.cursor)); - } else if (ch >= '0' && ch <= '7') { - do { - ch = input[this.cursor++]; - } while (ch >= '0' && ch <= '7'); - this.cursor--; - - token.value = parseInt(input.substring(token.start, this.cursor)); - } else { - this.cursor--; - this.lexExponent(); // 0E1, &c. - token.value = 0; - } - }, - - lexNumber: function (ch) { - var token = this.token, input = this.source; - token.type = NUMBER; - - var floating = false; - do { - ch = input[this.cursor++]; - if (ch === '.' && !floating) { - floating = true; - ch = input[this.cursor++]; - } - } while (ch >= '0' && ch <= '9'); - - this.cursor--; - - var exponent = this.lexExponent(); - floating = floating || exponent; - - var str = input.substring(token.start, this.cursor); - token.value = floating ? parseFloat(str) : parseInt(str); - }, - - lexDot: function (ch) { - var token = this.token, input = this.source; - var next = input[this.cursor]; - if (next >= '0' && next <= '9') { - do { - ch = input[this.cursor++]; - } while (ch >= '0' && ch <= '9'); - this.cursor--; - - this.lexExponent(); - - token.type = NUMBER; - token.value = parseFloat( - input.substring(token.start, this.cursor)); - } else { - token.type = DOT; - token.assignOp = null; - token.value = '.'; - } - }, - - lexString: function (ch) { - var token = this.token, input = this.source; - token.type = STRING; - - var hasEscapes = false; - var delim = ch; - if (input.length <= this.cursor) - throw this.newSyntaxError("Unterminated string literal"); - while ((ch = input[this.cursor++]) !== delim) { - if (this.cursor == input.length) - throw this.newSyntaxError("Unterminated string literal"); - if (ch === '\\') { - hasEscapes = true; - if (++this.cursor == input.length) - throw this.newSyntaxError("Unterminated string literal"); - } - } - - token.value = hasEscapes - ? eval(input.substring(token.start, this.cursor)) - : input.substring(token.start + 1, this.cursor - 1); - }, - - lexRegExp: function (ch) { - var token = this.token, input = this.source; - token.type = REGEXP; - - do { - ch = input[this.cursor++]; - if (ch === '\\') { - this.cursor++; - } else if (ch === '[') { - do { - if (ch === undefined) - throw this.newSyntaxError("Unterminated character class"); - - if (ch === '\\') - this.cursor++; - - ch = input[this.cursor++]; - } while (ch !== ']'); - } else if (ch === undefined) { - throw this.newSyntaxError("Unterminated regex"); - } - } while (ch !== '/'); - - do { - ch = input[this.cursor++]; - } while (ch >= 'a' && ch <= 'z'); - - this.cursor--; - - token.value = eval(input.substring(token.start, this.cursor)); - }, - - lexOp: function (ch) { - var token = this.token, input = this.source; - - // A bit ugly, but it seems wasteful to write a trie lookup routine - // for only 3 characters... - var node = opTokens[ch]; - var next = input[this.cursor]; - if (next in node) { - node = node[next]; - this.cursor++; - next = input[this.cursor]; - if (next in node) { - node = node[next]; - this.cursor++; - next = input[this.cursor]; - } - } - - var op = node.op; - if (definitions.assignOps[op] && input[this.cursor] === '=') { - this.cursor++; - token.type = ASSIGN; - token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]]; - op += '='; - } else { - token.type = definitions.tokenIds[definitions.opTypeNames[op]]; - token.assignOp = null; - } - - token.value = op; - }, - - // FIXME: Unicode escape sequences - lexIdent: function (ch) { - var token = this.token; - var id = ch; - - while ((ch = this.getValidIdentifierChar(false)) !== null) { - id += ch; - } - - token.type = definitions.keywords[id] || IDENTIFIER; - if (token.type in this.blackList) { - // banned keyword, this is an identifier - token.type = IDENTIFIER; - } - token.value = id; - }, - - /* - * Tokenizer.get :: void -> token type - * - * Consume input *only* if there is no lookahead. - * Dispatch to the appropriate lexing function depending on the input. - */ - get: function (scanOperand) { - var token; - while (this.lookahead) { - --this.lookahead; - this.tokenIndex = (this.tokenIndex + 1) & 3; - token = this.tokens[this.tokenIndex]; - if (token.type !== NEWLINE || this.scanNewlines) - return token.type; - } - - this.skip(); - - this.tokenIndex = (this.tokenIndex + 1) & 3; - token = this.tokens[this.tokenIndex]; - if (!token) - this.tokens[this.tokenIndex] = token = {}; - - var input = this.source; - if (this.cursor >= input.length) - return token.type = END; - - token.start = this.cursor; - token.lineno = this.lineno; - - var ich = this.getValidIdentifierChar(true); - var ch = (ich === null) ? input[this.cursor++] : null; - if (ich !== null) { - this.lexIdent(ich); - } else if (scanOperand && ch === '/') { - this.lexRegExp(ch); - } else if (ch in opTokens) { - this.lexOp(ch); - } else if (ch === '.') { - this.lexDot(ch); - } else if (ch >= '1' && ch <= '9') { - this.lexNumber(ch); - } else if (ch === '0') { - this.lexZeroNumber(ch); - } else if (ch === '"' || ch === "'") { - this.lexString(ch); - } else if (this.scanNewlines && (ch === '\n' || ch === '\r')) { - // if this was a \r, look for \r\n - if (ch === '\r' && input[this.cursor] === '\n') this.cursor++; - token.type = NEWLINE; - token.value = '\n'; - this.lineno++; - } else { - throw this.newSyntaxError("Illegal token"); - } - - token.end = this.cursor; - return token.type; - }, - - /* - * Tokenizer.unget :: void -> undefined - * - * Match depends on unget returning undefined. - */ - unget: function () { - if (++this.lookahead === 4) throw "PANIC: too much lookahead!"; - this.tokenIndex = (this.tokenIndex - 1) & 3; - }, - - newSyntaxError: function (m) { - m = (this.filename ? this.filename + ":" : "") + this.lineno + ": " + m; - var e = new SyntaxError(m, this.filename, this.lineno); - e.source = this.source; - e.cursor = this.lookahead - ? this.tokens[(this.tokenIndex + this.lookahead) & 3].start - : this.cursor; - return e; - }, - - - /* Gets a single valid identifier char from the input stream, or null - * if there is none. - */ - getValidIdentifierChar: function(first) { - var input = this.source; - if (this.cursor >= input.length) return null; - var ch = input[this.cursor]; - - // first check for \u escapes - if (ch === '\\' && input[this.cursor+1] === 'u') { - // get the character value - try { - ch = String.fromCharCode(parseInt( - input.substring(this.cursor + 2, this.cursor + 6), - 16)); - } catch (ex) { - return null; - } - this.cursor += 5; - } - - var valid = isValidIdentifierChar(ch, first); - if (valid) this.cursor++; - return (valid ? ch : null); - }, - }; - - - return { - isIdentifier: isIdentifier, - Tokenizer: Tokenizer - }; - -}()); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/jsparse.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/jsparse.js deleted file mode 100644 index b78078c..0000000 --- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/jsparse.js +++ /dev/null @@ -1,2042 +0,0 @@ -/* -*- Mode: JS; tab-width: 4; indent-tabs-mode: nil; -*- - * vim: set sw=4 ts=4 et tw=78: - * ***** BEGIN LICENSE BLOCK ***** - * - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Narcissus JavaScript engine. - * - * The Initial Developer of the Original Code is - * Brendan Eich <brendan@mozilla.org>. - * Portions created by the Initial Developer are Copyright (C) 2004 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Tom Austin <taustin@ucsc.edu> - * Brendan Eich <brendan@mozilla.org> - * Shu-Yu Guo <shu@rfrn.org> - * Dave Herman <dherman@mozilla.com> - * Dimitris Vardoulakis <dimvar@ccs.neu.edu> - * Patrick Walton <pcwalton@mozilla.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/** - * GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript. - * * - * Copyright (C) 2011, 2012, 2014 Loic J. Duros - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -/* - * Narcissus - JS implemented in JS. - * - * Parser. - */ - -"use strict"; - -Narcissus.parser = (function() { - - var lexer = Narcissus.lexer; - var definitions = Narcissus.definitions; - - const StringMap = definitions.StringMap; - const Stack = definitions.Stack; - - var comment; - - // Set constants in the local scope. - //eval(definitions.consts); - const END = 0, - NEWLINE = 1, - SEMICOLON = 2, - COMMA = 3, - ASSIGN = 4, - HOOK = 5, - COLON = 6, - CONDITIONAL = 7, - OR = 8, - AND = 9, - BITWISE_OR = 10, - BITWISE_XOR = 11, - BITWISE_AND = 12, - EQ = 13, - NE = 14, - STRICT_EQ = 15, - STRICT_NE = 16, - LT = 17, - LE = 18, - GE = 19, - GT = 20, - LSH = 21, - RSH = 22, - URSH = 23, - PLUS = 24, - MINUS = 25, - MUL = 26, - DIV = 27, - MOD = 28, - NOT = 29, - BITWISE_NOT = 30, - UNARY_PLUS = 31, - UNARY_MINUS = 32, - INCREMENT = 33, - DECREMENT = 34, - DOT = 35, - LEFT_BRACKET = 36, - RIGHT_BRACKET = 37, - LEFT_CURLY = 38, - RIGHT_CURLY = 39, - LEFT_PAREN = 40, - RIGHT_PAREN = 41, - SCRIPT = 42, - BLOCK = 43, - LABEL = 44, - FOR_IN = 45, - CALL = 46, - NEW_WITH_ARGS = 47, - INDEX = 48, - ARRAY_INIT = 49, - OBJECT_INIT = 50, - PROPERTY_INIT = 51, - GETTER = 52, - SETTER = 53, - GROUP = 54, - LIST = 55, - LET_BLOCK = 56, - ARRAY_COMP = 57, - GENERATOR = 58, - COMP_TAIL = 59, - IDENTIFIER = 60, - NUMBER = 61, - STRING = 62, - REGEXP = 63, - BREAK = 64, - CASE = 65, - CATCH = 66, - CONST = 67, - CONTINUE = 68, - DEBUGGER = 69, - DEFAULT = 70, - DELETE = 71, - DO = 72, - ELSE = 73, - EXPORT = 74, - FALSE = 75, - FINALLY = 76, - FOR = 77, - FUNCTION = 78, - IF = 79, - IMPORT = 80, - IN = 81, - INSTANCEOF = 82, - LET = 83, - MODULE = 84, - NEW = 85, - NULL = 86, - RETURN = 87, - SWITCH = 88, - THIS = 89, - THROW = 90, - TRUE = 91, - TRY = 92, - TYPEOF = 93, - VAR = 94, - VOID = 95, - YIELD = 96, - WHILE = 97, - WITH = 98; - - // Banned statement types by language version. - const blackLists = { 160: {}, 185: {}, harmony: {} }; - /* blackLists[160][IMPORT] = true; - blackLists[160][EXPORT] = true; - blackLists[160][LET] = true; - blackLists[160][MODULE] = true; - blackLists[160][YIELD] = true; - blackLists[185][IMPORT] = true; - blackLists[185][EXPORT] = true; - blackLists[185][MODULE] = true; - blackLists.harmony[WITH] = true; -*/ - /* - * pushDestructuringVarDecls :: (node, hoisting node) -> void - * - * Recursively add all destructured declarations to varDecls. - */ - function pushDestructuringVarDecls(n, s) { - for (var i in n) { - var sub = n[i]; - if (sub.type === IDENTIFIER) { - s.varDecls.push(sub); - } else { - pushDestructuringVarDecls(sub, s); - } - } - } - - function StaticContext(parentScript, parentBlock, inModule, inFunction) { - this.parentScript = parentScript; - this.parentBlock = parentBlock || parentScript; - this.inModule = inModule || false; - this.inFunction = inFunction || false; - this.inForLoopInit = false; - this.topLevel = true; - this.allLabels = new Stack(); - this.currentLabels = new Stack(); - this.labeledTargets = new Stack(); - this.defaultLoopTarget = null; - this.defaultTarget = null; - this.blackList = blackLists[Narcissus.options.version]; - Narcissus.options.ecma3OnlyMode && (this.ecma3OnlyMode = true); - Narcissus.options.parenFreeMode && (this.parenFreeMode = true); - } - - StaticContext.prototype = { - ecma3OnlyMode: false, - parenFreeMode: false, - // non-destructive update via prototype extension - update: function(ext) { - var desc = {}; - for (var key in ext) { - desc[key] = { - value: ext[key], - writable: true, - enumerable: true, - configurable: true - } - } - return Object.create(this, desc); - }, - pushLabel: function(label) { - return this.update({ currentLabels: this.currentLabels.push(label), - allLabels: this.allLabels.push(label) }); - }, - pushTarget: function(target) { - var isDefaultLoopTarget = target.isLoop; - var isDefaultTarget = isDefaultLoopTarget || target.type === SWITCH; - - if (this.currentLabels.isEmpty()) { - if (isDefaultLoopTarget) this.update({ defaultLoopTarget: target }); - if (isDefaultTarget) this.update({ defaultTarget: target }); - return this; - } - - target.labels = new StringMap(); - this.currentLabels.forEach(function(label) { - target.labels.set(label, true); - }); - return this.update({ currentLabels: new Stack(), - labeledTargets: this.labeledTargets.push(target), - defaultLoopTarget: isDefaultLoopTarget - ? target - : this.defaultLoopTarget, - defaultTarget: isDefaultTarget - ? target - : this.defaultTarget }); - }, - nest: function() { - return this.topLevel ? this.update({ topLevel: false }) : this; - }, - allow: function(type) { - switch (type) { - case EXPORT: - if (!this.inModule || this.inFunction || !this.topLevel) - return false; - // FALL THROUGH - - case IMPORT: - return !this.inFunction && this.topLevel; - - case MODULE: - return !this.inFunction && this.topLevel; - - default: - return true; - } - } - }; - - /* - * Script :: (tokenizer, boolean, boolean) -> node - * - * Parses the toplevel and module/function bodies. - */ - function Script(t, inModule, inFunction) { - var n = new Node(t, scriptInit()); - Statements(t, new StaticContext(n, n, inModule, inFunction), n); - return n; - } - - // We extend Array slightly with a top-of-stack method. - definitions.defineProperty(Array.prototype, "top", - function() { - return this.length && this[this.length-1]; - }, false, false, true); - - /* - * Node :: (tokenizer, optional init object) -> node - */ - function Node(t, init) { - var token = t.token; - if (token) { - // If init.type exists it will override token.type. - this.type = token.type; - this.value = token.value; - this.lineno = token.lineno; - - // Start and end are file positions for error handling. - this.start = token.start; - this.end = token.end; - } else { - this.lineno = t.lineno; - } - - // Node uses a tokenizer for debugging (getSource, filename getter). - this.tokenizer = t; - this.children = []; - - for (var prop in init) - this[prop] = init[prop]; - } - - /* - * SyntheticNode :: (tokenizer, optional init object) -> node - */ - function SyntheticNode(t, init) { - // print("SYNTHETIC NODE"); - // if (init.type === COMMA) { - // print("SYNTHETIC COMMA"); - // print(init); - // } - this.tokenizer = t; - this.children = []; - for (var prop in init) - this[prop] = init[prop]; - this.synthetic = true; - } - - var Np = Node.prototype = SyntheticNode.prototype = {}; - Np.constructor = Node; - - const TO_SOURCE_SKIP = { - type: true, - value: true, - lineno: true, - start: true, - end: true, - tokenizer: true, - assignOp: true - }; - function unevalableConst(code) { - var token = definitions.tokens[code]; - var constName = definitions.opTypeNames.hasOwnProperty(token) - ? definitions.opTypeNames[token] - : token in definitions.keywords - ? token.toUpperCase() - : token; - return { toSource: function() { return constName } }; - } - Np.toSource = function toSource() { - var mock = {}; - var self = this; - mock.type = unevalableConst(this.type); - if ("value" in this) - mock.value = this.value; - if ("lineno" in this) - mock.lineno = this.lineno; - if ("start" in this) - mock.start = this.start; - if ("end" in this) - mock.end = this.end; - if (this.assignOp) - mock.assignOp = unevalableConst(this.assignOp); - for (var key in this) { - if (this.hasOwnProperty(key) && !(key in TO_SOURCE_SKIP)) - mock[key] = this[key]; - } - return mock.toSource(); - }; - - // Always use push to add operands to an expression, to update start and end. - Np.push = function (kid) { - // kid can be null e.g. [1, , 2]. - if (kid !== null) { - if (kid.start < this.start) - this.start = kid.start; - if (this.end < kid.end) - this.end = kid.end; - } - return this.children.push(kid); - } - - Node.indentLevel = 0; - - function tokenString(tt) { - var t = definitions.tokens[tt]; - return /^\W/.test(t) ? definitions.opTypeNames[t] : t.toUpperCase(); - } - - Np.toString = function () { - var a = []; - for (var i in this) { - if (this.hasOwnProperty(i) && i !== 'type' && i !== 'target') - a.push({id: i, value: this[i]}); - } - a.sort(function (a,b) { return (a.id < b.id) ? -1 : 1; }); - const INDENTATION = " "; - var n = ++Node.indentLevel; - var s = "{\n" + INDENTATION.repeat(n) + "type: " + tokenString(this.type); - for (i = 0; i < a.length; i++) - s += ",\n" + INDENTATION.repeat(n) + a[i].id + ": " + a[i].value; - n = --Node.indentLevel; - s += "\n" + INDENTATION.repeat(n) + "}"; - return s; - } - - Np.getSource = function () { - return this.tokenizer.source.slice(this.start, this.end); - }; - - /* - * Helper init objects for common nodes. - */ - - const LOOP_INIT = { isLoop: true }; - - function blockInit() { - return { type: BLOCK, varDecls: [] }; - } - - function scriptInit() { - return { type: SCRIPT, - funDecls: [], - varDecls: [], - modDefns: new StringMap(), - modAssns: new StringMap(), - modDecls: new StringMap(), - modLoads: new StringMap(), - impDecls: [], - expDecls: [], - exports: new StringMap(), - hasEmptyReturn: false, - hasReturnWithValue: false, - isGenerator: false }; - } - - definitions.defineGetter(Np, "filename", - function() { - return this.tokenizer.filename; - }); - - definitions.defineGetter(Np, "length", - function() { - throw new Error("Node.prototype.length is gone; " + - "use n.children.length instead"); - }); - - definitions.defineProperty(String.prototype, "repeat", - function(n) { - var s = "", t = this + s; - while (--n >= 0) - s += t; - return s; - }, false, false, true); - - function MaybeLeftParen(t, x) { - if (x.parenFreeMode) - return t.match(LEFT_PAREN) ? LEFT_PAREN : END; - return t.mustMatch(LEFT_PAREN).type; - } - - function MaybeRightParen(t, p) { - if (p === LEFT_PAREN) - t.mustMatch(RIGHT_PAREN); - } - - /* - * Statements :: (tokenizer, compiler context, node) -> void - * - * Parses a sequence of Statements. - */ - function Statements(t, x, n) { - try { - while (!t.done && t.peek(true) !== RIGHT_CURLY) - n.push(Statement(t, x)); - } catch (e) { - if (t.done) - t.unexpectedEOF = true; - throw e; - } - } - - function Block(t, x) { - t.mustMatch(LEFT_CURLY); - var n = new Node(t, blockInit()); - Statements(t, x.update({ parentBlock: n }).pushTarget(n), n); - t.mustMatch(RIGHT_CURLY); - return n; - } - - const DECLARED_FORM = 0, EXPRESSED_FORM = 1, STATEMENT_FORM = 2; - - /* - * Export :: (binding node, boolean) -> Export - * - * Static semantic representation of a module export. - */ - function Export(node, isDefinition) { - this.node = node; // the AST node declaring this individual export - this.isDefinition = isDefinition; // is the node an 'export'-annotated definition? - this.resolved = null; // resolved pointer to the target of this export - } - - /* - * registerExport :: (StringMap, EXPORT node) -> void - */ - function registerExport(exports, decl) { - function register(name, exp) { - if (exports.has(name)) - throw new SyntaxError("multiple exports of " + name); - exports.set(name, exp); - } - - switch (decl.type) { - case MODULE: - case FUNCTION: - register(decl.name, new Export(decl, true)); - break; - - case VAR: - for (var i = 0; i < decl.children.length; i++) - register(decl.children[i].name, new Export(decl.children[i], true)); - break; - - case LET: - case CONST: - throw new Error("NYI: " + definitions.tokens[decl.type]); - - case EXPORT: - for (var i = 0; i < decl.pathList.length; i++) { - var path = decl.pathList[i]; - switch (path.type) { - case OBJECT_INIT: - for (var j = 0; j < path.children.length; j++) { - // init :: IDENTIFIER | PROPERTY_INIT - var init = path.children[j]; - if (init.type === IDENTIFIER) - register(init.value, new Export(init, false)); - else - register(init.children[0].value, new Export(init.children[1], false)); - } - break; - - case DOT: - register(path.children[1].value, new Export(path, false)); - break; - - case IDENTIFIER: - register(path.value, new Export(path, false)); - break; - - default: - throw new Error("unexpected export path: " + definitions.tokens[path.type]); - } - } - break; - - default: - throw new Error("unexpected export decl: " + definitions.tokens[exp.type]); - } - } - - /* - * Module :: (node) -> Module - * - * Static semantic representation of a module. - */ - function Module(node) { - var exports = node.body.exports; - var modDefns = node.body.modDefns; - - var exportedModules = new StringMap(); - - exports.forEach(function(name, exp) { - var node = exp.node; - if (node.type === MODULE) { - exportedModules.set(name, node); - } else if (!exp.isDefinition && node.type === IDENTIFIER && modDefns.has(node.value)) { - var mod = modDefns.get(node.value); - exportedModules.set(name, mod); - } - }); - - this.node = node; - this.exports = exports; - this.exportedModules = exportedModules; - } - - /* - * Statement :: (tokenizer, compiler context) -> node - * - * Parses a Statement. - */ - function Statement(t, x) { - var i, label, n, n2, p, c, ss, tt = t.get(true), tt2, x2, x3; - - var comments = t.blockComments; - - if (x.blackList[tt]) - throw t.newSyntaxError(definitions.tokens[tt] + " statements only allowed in Harmony"); - if (!x.allow(tt)) - throw t.newSyntaxError(definitions.tokens[tt] + " statement in illegal context"); - - // Cases for statements ending in a right curly return early, avoiding the - // common semicolon insertion magic after this switch. - switch (tt) { - case IMPORT: - n = new Node(t); - n.pathList = ImportPathList(t, x); - x.parentScript.impDecls.push(n); - n.blockComments = comments; - break; - - case EXPORT: - switch (t.peek()) { - case MODULE: - case FUNCTION: - case LET: - case VAR: - case CONST: - n = Statement(t, x); - n.blockComments = comments; - n.exported = true; - x.parentScript.expDecls.push(n); - registerExport(x.parentScript.exports, n); - return n; - - default: - n = new Node(t); - n.blockComments = comments; - n.pathList = ExportPathList(t, x); - break; - } - x.parentScript.expDecls.push(n); - registerExport(x.parentScript.exports, n); - break; - - case MODULE: - n = new Node(t); - n.blockComments = comments; - t.mustMatch(IDENTIFIER); - label = t.token.value; - - if (t.match(LEFT_CURLY)) { - n.name = label; - n.body = Script(t, true, false); - n.module = new Module(n); - t.mustMatch(RIGHT_CURLY); - x.parentScript.modDefns.set(n.name, n); - return n; - } - - t.unget(); - ModuleVariables(t, x, n); - return n; - - case FUNCTION: - // DECLARED_FORM extends funDecls of x, STATEMENT_FORM doesn't. - return FunctionDefinition(t, x, true, x.topLevel ? DECLARED_FORM : STATEMENT_FORM, comments); - - case LEFT_CURLY: - n = new Node(t, blockInit()); - n.blockComments = comments; - Statements(t, x.update({ parentBlock: n }).pushTarget(n).nest(), n); - t.mustMatch(RIGHT_CURLY); - return n; - - case IF: - n = new Node(t); - n.blockComments = comments; - n.condition = HeadExpression(t, x); - x2 = x.pushTarget(n).nest(); - n.thenPart = Statement(t, x2); - n.elsePart = t.match(ELSE, true) ? Statement(t, x2) : null; - return n; - - case SWITCH: - // This allows CASEs after a DEFAULT, which is in the standard. - n = new Node(t, { cases: [], defaultIndex: -1 }); - n.blockComments = comments; - n.discriminant = HeadExpression(t, x); - x2 = x.pushTarget(n).nest(); - t.mustMatch(LEFT_CURLY); - while ((tt = t.get()) !== RIGHT_CURLY) { - switch (tt) { - case DEFAULT: - if (n.defaultIndex >= 0) - throw t.newSyntaxError("More than one switch default"); - // FALL THROUGH - case CASE: - n2 = new Node(t); - if (tt === DEFAULT) - n.defaultIndex = n.cases.length; - else - n2.caseLabel = Expression(t, x2, COLON); - break; - - default: - throw t.newSyntaxError("Invalid switch case"); - } - t.mustMatch(COLON); - n2.statements = new Node(t, blockInit()); - while ((tt=t.peek(true)) !== CASE && tt !== DEFAULT && - tt !== RIGHT_CURLY) - n2.statements.push(Statement(t, x2)); - n.cases.push(n2); - } - return n; - - case FOR: - n = new Node(t, LOOP_INIT); - n.blockComments = comments; - if (t.match(IDENTIFIER)) { - if (t.token.value === "each") - n.isEach = true; - else - t.unget(); - } - if (!x.parenFreeMode) - t.mustMatch(LEFT_PAREN); - x2 = x.pushTarget(n).nest(); - x3 = x.update({ inForLoopInit: true }); - n2 = null; - if ((tt = t.peek(true)) !== SEMICOLON) { - if (tt === VAR || tt === CONST) { - t.get(); - n2 = Variables(t, x3); - } else if (tt === LET) { - t.get(); - if (t.peek() === LEFT_PAREN) { - n2 = LetBlock(t, x3, false); - } else { - // Let in for head, we need to add an implicit block - // around the rest of the for. - x3.parentBlock = n; - n.varDecls = []; - n2 = Variables(t, x3); - } - } else { - n2 = Expression(t, x3); - } - } - if (n2 && t.match(IN)) { - n.type = FOR_IN; - n.object = Expression(t, x3); - if (n2.type === VAR || n2.type === LET) { - c = n2.children; - - // Destructuring turns one decl into multiples, so either - // there must be only one destructuring or only one - // decl. - if (c.length !== 1 && n2.destructurings.length !== 1) { - throw new SyntaxError("Invalid for..in left-hand side", - t.filename, n2.lineno); - } - if (n2.destructurings.length > 0) { - n.iterator = n2.destructurings[0]; - } else { - n.iterator = c[0]; - } - n.varDecl = n2; - } else { - if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) { - n2.destructuredNames = checkDestructuring(t, x3, n2); - } - n.iterator = n2; - } - } else { - x3.inForLoopInit = false; - n.setup = n2; - t.mustMatch(SEMICOLON); - if (n.isEach) - throw t.newSyntaxError("Invalid for each..in loop"); - n.condition = (t.peek(true) === SEMICOLON) - ? null - : Expression(t, x3); - t.mustMatch(SEMICOLON); - tt2 = t.peek(true); - n.update = (x.parenFreeMode - ? tt2 === LEFT_CURLY || definitions.isStatementStartCode[tt2] - : tt2 === RIGHT_PAREN) - ? null - : Expression(t, x3); - } - if (!x.parenFreeMode) - t.mustMatch(RIGHT_PAREN); - n.body = Statement(t, x2); - return n; - - case WHILE: - n = new Node(t, { isLoop: true }); - n.blockComments = comments; - n.condition = HeadExpression(t, x); - n.body = Statement(t, x.pushTarget(n).nest()); - return n; - - case DO: - n = new Node(t, { isLoop: true }); - n.blockComments = comments; - n.body = Statement(t, x.pushTarget(n).nest()); - t.mustMatch(WHILE); - n.condition = HeadExpression(t, x); - if (!x.ecmaStrictMode) { - // <script language="JavaScript"> (without version hints) may need - // automatic semicolon insertion without a newline after do-while. - // See http://bugzilla.mozilla.org/show_bug.cgi?id=238945. - t.match(SEMICOLON); - return n; - } - break; - - case BREAK: - case CONTINUE: - n = new Node(t); - n.blockComments = comments; - - // handle the |foo: break foo;| corner case - x2 = x.pushTarget(n); - - if (t.peekOnSameLine() === IDENTIFIER) { - t.get(); - n.label = t.token.value; - } - - if (n.label) { - n.target = x2.labeledTargets.find(function(target) { return target.labels.has(n.label) }); - } else if (tt === CONTINUE) { - n.target = x2.defaultLoopTarget; - } else { - n.target = x2.defaultTarget; - } - - if (!n.target) - throw t.newSyntaxError("Invalid " + ((tt === BREAK) ? "break" : "continue")); - if (!n.target.isLoop && tt === CONTINUE) - throw t.newSyntaxError("Invalid continue"); - - break; - - case TRY: - n = new Node(t, { catchClauses: [] }); - n.blockComments = comments; - n.tryBlock = Block(t, x); - while (t.match(CATCH)) { - n2 = new Node(t); - p = MaybeLeftParen(t, x); - switch (t.get()) { - case LEFT_BRACKET: - case LEFT_CURLY: - // Destructured catch identifiers. - t.unget(); - n2.varName = DestructuringExpression(t, x, true); - break; - case IDENTIFIER: - n2.varName = t.token.value; - break; - default: - throw t.newSyntaxError("missing identifier in catch"); - break; - } - if (t.match(IF)) { - if (x.ecma3OnlyMode) - throw t.newSyntaxError("Illegal catch guard"); - if (n.catchClauses.length && !n.catchClauses.top().guard) - throw t.newSyntaxError("Guarded catch after unguarded"); - n2.guard = Expression(t, x); - } - MaybeRightParen(t, p); - n2.block = Block(t, x); - n.catchClauses.push(n2); - } - if (t.match(FINALLY)) - n.finallyBlock = Block(t, x); - if (!n.catchClauses.length && !n.finallyBlock) - throw t.newSyntaxError("Invalid try statement"); - return n; - - case CATCH: - case FINALLY: - throw t.newSyntaxError(definitions.tokens[tt] + " without preceding try"); - - case THROW: - n = new Node(t); - n.blockComments = comments; - n.exception = Expression(t, x); - break; - - case RETURN: - n = ReturnOrYield(t, x); - break; - - case WITH: - n = new Node(t); - n.blockComments = comments; - n.object = HeadExpression(t, x); - n.body = Statement(t, x.pushTarget(n).nest()); - return n; - - case VAR: - case CONST: - n = Variables(t, x); - break; - - case LET: - if (t.peek() === LEFT_PAREN) - n = LetBlock(t, x, true); - else - n = Variables(t, x); - break; - - case DEBUGGER: - n = new Node(t); - n.blockComments = comments; - break; - - case NEWLINE: - case SEMICOLON: - n = new Node(t, { type: SEMICOLON }); - n.blockComments = comments; - n.expression = null; - return n; - - default: - if (tt === IDENTIFIER) { - tt = t.peek(); - // Labeled statement. - if (tt === COLON) { - label = t.token.value; - if (x.allLabels.has(label)) - throw t.newSyntaxError("Duplicate label"); - t.get(); - n = new Node(t, { type: LABEL, label: label }); - n.blockComments = comments; - n.statement = Statement(t, x.pushLabel(label).nest()); - n.target = (n.statement.type === LABEL) ? n.statement.target : n.statement; - return n; - } - } - - // Expression statement. - // We unget the current token to parse the expression as a whole. - n = new Node(t, { type: SEMICOLON }); - t.unget(); - n.blockComments = comments; - n.expression = Expression(t, x); - n.end = n.expression.end; - break; - } - - n.blockComments = comments; - MagicalSemicolon(t); - return n; - } - - /* - * MagicalSemicolon :: (tokenizer) -> void - */ - function MagicalSemicolon(t) { - var tt; - if (t.lineno === t.token.lineno) { - tt = t.peekOnSameLine(); - if (tt !== END && tt !== NEWLINE && tt !== SEMICOLON && tt !== RIGHT_CURLY) - throw t.newSyntaxError("missing ; before statement"); - } - t.match(SEMICOLON); - } - - /* - * ReturnOrYield :: (tokenizer, compiler context) -> (RETURN | YIELD) node - */ - function ReturnOrYield(t, x) { - var n, b, tt = t.token.type, tt2; - - var parentScript = x.parentScript; - - if (tt === RETURN) { - if (!x.inFunction) { - // pass - //throw t.newSyntaxError("Return not in function"); - } - - } else /* if (tt === YIELD) */ { - if (!x.inFunction) - throw t.newSyntaxError("Yield not in function"); - parentScript.isGenerator = true; - } - n = new Node(t, { value: undefined }); - - tt2 = (tt === RETURN) ? t.peekOnSameLine(true) : t.peek(true); - if (tt2 !== END && tt2 !== NEWLINE && - tt2 !== SEMICOLON && tt2 !== RIGHT_CURLY - && (tt !== YIELD || - (tt2 !== tt && tt2 !== RIGHT_BRACKET && tt2 !== RIGHT_PAREN && - tt2 !== COLON && tt2 !== COMMA))) { - if (tt === RETURN) { - n.value = Expression(t, x); - parentScript.hasReturnWithValue = true; - } else { - n.value = AssignExpression(t, x); - } - } else if (tt === RETURN) { - parentScript.hasEmptyReturn = true; - } - - // Disallow return v; in generator. - if (parentScript.hasReturnWithValue && parentScript.isGenerator) - throw t.newSyntaxError("Generator returns a value"); - - return n; - } - - /* - * ModuleExpression :: (tokenizer, compiler context) -> (STRING | IDENTIFIER | DOT) node - */ - function ModuleExpression(t, x) { - return t.match(STRING) ? new Node(t) : QualifiedPath(t, x); - } - - /* - * ImportPathList :: (tokenizer, compiler context) -> Array[DOT node] - */ - function ImportPathList(t, x) { - var a = []; - do { - a.push(ImportPath(t, x)); - } while (t.match(COMMA)); - return a; - } - - /* - * ImportPath :: (tokenizer, compiler context) -> DOT node - */ - function ImportPath(t, x) { - var n = QualifiedPath(t, x); - if (!t.match(DOT)) { - if (n.type === IDENTIFIER) - throw t.newSyntaxError("cannot import local variable"); - return n; - } - - var n2 = new Node(t); - n2.push(n); - n2.push(ImportSpecifierSet(t, x)); - return n2; - } - - /* - * ExplicitSpecifierSet :: (tokenizer, compiler context, (tokenizer, compiler context) -> node) - * -> OBJECT_INIT node - */ - function ExplicitSpecifierSet(t, x, SpecifierRHS) { - var n, n2, id, tt; - - n = new Node(t, { type: OBJECT_INIT }); - t.mustMatch(LEFT_CURLY); - - if (!t.match(RIGHT_CURLY)) { - do { - id = Identifier(t, x); - if (t.match(COLON)) { - n2 = new Node(t, { type: PROPERTY_INIT }); - n2.push(id); - n2.push(SpecifierRHS(t, x)); - n.push(n2); - } else { - n.push(id); - } - } while (!t.match(RIGHT_CURLY) && t.mustMatch(COMMA)); - } - - return n; - } - - /* - * ImportSpecifierSet :: (tokenizer, compiler context) -> (IDENTIFIER | OBJECT_INIT) node - */ - function ImportSpecifierSet(t, x) { - return t.match(MUL) - ? new Node(t, { type: IDENTIFIER, name: "*" }) - : ExplicitSpecifierSet(t, x, Identifier); - } - - /* - * Identifier :: (tokenizer, compiler context) -> IDENTIFIER node - */ - function Identifier(t, x) { - t.mustMatch(IDENTIFIER); - return new Node(t, { type: IDENTIFIER }); - } - - /* - * IdentifierName :: (tokenizer) -> IDENTIFIER node - */ - function IdentifierName(t) { - if (t.match(IDENTIFIER)) - return new Node(t, { type: IDENTIFIER }); - t.get(); - if (t.token.value in definitions.keywords) - return new Node(t, { type: IDENTIFIER }); - throw t.newSyntaxError("missing IdentifierName"); - } - - /* - * QualifiedPath :: (tokenizer, compiler context) -> (IDENTIFIER | DOT) node - */ - function QualifiedPath(t, x) { - var n, n2; - - n = Identifier(t, x); - - while (t.match(DOT)) { - if (t.peek() !== IDENTIFIER) { - // Unget the '.' token, which isn't part of the QualifiedPath. - t.unget(); - break; - } - n2 = new Node(t); - n2.push(n); - n2.push(Identifier(t, x)); - n = n2; - } - - return n; - } - - /* - * ExportPath :: (tokenizer, compiler context) -> (IDENTIFIER | DOT | OBJECT_INIT) node - */ - function ExportPath(t, x) { - if (t.peek() === LEFT_CURLY) - return ExplicitSpecifierSet(t, x, QualifiedPath); - return QualifiedPath(t, x); - } - - /* - * ExportPathList :: (tokenizer, compiler context) - * -> Array[(IDENTIFIER | DOT | OBJECT_INIT) node] - */ - function ExportPathList(t, x) { - var a = []; - do { - a.push(ExportPath(t, x)); - } while (t.match(COMMA)); - return a; - } - - /* - * FunctionDefinition :: (tokenizer, compiler context, boolean, - * DECLARED_FORM or EXPRESSED_FORM or STATEMENT_FORM, - * [string] or null or undefined) - * -> node - */ - function FunctionDefinition(t, x, requireName, functionForm, comments) { - var tt; - var f = new Node(t, { params: [], paramComments: [] }); - if (typeof comment === "undefined") - comment = null; - f.blockComments = comments; - if (f.type !== FUNCTION) - f.type = (f.value === "get") ? GETTER : SETTER; - if (t.match(IDENTIFIER)) - f.name = t.token.value; - else if (requireName) - throw t.newSyntaxError("missing function identifier"); - - var inModule = x ? x.inModule : false; - var x2 = new StaticContext(null, null, inModule, true); - - t.mustMatch(LEFT_PAREN); - if (!t.match(RIGHT_PAREN)) { - do { - tt = t.get(); - f.paramComments.push(t.lastBlockComment()); - switch (tt) { - case LEFT_BRACKET: - case LEFT_CURLY: - // Destructured formal parameters. - t.unget(); - f.params.push(DestructuringExpression(t, x2)); - break; - case IDENTIFIER: - f.params.push(t.token.value); - break; - default: - throw t.newSyntaxError("missing formal parameter"); - break; - } - } while (t.match(COMMA)); - t.mustMatch(RIGHT_PAREN); - } - - // Do we have an expression closure or a normal body? - tt = t.get(); - if (tt !== LEFT_CURLY) - t.unget(); - - if (tt !== LEFT_CURLY) { - f.body = AssignExpression(t, x2); - if (f.body.isGenerator) - throw t.newSyntaxError("Generator returns a value"); - } else { - f.body = Script(t, inModule, true); - } - - if (tt === LEFT_CURLY) - t.mustMatch(RIGHT_CURLY); - - f.end = t.token.end; - f.functionForm = functionForm; - if (functionForm === DECLARED_FORM) - x.parentScript.funDecls.push(f); - return f; - } - - /* - * ModuleVariables :: (tokenizer, compiler context, MODULE node) -> void - * - * Parses a comma-separated list of module declarations (and maybe - * initializations). - */ - function ModuleVariables(t, x, n) { - var n1, n2; - do { - n1 = Identifier(t, x); - if (t.match(ASSIGN)) { - n2 = ModuleExpression(t, x); - n1.initializer = n2; - if (n2.type === STRING) - x.parentScript.modLoads.set(n1.value, n2.value); - else - x.parentScript.modAssns.set(n1.value, n1); - } - n.push(n1); - } while (t.match(COMMA)); - } - - /* - * Variables :: (tokenizer, compiler context) -> node - * - * Parses a comma-separated list of var declarations (and maybe - * initializations). - */ - function Variables(t, x, letBlock) { - var n, n2, ss, i, s, tt; - - tt = t.token.type; - switch (tt) { - case VAR: - case CONST: - s = x.parentScript; - break; - case LET: - s = x.parentBlock; - break; - case LEFT_PAREN: - tt = LET; - s = letBlock; - break; - } - - n = new Node(t, { type: tt, destructurings: [] }); - - do { - tt = t.get(); - if (tt === LEFT_BRACKET || tt === LEFT_CURLY) { - // Need to unget to parse the full destructured expression. - t.unget(); - - var dexp = DestructuringExpression(t, x, true); - - n2 = new Node(t, { type: IDENTIFIER, - name: dexp, - readOnly: n.type === CONST }); - n.push(n2); - pushDestructuringVarDecls(n2.name.destructuredNames, s); - n.destructurings.push({ exp: dexp, decl: n2 }); - - if (x.inForLoopInit && t.peek() === IN) { - continue; - } - - t.mustMatch(ASSIGN); - if (t.token.assignOp) - throw t.newSyntaxError("Invalid variable initialization"); - - n2.blockComment = t.lastBlockComment(); - n2.initializer = AssignExpression(t, x); - - continue; - } - - if (tt !== IDENTIFIER) - throw t.newSyntaxError("missing variable name"); - - n2 = new Node(t, { type: IDENTIFIER, - name: t.token.value, - readOnly: n.type === CONST }); - n.push(n2); - s.varDecls.push(n2); - - if (t.match(ASSIGN)) { - var comment = t.lastBlockComment(); - if (t.token.assignOp) - throw t.newSyntaxError("Invalid variable initialization"); - - n2.initializer = AssignExpression(t, x); - } else { - var comment = t.lastBlockComment(); - } - n2.blockComment = comment; - } while (t.match(COMMA)); - - return n; - } - - /* - * LetBlock :: (tokenizer, compiler context, boolean) -> node - * - * Does not handle let inside of for loop init. - */ - function LetBlock(t, x, isStatement) { - var n, n2; - - // t.token.type must be LET - n = new Node(t, { type: LET_BLOCK, varDecls: [] }); - t.mustMatch(LEFT_PAREN); - n.variables = Variables(t, x, n); - t.mustMatch(RIGHT_PAREN); - - if (isStatement && t.peek() !== LEFT_CURLY) { - /* - * If this is really an expression in let statement guise, then we - * need to wrap the LET_BLOCK node in a SEMICOLON node so that we pop - * the return value of the expression. - */ - n2 = new Node(t, { type: SEMICOLON, - expression: n }); - isStatement = false; - } - - if (isStatement) - n.block = Block(t, x); - else - n.expression = AssignExpression(t, x); - - return n; - } - - function checkDestructuring(t, x, n, simpleNamesOnly) { - if (n.type === ARRAY_COMP) - throw t.newSyntaxError("Invalid array comprehension left-hand side"); - if (n.type !== ARRAY_INIT && n.type !== OBJECT_INIT) - return undefined; - - var lhss = {}; - var nn, n2, idx, sub, cc, c = n.children; - for (var i = 0, j = c.length; i < j; i++) { - if (!(nn = c[i])) - continue; - if (nn.type === PROPERTY_INIT) { - cc = nn.children; - sub = cc[1]; - idx = cc[0].value; - } else if (n.type === OBJECT_INIT) { - // Do we have destructuring shorthand {foo, bar}? - sub = nn; - idx = nn.value; - } else { - sub = nn; - idx = i; - } - - if (sub.type === ARRAY_INIT || sub.type === OBJECT_INIT) { - lhss[idx] = checkDestructuring(t, x, sub, simpleNamesOnly); - } else { - if (simpleNamesOnly && sub.type !== IDENTIFIER) { - // In declarations, lhs must be simple names - throw t.newSyntaxError("missing name in pattern"); - } - - lhss[idx] = sub; - } - } - - return lhss; - } - - function DestructuringExpression(t, x, simpleNamesOnly) { - var n = PrimaryExpression(t, x); - // Keep the list of lefthand sides for varDecls - n.destructuredNames = checkDestructuring(t, x, n, simpleNamesOnly); - return n; - } - - function GeneratorExpression(t, x, e) { - return new Node(t, { type: GENERATOR, - expression: e, - tail: ComprehensionTail(t, x) }); - } - - function ComprehensionTail(t, x) { - var body, n, n2, n3, p; - - // t.token.type must be FOR - body = new Node(t, { type: COMP_TAIL }); - - do { - // Comprehension tails are always for..in loops. - n = new Node(t, { type: FOR_IN, isLoop: true }); - if (t.match(IDENTIFIER)) { - // But sometimes they're for each..in. - if (t.token.value === "each") - n.isEach = true; - else - t.unget(); - } - p = MaybeLeftParen(t, x); - switch(t.get()) { - case LEFT_BRACKET: - case LEFT_CURLY: - t.unget(); - // Destructured left side of for in comprehension tails. - n.iterator = DestructuringExpression(t, x); - break; - - case IDENTIFIER: - n.iterator = n3 = new Node(t, { type: IDENTIFIER }); - n3.name = n3.value; - n.varDecl = n2 = new Node(t, { type: VAR }); - n2.push(n3); - x.parentScript.varDecls.push(n3); - // Don't add to varDecls since the semantics of comprehensions is - // such that the variables are in their own function when - // desugared. - break; - - default: - throw t.newSyntaxError("missing identifier"); - } - t.mustMatch(IN); - n.object = Expression(t, x); - MaybeRightParen(t, p); - body.push(n); - } while (t.match(FOR)); - - // Optional guard. - if (t.match(IF)) - body.guard = HeadExpression(t, x); - - return body; - } - - function HeadExpression(t, x) { - var p = MaybeLeftParen(t, x); - var n = ParenExpression(t, x); - MaybeRightParen(t, p); - if (p === END && !n.parenthesized) { - var tt = t.peek(); - if (tt !== LEFT_CURLY && !definitions.isStatementStartCode[tt]) - throw t.newSyntaxError("Unparenthesized head followed by unbraced body"); - } - return n; - } - - function ParenExpression(t, x) { - // Always accept the 'in' operator in a parenthesized expression, - // where it's unambiguous, even if we might be parsing the init of a - // for statement. - var n = Expression(t, x.update({ inForLoopInit: x.inForLoopInit && - (t.token.type === LEFT_PAREN) })); - - if (t.match(FOR)) { - if (n.type === YIELD && !n.parenthesized) - throw t.newSyntaxError("Yield expression must be parenthesized"); - if (n.type === COMMA && !n.parenthesized) - throw t.newSyntaxError("Generator expression must be parenthesized"); - n = GeneratorExpression(t, x, n); - } - - return n; - } - - /* - * Expression :: (tokenizer, compiler context) -> node - * - * Top-down expression parser matched against SpiderMonkey. - */ - function Expression(t, x) { - var n, n2; - - n = AssignExpression(t, x); - if (t.match(COMMA)) { - n2 = new Node(t, { type: COMMA }); - n2.push(n); - n = n2; - do { - n2 = n.children[n.children.length-1]; - if (n2.type === YIELD && !n2.parenthesized) - throw t.newSyntaxError("Yield expression must be parenthesized"); - n.push(AssignExpression(t, x)); - } while (t.match(COMMA)); - } - - return n; - } - - function AssignExpression(t, x) { - var n, lhs; - - // Have to treat yield like an operand because it could be the leftmost - // operand of the expression. - if (t.match(YIELD, true)) - return ReturnOrYield(t, x); - - n = new Node(t, { type: ASSIGN }); - lhs = ConditionalExpression(t, x); - - if (!t.match(ASSIGN)) { - return lhs; - } - - n.blockComment = t.lastBlockComment(); - - switch (lhs.type) { - case OBJECT_INIT: - case ARRAY_INIT: - lhs.destructuredNames = checkDestructuring(t, x, lhs); - // FALL THROUGH - case IDENTIFIER: case DOT: case INDEX: case CALL: - break; - default: - throw t.newSyntaxError("Bad left-hand side of assignment"); - break; - } - - n.assignOp = lhs.assignOp = t.token.assignOp; - n.push(lhs); - n.push(AssignExpression(t, x)); - - return n; - } - - function ConditionalExpression(t, x) { - var n, n2; - - n = OrExpression(t, x); - if (t.match(HOOK)) { - n2 = n; - n = new Node(t, { type: HOOK }); - n.push(n2); - /* - * Always accept the 'in' operator in the middle clause of a ternary, - * where it's unambiguous, even if we might be parsing the init of a - * for statement. - */ - n.push(AssignExpression(t, x.update({ inForLoopInit: false }))); - if (!t.match(COLON)) - throw t.newSyntaxError("missing : after ?"); - n.push(AssignExpression(t, x)); - } - - return n; - } - - function OrExpression(t, x) { - var n, n2; - - n = AndExpression(t, x); - while (t.match(OR)) { - n2 = new Node(t); - n2.push(n); - n2.push(AndExpression(t, x)); - n = n2; - } - - return n; - } - - function AndExpression(t, x) { - var n, n2; - - n = BitwiseOrExpression(t, x); - while (t.match(AND)) { - n2 = new Node(t); - n2.push(n); - n2.push(BitwiseOrExpression(t, x)); - n = n2; - } - - return n; - } - - function BitwiseOrExpression(t, x) { - var n, n2; - - n = BitwiseXorExpression(t, x); - while (t.match(BITWISE_OR)) { - n2 = new Node(t); - n2.push(n); - n2.push(BitwiseXorExpression(t, x)); - n = n2; - } - - return n; - } - - function BitwiseXorExpression(t, x) { - var n, n2; - - n = BitwiseAndExpression(t, x); - while (t.match(BITWISE_XOR)) { - n2 = new Node(t); - n2.push(n); - n2.push(BitwiseAndExpression(t, x)); - n = n2; - } - - return n; - } - - function BitwiseAndExpression(t, x) { - var n, n2; - - n = EqualityExpression(t, x); - while (t.match(BITWISE_AND)) { - n2 = new Node(t); - n2.push(n); - n2.push(EqualityExpression(t, x)); - n = n2; - } - - return n; - } - - function EqualityExpression(t, x) { - var n, n2; - - n = RelationalExpression(t, x); - while (t.match(EQ) || t.match(NE) || - t.match(STRICT_EQ) || t.match(STRICT_NE)) { - n2 = new Node(t); - n2.push(n); - n2.push(RelationalExpression(t, x)); - n = n2; - } - - return n; - } - - function RelationalExpression(t, x) { - var n, n2; - - /* - * Uses of the in operator in shiftExprs are always unambiguous, - * so unset the flag that prohibits recognizing it. - */ - var x2 = x.update({ inForLoopInit: false }); - n = ShiftExpression(t, x2); - while ((t.match(LT) || t.match(LE) || t.match(GE) || t.match(GT) || - (!x.inForLoopInit && t.match(IN)) || - t.match(INSTANCEOF))) { - n2 = new Node(t); - n2.push(n); - n2.push(ShiftExpression(t, x2)); - n = n2; - } - - return n; - } - - function ShiftExpression(t, x) { - var n, n2; - - n = AddExpression(t, x); - while (t.match(LSH) || t.match(RSH) || t.match(URSH)) { - n2 = new Node(t); - n2.push(n); - n2.push(AddExpression(t, x)); - n = n2; - } - - return n; - } - - function AddExpression(t, x) { - var n, n2; - - n = MultiplyExpression(t, x); - while (t.match(PLUS) || t.match(MINUS)) { - n2 = new Node(t); - n2.push(n); - n2.push(MultiplyExpression(t, x)); - n = n2; - } - - return n; - } - - function MultiplyExpression(t, x) { - var n, n2; - - n = UnaryExpression(t, x); - while (t.match(MUL) || t.match(DIV) || t.match(MOD)) { - n2 = new Node(t); - n2.push(n); - n2.push(UnaryExpression(t, x)); - n = n2; - } - - return n; - } - - function UnaryExpression(t, x) { - var n, n2, tt; - - switch (tt = t.get(true)) { - case DELETE: case VOID: case TYPEOF: - case NOT: case BITWISE_NOT: case PLUS: case MINUS: - if (tt === PLUS) - n = new Node(t, { type: UNARY_PLUS }); - else if (tt === MINUS) - n = new Node(t, { type: UNARY_MINUS }); - else - n = new Node(t); - n.push(UnaryExpression(t, x)); - break; - - case INCREMENT: - case DECREMENT: - // Prefix increment/decrement. - n = new Node(t); - n.push(MemberExpression(t, x, true)); - break; - - default: - t.unget(); - n = MemberExpression(t, x, true); - - // Don't look across a newline boundary for a postfix {in,de}crement. - if (t.tokens[(t.tokenIndex + t.lookahead - 1) & 3].lineno === - t.lineno) { - if (t.match(INCREMENT) || t.match(DECREMENT)) { - n2 = new Node(t, { postfix: true }); - n2.push(n); - n = n2; - } - } - break; - } - - return n; - } - - function MemberExpression(t, x, allowCallSyntax) { - var n, n2, name, tt; - - if (t.match(NEW)) { - n = new Node(t); - n.push(MemberExpression(t, x, false)); - if (t.match(LEFT_PAREN)) { - n.type = NEW_WITH_ARGS; - n.push(ArgumentList(t, x)); - } - } else { - n = PrimaryExpression(t, x); - } - - while ((tt = t.get()) !== END) { - switch (tt) { - case DOT: - n2 = new Node(t); - n2.push(n); - n2.push(IdentifierName(t)); - break; - - case LEFT_BRACKET: - n2 = new Node(t, { type: INDEX }); - n2.push(n); - n2.push(Expression(t, x)); - t.mustMatch(RIGHT_BRACKET); - break; - - case LEFT_PAREN: - if (allowCallSyntax) { - n2 = new Node(t, { type: CALL }); - n2.push(n); - n2.push(ArgumentList(t, x)); - break; - } - - // FALL THROUGH - default: - t.unget(); - return n; - } - - n = n2; - } - - return n; - } - - function ArgumentList(t, x) { - var n, n2; - - n = new Node(t, { type: LIST }); - if (t.match(RIGHT_PAREN, true)) - return n; - do { - n2 = AssignExpression(t, x); - if (n2.type === YIELD && !n2.parenthesized && t.peek() === COMMA) - throw t.newSyntaxError("Yield expression must be parenthesized"); - if (t.match(FOR)) { - n2 = GeneratorExpression(t, x, n2); - if (n.children.length > 1 || t.peek(true) === COMMA) - throw t.newSyntaxError("Generator expression must be parenthesized"); - } - n.push(n2); - } while (t.match(COMMA)); - t.mustMatch(RIGHT_PAREN); - - return n; - } - - function PrimaryExpression(t, x) { - var n, n2, tt = t.get(true); - - switch (tt) { - case FUNCTION: - n = FunctionDefinition(t, x, false, EXPRESSED_FORM); - break; - - case LEFT_BRACKET: - n = new Node(t, { type: ARRAY_INIT }); - while ((tt = t.peek(true)) !== RIGHT_BRACKET) { - if (tt === COMMA) { - t.get(); - n.push(null); - continue; - } - n.push(AssignExpression(t, x)); - if (tt !== COMMA && !t.match(COMMA)) - break; - } - - // If we matched exactly one element and got a FOR, we have an - // array comprehension. - if (n.children.length === 1 && t.match(FOR)) { - n2 = new Node(t, { type: ARRAY_COMP, - expression: n.children[0], - tail: ComprehensionTail(t, x) }); - n = n2; - } - t.mustMatch(RIGHT_BRACKET); - break; - - case LEFT_CURLY: - var id, fd; - n = new Node(t, { type: OBJECT_INIT }); - - object_init: - if (!t.match(RIGHT_CURLY)) { - do { - tt = t.get(); - if ((t.token.value === "get" || t.token.value === "set") && - t.peek() === IDENTIFIER) { - if (x.ecma3OnlyMode) - throw t.newSyntaxError("Illegal property accessor"); - n.push(FunctionDefinition(t, x, true, EXPRESSED_FORM)); - } else { - var comments = t.blockComments; - switch (tt) { - case IDENTIFIER: case NUMBER: case STRING: - id = new Node(t, { type: IDENTIFIER }); - break; - case RIGHT_CURLY: - if (x.ecma3OnlyMode) - throw t.newSyntaxError("Illegal trailing ,"); - break object_init; - default: - if (t.token.value in definitions.keywords) { - id = new Node(t, { type: IDENTIFIER }); - break; - } - throw t.newSyntaxError("Invalid property name"); - } - if (t.match(COLON)) { - n2 = new Node(t, { type: PROPERTY_INIT }); - n2.push(id); - n2.push(AssignExpression(t, x)); - n2.blockComments = comments; - n.push(n2); - } else { - // Support, e.g., |var {x, y} = o| as destructuring shorthand - // for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8. - if (t.peek() !== COMMA && t.peek() !== RIGHT_CURLY) - throw t.newSyntaxError("missing : after property"); - n.push(id); - } - } - } while (t.match(COMMA)); - t.mustMatch(RIGHT_CURLY); - } - break; - - case LEFT_PAREN: - n = ParenExpression(t, x); - t.mustMatch(RIGHT_PAREN); - n.parenthesized = true; - break; - - case LET: - n = LetBlock(t, x, false); - break; - - case NULL: case THIS: case TRUE: case FALSE: - case IDENTIFIER: case NUMBER: case STRING: case REGEXP: - n = new Node(t); - break; - - default: - n = new Node(t); - // don't throw an error by default. Just make it a node and forget it :-} - //throw t.newSyntaxError("missing operand"); - break; - } - - return n; - } - - /* - * parse :: (source, filename, line number) -> node - */ - function parse(s, f, l) { - var t = new lexer.Tokenizer(s, f, l); - var n = Script(t, false, false); - if (!t.done) - throw t.newSyntaxError("Syntax error"); - - return n; - } - - /* - * parseStdin :: (source, {line number}, string, (string) -> boolean) -> program node - */ - function parseStdin(s, ln, prefix, isCommand) { - // the special .begin command is only recognized at the beginning - if (s.match(/^[\s]*\.begin[\s]*$/)) { - ++ln.value; - return parseMultiline(ln, prefix); - } - - // commands at the beginning are treated as the entire input - if (isCommand(s.trim())) - s = ""; - - for (;;) { - try { - var t = new lexer.Tokenizer(s, "stdin", ln.value); - var n = Script(t, false, false); - ln.value = t.lineno; - return n; - } catch (e) { - if (!t.unexpectedEOF) - throw e; - - // commands in the middle are not treated as part of the input - var more; - do { - if (prefix) - putstr(prefix); - more = readline(); - if (!more) - throw e; - } while (isCommand(more.trim())); - - s += "\n" + more; - } - } - } - - /* - * parseMultiline :: ({line number}, string | null) -> program node - */ - function parseMultiline(ln, prefix) { - var s = ""; - for (;;) { - if (prefix) - putstr(prefix); - var more = readline(); - if (more === null) - return null; - // the only command recognized in multiline mode is .end - if (more.match(/^[\s]*\.end[\s]*$/)) - break; - s += "\n" + more; - } - var t = new lexer.Tokenizer(s, "stdin", ln.value); - var n = Script(t, false, false); - ln.value = t.lineno; - return n; - } - - return { - parse: parse, - parseStdin: parseStdin, - Node: Node, - SyntheticNode: SyntheticNode, - DECLARED_FORM: DECLARED_FORM, - EXPRESSED_FORM: EXPRESSED_FORM, - STATEMENT_FORM: STATEMENT_FORM, - Tokenizer: lexer.Tokenizer, - FunctionDefinition: FunctionDefinition, - Module: Module, - Export: Export - }; - -}()); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/parse.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/parse.js deleted file mode 100644 index 07c800e..0000000 --- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/data/chrome_worker/parser/parse.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript. - * * - * Copyright (C) 2011, 2012, 2014 Loic J. Duros - * Copyright (C) 2014, 2015 Nik Nyby - * - * This file is part of GNU LibreJS. - * - * GNU LibreJS is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GNU LibreJS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU LibreJS. If not, see <http://www.gnu.org/licenses/>. - */ - -/** - * parse.js - * - * A chrome worker that we keep working for the duration - * of the session. - * - * It takes about 10-12M in memory when not actively running, and it - * is much faster than reloading the Narcissus scripts for every - * script. - * - */ - -importScripts('./jsdefs.js', './jslex.js', './jsparse.js'); - -self.onmessage = function(event) { - if (event.data === 'stop') { - // destroy chrome worker. - self.close(); - return; - } - - var obj = JSON.parse(event.data); - var tree; - - try { - tree = new Narcissus.parser.parse(obj.code); - self.postMessage({'tree': tree, 'hash': obj.hash}); - } catch (x) { - // error with parsing. Delete all. - self.postMessage({'hash': obj.hash}); - } - - tree = null; - obj = null; -}; |