diff --git a/config/application.rb b/config/application.rb index 4afbf473c37..b4f103f8c16 100644 --- a/config/application.rb +++ b/config/application.rb @@ -32,6 +32,7 @@ module Discourse # -- all .rb files in that directory are automatically loaded. require 'discourse' + require 'es6_module_transpiler/rails' require 'js_locale_helper' # mocha hates us, active_support/testing/mochaing.rb line 2 is requiring the wrong diff --git a/lib/es6_module_transpiler/rails.rb b/lib/es6_module_transpiler/rails.rb new file mode 100644 index 00000000000..f9fafb626d5 --- /dev/null +++ b/lib/es6_module_transpiler/rails.rb @@ -0,0 +1,39 @@ +require 'es6_module_transpiler/rails/version' +require 'es6_module_transpiler/tilt' +require 'es6_module_transpiler/sprockets' + +module ES6ModuleTranspiler + def self.compile_to + @compile_to || :amd + end + + def self.compile_to=(target) + @compile_to = target + end + + def self.prefix_patterns + @prefix_patterns ||= [] + end + + def self.add_prefix_pattern(pattern, prefix) + prefix_patterns << [pattern, prefix] + end + + def self.lookup_prefix(path) + _, prefix = prefix_patterns.detect {|pattern, prefix| pattern =~ path } + + prefix + end + + def self.transform=(transform) + @transform = transform + end + + def self.transform + @transform + end + + def self.compiler_options + @compiler_options ||= {} + end +end diff --git a/lib/es6_module_transpiler/rails/version.rb b/lib/es6_module_transpiler/rails/version.rb new file mode 100644 index 00000000000..46a297c669e --- /dev/null +++ b/lib/es6_module_transpiler/rails/version.rb @@ -0,0 +1,5 @@ +module ES6ModuleTranspiler + module Rails + VERSION = '0.4.0' + end +end diff --git a/lib/es6_module_transpiler/sprockets.rb b/lib/es6_module_transpiler/sprockets.rb new file mode 100644 index 00000000000..1a62c5cbfb0 --- /dev/null +++ b/lib/es6_module_transpiler/sprockets.rb @@ -0,0 +1,3 @@ +require 'sprockets' + +Sprockets.register_engine '.es6', Tilt::ES6ModuleTranspilerTemplate diff --git a/lib/es6_module_transpiler/support/es6-module-transpiler.js b/lib/es6_module_transpiler/support/es6-module-transpiler.js new file mode 100644 index 00000000000..dfb91bc439b --- /dev/null +++ b/lib/es6_module_transpiler/support/es6-module-transpiler.js @@ -0,0 +1,7195 @@ +// Copyright 2012 Traceur Authors. +// +// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * The traceur runtime. + */ +(function(global) { + 'use strict'; + + var $create = Object.create; + var $defineProperty = Object.defineProperty; + var $freeze = Object.freeze; + var $getOwnPropertyNames = Object.getOwnPropertyNames; + var $getPrototypeOf = Object.getPrototypeOf; + var $hasOwnProperty = Object.prototype.hasOwnProperty; + + function nonEnum(value) { + return { + configurable: true, + enumerable: false, + value: value, + writable: true + }; + } + + var method = nonEnum; + + function polyfillString(String) { + // Harmony String Extras + // http://wiki.ecmascript.org/doku.php?id=harmony:string_extras + Object.defineProperties(String.prototype, { + startsWith: method(function(s) { + return this.lastIndexOf(s, 0) === 0; + }), + endsWith: method(function(s) { + var t = String(s); + var l = this.length - t.length; + return l >= 0 && this.indexOf(t, l) === l; + }), + contains: method(function(s) { + return this.indexOf(s) !== -1; + }), + toArray: method(function() { + return this.split(''); + }) + }); + + // 15.5.3.4 String.raw ( callSite, ...substitutions) + $defineProperty(String, 'raw', { + value: function(callsite) { + var raw = callsite.raw; + var len = raw.length >>> 0; // ToUint + if (len === 0) + return ''; + var s = ''; + var i = 0; + while (true) { + s += raw[i]; + if (i + 1 === len) + return s; + s += arguments[++i]; + } + }, + configurable: true, + enumerable: false, + writable: true + }); + } + + var counter = 0; + + /** + * Generates a new unique string. + * @return {string} + */ + function newUniqueString() { + return '__$' + Math.floor(Math.random() * 1e9) + '$' + ++counter + '$__'; + } + + var nameRe = /^__\$(?:\d+)\$(?:\d+)\$__$/; + + var internalStringValueName = newUniqueString(); + + /** + * Creates a new private name object. + * @param {string=} string Optional string used for toString. + * @constructor + */ + function Name(string) { + if (!string) + string = newUniqueString(); + $defineProperty(this, internalStringValueName, {value: newUniqueString()}); + + function toString() { + return string; + } + $freeze(toString); + $freeze(toString.prototype); + var toStringDescr = method(toString); + $defineProperty(this, 'toString', toStringDescr); + + this.public = $freeze($create(null, { + toString: method($freeze(function toString() { + return string; + })) + })); + $freeze(this.public.toString.prototype); + + $freeze(this); + }; + $freeze(Name); + $freeze(Name.prototype); + + function assertName(val) { + if (!NameModule.isName(val)) + throw new TypeError(val + ' is not a Name'); + return val; + } + + // Private name. + + // Collection getters and setters + var elementDeleteName = new Name(); + var elementGetName = new Name(); + var elementSetName = new Name(); + + // HACK: We should use runtime/modules/std/name.js or something like that. + var NameModule = $freeze({ + Name: function(str) { + return new Name(str); + }, + isName: function(x) { + return x instanceof Name; + }, + elementGet: elementGetName, + elementSet: elementSetName, + elementDelete: elementDeleteName + }); + + var filter = Array.prototype.filter.call.bind(Array.prototype.filter); + + // Override getOwnPropertyNames to filter out private name keys. + function getOwnPropertyNames(object) { + return filter($getOwnPropertyNames(object), function(str) { + return !nameRe.test(str); + }); + } + + // Override Object.prototpe.hasOwnProperty to always return false for + // private names. + function hasOwnProperty(name) { + if (NameModule.isName(name) || nameRe.test(name)) + return false; + return $hasOwnProperty.call(this, name); + } + + function elementDelete(object, name) { + if (traceur.options.trapMemberLookup && + hasPrivateNameProperty(object, elementDeleteName)) { + return getProperty(object, elementDeleteName).call(object, name); + } + return deleteProperty(object, name); + } + + function elementGet(object, name) { + if (traceur.options.trapMemberLookup && + hasPrivateNameProperty(object, elementGetName)) { + return getProperty(object, elementGetName).call(object, name); + } + return getProperty(object, name); + } + + function elementHas(object, name) { + // Should we allow trapping this too? + return has(object, name); + } + + function elementSet(object, name, value) { + if (traceur.options.trapMemberLookup && + hasPrivateNameProperty(object, elementSetName)) { + getProperty(object, elementSetName).call(object, name, value); + } else { + setProperty(object, name, value); + } + return value; + } + + function assertNotName(s) { + if (nameRe.test(s)) + throw Error('Invalid access to private name'); + } + + function deleteProperty(object, name) { + if (NameModule.isName(name)) + return delete object[name[internalStringValueName]]; + if (nameRe.test(name)) + return true; + return delete object[name]; + } + + function getProperty(object, name) { + if (NameModule.isName(name)) + return object[name[internalStringValueName]]; + if (nameRe.test(name)) + return undefined; + return object[name]; + } + + function hasPrivateNameProperty(object, name) { + return name[internalStringValueName] in Object(object); + } + + function has(object, name) { + if (NameModule.isName(name) || nameRe.test(name)) + return false; + return name in Object(object); + } + + // This is a bit simplistic. + // http://wiki.ecmascript.org/doku.php?id=strawman:refactoring_put#object._get_set_property_built-ins + function setProperty(object, name, value) { + if (NameModule.isName(name)) { + var descriptor = $getPropertyDescriptor(object, + [name[internalStringValueName]]); + if (descriptor) + object[name[internalStringValueName]] = value; + else + $defineProperty(object, name[internalStringValueName], nonEnum(value)); + } else { + assertNotName(name); + object[name] = value; + } + } + + function defineProperty(object, name, descriptor) { + if (NameModule.isName(name)) { + // Private names should never be enumerable. + if (descriptor.enumerable) { + descriptor = Object.create(descriptor, { + enumerable: {value: false} + }); + } + $defineProperty(object, name[internalStringValueName], descriptor); + } else { + assertNotName(name); + $defineProperty(object, name, descriptor); + } + } + + function $getPropertyDescriptor(obj, name) { + while (obj !== null) { + var result = Object.getOwnPropertyDescriptor(obj, name); + if (result) + return result; + obj = $getPrototypeOf(obj); + } + return undefined; + } + + function getPropertyDescriptor(obj, name) { + if (NameModule.isName(name)) + return undefined; + assertNotName(name); + return $getPropertyDescriptor(obj, name); + } + + function polyfillObject(Object) { + $defineProperty(Object, 'defineProperty', {value: defineProperty}); + $defineProperty(Object, 'deleteProperty', method(deleteProperty)); + $defineProperty(Object, 'getOwnPropertyNames', + {value: getOwnPropertyNames}); + $defineProperty(Object, 'getProperty', method(getProperty)); + $defineProperty(Object, 'getPropertyDescriptor', + method(getPropertyDescriptor)); + $defineProperty(Object, 'has', method(has)); + $defineProperty(Object, 'setProperty', method(setProperty)); + $defineProperty(Object.prototype, 'hasOwnProperty', + {value: hasOwnProperty}); + + // Object.is + + // Unlike === this returns true for (NaN, NaN) and false for (0, -0). + function is(left, right) { + if (left === right) + return left !== 0 || 1 / left === 1 / right; + return left !== left && right !== right; + } + + $defineProperty(Object, 'is', method(is)); + } + + // Iterators. + var iteratorName = new Name('iterator'); + + var IterModule = { + get iterator() { + return iteratorName; + } + // TODO: Implement the rest of @iter and move it to a different file that + // gets compiled. + }; + + function getIterator(collection) { + return getProperty(collection, iteratorName).call(collection); + } + + function returnThis() { + return this; + } + + function addIterator(object) { + // Generator instances are iterable. + setProperty(object, iteratorName, returnThis); + return object; + } + + function polyfillArray(Array) { + // Make arrays iterable. + defineProperty(Array.prototype, IterModule.iterator, method(function() { + var index = 0; + var array = this; + return { + next: function() { + if (index < array.length) { + return array[index++]; + } + throw StopIterationLocal; + } + }; + })); + } + + // Generators: GeneratorReturn + var GeneratorReturnLocal; + + function setGeneratorReturn(GeneratorReturn, global) { + switch (typeof GeneratorReturn) { + case 'function': + // StopIterationLocal instanceof GeneratorReturnLocal means we probably + // want to maintain that invariant when we change GeneratorReturnLocal. + if (typeof GeneratorReturnLocal === 'function' && + StopIterationLocal instanceof GeneratorReturnLocal) { + GeneratorReturnLocal = GeneratorReturn; + setStopIteration(undefined, global); + return; + } + GeneratorReturnLocal = GeneratorReturn; + return; + case 'undefined': + GeneratorReturnLocal = function(v) { + this.value = v; + }; + GeneratorReturnLocal.prototype = { + toString: function() { + return '[object GeneratorReturn ' + this.value + ']'; + } + }; + return; + default: + throw new TypeError('constructor function required'); + } + } + + setGeneratorReturn(); + + // Generators: StopIteration + var StopIterationLocal; + + function isStopIteration(x) { + return x === StopIterationLocal || x instanceof GeneratorReturnLocal; + } + + function setStopIteration(StopIteration, global) { + switch (typeof StopIteration) { + case 'object': + StopIterationLocal = StopIteration; + break; + case 'undefined': + StopIterationLocal = new GeneratorReturnLocal(); + StopIterationLocal.toString = function() { + return '[object StopIteration]'; + }; + break; + default: + throw new TypeError('invalid StopIteration type.'); + } + if (global) + global.StopIteration = StopIteration; + } + + setStopIteration(global.StopIteration, global); + + /** + * @param {Function} canceller + * @constructor + */ + function Deferred(canceller) { + this.canceller_ = canceller; + this.listeners_ = []; + } + + function notify(self) { + while (self.listeners_.length > 0) { + var current = self.listeners_.shift(); + var currentResult = undefined; + try { + try { + if (self.result_[1]) { + if (current.errback) + currentResult = current.errback.call(undefined, self.result_[0]); + } else { + if (current.callback) + currentResult = current.callback.call(undefined, self.result_[0]); + } + current.deferred.callback(currentResult); + } catch (err) { + current.deferred.errback(err); + } + } catch (unused) {} + } + } + + function fire(self, value, isError) { + if (self.fired_) + throw new Error('already fired'); + + self.fired_ = true; + self.result_ = [value, isError]; + notify(self); + } + + Deferred.prototype = { + fired_: false, + result_: undefined, + + createPromise: function() { + return {then: this.then.bind(this), cancel: this.cancel.bind(this)}; + }, + + callback: function(value) { + fire(this, value, false); + }, + + errback: function(err) { + fire(this, err, true); + }, + + then: function(callback, errback) { + var result = new Deferred(this.cancel.bind(this)); + this.listeners_.push({ + deferred: result, + callback: callback, + errback: errback + }); + if (this.fired_) + notify(this); + return result.createPromise(); + }, + + cancel: function() { + if (this.fired_) + throw new Error('already finished'); + var result; + if (this.canceller_) { + result = this.canceller_(this); + if (!result instanceof Error) + result = new Error(result); + } else { + result = new Error('cancelled'); + } + if (!this.fired_) { + this.result_ = [result, true]; + notify(this); + } + } + }; + + var modules = $freeze({ + get '@name'() { + return NameModule; + }, + get '@iter'() { + return IterModule; + } + }); + + // TODO(arv): Don't export this. + global.Deferred = Deferred; + + function setupGlobals(global) { + polyfillString(global.String); + polyfillObject(global.Object); + polyfillArray(global.Array); + } + + setupGlobals(global); + + // Return the runtime namespace. + var runtime = { + Deferred: Deferred, + GeneratorReturn: GeneratorReturnLocal, + setGeneratorReturn: setGeneratorReturn, + StopIteration: StopIterationLocal, + setStopIteration: setStopIteration, + isStopIteration: isStopIteration, + addIterator: addIterator, + assertName: assertName, + createName: NameModule.Name, + deleteProperty: deleteProperty, + elementDelete: elementDelete, + elementGet: elementGet, + elementHas: elementHas, + elementSet: elementSet, + getIterator: getIterator, + getProperty: getProperty, + setProperty: setProperty, + setupGlobals: setupGlobals, + has: has, + modules: modules, + }; + + // This file is sometimes used without traceur.js. + if (typeof traceur !== 'undefined') + traceur.setRuntime(runtime); + else + global.traceur = {runtime: runtime}; + +})(typeof global !== 'undefined' ? global : this); + +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.ModuleTranspiler=e():"undefined"!=typeof global?global.ModuleTranspiler=e():"undefined"!=typeof self&&(self.ModuleTranspiler=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + Copyright (C) 2013 Thaddee Tyl + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2012 Mathias Bynens + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Kris Kowal + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Arpad Borsos + Copyright (C) 2011 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*jslint bitwise:true plusplus:true */ +/*global esprima:true, define:true, exports:true, window: true, +throwError: true, generateStatement: true, peek: true, +parseAssignmentExpression: true, parseBlock: true, +parseClassExpression: true, parseClassDeclaration: true, parseExpression: true, +parseForStatement: true, +parseFunctionDeclaration: true, parseFunctionExpression: true, +parseFunctionSourceElements: true, parseVariableIdentifier: true, +parseImportSpecifier: true, +parseLeftHandSideExpression: true, parseParams: true, validateParam: true, +parseSpreadOrAssignmentExpression: true, +parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true, +parseYieldExpression: true +*/ + +(function (root, factory) { + 'use strict'; + + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory((root.esprima = {})); + } +}(this, function (exports) { + 'use strict'; + + var Token, + TokenName, + FnExprTokens, + Syntax, + PropertyKind, + Messages, + Regex, + SyntaxTreeDelegate, + ClassPropertyType, + source, + strict, + index, + lineNumber, + lineStart, + length, + delegate, + lookahead, + state, + extra; + + Token = { + BooleanLiteral: 1, + EOF: 2, + Identifier: 3, + Keyword: 4, + NullLiteral: 5, + NumericLiteral: 6, + Punctuator: 7, + StringLiteral: 8, + RegularExpression: 9, + Template: 10 + }; + + TokenName = {}; + TokenName[Token.BooleanLiteral] = 'Boolean'; + TokenName[Token.EOF] = ''; + TokenName[Token.Identifier] = 'Identifier'; + TokenName[Token.Keyword] = 'Keyword'; + TokenName[Token.NullLiteral] = 'Null'; + TokenName[Token.NumericLiteral] = 'Numeric'; + TokenName[Token.Punctuator] = 'Punctuator'; + TokenName[Token.StringLiteral] = 'String'; + TokenName[Token.RegularExpression] = 'RegularExpression'; + + // A function following one of those tokens is an expression. + FnExprTokens = ["(", "{", "[", "in", "typeof", "instanceof", "new", + "return", "case", "delete", "throw", "void", + // assignment operators + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", ",", + // binary/unary operators + "+", "-", "*", "/", "%", "++", "--", "<<", ">>", ">>>", "&", + "|", "^", "!", "~", "&&", "||", "?", ":", "===", "==", ">=", + "<=", "<", ">", "!=", "!=="]; + + Syntax = { + ArrayExpression: 'ArrayExpression', + ArrayPattern: 'ArrayPattern', + ArrowFunctionExpression: 'ArrowFunctionExpression', + AssignmentExpression: 'AssignmentExpression', + BinaryExpression: 'BinaryExpression', + BlockStatement: 'BlockStatement', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ClassBody: 'ClassBody', + ClassDeclaration: 'ClassDeclaration', + ClassExpression: 'ClassExpression', + ClassHeritage: 'ClassHeritage', + ComprehensionBlock: 'ComprehensionBlock', + ComprehensionExpression: 'ComprehensionExpression', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DebuggerStatement: 'DebuggerStatement', + DoWhileStatement: 'DoWhileStatement', + EmptyStatement: 'EmptyStatement', + ExportDeclaration: 'ExportDeclaration', + ExportBatchSpecifier: 'ExportBatchSpecifier', + ExportSpecifier: 'ExportSpecifier', + ExpressionStatement: 'ExpressionStatement', + ForInStatement: 'ForInStatement', + ForOfStatement: 'ForOfStatement', + ForStatement: 'ForStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + ImportDeclaration: 'ImportDeclaration', + ImportSpecifier: 'ImportSpecifier', + LabeledStatement: 'LabeledStatement', + Literal: 'Literal', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + MethodDefinition: 'MethodDefinition', + ModuleDeclaration: 'ModuleDeclaration', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + ObjectPattern: 'ObjectPattern', + Program: 'Program', + Property: 'Property', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SpreadElement: 'SpreadElement', + SwitchCase: 'SwitchCase', + SwitchStatement: 'SwitchStatement', + TaggedTemplateExpression: 'TaggedTemplateExpression', + TemplateElement: 'TemplateElement', + TemplateLiteral: 'TemplateLiteral', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement', + YieldExpression: 'YieldExpression' + }; + + PropertyKind = { + Data: 1, + Get: 2, + Set: 4 + }; + + ClassPropertyType = { + 'static': 'static', + prototype: 'prototype' + }; + + // Error messages should be identical to V8. + Messages = { + UnexpectedToken: 'Unexpected token %0', + UnexpectedNumber: 'Unexpected number', + UnexpectedString: 'Unexpected string', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedTemplate: 'Unexpected quasi %0', + UnexpectedEOS: 'Unexpected end of input', + NewlineAfterThrow: 'Illegal newline after throw', + InvalidRegExp: 'Invalid regular expression', + UnterminatedRegExp: 'Invalid regular expression: missing /', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInFormalsList: 'Invalid left-hand side in formals list', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', + MultipleDefaultsInSwitch: 'More than one default clause in switch statement', + NoCatchOrFinally: 'Missing catch or finally after try', + UnknownLabel: 'Undefined label \'%0\'', + Redeclaration: '%0 \'%1\' has already been declared', + IllegalContinue: 'Illegal continue statement', + IllegalBreak: 'Illegal break statement', + IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition', + IllegalReturn: 'Illegal return statement', + IllegalYield: 'Illegal yield expression', + IllegalSpread: 'Illegal spread element', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictParamDupe: 'Strict mode function may not have duplicate parameter names', + ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list', + DefaultRestParameter: 'Rest parameter can not have a default value', + ElementAfterSpreadElement: 'Spread must be the final element of an element list', + ObjectPatternAsRestParameter: 'Invalid rest parameter', + ObjectPatternAsSpread: 'Invalid spread argument', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', + AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', + AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', + StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', + StrictReservedWord: 'Use of future reserved word in strict mode', + NewlineAfterModule: 'Illegal newline after module', + NoFromAfterImport: 'Missing from after import', + InvalidModuleSpecifier: 'Invalid module specifier', + NestedModule: 'Module declaration can not be nested', + NoYieldInGenerator: 'Missing yield in generator', + NoUnintializedConst: 'Const must be initialized', + ComprehensionRequiresBlock: 'Comprehension must have at least one block', + ComprehensionError: 'Comprehension Error', + EachNotAllowed: 'Each is not supported' + }; + + // See also tools/generate-unicode-regex.py. + Regex = { + NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), + NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') + }; + + // Ensure the condition is true, otherwise throw an error. + // This is only to have a better contract semantic, i.e. another safety net + // to catch a logic error. The condition shall be fulfilled in normal case. + // Do NOT use this to enforce a certain condition on any user input. + + function assert(condition, message) { + if (!condition) { + throw new Error('ASSERT: ' + message); + } + } + + function isDecimalDigit(ch) { + return (ch >= 48 && ch <= 57); // 0..9 + } + + function isHexDigit(ch) { + return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; + } + + function isOctalDigit(ch) { + return '01234567'.indexOf(ch) >= 0; + } + + + // 7.2 White Space + + function isWhiteSpace(ch) { + return (ch === 32) || // space + (ch === 9) || // tab + (ch === 0xB) || + (ch === 0xC) || + (ch === 0xA0) || + (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0); + } + + // 7.3 Line Terminators + + function isLineTerminator(ch) { + return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029); + } + + // 7.6 Identifier Names and Identifiers + + function isIdentifierStart(ch) { + return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) + (ch >= 65 && ch <= 90) || // A..Z + (ch >= 97 && ch <= 122) || // a..z + (ch === 92) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))); + } + + function isIdentifierPart(ch) { + return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) + (ch >= 65 && ch <= 90) || // A..Z + (ch >= 97 && ch <= 122) || // a..z + (ch >= 48 && ch <= 57) || // 0..9 + (ch === 92) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))); + } + + // 7.6.1.2 Future Reserved Words + + function isFutureReservedWord(id) { + switch (id) { + case 'class': + case 'enum': + case 'export': + case 'extends': + case 'import': + case 'super': + return true; + default: + return false; + } + } + + function isStrictModeReservedWord(id) { + switch (id) { + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'yield': + case 'let': + return true; + default: + return false; + } + } + + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; + } + + // 7.6.1.1 Keywords + + function isKeyword(id) { + if (strict && isStrictModeReservedWord(id)) { + return true; + } + + // 'const' is specialized as Keyword in V8. + // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next. + // Some others are from future reserved words. + + switch (id.length) { + case 2: + return (id === 'if') || (id === 'in') || (id === 'do'); + case 3: + return (id === 'var') || (id === 'for') || (id === 'new') || + (id === 'try') || (id === 'let'); + case 4: + return (id === 'this') || (id === 'else') || (id === 'case') || + (id === 'void') || (id === 'with') || (id === 'enum'); + case 5: + return (id === 'while') || (id === 'break') || (id === 'catch') || + (id === 'throw') || (id === 'const') || (id === 'yield') || + (id === 'class') || (id === 'super'); + case 6: + return (id === 'return') || (id === 'typeof') || (id === 'delete') || + (id === 'switch') || (id === 'export') || (id === 'import'); + case 7: + return (id === 'default') || (id === 'finally') || (id === 'extends'); + case 8: + return (id === 'function') || (id === 'continue') || (id === 'debugger'); + case 10: + return (id === 'instanceof'); + default: + return false; + } + } + + // 7.4 Comments + + function skipComment() { + var ch, blockComment, lineComment; + + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source.charCodeAt(index); + + if (lineComment) { + ++index; + if (isLineTerminator(ch)) { + lineComment = false; + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + } + } else if (blockComment) { + if (isLineTerminator(ch)) { + if (ch === 13 && source.charCodeAt(index + 1) === 10) { + ++index; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source.charCodeAt(index++); + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + // Block comment ends with '*/' (char #42, char #47). + if (ch === 42) { + ch = source.charCodeAt(index); + if (ch === 47) { + ++index; + blockComment = false; + } + } + } + } else if (ch === 47) { + ch = source.charCodeAt(index + 1); + // Line comment starts with '//' (char #47, char #47). + if (ch === 47) { + index += 2; + lineComment = true; + } else if (ch === 42) { + // Block comment starts with '/*' (char #47, char #42). + index += 2; + blockComment = true; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + ++index; + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function scanHexEscape(prefix) { + var i, len, ch, code = 0; + + len = (prefix === 'u') ? 4 : 2; + for (i = 0; i < len; ++i) { + if (index < length && isHexDigit(source[index])) { + ch = source[index++]; + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } else { + return ''; + } + } + return String.fromCharCode(code); + } + + function scanUnicodeCodePointEscape() { + var ch, code, cu1, cu2; + + ch = source[index]; + code = 0; + + // At least, one hex digit is required. + if (ch === '}') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + while (index < length) { + ch = source[index++]; + if (!isHexDigit(ch)) { + break; + } + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } + + if (code > 0x10FFFF || ch !== '}') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + // UTF-16 Encoding + if (code <= 0xFFFF) { + return String.fromCharCode(code); + } + cu1 = ((code - 0x10000) >> 10) + 0xD800; + cu2 = ((code - 0x10000) & 1023) + 0xDC00; + return String.fromCharCode(cu1, cu2); + } + + function getEscapedIdentifier() { + var ch, id; + + ch = source.charCodeAt(index++); + id = String.fromCharCode(ch); + + // '\u' (char #92, char #117) denotes an escaped character. + if (ch === 92) { + if (source.charCodeAt(index) !== 117) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + ++index; + ch = scanHexEscape('u'); + if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + id = ch; + } + + while (index < length) { + ch = source.charCodeAt(index); + if (!isIdentifierPart(ch)) { + break; + } + ++index; + id += String.fromCharCode(ch); + + // '\u' (char #92, char #117) denotes an escaped character. + if (ch === 92) { + id = id.substr(0, id.length - 1); + if (source.charCodeAt(index) !== 117) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + ++index; + ch = scanHexEscape('u'); + if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + id += ch; + } + } + + return id; + } + + function getIdentifier() { + var start, ch; + + start = index++; + while (index < length) { + ch = source.charCodeAt(index); + if (ch === 92) { + // Blackslash (char #92) marks Unicode escape sequence. + index = start; + return getEscapedIdentifier(); + } + if (isIdentifierPart(ch)) { + ++index; + } else { + break; + } + } + + return source.slice(start, index); + } + + function scanIdentifier() { + var start, id, type; + + start = index; + + // Backslash (char #92) starts an escaped character. + id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier(); + + // There is no keyword or literal with only one character. + // Thus, it must be an identifier. + if (id.length === 1) { + type = Token.Identifier; + } else if (isKeyword(id)) { + type = Token.Keyword; + } else if (id === 'null') { + type = Token.NullLiteral; + } else if (id === 'true' || id === 'false') { + type = Token.BooleanLiteral; + } else { + type = Token.Identifier; + } + + return { + type: type, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + + // 7.7 Punctuators + + function scanPunctuator() { + var start = index, + code = source.charCodeAt(index), + code2, + ch1 = source[index], + ch2, + ch3, + ch4; + + switch (code) { + // Check for most common single-character punctuators. + case 40: // ( open bracket + case 41: // ) close bracket + case 59: // ; semicolon + case 44: // , comma + case 123: // { open curly brace + case 125: // } close curly brace + case 91: // [ + case 93: // ] + case 58: // : + case 63: // ? + case 126: // ~ + ++index; + if (extra.tokenize) { + if (code === 40) { + extra.openParenToken = extra.tokens.length; + } else if (code === 123) { + extra.openCurlyToken = extra.tokens.length; + } + } + return { + type: Token.Punctuator, + value: String.fromCharCode(code), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + + default: + code2 = source.charCodeAt(index + 1); + + // '=' (char #61) marks an assignment or comparison operator. + if (code2 === 61) { + switch (code) { + case 37: // % + case 38: // & + case 42: // *: + case 43: // + + case 45: // - + case 47: // / + case 60: // < + case 62: // > + case 94: // ^ + case 124: // | + index += 2; + return { + type: Token.Punctuator, + value: String.fromCharCode(code) + String.fromCharCode(code2), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + + case 33: // ! + case 61: // = + index += 2; + + // !== and === + if (source.charCodeAt(index) === 61) { + ++index; + } + return { + type: Token.Punctuator, + value: source.slice(start, index), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + default: + break; + } + } + break; + } + + // Peek more characters. + + ch2 = source[index + 1]; + ch3 = source[index + 2]; + ch4 = source[index + 3]; + + // 4-character punctuator: >>>= + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + if (ch4 === '=') { + index += 4; + return { + type: Token.Punctuator, + value: '>>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + // 3-character punctuators: === !== >>> <<= >>= + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + index += 3; + return { + type: Token.Punctuator, + value: '>>>', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '<' && ch2 === '<' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '<<=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '>' && ch2 === '>' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '.' && ch2 === '.' && ch3 === '.') { + index += 3; + return { + type: Token.Punctuator, + value: '...', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // Other 2-character punctuators: ++ -- << >> && || + + if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { + index += 2; + return { + type: Token.Punctuator, + value: ch1 + ch2, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '=' && ch2 === '>') { + index += 2; + return { + type: Token.Punctuator, + value: '=>', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '.') { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + // 7.8.3 Numeric Literals + + function scanHexLiteral(start) { + var number = ''; + + while (index < length) { + if (!isHexDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.NumericLiteral, + value: parseInt('0x' + number, 16), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanOctalLiteral(prefix, start) { + var number, octal; + + if (isOctalDigit(prefix)) { + octal = true; + number = '0' + source[index++]; + } else { + octal = false; + ++index; + number = ''; + } + + while (index < length) { + if (!isOctalDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (!octal && number.length === 0) { + // only 0o or 0O + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 8), + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanNumericLiteral() { + var number, start, ch, octal; + + ch = source[index]; + assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), + 'Numeric literal must start with a decimal digit or a decimal point'); + + start = index; + number = ''; + if (ch !== '.') { + number = source[index++]; + ch = source[index]; + + // Hex number starts with '0x'. + // Octal number starts with '0'. + // Octal number in ES6 starts with '0o'. + // Binary number in ES6 starts with '0b'. + if (number === '0') { + if (ch === 'x' || ch === 'X') { + ++index; + return scanHexLiteral(start); + } + if (ch === 'b' || ch === 'B') { + ++index; + number = ''; + + while (index < length) { + ch = source[index]; + if (ch !== '0' && ch !== '1') { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + // only 0b or 0B + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (index < length) { + ch = source.charCodeAt(index); + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + return { + type: Token.NumericLiteral, + value: parseInt(number, 2), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) { + return scanOctalLiteral(ch, start); + } + // decimal number starts with '0' such as '09' is illegal. + if (ch && isDecimalDigit(ch.charCodeAt(0))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === '.') { + number += source[index++]; + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === 'e' || ch === 'E') { + number += source[index++]; + + ch = source[index]; + if (ch === '+' || ch === '-') { + number += source[index++]; + } + if (isDecimalDigit(source.charCodeAt(index))) { + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + } else { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.NumericLiteral, + value: parseFloat(number), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.8.4 String Literals + + function scanStringLiteral() { + var str = '', quote, start, ch, code, unescaped, restore, octal = false; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + while (index < length) { + ch = source[index++]; + + if (ch === quote) { + quote = ''; + break; + } else if (ch === '\\') { + ch = source[index++]; + if (!ch || !isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'n': + str += '\n'; + break; + case 'r': + str += '\r'; + break; + case 't': + str += '\t'; + break; + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + str += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + str += unescaped; + } else { + index = restore; + str += ch; + } + } + break; + case 'b': + str += '\b'; + break; + case 'f': + str += '\f'; + break; + case 'v': + str += '\x0B'; + break; + + default: + if (isOctalDigit(ch)) { + code = '01234567'.indexOf(ch); + + // \0 is not octal escape sequence + if (code !== 0) { + octal = true; + } + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + str += String.fromCharCode(code); + } else { + str += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + break; + } else { + str += ch; + } + } + + if (quote !== '') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.StringLiteral, + value: str, + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanTemplate() { + var cooked = '', ch, start, terminated, tail, restore, unescaped, code, octal; + + terminated = false; + tail = false; + start = index; + + ++index; + + while (index < length) { + ch = source[index++]; + if (ch === '`') { + tail = true; + terminated = true; + break; + } else if (ch === '$') { + if (source[index] === '{') { + ++index; + terminated = true; + break; + } + cooked += ch; + } else if (ch === '\\') { + ch = source[index++]; + if (!isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'n': + cooked += '\n'; + break; + case 'r': + cooked += '\r'; + break; + case 't': + cooked += '\t'; + break; + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + cooked += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + cooked += unescaped; + } else { + index = restore; + cooked += ch; + } + } + break; + case 'b': + cooked += '\b'; + break; + case 'f': + cooked += '\f'; + break; + case 'v': + cooked += '\v'; + break; + + default: + if (isOctalDigit(ch)) { + code = '01234567'.indexOf(ch); + + // \0 is not octal escape sequence + if (code !== 0) { + octal = true; + } + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + cooked += String.fromCharCode(code); + } else { + cooked += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + cooked += '\n'; + } else { + cooked += ch; + } + } + + if (!terminated) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.Template, + value: { + cooked: cooked, + raw: source.slice(start + 1, index - ((tail) ? 1 : 2)) + }, + tail: tail, + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanTemplateElement(option) { + var startsWith, template; + + lookahead = null; + skipComment(); + + startsWith = (option.head) ? '`' : '}'; + + if (source[index] !== startsWith) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + template = scanTemplate(); + + peek(); + + return template; + } + + function scanRegExp() { + var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; + + lookahead = null; + skipComment(); + + start = index; + ch = source[index]; + assert(ch === '/', 'Regular expression literal must start with a slash'); + str = source[index++]; + + while (index < length) { + ch = source[index++]; + str += ch; + if (classMarker) { + if (ch === ']') { + classMarker = false; + } + } else { + if (ch === '\\') { + ch = source[index++]; + // ECMA-262 7.8.5 + if (isLineTerminator(ch.charCodeAt(0))) { + throwError({}, Messages.UnterminatedRegExp); + } + str += ch; + } else if (ch === '/') { + terminated = true; + break; + } else if (ch === '[') { + classMarker = true; + } else if (isLineTerminator(ch.charCodeAt(0))) { + throwError({}, Messages.UnterminatedRegExp); + } + } + } + + if (!terminated) { + throwError({}, Messages.UnterminatedRegExp); + } + + // Exclude leading and trailing slash. + pattern = str.substr(1, str.length - 2); + + flags = ''; + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch.charCodeAt(0))) { + break; + } + + ++index; + if (ch === '\\' && index < length) { + ch = source[index]; + if (ch === 'u') { + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + flags += ch; + for (str += '\\u'; restore < index; ++restore) { + str += source[restore]; + } + } else { + index = restore; + flags += 'u'; + str += '\\u'; + } + } else { + str += '\\'; + } + } else { + flags += ch; + str += ch; + } + } + + try { + value = new RegExp(pattern, flags); + } catch (e) { + throwError({}, Messages.InvalidRegExp); + } + + peek(); + + + if (extra.tokenize) { + return { + type: Token.RegularExpression, + value: value, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + return { + literal: str, + value: value, + range: [start, index] + }; + } + + function isIdentifierName(token) { + return token.type === Token.Identifier || + token.type === Token.Keyword || + token.type === Token.BooleanLiteral || + token.type === Token.NullLiteral; + } + + function advanceSlash() { + var prevToken, + checkToken; + // Using the following algorithm: + // https://github.com/mozilla/sweet.js/wiki/design + prevToken = extra.tokens[extra.tokens.length - 1]; + if (!prevToken) { + // Nothing before that: it cannot be a division. + return scanRegExp(); + } + if (prevToken.type === "Punctuator") { + if (prevToken.value === ")") { + checkToken = extra.tokens[extra.openParenToken - 1]; + if (checkToken && + checkToken.type === "Keyword" && + (checkToken.value === "if" || + checkToken.value === "while" || + checkToken.value === "for" || + checkToken.value === "with")) { + return scanRegExp(); + } + return scanPunctuator(); + } + if (prevToken.value === "}") { + // Dividing a function by anything makes little sense, + // but we have to check for that. + if (extra.tokens[extra.openCurlyToken - 3] && + extra.tokens[extra.openCurlyToken - 3].type === "Keyword") { + // Anonymous function. + checkToken = extra.tokens[extra.openCurlyToken - 4]; + if (!checkToken) { + return scanPunctuator(); + } + } else if (extra.tokens[extra.openCurlyToken - 4] && + extra.tokens[extra.openCurlyToken - 4].type === "Keyword") { + // Named function. + checkToken = extra.tokens[extra.openCurlyToken - 5]; + if (!checkToken) { + return scanRegExp(); + } + } else { + return scanPunctuator(); + } + // checkToken determines whether the function is + // a declaration or an expression. + if (FnExprTokens.indexOf(checkToken.value) >= 0) { + // It is an expression. + return scanPunctuator(); + } + // It is a declaration. + return scanRegExp(); + } + return scanRegExp(); + } + if (prevToken.type === "Keyword") { + return scanRegExp(); + } + return scanPunctuator(); + } + + function advance() { + var ch; + + skipComment(); + + if (index >= length) { + return { + type: Token.EOF, + lineNumber: lineNumber, + lineStart: lineStart, + range: [index, index] + }; + } + + ch = source.charCodeAt(index); + + // Very common: ( and ) and ; + if (ch === 40 || ch === 41 || ch === 58) { + return scanPunctuator(); + } + + // String literal starts with single quote (#39) or double quote (#34). + if (ch === 39 || ch === 34) { + return scanStringLiteral(); + } + + if (ch === 96) { + return scanTemplate(); + } + if (isIdentifierStart(ch)) { + return scanIdentifier(); + } + + // Dot (.) char #46 can also start a floating-point number, hence the need + // to check the next character. + if (ch === 46) { + if (isDecimalDigit(source.charCodeAt(index + 1))) { + return scanNumericLiteral(); + } + return scanPunctuator(); + } + + if (isDecimalDigit(ch)) { + return scanNumericLiteral(); + } + + // Slash (/) char #47 can also start a regex. + if (extra.tokenize && ch === 47) { + return advanceSlash(); + } + + return scanPunctuator(); + } + + function lex() { + var token; + + token = lookahead; + index = token.range[1]; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + + lookahead = advance(); + + index = token.range[1]; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + + return token; + } + + function peek() { + var pos, line, start; + + pos = index; + line = lineNumber; + start = lineStart; + lookahead = advance(); + index = pos; + lineNumber = line; + lineStart = start; + } + + function lookahead2() { + var adv, pos, line, start, result; + + // If we are collecting the tokens, don't grab the next one yet. + adv = (typeof extra.advance === 'function') ? extra.advance : advance; + + pos = index; + line = lineNumber; + start = lineStart; + + // Scan for the next immediate token. + if (lookahead === null) { + lookahead = adv(); + } + index = lookahead.range[1]; + lineNumber = lookahead.lineNumber; + lineStart = lookahead.lineStart; + + // Grab the token right after. + result = adv(); + index = pos; + lineNumber = line; + lineStart = start; + + return result; + } + + SyntaxTreeDelegate = { + + name: 'SyntaxTree', + + postProcess: function (node) { + return node; + }, + + createArrayExpression: function (elements) { + return { + type: Syntax.ArrayExpression, + elements: elements + }; + }, + + createAssignmentExpression: function (operator, left, right) { + return { + type: Syntax.AssignmentExpression, + operator: operator, + left: left, + right: right + }; + }, + + createBinaryExpression: function (operator, left, right) { + var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : + Syntax.BinaryExpression; + return { + type: type, + operator: operator, + left: left, + right: right + }; + }, + + createBlockStatement: function (body) { + return { + type: Syntax.BlockStatement, + body: body + }; + }, + + createBreakStatement: function (label) { + return { + type: Syntax.BreakStatement, + label: label + }; + }, + + createCallExpression: function (callee, args) { + return { + type: Syntax.CallExpression, + callee: callee, + 'arguments': args + }; + }, + + createCatchClause: function (param, body) { + return { + type: Syntax.CatchClause, + param: param, + body: body + }; + }, + + createConditionalExpression: function (test, consequent, alternate) { + return { + type: Syntax.ConditionalExpression, + test: test, + consequent: consequent, + alternate: alternate + }; + }, + + createContinueStatement: function (label) { + return { + type: Syntax.ContinueStatement, + label: label + }; + }, + + createDebuggerStatement: function () { + return { + type: Syntax.DebuggerStatement + }; + }, + + createDoWhileStatement: function (body, test) { + return { + type: Syntax.DoWhileStatement, + body: body, + test: test + }; + }, + + createEmptyStatement: function () { + return { + type: Syntax.EmptyStatement + }; + }, + + createExpressionStatement: function (expression) { + return { + type: Syntax.ExpressionStatement, + expression: expression + }; + }, + + createForStatement: function (init, test, update, body) { + return { + type: Syntax.ForStatement, + init: init, + test: test, + update: update, + body: body + }; + }, + + createForInStatement: function (left, right, body) { + return { + type: Syntax.ForInStatement, + left: left, + right: right, + body: body, + each: false + }; + }, + + createForOfStatement: function (left, right, body) { + return { + type: Syntax.ForOfStatement, + left: left, + right: right, + body: body, + }; + }, + + createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression) { + return { + type: Syntax.FunctionDeclaration, + id: id, + params: params, + defaults: defaults, + body: body, + rest: rest, + generator: generator, + expression: expression + }; + }, + + createFunctionExpression: function (id, params, defaults, body, rest, generator, expression) { + return { + type: Syntax.FunctionExpression, + id: id, + params: params, + defaults: defaults, + body: body, + rest: rest, + generator: generator, + expression: expression + }; + }, + + createIdentifier: function (name) { + return { + type: Syntax.Identifier, + name: name + }; + }, + + createIfStatement: function (test, consequent, alternate) { + return { + type: Syntax.IfStatement, + test: test, + consequent: consequent, + alternate: alternate + }; + }, + + createLabeledStatement: function (label, body) { + return { + type: Syntax.LabeledStatement, + label: label, + body: body + }; + }, + + createLiteral: function (token) { + return { + type: Syntax.Literal, + value: token.value, + raw: source.slice(token.range[0], token.range[1]) + }; + }, + + createMemberExpression: function (accessor, object, property) { + return { + type: Syntax.MemberExpression, + computed: accessor === '[', + object: object, + property: property + }; + }, + + createNewExpression: function (callee, args) { + return { + type: Syntax.NewExpression, + callee: callee, + 'arguments': args + }; + }, + + createObjectExpression: function (properties) { + return { + type: Syntax.ObjectExpression, + properties: properties + }; + }, + + createPostfixExpression: function (operator, argument) { + return { + type: Syntax.UpdateExpression, + operator: operator, + argument: argument, + prefix: false + }; + }, + + createProgram: function (body) { + return { + type: Syntax.Program, + body: body + }; + }, + + createProperty: function (kind, key, value, method, shorthand) { + return { + type: Syntax.Property, + key: key, + value: value, + kind: kind, + method: method, + shorthand: shorthand + }; + }, + + createReturnStatement: function (argument) { + return { + type: Syntax.ReturnStatement, + argument: argument + }; + }, + + createSequenceExpression: function (expressions) { + return { + type: Syntax.SequenceExpression, + expressions: expressions + }; + }, + + createSwitchCase: function (test, consequent) { + return { + type: Syntax.SwitchCase, + test: test, + consequent: consequent + }; + }, + + createSwitchStatement: function (discriminant, cases) { + return { + type: Syntax.SwitchStatement, + discriminant: discriminant, + cases: cases + }; + }, + + createThisExpression: function () { + return { + type: Syntax.ThisExpression + }; + }, + + createThrowStatement: function (argument) { + return { + type: Syntax.ThrowStatement, + argument: argument + }; + }, + + createTryStatement: function (block, guardedHandlers, handlers, finalizer) { + return { + type: Syntax.TryStatement, + block: block, + guardedHandlers: guardedHandlers, + handlers: handlers, + finalizer: finalizer + }; + }, + + createUnaryExpression: function (operator, argument) { + if (operator === '++' || operator === '--') { + return { + type: Syntax.UpdateExpression, + operator: operator, + argument: argument, + prefix: true + }; + } + return { + type: Syntax.UnaryExpression, + operator: operator, + argument: argument + }; + }, + + createVariableDeclaration: function (declarations, kind) { + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: kind + }; + }, + + createVariableDeclarator: function (id, init) { + return { + type: Syntax.VariableDeclarator, + id: id, + init: init + }; + }, + + createWhileStatement: function (test, body) { + return { + type: Syntax.WhileStatement, + test: test, + body: body + }; + }, + + createWithStatement: function (object, body) { + return { + type: Syntax.WithStatement, + object: object, + body: body + }; + }, + + createTemplateElement: function (value, tail) { + return { + type: Syntax.TemplateElement, + value: value, + tail: tail + }; + }, + + createTemplateLiteral: function (quasis, expressions) { + return { + type: Syntax.TemplateLiteral, + quasis: quasis, + expressions: expressions + }; + }, + + createSpreadElement: function (argument) { + return { + type: Syntax.SpreadElement, + argument: argument + }; + }, + + createTaggedTemplateExpression: function (tag, quasi) { + return { + type: Syntax.TaggedTemplateExpression, + tag: tag, + quasi: quasi + }; + }, + + createArrowFunctionExpression: function (params, defaults, body, rest, expression) { + return { + type: Syntax.ArrowFunctionExpression, + id: null, + params: params, + defaults: defaults, + body: body, + rest: rest, + generator: false, + expression: expression + }; + }, + + createMethodDefinition: function (propertyType, kind, key, value) { + return { + type: Syntax.MethodDefinition, + key: key, + value: value, + kind: kind, + 'static': propertyType === ClassPropertyType.static + }; + }, + + createClassBody: function (body) { + return { + type: Syntax.ClassBody, + body: body + }; + }, + + createClassExpression: function (id, superClass, body) { + return { + type: Syntax.ClassExpression, + id: id, + superClass: superClass, + body: body + }; + }, + + createClassDeclaration: function (id, superClass, body) { + return { + type: Syntax.ClassDeclaration, + id: id, + superClass: superClass, + body: body + }; + }, + + createExportSpecifier: function (id, name) { + return { + type: Syntax.ExportSpecifier, + id: id, + name: name + }; + }, + + createExportBatchSpecifier: function () { + return { + type: Syntax.ExportBatchSpecifier + }; + }, + + createExportDeclaration: function (def, declaration, specifiers, source) { + return { + type: Syntax.ExportDeclaration, + declaration: declaration, + default: def, + specifiers: specifiers, + source: source + }; + }, + + createImportSpecifier: function (id, name) { + return { + type: Syntax.ImportSpecifier, + id: id, + name: name + }; + }, + + createImportDeclaration: function (specifiers, kind, source) { + return { + type: Syntax.ImportDeclaration, + specifiers: specifiers, + kind: kind, + source: source + }; + }, + + createYieldExpression: function (argument, delegate) { + return { + type: Syntax.YieldExpression, + argument: argument, + delegate: delegate + }; + }, + + createModuleDeclaration: function (id, source, body) { + return { + type: Syntax.ModuleDeclaration, + id: id, + source: source, + body: body + }; + } + + + }; + + // Return true if there is a line terminator before the next token. + + function peekLineTerminator() { + var pos, line, start, found; + + pos = index; + line = lineNumber; + start = lineStart; + skipComment(); + found = lineNumber !== line; + index = pos; + lineNumber = line; + lineStart = start; + + return found; + } + + // Throw an exception + + function throwError(token, messageFormat) { + var error, + args = Array.prototype.slice.call(arguments, 2), + msg = messageFormat.replace( + /%(\d)/g, + function (whole, index) { + assert(index < args.length, 'Message reference must be in range'); + return args[index]; + } + ); + + if (typeof token.lineNumber === 'number') { + error = new Error('Line ' + token.lineNumber + ': ' + msg); + error.index = token.range[0]; + error.lineNumber = token.lineNumber; + error.column = token.range[0] - lineStart + 1; + } else { + error = new Error('Line ' + lineNumber + ': ' + msg); + error.index = index; + error.lineNumber = lineNumber; + error.column = index - lineStart + 1; + } + + error.description = msg; + throw error; + } + + function throwErrorTolerant() { + try { + throwError.apply(null, arguments); + } catch (e) { + if (extra.errors) { + extra.errors.push(e); + } else { + throw e; + } + } + } + + + // Throw an exception because of the token. + + function throwUnexpected(token) { + if (token.type === Token.EOF) { + throwError(token, Messages.UnexpectedEOS); + } + + if (token.type === Token.NumericLiteral) { + throwError(token, Messages.UnexpectedNumber); + } + + if (token.type === Token.StringLiteral) { + throwError(token, Messages.UnexpectedString); + } + + if (token.type === Token.Identifier) { + throwError(token, Messages.UnexpectedIdentifier); + } + + if (token.type === Token.Keyword) { + if (isFutureReservedWord(token.value)) { + throwError(token, Messages.UnexpectedReserved); + } else if (strict && isStrictModeReservedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictReservedWord); + return; + } + throwError(token, Messages.UnexpectedToken, token.value); + } + + if (token.type === Token.Template) { + throwError(token, Messages.UnexpectedTemplate, token.value.raw); + } + + // BooleanLiteral, NullLiteral, or Punctuator. + throwError(token, Messages.UnexpectedToken, token.value); + } + + // Expect the next token to match the specified punctuator. + // If not, an exception will be thrown. + + function expect(value) { + var token = lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + throwUnexpected(token); + } + } + + // Expect the next token to match the specified keyword. + // If not, an exception will be thrown. + + function expectKeyword(keyword) { + var token = lex(); + if (token.type !== Token.Keyword || token.value !== keyword) { + throwUnexpected(token); + } + } + + // Return true if the next token matches the specified punctuator. + + function match(value) { + return lookahead.type === Token.Punctuator && lookahead.value === value; + } + + // Return true if the next token matches the specified keyword + + function matchKeyword(keyword) { + return lookahead.type === Token.Keyword && lookahead.value === keyword; + } + + + // Return true if the next token matches the specified contextual keyword + + function matchContextualKeyword(keyword) { + return lookahead.type === Token.Identifier && lookahead.value === keyword; + } + + // Return true if the next token is an assignment operator + + function matchAssign() { + var op; + + if (lookahead.type !== Token.Punctuator) { + return false; + } + op = lookahead.value; + return op === '=' || + op === '*=' || + op === '/=' || + op === '%=' || + op === '+=' || + op === '-=' || + op === '<<=' || + op === '>>=' || + op === '>>>=' || + op === '&=' || + op === '^=' || + op === '|='; + } + + function consumeSemicolon() { + var line; + + // Catch the very common case first: immediately a semicolon (char #59). + if (source.charCodeAt(index) === 59) { + lex(); + return; + } + + line = lineNumber; + skipComment(); + if (lineNumber !== line) { + return; + } + + if (match(';')) { + lex(); + return; + } + + if (lookahead.type !== Token.EOF && !match('}')) { + throwUnexpected(lookahead); + } + } + + // Return true if provided expression is LeftHandSideExpression + + function isLeftHandSide(expr) { + return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; + } + + function isAssignableLeftHandSide(expr) { + return isLeftHandSide(expr) || expr.type === Syntax.ObjectPattern || expr.type === Syntax.ArrayPattern; + } + + // 11.1.4 Array Initialiser + + function parseArrayInitialiser() { + var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true, body; + + expect('['); + while (!match(']')) { + if (lookahead.value === 'for' && + lookahead.type === Token.Keyword) { + if (!possiblecomprehension) { + throwError({}, Messages.ComprehensionError); + } + matchKeyword('for'); + tmp = parseForStatement({ignore_body: true}); + tmp.of = tmp.type === Syntax.ForOfStatement; + tmp.type = Syntax.ComprehensionBlock; + if (tmp.left.kind) { // can't be let or const + throwError({}, Messages.ComprehensionError); + } + blocks.push(tmp); + } else if (lookahead.value === 'if' && + lookahead.type === Token.Keyword) { + if (!possiblecomprehension) { + throwError({}, Messages.ComprehensionError); + } + expectKeyword('if'); + expect('('); + filter = parseExpression(); + expect(')'); + } else if (lookahead.value === ',' && + lookahead.type === Token.Punctuator) { + possiblecomprehension = false; // no longer allowed. + lex(); + elements.push(null); + } else { + tmp = parseSpreadOrAssignmentExpression(); + elements.push(tmp); + if (tmp && tmp.type === Syntax.SpreadElement) { + if (!match(']')) { + throwError({}, Messages.ElementAfterSpreadElement); + } + } else if (!(match(']') || matchKeyword('for') || matchKeyword('if'))) { + expect(','); // this lexes. + possiblecomprehension = false; + } + } + } + + expect(']'); + + if (filter && !blocks.length) { + throwError({}, Messages.ComprehensionRequiresBlock); + } + + if (blocks.length) { + if (elements.length !== 1) { + throwError({}, Messages.ComprehensionError); + } + return { + type: Syntax.ComprehensionExpression, + filter: filter, + blocks: blocks, + body: elements[0] + }; + } + return delegate.createArrayExpression(elements); + } + + // 11.1.5 Object Initialiser + + function parsePropertyFunction(options) { + var previousStrict, previousYieldAllowed, params, defaults, body; + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = options.generator; + params = options.params || []; + defaults = options.defaults || []; + + body = parseConciseBody(); + if (options.name && strict && isRestrictedWord(params[0].name)) { + throwErrorTolerant(options.name, Messages.StrictParamName); + } + if (state.yieldAllowed && !state.yieldFound) { + throwErrorTolerant({}, Messages.NoYieldInGenerator); + } + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createFunctionExpression(null, params, defaults, body, options.rest || null, options.generator, body.type !== Syntax.BlockStatement); + } + + + function parsePropertyMethodFunction(options) { + var previousStrict, tmp, method; + + previousStrict = strict; + strict = true; + + tmp = parseParams(); + + if (tmp.stricted) { + throwErrorTolerant(tmp.stricted, tmp.message); + } + + + method = parsePropertyFunction({ + params: tmp.params, + defaults: tmp.defaults, + rest: tmp.rest, + generator: options.generator + }); + + strict = previousStrict; + + return method; + } + + + function parseObjectPropertyKey() { + var token = lex(); + + // Note: This function is called only from parseObjectProperty(), where + // EOF and Punctuator tokens are already filtered out. + + if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { + if (strict && token.octal) { + throwErrorTolerant(token, Messages.StrictOctalLiteral); + } + return delegate.createLiteral(token); + } + + return delegate.createIdentifier(token.value); + } + + function parseObjectProperty() { + var token, key, id, value, param; + + token = lookahead; + + if (token.type === Token.Identifier) { + + id = parseObjectPropertyKey(); + + // Property Assignment: Getter and Setter. + + if (token.value === 'get' && !(match(':') || match('('))) { + key = parseObjectPropertyKey(); + expect('('); + expect(')'); + return delegate.createProperty('get', key, parsePropertyFunction({ generator: false }), false, false); + } + if (token.value === 'set' && !(match(':') || match('('))) { + key = parseObjectPropertyKey(); + expect('('); + token = lookahead; + param = [ parseVariableIdentifier() ]; + expect(')'); + return delegate.createProperty('set', key, parsePropertyFunction({ params: param, generator: false, name: token }), false, false); + } + if (match(':')) { + lex(); + return delegate.createProperty('init', id, parseAssignmentExpression(), false, false); + } + if (match('(')) { + return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: false }), true, false); + } + return delegate.createProperty('init', id, id, false, true); + } + if (token.type === Token.EOF || token.type === Token.Punctuator) { + if (!match('*')) { + throwUnexpected(token); + } + lex(); + + id = parseObjectPropertyKey(); + + if (!match('(')) { + throwUnexpected(lex()); + } + + return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: true }), true, false); + } + key = parseObjectPropertyKey(); + if (match(':')) { + lex(); + return delegate.createProperty('init', key, parseAssignmentExpression(), false, false); + } + if (match('(')) { + return delegate.createProperty('init', key, parsePropertyMethodFunction({ generator: false }), true, false); + } + throwUnexpected(lex()); + } + + function parseObjectInitialiser() { + var properties = [], property, name, key, kind, map = {}, toString = String; + + expect('{'); + + while (!match('}')) { + property = parseObjectProperty(); + + if (property.key.type === Syntax.Identifier) { + name = property.key.name; + } else { + name = toString(property.key.value); + } + kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; + + key = '$' + name; + if (Object.prototype.hasOwnProperty.call(map, key)) { + if (map[key] === PropertyKind.Data) { + if (strict && kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.StrictDuplicateProperty); + } else if (kind !== PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } + } else { + if (kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } else if (map[key] & kind) { + throwErrorTolerant({}, Messages.AccessorGetSet); + } + } + map[key] |= kind; + } else { + map[key] = kind; + } + + properties.push(property); + + if (!match('}')) { + expect(','); + } + } + + expect('}'); + + return delegate.createObjectExpression(properties); + } + + function parseTemplateElement(option) { + var token = scanTemplateElement(option); + if (strict && token.octal) { + throwError(token, Messages.StrictOctalLiteral); + } + return delegate.createTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail); + } + + function parseTemplateLiteral() { + var quasi, quasis, expressions; + + quasi = parseTemplateElement({ head: true }); + quasis = [ quasi ]; + expressions = []; + + while (!quasi.tail) { + expressions.push(parseExpression()); + quasi = parseTemplateElement({ head: false }); + quasis.push(quasi); + } + + return delegate.createTemplateLiteral(quasis, expressions); + } + + // 11.1.6 The Grouping Operator + + function parseGroupExpression() { + var expr; + + expect('('); + + ++state.parenthesizedCount; + + expr = parseExpression(); + + expect(')'); + + return expr; + } + + + // 11.1 Primary Expressions + + function parsePrimaryExpression() { + var type, token; + + token = lookahead; + type = lookahead.type; + + if (type === Token.Identifier) { + lex(); + return delegate.createIdentifier(token.value); + } + + if (type === Token.StringLiteral || type === Token.NumericLiteral) { + if (strict && lookahead.octal) { + throwErrorTolerant(lookahead, Messages.StrictOctalLiteral); + } + return delegate.createLiteral(lex()); + } + + if (type === Token.Keyword) { + if (matchKeyword('this')) { + lex(); + return delegate.createThisExpression(); + } + + if (matchKeyword('function')) { + return parseFunctionExpression(); + } + + if (matchKeyword('class')) { + return parseClassExpression(); + } + + if (matchKeyword('super')) { + lex(); + return delegate.createIdentifier('super'); + } + } + + if (type === Token.BooleanLiteral) { + token = lex(); + token.value = (token.value === 'true'); + return delegate.createLiteral(token); + } + + if (type === Token.NullLiteral) { + token = lex(); + token.value = null; + return delegate.createLiteral(token); + } + + if (match('[')) { + return parseArrayInitialiser(); + } + + if (match('{')) { + return parseObjectInitialiser(); + } + + if (match('(')) { + return parseGroupExpression(); + } + + if (match('/') || match('/=')) { + return delegate.createLiteral(scanRegExp()); + } + + if (type === Token.Template) { + return parseTemplateLiteral(); + } + + return throwUnexpected(lex()); + } + + // 11.2 Left-Hand-Side Expressions + + function parseArguments() { + var args = [], arg; + + expect('('); + + if (!match(')')) { + while (index < length) { + arg = parseSpreadOrAssignmentExpression(); + args.push(arg); + + if (match(')')) { + break; + } else if (arg.type === Syntax.SpreadElement) { + throwError({}, Messages.ElementAfterSpreadElement); + } + + expect(','); + } + } + + expect(')'); + + return args; + } + + function parseSpreadOrAssignmentExpression() { + if (match('...')) { + lex(); + return delegate.createSpreadElement(parseAssignmentExpression()); + } + return parseAssignmentExpression(); + } + + function parseNonComputedProperty() { + var token = lex(); + + if (!isIdentifierName(token)) { + throwUnexpected(token); + } + + return delegate.createIdentifier(token.value); + } + + function parseNonComputedMember() { + expect('.'); + + return parseNonComputedProperty(); + } + + function parseComputedMember() { + var expr; + + expect('['); + + expr = parseExpression(); + + expect(']'); + + return expr; + } + + function parseNewExpression() { + var callee, args; + + expectKeyword('new'); + callee = parseLeftHandSideExpression(); + args = match('(') ? parseArguments() : []; + + return delegate.createNewExpression(callee, args); + } + + function parseLeftHandSideExpressionAllowCall() { + var expr, args, property; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) { + if (match('(')) { + args = parseArguments(); + expr = delegate.createCallExpression(expr, args); + } else if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + } + } + + return expr; + } + + + function parseLeftHandSideExpression() { + var expr, property; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || lookahead.type === Token.Template) { + if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + } + } + + return expr; + } + + // 11.3 Postfix Expressions + + function parsePostfixExpression() { + var expr = parseLeftHandSideExpressionAllowCall(), + token = lookahead; + + if (lookahead.type !== Token.Punctuator) { + return expr; + } + + if ((match('++') || match('--')) && !peekLineTerminator()) { + // 11.3.1, 11.3.2 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPostfix); + } + + if (!isLeftHandSide(expr)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + + token = lex(); + expr = delegate.createPostfixExpression(token.value, expr); + } + + return expr; + } + + // 11.4 Unary Operators + + function parseUnaryExpression() { + var token, expr; + + if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { + return parsePostfixExpression(); + } + + if (match('++') || match('--')) { + token = lex(); + expr = parseUnaryExpression(); + // 11.4.4, 11.4.5 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPrefix); + } + + if (!isLeftHandSide(expr)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + + return delegate.createUnaryExpression(token.value, expr); + } + + if (match('+') || match('-') || match('~') || match('!')) { + token = lex(); + expr = parseUnaryExpression(); + return delegate.createUnaryExpression(token.value, expr); + } + + if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { + token = lex(); + expr = parseUnaryExpression(); + expr = delegate.createUnaryExpression(token.value, expr); + if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { + throwErrorTolerant({}, Messages.StrictDelete); + } + return expr; + } + + return parsePostfixExpression(); + } + + function binaryPrecedence(token, allowIn) { + var prec = 0; + + if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { + return 0; + } + + switch (token.value) { + case '||': + prec = 1; + break; + + case '&&': + prec = 2; + break; + + case '|': + prec = 3; + break; + + case '^': + prec = 4; + break; + + case '&': + prec = 5; + break; + + case '==': + case '!=': + case '===': + case '!==': + prec = 6; + break; + + case '<': + case '>': + case '<=': + case '>=': + case 'instanceof': + prec = 7; + break; + + case 'in': + prec = allowIn ? 7 : 0; + break; + + case '<<': + case '>>': + case '>>>': + prec = 8; + break; + + case '+': + case '-': + prec = 9; + break; + + case '*': + case '/': + case '%': + prec = 11; + break; + + default: + break; + } + + return prec; + } + + // 11.5 Multiplicative Operators + // 11.6 Additive Operators + // 11.7 Bitwise Shift Operators + // 11.8 Relational Operators + // 11.9 Equality Operators + // 11.10 Binary Bitwise Operators + // 11.11 Binary Logical Operators + + function parseBinaryExpression() { + var expr, token, prec, previousAllowIn, stack, right, operator, left, i; + + previousAllowIn = state.allowIn; + state.allowIn = true; + + expr = parseUnaryExpression(); + + token = lookahead; + prec = binaryPrecedence(token, previousAllowIn); + if (prec === 0) { + return expr; + } + token.prec = prec; + lex(); + + stack = [expr, token, parseUnaryExpression()]; + + while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) { + + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { + right = stack.pop(); + operator = stack.pop().value; + left = stack.pop(); + stack.push(delegate.createBinaryExpression(operator, left, right)); + } + + // Shift. + token = lex(); + token.prec = prec; + stack.push(token); + stack.push(parseUnaryExpression()); + } + + state.allowIn = previousAllowIn; + + // Final reduce to clean-up the stack. + i = stack.length - 1; + expr = stack[i]; + while (i > 1) { + expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr); + i -= 2; + } + return expr; + } + + + // 11.12 Conditional Operator + + function parseConditionalExpression() { + var expr, previousAllowIn, consequent, alternate; + + expr = parseBinaryExpression(); + + if (match('?')) { + lex(); + previousAllowIn = state.allowIn; + state.allowIn = true; + consequent = parseAssignmentExpression(); + state.allowIn = previousAllowIn; + expect(':'); + alternate = parseAssignmentExpression(); + + expr = delegate.createConditionalExpression(expr, consequent, alternate); + } + + return expr; + } + + // 11.13 Assignment Operators + + function reinterpretAsAssignmentBindingPattern(expr) { + var i, len, property, element; + + if (expr.type === Syntax.ObjectExpression) { + expr.type = Syntax.ObjectPattern; + for (i = 0, len = expr.properties.length; i < len; i += 1) { + property = expr.properties[i]; + if (property.kind !== 'init') { + throwError({}, Messages.InvalidLHSInAssignment); + } + reinterpretAsAssignmentBindingPattern(property.value); + } + } else if (expr.type === Syntax.ArrayExpression) { + expr.type = Syntax.ArrayPattern; + for (i = 0, len = expr.elements.length; i < len; i += 1) { + element = expr.elements[i]; + if (element) { + reinterpretAsAssignmentBindingPattern(element); + } + } + } else if (expr.type === Syntax.Identifier) { + if (isRestrictedWord(expr.name)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + } else if (expr.type === Syntax.SpreadElement) { + reinterpretAsAssignmentBindingPattern(expr.argument); + if (expr.argument.type === Syntax.ObjectPattern) { + throwError({}, Messages.ObjectPatternAsSpread); + } + } else { + if (expr.type !== Syntax.MemberExpression && expr.type !== Syntax.CallExpression && expr.type !== Syntax.NewExpression) { + throwError({}, Messages.InvalidLHSInAssignment); + } + } + } + + + function reinterpretAsDestructuredParameter(options, expr) { + var i, len, property, element; + + if (expr.type === Syntax.ObjectExpression) { + expr.type = Syntax.ObjectPattern; + for (i = 0, len = expr.properties.length; i < len; i += 1) { + property = expr.properties[i]; + if (property.kind !== 'init') { + throwError({}, Messages.InvalidLHSInFormalsList); + } + reinterpretAsDestructuredParameter(options, property.value); + } + } else if (expr.type === Syntax.ArrayExpression) { + expr.type = Syntax.ArrayPattern; + for (i = 0, len = expr.elements.length; i < len; i += 1) { + element = expr.elements[i]; + if (element) { + reinterpretAsDestructuredParameter(options, element); + } + } + } else if (expr.type === Syntax.Identifier) { + validateParam(options, expr, expr.name); + } else { + if (expr.type !== Syntax.MemberExpression) { + throwError({}, Messages.InvalidLHSInFormalsList); + } + } + } + + function reinterpretAsCoverFormalsList(expressions) { + var i, len, param, params, defaults, defaultCount, options, rest; + + params = []; + defaults = []; + defaultCount = 0; + rest = null; + options = { + paramSet: {} + }; + + for (i = 0, len = expressions.length; i < len; i += 1) { + param = expressions[i]; + if (param.type === Syntax.Identifier) { + params.push(param); + defaults.push(null); + validateParam(options, param, param.name); + } else if (param.type === Syntax.ObjectExpression || param.type === Syntax.ArrayExpression) { + reinterpretAsDestructuredParameter(options, param); + params.push(param); + defaults.push(null); + } else if (param.type === Syntax.SpreadElement) { + assert(i === len - 1, "It is guaranteed that SpreadElement is last element by parseExpression"); + reinterpretAsDestructuredParameter(options, param.argument); + rest = param.argument; + } else if (param.type === Syntax.AssignmentExpression) { + params.push(param.left); + defaults.push(param.right); + ++defaultCount; + validateParam(options, param.left, param.left.name); + } else { + return null; + } + } + + if (options.message === Messages.StrictParamDupe) { + throwError( + strict ? options.stricted : options.firstRestricted, + options.message + ); + } + + if (defaultCount === 0) { + defaults = []; + } + + return { + params: params, + defaults: defaults, + rest: rest, + stricted: options.stricted, + firstRestricted: options.firstRestricted, + message: options.message + }; + } + + function parseArrowFunctionExpression(options) { + var previousStrict, previousYieldAllowed, body; + + expect('=>'); + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + body = parseConciseBody(); + + if (strict && options.firstRestricted) { + throwError(options.firstRestricted, options.message); + } + if (strict && options.stricted) { + throwErrorTolerant(options.stricted, options.message); + } + + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createArrowFunctionExpression(options.params, options.defaults, body, options.rest, body.type !== Syntax.BlockStatement); + } + + function parseAssignmentExpression() { + var expr, token, params, oldParenthesizedCount; + + if (matchKeyword('yield')) { + return parseYieldExpression(); + } + + oldParenthesizedCount = state.parenthesizedCount; + + if (match('(')) { + token = lookahead2(); + if ((token.type === Token.Punctuator && token.value === ')') || token.value === '...') { + params = parseParams(); + if (!match('=>')) { + throwUnexpected(lex()); + } + return parseArrowFunctionExpression(params); + } + } + + token = lookahead; + expr = parseConditionalExpression(); + + if (match('=>') && + (state.parenthesizedCount === oldParenthesizedCount || + state.parenthesizedCount === (oldParenthesizedCount + 1))) { + if (expr.type === Syntax.Identifier) { + params = reinterpretAsCoverFormalsList([ expr ]); + } else if (expr.type === Syntax.SequenceExpression) { + params = reinterpretAsCoverFormalsList(expr.expressions); + } + if (params) { + return parseArrowFunctionExpression(params); + } + } + + if (matchAssign()) { + // 11.13.1 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant(token, Messages.StrictLHSAssignment); + } + + // ES.next draf 11.13 Runtime Semantics step 1 + if (match('=') && (expr.type === Syntax.ObjectExpression || expr.type === Syntax.ArrayExpression)) { + reinterpretAsAssignmentBindingPattern(expr); + } else if (!isLeftHandSide(expr)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + + expr = delegate.createAssignmentExpression(lex().value, expr, parseAssignmentExpression()); + } + + return expr; + } + + // 11.14 Comma Operator + + function parseExpression() { + var expr, expressions, sequence, coverFormalsList, spreadFound, oldParenthesizedCount; + + oldParenthesizedCount = state.parenthesizedCount; + + expr = parseAssignmentExpression(); + expressions = [ expr ]; + + if (match(',')) { + while (index < length) { + if (!match(',')) { + break; + } + + lex(); + expr = parseSpreadOrAssignmentExpression(); + expressions.push(expr); + + if (expr.type === Syntax.SpreadElement) { + spreadFound = true; + if (!match(')')) { + throwError({}, Messages.ElementAfterSpreadElement); + } + break; + } + } + + sequence = delegate.createSequenceExpression(expressions); + } + + if (match('=>')) { + // Do not allow nested parentheses on the LHS of the =>. + if (state.parenthesizedCount === oldParenthesizedCount || state.parenthesizedCount === (oldParenthesizedCount + 1)) { + expr = expr.type === Syntax.SequenceExpression ? expr.expressions : expressions; + coverFormalsList = reinterpretAsCoverFormalsList(expr); + if (coverFormalsList) { + return parseArrowFunctionExpression(coverFormalsList); + } + } + throwUnexpected(lex()); + } + + if (spreadFound && lookahead2().value !== '=>') { + throwError({}, Messages.IllegalSpread); + } + + return sequence || expr; + } + + // 12.1 Block + + function parseStatementList() { + var list = [], + statement; + + while (index < length) { + if (match('}')) { + break; + } + statement = parseSourceElement(); + if (typeof statement === 'undefined') { + break; + } + list.push(statement); + } + + return list; + } + + function parseBlock() { + var block; + + expect('{'); + + block = parseStatementList(); + + expect('}'); + + return delegate.createBlockStatement(block); + } + + // 12.2 Variable Statement + + function parseVariableIdentifier() { + var token = lex(); + + if (token.type !== Token.Identifier) { + throwUnexpected(token); + } + + return delegate.createIdentifier(token.value); + } + + function parseVariableDeclaration(kind) { + var id, + init = null; + if (match('{')) { + id = parseObjectInitialiser(); + reinterpretAsAssignmentBindingPattern(id); + } else if (match('[')) { + id = parseArrayInitialiser(); + reinterpretAsAssignmentBindingPattern(id); + } else { + if (state.allowDefault) { + id = matchKeyword('default') ? parseNonComputedProperty() : parseVariableIdentifier(); + } else { + id = parseVariableIdentifier(); + } + // 12.2.1 + if (strict && isRestrictedWord(id.name)) { + throwErrorTolerant({}, Messages.StrictVarName); + } + } + + if (kind === 'const') { + if (!match('=')) { + throwError({}, Messages.NoUnintializedConst); + } + expect('='); + init = parseAssignmentExpression(); + } else if (match('=')) { + lex(); + init = parseAssignmentExpression(); + } + + return delegate.createVariableDeclarator(id, init); + } + + function parseVariableDeclarationList(kind) { + var list = []; + + do { + list.push(parseVariableDeclaration(kind)); + if (!match(',')) { + break; + } + lex(); + } while (index < length); + + return list; + } + + function parseVariableStatement() { + var declarations; + + expectKeyword('var'); + + declarations = parseVariableDeclarationList(); + + consumeSemicolon(); + + return delegate.createVariableDeclaration(declarations, 'var'); + } + + // kind may be `const` or `let` + // Both are experimental and not in the specification yet. + // see http://wiki.ecmascript.org/doku.php?id=harmony:const + // and http://wiki.ecmascript.org/doku.php?id=harmony:let + function parseConstLetDeclaration(kind) { + var declarations; + + expectKeyword(kind); + + declarations = parseVariableDeclarationList(kind); + + consumeSemicolon(); + + return delegate.createVariableDeclaration(declarations, kind); + } + + // http://wiki.ecmascript.org/doku.php?id=harmony:modules + + function parseModuleDeclaration() { + var id, src, body; + + lex(); // 'module' + + if (peekLineTerminator()) { + throwError({}, Messages.NewlineAfterModule); + } + + switch (lookahead.type) { + + case Token.StringLiteral: + id = parsePrimaryExpression(); + body = parseModuleBlock(); + src = null; + break; + + case Token.Identifier: + id = parseVariableIdentifier(); + body = null; + if (!matchContextualKeyword('from')) { + throwUnexpected(lex()); + } + lex(); + src = parsePrimaryExpression(); + if (src.type !== Syntax.Literal) { + throwError({}, Messages.InvalidModuleSpecifier); + } + break; + } + + consumeSemicolon(); + return delegate.createModuleDeclaration(id, src, body); + } + + function parseExportBatchSpecifier() { + expect('*'); + return delegate.createExportBatchSpecifier(); + } + + function parseExportSpecifier() { + var id, name = null; + + id = parseVariableIdentifier(); + if (matchContextualKeyword('as')) { + lex(); + name = parseNonComputedProperty(); + } + + return delegate.createExportSpecifier(id, name); + } + + function parseExportDeclaration() { + var previousAllowDefault, decl, def, src, specifiers; + + expectKeyword('export'); + + if (matchKeyword('default')) { + lex(); + if (match('=')) { + lex(); + def = parseAssignmentExpression(); + } else if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'let': + case 'const': + case 'var': + case 'class': + def = parseSourceElement(); + break; + case 'function': + def = parseFunctionExpression(); + break; + default: + throwUnexpected(lex()); + } + } else { + def = parseAssignmentExpression(); + } + consumeSemicolon(); + return delegate.createExportDeclaration(true, def, null, null); + } + + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'let': + case 'const': + case 'var': + case 'class': + case 'function': + previousAllowDefault = state.allowDefault; + state.allowDefault = true; + decl = delegate.createExportDeclaration(false, parseSourceElement(), null, null); + state.allowDefault = previousAllowDefault; + return decl; + } + throwUnexpected(lex()); + } + + specifiers = []; + src = null; + + if (match('*')) { + specifiers.push(parseExportBatchSpecifier()); + } else { + expect('{'); + do { + specifiers.push(parseExportSpecifier()); + } while (match(',') && lex()); + expect('}'); + } + + if (matchContextualKeyword('from')) { + lex(); + src = parsePrimaryExpression(); + if (src.type !== Syntax.Literal) { + throwError({}, Messages.InvalidModuleSpecifier); + } + } + + consumeSemicolon(); + + return delegate.createExportDeclaration(false, null, specifiers, src); + } + + function parseImportDeclaration() { + var specifiers, kind, src; + + expectKeyword('import'); + specifiers = []; + + if (isIdentifierName(lookahead)) { + kind = 'default'; + specifiers.push(parseImportSpecifier()); + + if (!matchContextualKeyword('from')) { + throwError({}, Messages.NoFromAfterImport); + } + lex(); + } else if (match('{')) { + kind = 'named'; + lex(); + do { + specifiers.push(parseImportSpecifier()); + } while (match(',') && lex()); + expect('}'); + + if (!matchContextualKeyword('from')) { + throwError({}, Messages.NoFromAfterImport); + } + lex(); + } + + src = parsePrimaryExpression(); + if (src.type !== Syntax.Literal) { + throwError({}, Messages.InvalidModuleSpecifier); + } + + consumeSemicolon(); + + return delegate.createImportDeclaration(specifiers, kind, src); + } + + function parseImportSpecifier() { + var id, name = null; + + id = parseNonComputedProperty(); + if (matchContextualKeyword('as')) { + lex(); + name = parseVariableIdentifier(); + } + + return delegate.createImportSpecifier(id, name); + } + + // 12.3 Empty Statement + + function parseEmptyStatement() { + expect(';'); + return delegate.createEmptyStatement(); + } + + // 12.4 Expression Statement + + function parseExpressionStatement() { + var expr = parseExpression(); + consumeSemicolon(); + return delegate.createExpressionStatement(expr); + } + + // 12.5 If statement + + function parseIfStatement() { + var test, consequent, alternate; + + expectKeyword('if'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + consequent = parseStatement(); + + if (matchKeyword('else')) { + lex(); + alternate = parseStatement(); + } else { + alternate = null; + } + + return delegate.createIfStatement(test, consequent, alternate); + } + + // 12.6 Iteration Statements + + function parseDoWhileStatement() { + var body, test, oldInIteration; + + expectKeyword('do'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + if (match(';')) { + lex(); + } + + return delegate.createDoWhileStatement(body, test); + } + + function parseWhileStatement() { + var test, body, oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + return delegate.createWhileStatement(test, body); + } + + function parseForVariableDeclaration() { + var token = lex(), + declarations = parseVariableDeclarationList(); + + return delegate.createVariableDeclaration(declarations, token.value); + } + + function parseForStatement(opts) { + var init, test, update, left, right, body, operator, oldInIteration; + init = test = update = null; + expectKeyword('for'); + + // http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators&s=each + if (matchContextualKeyword("each")) { + throwError({}, Messages.EachNotAllowed); + } + + expect('('); + + if (match(';')) { + lex(); + } else { + if (matchKeyword('var') || matchKeyword('let') || matchKeyword('const')) { + state.allowIn = false; + init = parseForVariableDeclaration(); + state.allowIn = true; + + if (init.declarations.length === 1) { + if (matchKeyword('in') || matchContextualKeyword('of')) { + operator = lookahead; + if (!((operator.value === 'in' || init.kind !== 'var') && init.declarations[0].init)) { + lex(); + left = init; + right = parseExpression(); + init = null; + } + } + } + } else { + state.allowIn = false; + init = parseExpression(); + state.allowIn = true; + + if (matchContextualKeyword('of')) { + operator = lex(); + left = init; + right = parseExpression(); + init = null; + } else if (matchKeyword('in')) { + // LeftHandSideExpression + if (!isAssignableLeftHandSide(init)) { + throwError({}, Messages.InvalidLHSInForIn); + } + operator = lex(); + left = init; + right = parseExpression(); + init = null; + } + } + + if (typeof left === 'undefined') { + expect(';'); + } + } + + if (typeof left === 'undefined') { + + if (!match(';')) { + test = parseExpression(); + } + expect(';'); + + if (!match(')')) { + update = parseExpression(); + } + } + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + if (!(opts !== undefined && opts.ignore_body)) { + body = parseStatement(); + } + + state.inIteration = oldInIteration; + + if (typeof left === 'undefined') { + return delegate.createForStatement(init, test, update, body); + } + + if (operator.value === 'in') { + return delegate.createForInStatement(left, right, body); + } + return delegate.createForOfStatement(left, right, body); + } + + // 12.7 The continue statement + + function parseContinueStatement() { + var label = null, key; + + expectKeyword('continue'); + + // Optimize the most common form: 'continue;'. + if (source.charCodeAt(index) === 59) { + lex(); + + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return delegate.createContinueStatement(null); + } + + if (peekLineTerminator()) { + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return delegate.createContinueStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return delegate.createContinueStatement(label); + } + + // 12.8 The break statement + + function parseBreakStatement() { + var label = null, key; + + expectKeyword('break'); + + // Catch the very common case first: immediately a semicolon (char #59). + if (source.charCodeAt(index) === 59) { + lex(); + + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return delegate.createBreakStatement(null); + } + + if (peekLineTerminator()) { + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return delegate.createBreakStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return delegate.createBreakStatement(label); + } + + // 12.9 The return statement + + function parseReturnStatement() { + var argument = null; + + expectKeyword('return'); + + if (!state.inFunctionBody) { + throwErrorTolerant({}, Messages.IllegalReturn); + } + + // 'return' followed by a space and an identifier is very common. + if (source.charCodeAt(index) === 32) { + if (isIdentifierStart(source.charCodeAt(index + 1))) { + argument = parseExpression(); + consumeSemicolon(); + return delegate.createReturnStatement(argument); + } + } + + if (peekLineTerminator()) { + return delegate.createReturnStatement(null); + } + + if (!match(';')) { + if (!match('}') && lookahead.type !== Token.EOF) { + argument = parseExpression(); + } + } + + consumeSemicolon(); + + return delegate.createReturnStatement(argument); + } + + // 12.10 The with statement + + function parseWithStatement() { + var object, body; + + if (strict) { + throwErrorTolerant({}, Messages.StrictModeWith); + } + + expectKeyword('with'); + + expect('('); + + object = parseExpression(); + + expect(')'); + + body = parseStatement(); + + return delegate.createWithStatement(object, body); + } + + // 12.10 The swith statement + + function parseSwitchCase() { + var test, + consequent = [], + sourceElement; + + if (matchKeyword('default')) { + lex(); + test = null; + } else { + expectKeyword('case'); + test = parseExpression(); + } + expect(':'); + + while (index < length) { + if (match('}') || matchKeyword('default') || matchKeyword('case')) { + break; + } + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + consequent.push(sourceElement); + } + + return delegate.createSwitchCase(test, consequent); + } + + function parseSwitchStatement() { + var discriminant, cases, clause, oldInSwitch, defaultFound; + + expectKeyword('switch'); + + expect('('); + + discriminant = parseExpression(); + + expect(')'); + + expect('{'); + + cases = []; + + if (match('}')) { + lex(); + return delegate.createSwitchStatement(discriminant, cases); + } + + oldInSwitch = state.inSwitch; + state.inSwitch = true; + defaultFound = false; + + while (index < length) { + if (match('}')) { + break; + } + clause = parseSwitchCase(); + if (clause.test === null) { + if (defaultFound) { + throwError({}, Messages.MultipleDefaultsInSwitch); + } + defaultFound = true; + } + cases.push(clause); + } + + state.inSwitch = oldInSwitch; + + expect('}'); + + return delegate.createSwitchStatement(discriminant, cases); + } + + // 12.13 The throw statement + + function parseThrowStatement() { + var argument; + + expectKeyword('throw'); + + if (peekLineTerminator()) { + throwError({}, Messages.NewlineAfterThrow); + } + + argument = parseExpression(); + + consumeSemicolon(); + + return delegate.createThrowStatement(argument); + } + + // 12.14 The try statement + + function parseCatchClause() { + var param, body; + + expectKeyword('catch'); + + expect('('); + if (match(')')) { + throwUnexpected(lookahead); + } + + param = parseExpression(); + // 12.14.1 + if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) { + throwErrorTolerant({}, Messages.StrictCatchVariable); + } + + expect(')'); + body = parseBlock(); + return delegate.createCatchClause(param, body); + } + + function parseTryStatement() { + var block, handlers = [], finalizer = null; + + expectKeyword('try'); + + block = parseBlock(); + + if (matchKeyword('catch')) { + handlers.push(parseCatchClause()); + } + + if (matchKeyword('finally')) { + lex(); + finalizer = parseBlock(); + } + + if (handlers.length === 0 && !finalizer) { + throwError({}, Messages.NoCatchOrFinally); + } + + return delegate.createTryStatement(block, [], handlers, finalizer); + } + + // 12.15 The debugger statement + + function parseDebuggerStatement() { + expectKeyword('debugger'); + + consumeSemicolon(); + + return delegate.createDebuggerStatement(); + } + + // 12 Statements + + function parseStatement() { + var type = lookahead.type, + expr, + labeledBody, + key; + + if (type === Token.EOF) { + throwUnexpected(lookahead); + } + + if (type === Token.Punctuator) { + switch (lookahead.value) { + case ';': + return parseEmptyStatement(); + case '{': + return parseBlock(); + case '(': + return parseExpressionStatement(); + default: + break; + } + } + + if (type === Token.Keyword) { + switch (lookahead.value) { + case 'break': + return parseBreakStatement(); + case 'continue': + return parseContinueStatement(); + case 'debugger': + return parseDebuggerStatement(); + case 'do': + return parseDoWhileStatement(); + case 'for': + return parseForStatement(); + case 'function': + return parseFunctionDeclaration(); + case 'class': + return parseClassDeclaration(); + case 'if': + return parseIfStatement(); + case 'return': + return parseReturnStatement(); + case 'switch': + return parseSwitchStatement(); + case 'throw': + return parseThrowStatement(); + case 'try': + return parseTryStatement(); + case 'var': + return parseVariableStatement(); + case 'while': + return parseWhileStatement(); + case 'with': + return parseWithStatement(); + default: + break; + } + } + + expr = parseExpression(); + + // 12.12 Labelled Statements + if ((expr.type === Syntax.Identifier) && match(':')) { + lex(); + + key = '$' + expr.name; + if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError({}, Messages.Redeclaration, 'Label', expr.name); + } + + state.labelSet[key] = true; + labeledBody = parseStatement(); + delete state.labelSet[key]; + return delegate.createLabeledStatement(expr, labeledBody); + } + + consumeSemicolon(); + + return delegate.createExpressionStatement(expr); + } + + // 13 Function Definition + + function parseConciseBody() { + if (match('{')) { + return parseFunctionSourceElements(); + } + return parseAssignmentExpression(); + } + + function parseFunctionSourceElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted, + oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesizedCount; + + expect('{'); + + while (index < length) { + if (lookahead.type !== Token.StringLiteral) { + break; + } + token = lookahead; + + sourceElement = parseSourceElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + oldLabelSet = state.labelSet; + oldInIteration = state.inIteration; + oldInSwitch = state.inSwitch; + oldInFunctionBody = state.inFunctionBody; + oldParenthesizedCount = state.parenthesizedCount; + + state.labelSet = {}; + state.inIteration = false; + state.inSwitch = false; + state.inFunctionBody = true; + state.parenthesizedCount = 0; + + while (index < length) { + if (match('}')) { + break; + } + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + + expect('}'); + + state.labelSet = oldLabelSet; + state.inIteration = oldInIteration; + state.inSwitch = oldInSwitch; + state.inFunctionBody = oldInFunctionBody; + state.parenthesizedCount = oldParenthesizedCount; + + return delegate.createBlockStatement(sourceElements); + } + + function validateParam(options, param, name) { + var key = '$' + name; + if (strict) { + if (isRestrictedWord(name)) { + options.stricted = param; + options.message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = Messages.StrictParamDupe; + } + } else if (!options.firstRestricted) { + if (isRestrictedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.firstRestricted = param; + options.message = Messages.StrictParamDupe; + } + } + options.paramSet[key] = true; + } + + function parseParam(options) { + var token, rest, param, def; + + token = lookahead; + if (token.value === '...') { + token = lex(); + rest = true; + } + + if (match('[')) { + param = parseArrayInitialiser(); + reinterpretAsDestructuredParameter(options, param); + } else if (match('{')) { + if (rest) { + throwError({}, Messages.ObjectPatternAsRestParameter); + } + param = parseObjectInitialiser(); + reinterpretAsDestructuredParameter(options, param); + } else { + param = parseVariableIdentifier(); + validateParam(options, token, token.value); + if (match('=')) { + if (rest) { + throwErrorTolerant(lookahead, Messages.DefaultRestParameter); + } + lex(); + def = parseAssignmentExpression(); + ++options.defaultCount; + } + } + + if (rest) { + if (!match(')')) { + throwError({}, Messages.ParameterAfterRestParameter); + } + options.rest = param; + return false; + } + + options.params.push(param); + options.defaults.push(def); + return !match(')'); + } + + function parseParams(firstRestricted) { + var options; + + options = { + params: [], + defaultCount: 0, + defaults: [], + rest: null, + firstRestricted: firstRestricted + }; + + expect('('); + + if (!match(')')) { + options.paramSet = {}; + while (index < length) { + if (!parseParam(options)) { + break; + } + expect(','); + } + } + + expect(')'); + + if (options.defaultCount === 0) { + options.defaults = []; + } + + return options; + } + + function parseFunctionDeclaration() { + var id, body, token, tmp, firstRestricted, message, previousStrict, previousYieldAllowed, generator, expression; + + expectKeyword('function'); + + generator = false; + if (match('*')) { + lex(); + generator = true; + } + + token = lookahead; + + if (state.allowDefault) { + id = matchKeyword('default') ? parseNonComputedProperty() : parseVariableIdentifier(); + } else { + id = parseVariableIdentifier(); + } + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + + tmp = parseParams(firstRestricted); + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = generator; + + // here we redo some work in order to set 'expression' + expression = !match('{'); + body = parseConciseBody(); + + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && tmp.stricted) { + throwErrorTolerant(tmp.stricted, message); + } + if (state.yieldAllowed && !state.yieldFound) { + throwErrorTolerant({}, Messages.NoYieldInGenerator); + } + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createFunctionDeclaration(id, tmp.params, tmp.defaults, body, tmp.rest, generator, expression); + } + + function parseFunctionExpression() { + var token, id = null, firstRestricted, message, tmp, body, previousStrict, previousYieldAllowed, generator, expression; + + expectKeyword('function'); + + generator = false; + + if (match('*')) { + lex(); + generator = true; + } + + if (!match('(')) { + token = lookahead; + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + tmp = parseParams(firstRestricted); + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = generator; + + // here we redo some work in order to set 'expression' + expression = !match('{'); + body = parseConciseBody(); + + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && tmp.stricted) { + throwErrorTolerant(tmp.stricted, message); + } + if (state.yieldAllowed && !state.yieldFound) { + throwErrorTolerant({}, Messages.NoYieldInGenerator); + } + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createFunctionExpression(id, tmp.params, tmp.defaults, body, tmp.rest, generator, expression); + } + + function parseYieldExpression() { + var delegateFlag, expr, previousYieldAllowed; + + expectKeyword('yield'); + + if (!state.yieldAllowed) { + throwErrorTolerant({}, Messages.IllegalYield); + } + + delegateFlag = false; + if (match('*')) { + lex(); + delegateFlag = true; + } + + // It is a Syntax Error if any AssignmentExpression Contains YieldExpression. + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + expr = parseAssignmentExpression(); + state.yieldAllowed = previousYieldAllowed; + state.yieldFound = true; + + return delegate.createYieldExpression(expr, delegateFlag); + } + + // 14 Classes + + function parseMethodDefinition(existingPropNames) { + var token, key, param, propType, isValidDuplicateProp = false; + + if (lookahead.value === 'static') { + propType = ClassPropertyType.static; + lex(); + } else { + propType = ClassPropertyType.prototype; + } + + if (match('*')) { + lex(); + return delegate.createMethodDefinition( + propType, + '', + parseObjectPropertyKey(), + parsePropertyMethodFunction({ generator: true }) + ); + } + + token = lookahead; + key = parseObjectPropertyKey(); + + if (token.value === 'get' && !match('(')) { + key = parseObjectPropertyKey(); + + // It is a syntax error if any other properties have a name + // duplicating this one unless they are a setter + if (existingPropNames[propType].hasOwnProperty(key.name)) { + isValidDuplicateProp = + // There isn't already a getter for this prop + existingPropNames[propType][key.name].get === undefined + // There isn't already a data prop by this name + && existingPropNames[propType][key.name].data === undefined + // The only existing prop by this name is a setter + && existingPropNames[propType][key.name].set !== undefined; + if (!isValidDuplicateProp) { + throwError(key, Messages.IllegalDuplicateClassProperty); + } + } else { + existingPropNames[propType][key.name] = {}; + } + existingPropNames[propType][key.name].get = true; + + expect('('); + expect(')'); + return delegate.createMethodDefinition( + propType, + 'get', + key, + parsePropertyFunction({ generator: false }) + ); + } + if (token.value === 'set' && !match('(')) { + key = parseObjectPropertyKey(); + + // It is a syntax error if any other properties have a name + // duplicating this one unless they are a getter + if (existingPropNames[propType].hasOwnProperty(key.name)) { + isValidDuplicateProp = + // There isn't already a setter for this prop + existingPropNames[propType][key.name].set === undefined + // There isn't already a data prop by this name + && existingPropNames[propType][key.name].data === undefined + // The only existing prop by this name is a getter + && existingPropNames[propType][key.name].get !== undefined; + if (!isValidDuplicateProp) { + throwError(key, Messages.IllegalDuplicateClassProperty); + } + } else { + existingPropNames[propType][key.name] = {}; + } + existingPropNames[propType][key.name].set = true; + + expect('('); + token = lookahead; + param = [ parseVariableIdentifier() ]; + expect(')'); + return delegate.createMethodDefinition( + propType, + 'set', + key, + parsePropertyFunction({ params: param, generator: false, name: token }) + ); + } + + // It is a syntax error if any other properties have the same name as a + // non-getter, non-setter method + if (existingPropNames[propType].hasOwnProperty(key.name)) { + throwError(key, Messages.IllegalDuplicateClassProperty); + } else { + existingPropNames[propType][key.name] = {}; + } + existingPropNames[propType][key.name].data = true; + + return delegate.createMethodDefinition( + propType, + '', + key, + parsePropertyMethodFunction({ generator: false }) + ); + } + + function parseClassElement(existingProps) { + if (match(';')) { + lex(); + return; + } + return parseMethodDefinition(existingProps); + } + + function parseClassBody() { + var classElement, classElements = [], existingProps = {}; + + existingProps[ClassPropertyType.static] = {}; + existingProps[ClassPropertyType.prototype] = {}; + + expect('{'); + + while (index < length) { + if (match('}')) { + break; + } + classElement = parseClassElement(existingProps); + + if (typeof classElement !== 'undefined') { + classElements.push(classElement); + } + } + + expect('}'); + + return delegate.createClassBody(classElements); + } + + function parseClassExpression() { + var id, previousYieldAllowed, superClass = null; + + expectKeyword('class'); + + if (!matchKeyword('extends') && !match('{')) { + id = parseVariableIdentifier(); + } + + if (matchKeyword('extends')) { + expectKeyword('extends'); + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + superClass = parseAssignmentExpression(); + state.yieldAllowed = previousYieldAllowed; + } + + return delegate.createClassExpression(id, superClass, parseClassBody()); + } + + function parseClassDeclaration() { + var id, previousYieldAllowed, superClass = null; + + expectKeyword('class'); + + if (state.allowDefault) { + id = matchKeyword('default') ? parseNonComputedProperty() : parseVariableIdentifier(); + } else { + id = parseVariableIdentifier(); + } + + if (matchKeyword('extends')) { + expectKeyword('extends'); + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + superClass = parseAssignmentExpression(); + state.yieldAllowed = previousYieldAllowed; + } + + return delegate.createClassDeclaration(id, superClass, parseClassBody()); + } + + // 15 Program + + function matchModuleDeclaration() { + var id; + if (matchContextualKeyword('module')) { + id = lookahead2(); + return id.type === Token.StringLiteral || id.type === Token.Identifier; + } + return false; + } + + function parseSourceElement() { + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'const': + case 'let': + return parseConstLetDeclaration(lookahead.value); + case 'function': + return parseFunctionDeclaration(); + case 'export': + return parseExportDeclaration(); + case 'import': + return parseImportDeclaration(); + default: + return parseStatement(); + } + } + + if (matchModuleDeclaration()) { + throwError({}, Messages.NestedModule); + } + + if (lookahead.type !== Token.EOF) { + return parseStatement(); + } + } + + function parseProgramElement() { + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'export': + return parseExportDeclaration(); + case 'import': + return parseImportDeclaration(); + } + } + + if (matchModuleDeclaration()) { + return parseModuleDeclaration(); + } + + return parseSourceElement(); + } + + function parseProgramElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted; + + while (index < length) { + token = lookahead; + if (token.type !== Token.StringLiteral) { + break; + } + + sourceElement = parseProgramElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + while (index < length) { + sourceElement = parseProgramElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + return sourceElements; + } + + function parseModuleElement() { + return parseSourceElement(); + } + + function parseModuleElements() { + var list = [], + statement; + + while (index < length) { + if (match('}')) { + break; + } + statement = parseModuleElement(); + if (typeof statement === 'undefined') { + break; + } + list.push(statement); + } + + return list; + } + + function parseModuleBlock() { + var block; + + expect('{'); + + block = parseModuleElements(); + + expect('}'); + + return delegate.createBlockStatement(block); + } + + function parseProgram() { + var body; + strict = false; + peek(); + body = parseProgramElements(); + return delegate.createProgram(body); + } + + // The following functions are needed only when the option to preserve + // the comments is active. + + function addComment(type, value, start, end, loc) { + assert(typeof start === 'number', 'Comment must have valid position'); + + // Because the way the actual token is scanned, often the comments + // (if any) are skipped twice during the lexical analysis. + // Thus, we need to skip adding a comment if the comment array already + // handled it. + if (extra.comments.length > 0) { + if (extra.comments[extra.comments.length - 1].range[1] > start) { + return; + } + } + + extra.comments.push({ + type: type, + value: value, + range: [start, end], + loc: loc + }); + } + + function scanComment() { + var comment, ch, loc, start, blockComment, lineComment; + + comment = ''; + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source[index]; + + if (lineComment) { + ch = source[index++]; + if (isLineTerminator(ch.charCodeAt(0))) { + loc.end = { + line: lineNumber, + column: index - lineStart - 1 + }; + lineComment = false; + addComment('Line', comment, start, index - 1, loc); + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + comment = ''; + } else if (index >= length) { + lineComment = false; + comment += ch; + loc.end = { + line: lineNumber, + column: length - lineStart + }; + addComment('Line', comment, start, length, loc); + } else { + comment += ch; + } + } else if (blockComment) { + if (isLineTerminator(ch.charCodeAt(0))) { + if (ch === '\r' && source[index + 1] === '\n') { + ++index; + comment += '\r\n'; + } else { + comment += ch; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source[index++]; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + comment += ch; + if (ch === '*') { + ch = source[index]; + if (ch === '/') { + comment = comment.substr(0, comment.length - 1); + blockComment = false; + ++index; + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Block', comment, start, index, loc); + comment = ''; + } + } + } + } else if (ch === '/') { + ch = source[index + 1]; + if (ch === '/') { + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + start = index; + index += 2; + lineComment = true; + if (index >= length) { + loc.end = { + line: lineNumber, + column: index - lineStart + }; + lineComment = false; + addComment('Line', comment, start, index, loc); + } + } else if (ch === '*') { + start = index; + index += 2; + blockComment = true; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 + } + }; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch.charCodeAt(0))) { + ++index; + } else if (isLineTerminator(ch.charCodeAt(0))) { + ++index; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function filterCommentLocation() { + var i, entry, comment, comments = []; + + for (i = 0; i < extra.comments.length; ++i) { + entry = extra.comments[i]; + comment = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + comment.range = entry.range; + } + if (extra.loc) { + comment.loc = entry.loc; + } + comments.push(comment); + } + + extra.comments = comments; + } + + function collectToken() { + var start, loc, token, range, value; + + skipComment(); + start = index; + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + token = extra.advance(); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + if (token.type !== Token.EOF) { + range = [token.range[0], token.range[1]]; + value = source.slice(token.range[0], token.range[1]); + extra.tokens.push({ + type: TokenName[token.type], + value: value, + range: range, + loc: loc + }); + } + + return token; + } + + function collectRegex() { + var pos, loc, regex, token; + + skipComment(); + + pos = index; + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + regex = extra.scanRegExp(); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + if (!extra.tokenize) { + // Pop the previous token, which is likely '/' or '/=' + if (extra.tokens.length > 0) { + token = extra.tokens[extra.tokens.length - 1]; + if (token.range[0] === pos && token.type === 'Punctuator') { + if (token.value === '/' || token.value === '/=') { + extra.tokens.pop(); + } + } + } + + extra.tokens.push({ + type: 'RegularExpression', + value: regex.literal, + range: [pos, index], + loc: loc + }); + } + + return regex; + } + + function filterTokenLocation() { + var i, entry, token, tokens = []; + + for (i = 0; i < extra.tokens.length; ++i) { + entry = extra.tokens[i]; + token = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + token.range = entry.range; + } + if (extra.loc) { + token.loc = entry.loc; + } + tokens.push(token); + } + + extra.tokens = tokens; + } + + function LocationMarker() { + this.range = [index, index]; + this.loc = { + start: { + line: lineNumber, + column: index - lineStart + }, + end: { + line: lineNumber, + column: index - lineStart + } + }; + } + + LocationMarker.prototype = { + constructor: LocationMarker, + + end: function () { + this.range[1] = index; + this.loc.end.line = lineNumber; + this.loc.end.column = index - lineStart; + }, + + applyGroup: function (node) { + if (extra.range) { + node.groupRange = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.groupLoc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + node = delegate.postProcess(node); + } + }, + + apply: function (node) { + var nodeType = typeof node; + assert(nodeType === "object", + "Applying location marker to an unexpected node type: " + + nodeType); + + if (extra.range) { + node.range = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.loc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + node = delegate.postProcess(node); + } + } + }; + + function createLocationMarker() { + return new LocationMarker(); + } + + function trackGroupExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + expect('('); + + ++state.parenthesizedCount; + expr = parseExpression(); + + expect(')'); + marker.end(); + marker.applyGroup(expr); + + return expr; + } + + function trackLeftHandSideExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || lookahead.type === Token.Template) { + if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + marker.end(); + marker.apply(expr); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + marker.end(); + marker.apply(expr); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function trackLeftHandSideExpressionAllowCall() { + var marker, expr, args; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) { + if (match('(')) { + args = parseArguments(); + expr = delegate.createCallExpression(expr, args); + marker.end(); + marker.apply(expr); + } else if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + marker.end(); + marker.apply(expr); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + marker.end(); + marker.apply(expr); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function filterGroup(node) { + var n, i, entry; + + n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {}; + for (i in node) { + if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') { + entry = node[i]; + if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) { + n[i] = entry; + } else { + n[i] = filterGroup(entry); + } + } + } + return n; + } + + function wrapTrackingFunction(range, loc) { + + return function (parseFunction) { + + function isBinary(node) { + return node.type === Syntax.LogicalExpression || + node.type === Syntax.BinaryExpression; + } + + function visit(node) { + var start, end; + + if (isBinary(node.left)) { + visit(node.left); + } + if (isBinary(node.right)) { + visit(node.right); + } + + if (range) { + if (node.left.groupRange || node.right.groupRange) { + start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0]; + end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1]; + node.range = [start, end]; + } else if (typeof node.range === 'undefined') { + start = node.left.range[0]; + end = node.right.range[1]; + node.range = [start, end]; + } + } + if (loc) { + if (node.left.groupLoc || node.right.groupLoc) { + start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start; + end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end; + node.loc = { + start: start, + end: end + }; + node = delegate.postProcess(node); + } else if (typeof node.loc === 'undefined') { + node.loc = { + start: node.left.loc.start, + end: node.right.loc.end + }; + node = delegate.postProcess(node); + } + } + } + + return function () { + var marker, node; + + skipComment(); + + marker = createLocationMarker(); + node = parseFunction.apply(null, arguments); + marker.end(); + + if (range && typeof node.range === 'undefined') { + marker.apply(node); + } + + if (loc && typeof node.loc === 'undefined') { + marker.apply(node); + } + + if (isBinary(node)) { + visit(node); + } + + return node; + }; + }; + } + + function patch() { + + var wrapTracking; + + if (extra.comments) { + extra.skipComment = skipComment; + skipComment = scanComment; + } + + if (extra.range || extra.loc) { + + extra.parseGroupExpression = parseGroupExpression; + extra.parseLeftHandSideExpression = parseLeftHandSideExpression; + extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall; + parseGroupExpression = trackGroupExpression; + parseLeftHandSideExpression = trackLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall; + + wrapTracking = wrapTrackingFunction(extra.range, extra.loc); + + extra.parseAssignmentExpression = parseAssignmentExpression; + extra.parseBinaryExpression = parseBinaryExpression; + extra.parseBlock = parseBlock; + extra.parseFunctionSourceElements = parseFunctionSourceElements; + extra.parseCatchClause = parseCatchClause; + extra.parseComputedMember = parseComputedMember; + extra.parseConditionalExpression = parseConditionalExpression; + extra.parseConstLetDeclaration = parseConstLetDeclaration; + extra.parseExportBatchSpecifier = parseExportBatchSpecifier; + extra.parseExportDeclaration = parseExportDeclaration; + extra.parseExportSpecifier = parseExportSpecifier; + extra.parseExpression = parseExpression; + extra.parseForVariableDeclaration = parseForVariableDeclaration; + extra.parseFunctionDeclaration = parseFunctionDeclaration; + extra.parseFunctionExpression = parseFunctionExpression; + extra.parseParams = parseParams; + extra.parseImportDeclaration = parseImportDeclaration; + extra.parseImportSpecifier = parseImportSpecifier; + extra.parseModuleDeclaration = parseModuleDeclaration; + extra.parseModuleBlock = parseModuleBlock; + extra.parseNewExpression = parseNewExpression; + extra.parseNonComputedProperty = parseNonComputedProperty; + extra.parseObjectProperty = parseObjectProperty; + extra.parseObjectPropertyKey = parseObjectPropertyKey; + extra.parsePostfixExpression = parsePostfixExpression; + extra.parsePrimaryExpression = parsePrimaryExpression; + extra.parseProgram = parseProgram; + extra.parsePropertyFunction = parsePropertyFunction; + extra.parseSpreadOrAssignmentExpression = parseSpreadOrAssignmentExpression; + extra.parseTemplateElement = parseTemplateElement; + extra.parseTemplateLiteral = parseTemplateLiteral; + extra.parseStatement = parseStatement; + extra.parseSwitchCase = parseSwitchCase; + extra.parseUnaryExpression = parseUnaryExpression; + extra.parseVariableDeclaration = parseVariableDeclaration; + extra.parseVariableIdentifier = parseVariableIdentifier; + extra.parseMethodDefinition = parseMethodDefinition; + extra.parseClassDeclaration = parseClassDeclaration; + extra.parseClassExpression = parseClassExpression; + extra.parseClassBody = parseClassBody; + + parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression); + parseBinaryExpression = wrapTracking(extra.parseBinaryExpression); + parseBlock = wrapTracking(extra.parseBlock); + parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements); + parseCatchClause = wrapTracking(extra.parseCatchClause); + parseComputedMember = wrapTracking(extra.parseComputedMember); + parseConditionalExpression = wrapTracking(extra.parseConditionalExpression); + parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration); + parseExportBatchSpecifier = wrapTracking(parseExportBatchSpecifier); + parseExportDeclaration = wrapTracking(parseExportDeclaration); + parseExportSpecifier = wrapTracking(parseExportSpecifier); + parseExpression = wrapTracking(extra.parseExpression); + parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration); + parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration); + parseFunctionExpression = wrapTracking(extra.parseFunctionExpression); + parseParams = wrapTracking(extra.parseParams); + parseImportDeclaration = wrapTracking(extra.parseImportDeclaration); + parseImportSpecifier = wrapTracking(extra.parseImportSpecifier); + parseModuleDeclaration = wrapTracking(extra.parseModuleDeclaration); + parseModuleBlock = wrapTracking(extra.parseModuleBlock); + parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression); + parseNewExpression = wrapTracking(extra.parseNewExpression); + parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty); + parseObjectProperty = wrapTracking(extra.parseObjectProperty); + parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey); + parsePostfixExpression = wrapTracking(extra.parsePostfixExpression); + parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression); + parseProgram = wrapTracking(extra.parseProgram); + parsePropertyFunction = wrapTracking(extra.parsePropertyFunction); + parseTemplateElement = wrapTracking(extra.parseTemplateElement); + parseTemplateLiteral = wrapTracking(extra.parseTemplateLiteral); + parseSpreadOrAssignmentExpression = wrapTracking(extra.parseSpreadOrAssignmentExpression); + parseStatement = wrapTracking(extra.parseStatement); + parseSwitchCase = wrapTracking(extra.parseSwitchCase); + parseUnaryExpression = wrapTracking(extra.parseUnaryExpression); + parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration); + parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier); + parseMethodDefinition = wrapTracking(extra.parseMethodDefinition); + parseClassDeclaration = wrapTracking(extra.parseClassDeclaration); + parseClassExpression = wrapTracking(extra.parseClassExpression); + parseClassBody = wrapTracking(extra.parseClassBody); + } + + if (typeof extra.tokens !== 'undefined') { + extra.advance = advance; + extra.scanRegExp = scanRegExp; + + advance = collectToken; + scanRegExp = collectRegex; + } + } + + function unpatch() { + if (typeof extra.skipComment === 'function') { + skipComment = extra.skipComment; + } + + if (extra.range || extra.loc) { + parseAssignmentExpression = extra.parseAssignmentExpression; + parseBinaryExpression = extra.parseBinaryExpression; + parseBlock = extra.parseBlock; + parseFunctionSourceElements = extra.parseFunctionSourceElements; + parseCatchClause = extra.parseCatchClause; + parseComputedMember = extra.parseComputedMember; + parseConditionalExpression = extra.parseConditionalExpression; + parseConstLetDeclaration = extra.parseConstLetDeclaration; + parseExportBatchSpecifier = extra.parseExportBatchSpecifier; + parseExportDeclaration = extra.parseExportDeclaration; + parseExportSpecifier = extra.parseExportSpecifier; + parseExpression = extra.parseExpression; + parseForVariableDeclaration = extra.parseForVariableDeclaration; + parseFunctionDeclaration = extra.parseFunctionDeclaration; + parseFunctionExpression = extra.parseFunctionExpression; + parseImportDeclaration = extra.parseImportDeclaration; + parseImportSpecifier = extra.parseImportSpecifier; + parseGroupExpression = extra.parseGroupExpression; + parseLeftHandSideExpression = extra.parseLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall; + parseModuleDeclaration = extra.parseModuleDeclaration; + parseModuleBlock = extra.parseModuleBlock; + parseNewExpression = extra.parseNewExpression; + parseNonComputedProperty = extra.parseNonComputedProperty; + parseObjectProperty = extra.parseObjectProperty; + parseObjectPropertyKey = extra.parseObjectPropertyKey; + parsePostfixExpression = extra.parsePostfixExpression; + parsePrimaryExpression = extra.parsePrimaryExpression; + parseProgram = extra.parseProgram; + parsePropertyFunction = extra.parsePropertyFunction; + parseTemplateElement = extra.parseTemplateElement; + parseTemplateLiteral = extra.parseTemplateLiteral; + parseSpreadOrAssignmentExpression = extra.parseSpreadOrAssignmentExpression; + parseStatement = extra.parseStatement; + parseSwitchCase = extra.parseSwitchCase; + parseUnaryExpression = extra.parseUnaryExpression; + parseVariableDeclaration = extra.parseVariableDeclaration; + parseVariableIdentifier = extra.parseVariableIdentifier; + parseMethodDefinition = extra.parseMethodDefinition; + parseClassDeclaration = extra.parseClassDeclaration; + parseClassExpression = extra.parseClassExpression; + parseClassBody = extra.parseClassBody; + } + + if (typeof extra.scanRegExp === 'function') { + advance = extra.advance; + scanRegExp = extra.scanRegExp; + } + } + + // This is used to modify the delegate. + + function extend(object, properties) { + var entry, result = {}; + + for (entry in object) { + if (object.hasOwnProperty(entry)) { + result[entry] = object[entry]; + } + } + + for (entry in properties) { + if (properties.hasOwnProperty(entry)) { + result[entry] = properties[entry]; + } + } + + return result; + } + + function tokenize(code, options) { + var toString, + token, + tokens; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + delegate = SyntaxTreeDelegate; + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + lookahead = null; + state = { + allowDefault: true, + allowIn: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false + }; + + extra = {}; + + // Options matching. + options = options || {}; + + // Of course we collect tokens here. + options.tokens = true; + extra.tokens = []; + extra.tokenize = true; + // The following two fields are necessary to compute the Regex tokens. + extra.openParenToken = -1; + extra.openCurlyToken = -1; + + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + + if (length > 0) { + if (typeof source[0] === 'undefined') { + // Try first to convert to a string. This is good as fast path + // for old IE which understands string indexing for string + // literals only and not for string object. + if (code instanceof String) { + source = code.valueOf(); + } + } + } + + patch(); + + try { + peek(); + if (lookahead.type === Token.EOF) { + return extra.tokens; + } + + token = lex(); + while (lookahead.type !== Token.EOF) { + try { + token = lex(); + } catch (lexError) { + token = lookahead; + if (extra.errors) { + extra.errors.push(lexError); + // We have to break on the first error + // to avoid infinite loops. + break; + } else { + throw lexError; + } + } + } + + filterTokenLocation(); + tokens = extra.tokens; + if (typeof extra.comments !== 'undefined') { + filterCommentLocation(); + tokens.comments = extra.comments; + } + if (typeof extra.errors !== 'undefined') { + tokens.errors = extra.errors; + } + } catch (e) { + throw e; + } finally { + unpatch(); + extra = {}; + } + return tokens; + } + + function parse(code, options) { + var program, toString; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + delegate = SyntaxTreeDelegate; + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + lookahead = null; + state = { + allowDefault: false, + allowIn: true, + labelSet: {}, + parenthesizedCount: 0, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + yieldAllowed: false, + yieldFound: false + }; + + extra = {}; + if (typeof options !== 'undefined') { + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + + if (extra.loc && options.source !== null && options.source !== undefined) { + delegate = extend(delegate, { + 'postProcess': function (node) { + node.loc.source = toString(options.source); + return node; + } + }); + } + + if (typeof options.tokens === 'boolean' && options.tokens) { + extra.tokens = []; + } + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + } + + if (length > 0) { + if (typeof source[0] === 'undefined') { + // Try first to convert to a string. This is good as fast path + // for old IE which understands string indexing for string + // literals only and not for string object. + if (code instanceof String) { + source = code.valueOf(); + } + } + } + + patch(); + try { + program = parseProgram(); + if (typeof extra.comments !== 'undefined') { + filterCommentLocation(); + program.comments = extra.comments; + } + if (typeof extra.tokens !== 'undefined') { + filterTokenLocation(); + program.tokens = extra.tokens; + } + if (typeof extra.errors !== 'undefined') { + program.errors = extra.errors; + } + if (extra.range || extra.loc) { + program.body = filterGroup(program.body); + } + } catch (e) { + throw e; + } finally { + unpatch(); + extra = {}; + } + + return program; + } + + // Sync with package.json and component.json. + exports.version = '1.1.0-dev-harmony'; + + exports.tokenize = tokenize; + + exports.parse = parse; + + // Deep copy. + exports.Syntax = (function () { + var name, types = {}; + + if (typeof Object.create === 'function') { + types = Object.create(null); + } + + for (name in Syntax) { + if (Syntax.hasOwnProperty(name)) { + types[name] = Syntax[name]; + } + } + + if (typeof Object.freeze === 'function') { + Object.freeze(types); + } + + return types; + }()); + +})); +/* vim: set sw=4 ts=4 et tw=80 : */ + +},{}],2:[function(require,module,exports){ +"use strict"; +var $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClassNoExtends = function(object, staticObject) { + var ctor = object.constructor; + Object.defineProperty(object, 'constructor', {enumerable: false}); + ctor.prototype = object; + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var CompileError = require("./compile_error"); +var __dependency1__ = require("./utils"); +var isEmpty = __dependency1__.isEmpty; +var array = __dependency1__.array; +var forEach = __dependency1__.forEach; +var AbstractCompiler = function() { + 'use strict'; + var $AbstractCompiler = ($__createClassNoExtends)({ + constructor: function(compiler, options) { + this.compiler = compiler; + this.exports = compiler.exports; + this.exportDefault = compiler.exportDefault; + this.imports = compiler.imports; + this.directives = compiler.directives; + this.moduleName = compiler.moduleName; + this.lines = compiler.lines; + this.string = compiler.string; + this.options = options; + var allDependencies = this.imports.concat(this.exports.filter(function(export_) { + return export_.source !== null; + })); + this.dependencyNames = array.uniq(allDependencies.map(function(dep) { + return dep.source.value; + })); + }, + buildImports: function() { + var imports = this.imports, moduleImports = this.moduleImports, source = this.source; + for (var idx = 0; idx < imports.length; idx++) { + var import_ = imports[idx], replacement = ""; + var dependencyName = import_.source.value; + if (import_.type === "ModuleDeclaration" && import_.source.type === "Literal") { + replacement = this.doModuleImport(import_.id.name, dependencyName, idx); + } else if (import_.type === "ImportDeclaration") { + if (import_.kind === "default") { + var specifier = import_.specifiers[0]; + replacement = this.doDefaultImport(specifier.id.name, dependencyName, idx); + } else if (import_.kind === "named") { + replacement = this.doImportSpecifiers(import_, idx); + } else if (import_.kind === undefined) { + replacement = this.doBareImport(import_.source.value); + } + } + source.replace(import_.range[0], import_.range[1], replacement); + } + }, + buildExports: function() { + var source = this.source, exports_ = this.exports; + { + var $__2 = traceur.runtime.getIterator(exports_); + try { + while (true) { + var export_ = $__2.next(); + { + var replacement = ""; + if (export_.default) { + var identifier = export_.declaration.name || null; + source.replace(export_.range[0], export_.declaration.range[0] - 1, this.doDefaultExport(identifier)); + } else if (export_.specifiers) { + var reexport; + if (export_.source) { + reexport = export_.source.value; + } + { + var $__1 = traceur.runtime.getIterator(export_.specifiers); + try { + while (true) { + var specifier = $__1.next(); + { + replacement += this.doExportSpecifier(specifier.id.name, reexport); + } + } + } catch (e) { + if (!traceur.runtime.isStopIteration(e)) throw e; + } + } + source.replace(export_.range[0], export_.range[1], replacement); + } else if (export_.declaration) { + if (export_.declaration.type === "VariableDeclaration") { + var name = export_.declaration.declarations[0].id.name; + source.replace(export_.range[0], export_.declaration.range[0] - 1, ""); + replacement = this.doExportDeclaration(name); + source.replace(export_.range[1], export_.range[1], replacement); + } else if (export_.declaration.type === "FunctionDeclaration") { + var name = export_.declaration.id.name; + source.replace(export_.range[0], export_.declaration.range[0] - 1, ""); + replacement = this.doExportDeclaration(name); + source.replace(export_.range[1] + 1, export_.range[1] + 1, replacement); + } else if (export_.declaration.type === "Identifier") { + var name = export_.declaration.name; + replacement = this.doExportDeclaration(name); + source.replace(export_.range[0], export_.range[1] - 1, replacement); + } + } + } + } + } catch (e) { + if (!traceur.runtime.isStopIteration(e)) throw e; + } + } + }, + indentLines: function() { + var indent = arguments[0] !== (void 0) ? arguments[0]: " "; + var innerLines = this.source.toString().split("\n"); + var inner = innerLines.reduce(function(acc, item) { + if (item === "") return acc + "\n"; + return acc + indent + item + "\n"; + }, ""); + return inner.replace(/\s+$/, ""); + } + }, {}); + return $AbstractCompiler; +}(); +module.exports = AbstractCompiler; + + +},{"./compile_error":5,"./utils":11}],3:[function(require,module,exports){ +"use strict"; +var $__superDescriptor = function(proto, name) { + if (!proto) throw new TypeError('super is null'); + return Object.getPropertyDescriptor(proto, name); +}, $__superCall = function(self, proto, name, args) { + var descriptor = $__superDescriptor(proto, name); + if (descriptor) { + if ('value'in descriptor) return descriptor.value.apply(self, args); + if (descriptor.get) return descriptor.get.call(self).apply(self, args); + } + throw new TypeError("Object has no method '" + name + "'."); +}, $__getProtoParent = function(superClass) { + if (typeof superClass === 'function') { + var prototype = superClass.prototype; + if (Object(prototype) === prototype || prototype === null) return superClass.prototype; + } + if (superClass === null) return null; + throw new TypeError(); +}, $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClass = function(object, staticObject, protoParent, superClass, hasConstructor) { + var ctor = object.constructor; + if (typeof superClass === 'function') ctor.__proto__ = superClass; + if (!hasConstructor && protoParent === null) ctor = object.constructor = function() {}; + var descriptors = $__getDescriptors(object); + descriptors.constructor.enumerable = false; + ctor.prototype = Object.create(protoParent, descriptors); + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var AbstractCompiler = require("./abstract_compiler"); +var SourceModifier = require("./source_modifier"); +var AMDCompiler = function($__super) { + 'use strict'; + var $__proto = $__getProtoParent($__super); + var $AMDCompiler = ($__createClass)({ + constructor: function() { + $__superCall(this, $__proto, "constructor", arguments); + }, + stringify: function() { + var string = this.string.toString(); + this.source = new SourceModifier(string); + this.map = []; + var out = this.buildPreamble(this.exports.length > 0); + this.buildImports(); + this.buildExports(); + out += this.indentLines(" "); + out += "\n });"; + return out; + }, + buildPreamble: function(hasExports) { + var out = "", dependencyNames = this.dependencyNames; + if (hasExports) dependencyNames.push("exports"); + out += "define("; + if (this.moduleName) out += ("\"" + this.moduleName + "\", "); + out += "\n ["; + var idx; + for (idx = 0; idx < dependencyNames.length; idx++) { + var name = dependencyNames[idx]; + out += ("\"" + name + "\""); + if (!(idx === dependencyNames.length - 1)) out += ","; + } + out += "],\n function("; + for (idx = 0; idx < dependencyNames.length; idx++) { + if (dependencyNames[idx] === "exports") { + out += "__exports__"; + } else { + out += ("__dependency" + (idx + 1) + "__"); + this.map[dependencyNames[idx]] = idx + 1; + } + if (!(idx === dependencyNames.length - 1)) out += ", "; + } + out += ") {\n"; + out += ' "use strict";\n'; + return out; + }, + doModuleImport: function(name, dependencyName, idx) { + return ("var " + name + " = __dependency" + this.map[dependencyName] + "__;\n"); + }, + doBareImport: function(name) { + return ""; + }, + doDefaultImport: function(name, dependencyName, idx) { + if (this.options.compatFix === true) { + return ("var " + name + " = __dependency" + this.map[dependencyName] + "__[\"default\"] || __dependency" + this.map[dependencyName] + "__;\n"); + } else { + return ("var " + name + " = __dependency" + this.map[dependencyName] + "__[\"default\"];\n"); + } + }, + doNamedImport: function(name, dependencyName, alias) { + return ("var " + alias + " = __dependency" + this.map[dependencyName] + "__." + name + ";\n"); + }, + doExportSpecifier: function(name, reexport) { + if (reexport) { + return ("__exports__." + name + " = __dependency" + this.map[reexport] + "__." + name + ";\n"); + } + return ("__exports__." + name + " = " + name + ";\n"); + }, + doExportDeclaration: function(name) { + return ("\n__exports__." + name + " = " + name + ";"); + }, + doDefaultExport: function() { + return "__exports__[\"default\"] = "; + }, + doImportSpecifiers: function(import_, idx) { + var dependencyName = import_.source.value; + var replacement = ""; + { + var $__1 = traceur.runtime.getIterator(import_.specifiers); + try { + while (true) { + var specifier = $__1.next(); + { + var alias = specifier.name ? specifier.name.name: specifier.id.name; + replacement += this.doNamedImport(specifier.id.name, dependencyName, alias); + } + } + } catch (e) { + if (!traceur.runtime.isStopIteration(e)) throw e; + } + } + return replacement; + } + }, {}, $__proto, $__super, false); + return $AMDCompiler; +}(AbstractCompiler); +module.exports = AMDCompiler; + + +},{"./abstract_compiler":2,"./source_modifier":10}],4:[function(require,module,exports){ +"use strict"; +var $__superDescriptor = function(proto, name) { + if (!proto) throw new TypeError('super is null'); + return Object.getPropertyDescriptor(proto, name); +}, $__superCall = function(self, proto, name, args) { + var descriptor = $__superDescriptor(proto, name); + if (descriptor) { + if ('value'in descriptor) return descriptor.value.apply(self, args); + if (descriptor.get) return descriptor.get.call(self).apply(self, args); + } + throw new TypeError("Object has no method '" + name + "'."); +}, $__getProtoParent = function(superClass) { + if (typeof superClass === 'function') { + var prototype = superClass.prototype; + if (Object(prototype) === prototype || prototype === null) return superClass.prototype; + } + if (superClass === null) return null; + throw new TypeError(); +}, $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClass = function(object, staticObject, protoParent, superClass, hasConstructor) { + var ctor = object.constructor; + if (typeof superClass === 'function') ctor.__proto__ = superClass; + if (!hasConstructor && protoParent === null) ctor = object.constructor = function() {}; + var descriptors = $__getDescriptors(object); + descriptors.constructor.enumerable = false; + ctor.prototype = Object.create(protoParent, descriptors); + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var AbstractCompiler = require("./abstract_compiler"); +var SourceModifier = require("./source_modifier"); +var string = require("./utils").string; +var SAFE_WARN_NAME = "__es6_transpiler_warn__"; +var SAFE_WARN_SOURCE = string.ltrim(string.unindent(("\n function " + SAFE_WARN_NAME + "(warning) {\n if (typeof console === 'undefined') {\n } else if (typeof console.warn === \"function\") {\n console.warn(warning);\n } else if (typeof console.log === \"function\") {\n console.log(warning);\n }\n }"))); +var MODULE_OBJECT_BUILDER_NAME = "__es6_transpiler_build_module_object__"; +var MODULE_OBJECT_BUILDER_SOURCE = string.ltrim(string.unindent(("\n function " + MODULE_OBJECT_BUILDER_NAME + "(name, imported) {\n var moduleInstanceObject = Object.create ? Object.create(null) : {};\n if (typeof imported === \"function\") {\n " + SAFE_WARN_NAME + "(\"imported module '\"+name+\"' exported a function - this may not work as expected\");\n }\n for (var key in imported) {\n if (Object.prototype.hasOwnProperty.call(imported, key)) {\n moduleInstanceObject[key] = imported[key];\n }\n }\n if (Object.freeze) {\n Object.freeze(moduleInstanceObject);\n }\n return moduleInstanceObject;\n }"))); +var CJSCompiler = function($__super) { + 'use strict'; + var $__proto = $__getProtoParent($__super); + var $CJSCompiler = ($__createClass)({ + constructor: function() { + $__superCall(this, $__proto, "constructor", arguments); + }, + stringify: function() { + var string = this.string.toString(); + this.source = new SourceModifier(string); + this.prelude = []; + this.buildImports(); + this.buildExports(); + var out = "\"use strict\";\n"; + { + var $__1 = traceur.runtime.getIterator(this.prelude); + try { + while (true) { + var source = $__1.next(); + { + out += source + "\n"; + } + } + } catch (e) { + if (!traceur.runtime.isStopIteration(e)) throw e; + } + } + out += this.source.toString(); + out = out.trim(); + return out; + }, + doModuleImport: function(name, dependencyName, idx) { + this.ensureHasModuleObjectBuilder(); + return ("var " + name + " = " + MODULE_OBJECT_BUILDER_NAME + "(\"" + name + "\", require(\"" + dependencyName + "\"));\n"); + }, + ensureHasModuleObjectBuilder: function() { + this.ensureHasSafeWarn(); + this.ensureInPrelude(MODULE_OBJECT_BUILDER_NAME, MODULE_OBJECT_BUILDER_SOURCE); + }, + ensureHasSafeWarn: function() { + this.ensureInPrelude(SAFE_WARN_NAME, SAFE_WARN_SOURCE); + }, + ensureInPrelude: function(name, source) { + if (!this.prelude[name]) { + this.prelude[name] = true; + this.prelude.push(source); + } + }, + doBareImport: function(name) { + return ("require(\"" + name + "\");"); + }, + doDefaultImport: function(name, dependencyName, idx) { + if (this.options.compatFix === true) { + return ("var " + name + " = require(\"" + dependencyName + "\")[\"default\"] || require(\"" + dependencyName + "\");\n"); + } else { + return ("var " + name + " = require(\"" + dependencyName + "\")[\"default\"];\n"); + } + }, + doNamedImport: function(name, dependencyName, alias) { + return ("var " + alias + " = require(\"" + dependencyName + "\")." + name + ";\n"); + }, + doExportSpecifier: function(name, reexport) { + if (reexport) { + return ("exports." + name + " = require(\"" + reexport + "\")." + name + ";\n"); + } + return ("exports." + name + " = " + name + ";\n"); + }, + doExportDeclaration: function(name) { + return ("\nexports." + name + " = " + name + ";"); + }, + doDefaultExport: function() { + return "exports[\"default\"] = "; + }, + doImportSpecifiers: function(import_, idx) { + var dependencyName = import_.source.value; + var replacement = ""; + { + var $__2 = traceur.runtime.getIterator(import_.specifiers); + try { + while (true) { + var specifier = $__2.next(); + { + var alias = specifier.name ? specifier.name.name: specifier.id.name; + replacement += this.doNamedImport(specifier.id.name, dependencyName, alias); + } + } + } catch (e) { + if (!traceur.runtime.isStopIteration(e)) throw e; + } + } + return replacement; + } + }, {}, $__proto, $__super, false); + return $CJSCompiler; +}(AbstractCompiler); +module.exports = CJSCompiler; + + +},{"./abstract_compiler":2,"./source_modifier":10,"./utils":11}],5:[function(require,module,exports){ +"use strict"; +var $__superDescriptor = function(proto, name) { + if (!proto) throw new TypeError('super is null'); + return Object.getPropertyDescriptor(proto, name); +}, $__superCall = function(self, proto, name, args) { + var descriptor = $__superDescriptor(proto, name); + if (descriptor) { + if ('value'in descriptor) return descriptor.value.apply(self, args); + if (descriptor.get) return descriptor.get.call(self).apply(self, args); + } + throw new TypeError("Object has no method '" + name + "'."); +}, $__getProtoParent = function(superClass) { + if (typeof superClass === 'function') { + var prototype = superClass.prototype; + if (Object(prototype) === prototype || prototype === null) return superClass.prototype; + } + if (superClass === null) return null; + throw new TypeError(); +}, $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClass = function(object, staticObject, protoParent, superClass, hasConstructor) { + var ctor = object.constructor; + if (typeof superClass === 'function') ctor.__proto__ = superClass; + if (!hasConstructor && protoParent === null) ctor = object.constructor = function() {}; + var descriptors = $__getDescriptors(object); + descriptors.constructor.enumerable = false; + ctor.prototype = Object.create(protoParent, descriptors); + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var CompileError = function($__super) { + 'use strict'; + var $__proto = $__getProtoParent($__super); + var $CompileError = ($__createClass)({constructor: function() { + $__superCall(this, $__proto, "constructor", arguments); + }}, {}, $__proto, $__super, false); + return $CompileError; +}(Error); +module.exports = CompileError; + + +},{}],6:[function(require,module,exports){ +"use strict"; +var $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClassNoExtends = function(object, staticObject) { + var ctor = object.constructor; + Object.defineProperty(object, 'constructor', {enumerable: false}); + ctor.prototype = object; + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var AMDCompiler = require("./amd_compiler"); +var YUICompiler = require("./yui_compiler"); +var CJSCompiler = require("./cjs_compiler"); +var GlobalsCompiler = require("./globals_compiler"); +var Parser = require("./parser"); +var Unique = require("./utils").Unique; +var Compiler = function() { + 'use strict'; + var $Compiler = ($__createClassNoExtends)({ + constructor: function(string, moduleName, options) { + if (moduleName == null) { + moduleName = null; + } + if (options == null) { + options = {}; + } + this.string = string; + this.moduleName = moduleName; + this.options = options; + this.inBlockComment = false; + this.reExportUnique = new Unique('reexport'); + this.parse(); + }, + parse: function() { + var parser = new Parser(this.string); + this.imports = parser.imports; + this.exports = parser.exports; + this.exportDefault = parser.exportDefault; + this.directives = parser.directives; + }, + toAMD: function() { + return new AMDCompiler(this, this.options).stringify(); + }, + toYUI: function() { + return new YUICompiler(this, this.options).stringify(); + }, + toCJS: function() { + return new CJSCompiler(this, this.options).stringify(); + }, + toGlobals: function() { + return new GlobalsCompiler(this, this.options).stringify(); + } + }, {}); + return $Compiler; +}(); +module.exports = Compiler; + + +},{"./amd_compiler":3,"./cjs_compiler":4,"./globals_compiler":7,"./parser":9,"./utils":11,"./yui_compiler":12}],7:[function(require,module,exports){ +"use strict"; +var $__superDescriptor = function(proto, name) { + if (!proto) throw new TypeError('super is null'); + return Object.getPropertyDescriptor(proto, name); +}, $__superCall = function(self, proto, name, args) { + var descriptor = $__superDescriptor(proto, name); + if (descriptor) { + if ('value'in descriptor) return descriptor.value.apply(self, args); + if (descriptor.get) return descriptor.get.call(self).apply(self, args); + } + throw new TypeError("Object has no method '" + name + "'."); +}, $__getProtoParent = function(superClass) { + if (typeof superClass === 'function') { + var prototype = superClass.prototype; + if (Object(prototype) === prototype || prototype === null) return superClass.prototype; + } + if (superClass === null) return null; + throw new TypeError(); +}, $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClass = function(object, staticObject, protoParent, superClass, hasConstructor) { + var ctor = object.constructor; + if (typeof superClass === 'function') ctor.__proto__ = superClass; + if (!hasConstructor && protoParent === null) ctor = object.constructor = function() {}; + var descriptors = $__getDescriptors(object); + descriptors.constructor.enumerable = false; + ctor.prototype = Object.create(protoParent, descriptors); + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var AbstractCompiler = require("./abstract_compiler"); +var SourceModifier = require("./source_modifier"); +var GlobalsCompiler = function($__super) { + 'use strict'; + var $__proto = $__getProtoParent($__super); + var $GlobalsCompiler = ($__createClass)({ + constructor: function() { + $__superCall(this, $__proto, "constructor", arguments); + }, + stringify: function() { + var string = this.string.toString(); + this.source = new SourceModifier(string); + this.map = []; + var out = this.buildPreamble(this.exports.length > 0); + this.buildImports(); + this.buildExports(); + if (!this.options.imports) this.options.imports = {}; + if (!this.options.global) this.options.global = "window"; + out += this.indentLines(); + out += "\n})"; + out += this.buildSuffix(); + out += ";"; + return out; + }, + buildPreamble: function() { + var out = "", dependencyNames = this.dependencyNames; + out += "(function("; + if (this.exports.length > 0) { + out += "__exports__"; + if (this.dependencyNames.length > 0) { + out += ', '; + } + } + for (var idx = 0; idx < dependencyNames.length; idx++) { + out += ("__dependency" + (idx + 1) + "__"); + this.map[dependencyNames[idx]] = idx + 1; + if (!(idx === dependencyNames.length - 1)) out += ", "; + } + out += ") {\n"; + out += ' "use strict";\n'; + return out; + }, + buildSuffix: function() { + var dependencyNames = this.dependencyNames; + var out = "("; + if (this.exports.length > 0) { + if (this.options.into) { + out += (this.options.global + "." + this.options.into + " = {}"); + } else { + out += this.options.global; + } + if (this.dependencyNames.length > 0) { + out += ', '; + } + } + for (var idx = 0; idx < dependencyNames.length; idx++) { + var name = dependencyNames[idx]; + out += (this.options.global + "." + (this.options.imports[name] || name)); + if (!(idx === dependencyNames.length - 1)) out += ", "; + } + out += ")"; + return out; + }, + doModuleImport: function(name, dependencyName, idx) { + return ("var " + name + " = __dependency" + this.map[dependencyName] + "__;\n"); + }, + doBareImport: function(name) { + return ""; + }, + doDefaultImport: function(name, dependencyName, idx) { + return ("var " + name + " = __dependency" + this.map[dependencyName] + "__;\n"); + }, + doNamedImport: function(name, dependencyName, alias) { + return ("var " + alias + " = __dependency" + this.map[dependencyName] + "__." + name + ";\n"); + }, + doExportSpecifier: function(name, reexport) { + if (reexport) { + return ("__exports__." + name + " = __dependency" + this.map[reexport] + "__." + name + ";\n"); + } + return ("__exports__." + name + " = " + name + ";\n"); + }, + doExportDeclaration: function(name) { + return ("\n__exports__." + name + " = " + name + ";"); + }, + doDefaultExport: function(identifier) { + if (identifier === null) { + throw new Error("The globals compiler does not support anonymous default exports."); + } + return ("__exports__." + identifier + " = "); + }, + doImportSpecifiers: function(import_, idx) { + var dependencyName = import_.source.value; + var replacement = ""; + { + var $__1 = traceur.runtime.getIterator(import_.specifiers); + try { + while (true) { + var specifier = $__1.next(); + { + var alias = specifier.name ? specifier.name.name: specifier.id.name; + replacement += this.doNamedImport(specifier.id.name, dependencyName, alias); + } + } + } catch (e) { + if (!traceur.runtime.isStopIteration(e)) throw e; + } + } + return replacement; + } + }, {}, $__proto, $__super, false); + return $GlobalsCompiler; +}(AbstractCompiler); +module.exports = GlobalsCompiler; + + +},{"./abstract_compiler":2,"./source_modifier":10}],8:[function(require,module,exports){ +"use strict"; +var Compiler = require("./compiler"); +var AbstractCompiler = require("./abstract_compiler"); +var AmdCompiler = require("./amd_compiler"); +var YuiCompiler = require("./yui_compiler"); +var CjsCompiler = require("./cjs_compiler"); +var GlobalsCompiler = require("./globals_compiler"); +var SourceModifier = require("./source_modifier"); +exports.Compiler = Compiler; +exports.AbstractCompiler = AbstractCompiler; +exports.AmdCompiler = AmdCompiler; +exports.YuiCompiler = YuiCompiler; +exports.CjsCompiler = CjsCompiler; +exports.GlobalsCompiler = GlobalsCompiler; +exports.SourceModifier = SourceModifier; + + +},{"./abstract_compiler":2,"./amd_compiler":3,"./cjs_compiler":4,"./compiler":6,"./globals_compiler":7,"./source_modifier":10,"./yui_compiler":12}],9:[function(require,module,exports){ +"use strict"; +var $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClassNoExtends = function(object, staticObject) { + var ctor = object.constructor; + Object.defineProperty(object, 'constructor', {enumerable: false}); + ctor.prototype = object; + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var esparse = require("esprima").parse; +var LITERAL = 'Literal'; +var Parser = function() { + 'use strict'; + var $Parser = ($__createClassNoExtends)({ + constructor: function(script) { + this.parse(script); + }, + parse: function(script) { + this.imports = []; + this.exports = []; + this.directives = []; + this.exportDefault = undefined; + this.walk(esparse(script, { + range: true, + comment: true + })); + }, + walk: function(node) { + if (node.type) { + var processor = this['process' + node.type]; + if (processor) { + var result = processor.call(this, node); + if (result === false) { + return; + } + } + } + if (node.body && node.body.length > 0) { + node.body.forEach(function(child) { + child.parent = node; + this.walk(child); + }.bind(this)); + } + if (node.comments && node.type === "Program") { + { + var $__1 = traceur.runtime.getIterator(node.comments); + try { + while (true) { + var comment = $__1.next(); + { + if (comment.value.indexOf("transpile:") !== - 1) { + this.directives.push(comment); + } + } + } + } catch (e) { + if (!traceur.runtime.isStopIteration(e)) throw e; + } + } + } + }, + processImportDeclaration: function(node) { + var $__2 = node, kind = $__2.kind, source = $__2.source; + if (source.type !== LITERAL || typeof source.value !== 'string') { + throw new Error('invalid module source: ' + source.value); + } + switch (kind) { + case 'named': + this.processNamedImportDeclaration(node); + break; + case "default": + this.processDefaultImportDeclaration(node); + break; + case undefined: + this.processNamedImportDeclaration(node); + break; + default: + throw new Error('unknown import kind: ' + kind); + } + }, + processNamedImportDeclaration: function(node) { + this.imports.push(node); + }, + processDefaultImportDeclaration: function(node) { + if (node.specifiers.length !== 1) { + throw new Error('expected one specifier for default import, got ' + specifiers.length); + } + this.imports.push(node); + }, + processExportDeclaration: function(node) { + if (!node.declaration && !node.specifiers) { + throw new Error('expected declaration or specifiers after `export` keyword'); + } + this.exports.push(node); + }, + processModuleDeclaration: function(node) { + this.imports.push(node); + } + }, {}); + return $Parser; +}(); +module.exports = Parser; + + +},{"esprima":1}],10:[function(require,module,exports){ +"use strict"; +var $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClassNoExtends = function(object, staticObject) { + var ctor = object.constructor; + Object.defineProperty(object, 'constructor', {enumerable: false}); + ctor.prototype = object; + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var SourceModifier = function() { + 'use strict'; + var $SourceModifier = ($__createClassNoExtends)({ + constructor: function(source) { + this.source = source; + this.rangeOps = []; + }, + mapIndex: function(index) { + for (var i = 0; i < this.rangeOps.length; i++) { + var curOp = this.rangeOps[i]; + if (curOp.start >= index) continue; + if (curOp.end <= index) { + index += curOp.diff; + continue; + } + throw 'Source location ' + index + ' has already been transformed!'; + } + return index; + }, + replace: function(start, end, replacement) { + var diff = replacement.length - (end - start + 1); + start = this.mapIndex(start); + end = this.mapIndex(end); + this.source = this.source.substr(0, start) + replacement + this.source.substr(end + 1); + this.rangeOps.push({ + start: start, + end: end, + diff: diff + }); + }, + getRange: function(start, end) { + return this.source.substr(this.mapIndex(start), this.mapIndex(end)); + }, + toString: function() { + return this.source; + } + }, {}); + return $SourceModifier; +}(); +module.exports = SourceModifier; + + +},{}],11:[function(require,module,exports){ +"use strict"; +var $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClassNoExtends = function(object, staticObject) { + var ctor = object.constructor; + Object.defineProperty(object, 'constructor', {enumerable: false}); + ctor.prototype = object; + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var hasOwnProp = {}.hasOwnProperty; +function isEmpty(object) { + for (var foo in object) { + if (Object.prototype.hasOwnProperty.call(object, foo)) { + return false; + } + } + return true; +} +function uniq(array) { + var result = []; + for (var i = 0; i < array.length; i++) { + var item = array[i]; + if (result.indexOf(item) === - 1) { + result.push(item); + } + } + return result; +} +var array = {uniq: uniq}; +function forEach(enumerable, callback) { + if (enumerable !== null && enumerable !== undefined && typeof enumerable.forEach === 'function') { + enumerable.forEach(callback); + return; + } + for (var key in enumerable) { + if (hasOwnProp.call(enumerable, key)) { + callback(enumerable[key], key); + } + } +} +function isWhitespace(str) { + return !str || /^\s*$/.test(str); +} +function indent(lines, level) { + var indentString = arguments[2] !== (void 0) ? arguments[2]: ' '; + return lines.map(function(line) { + if (!isWhitespace(line)) { + for (var i = 0; i < level; i++) { + line = indentString + line; + } + } + return line; + }); +} +var WHITESPACE_ONLY = /^\s*$/; +var LEADING_WHITESPACE = /^\s*/; +function unindent(string) { + var minIndent = null; + var lines = string.split('\n'); + { + var $__1 = traceur.runtime.getIterator(lines); + try { + while (true) { + var line = $__1.next(); + { + if (!WHITESPACE_ONLY.test(line)) { + var match = line.match(LEADING_WHITESPACE); + if (match) { + if (minIndent !== null) { + minIndent = Math.min(match[0].length, minIndent); + } else { + minIndent = match[0].length; + } + } + } + } + } + } catch (e) { + if (!traceur.runtime.isStopIteration(e)) throw e; + } + } + return lines.map((function(line) { + return line.slice(minIndent); + })).join('\n'); +} +function ltrim(string) { + return string.replace(LEADING_WHITESPACE, ''); +} +var string = { + indent: indent, + unindent: unindent, + ltrim: ltrim +}; +var Unique = function() { + 'use strict'; + var $Unique = ($__createClassNoExtends)({ + constructor: function(prefix) { + this.prefix = prefix; + this.index = 1; + }, + next: function() { + return ['__', this.prefix, this.index++, '__'].join(''); + } + }, {}); + return $Unique; +}(); +exports.isEmpty = isEmpty; +exports.Unique = Unique; +exports.array = array; +exports.forEach = forEach; +exports.string = string; + + +},{}],12:[function(require,module,exports){ +"use strict"; +var $__superDescriptor = function(proto, name) { + if (!proto) throw new TypeError('super is null'); + return Object.getPropertyDescriptor(proto, name); +}, $__superCall = function(self, proto, name, args) { + var descriptor = $__superDescriptor(proto, name); + if (descriptor) { + if ('value'in descriptor) return descriptor.value.apply(self, args); + if (descriptor.get) return descriptor.get.call(self).apply(self, args); + } + throw new TypeError("Object has no method '" + name + "'."); +}, $__getProtoParent = function(superClass) { + if (typeof superClass === 'function') { + var prototype = superClass.prototype; + if (Object(prototype) === prototype || prototype === null) return superClass.prototype; + } + if (superClass === null) return null; + throw new TypeError(); +}, $__getDescriptors = function(object) { + var descriptors = {}, name, names = Object.getOwnPropertyNames(object); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + descriptors[name] = Object.getOwnPropertyDescriptor(object, name); + } + return descriptors; +}, $__createClass = function(object, staticObject, protoParent, superClass, hasConstructor) { + var ctor = object.constructor; + if (typeof superClass === 'function') ctor.__proto__ = superClass; + if (!hasConstructor && protoParent === null) ctor = object.constructor = function() {}; + var descriptors = $__getDescriptors(object); + descriptors.constructor.enumerable = false; + ctor.prototype = Object.create(protoParent, descriptors); + Object.defineProperties(ctor, $__getDescriptors(staticObject)); + return ctor; +}; +var AbstractCompiler = require("./abstract_compiler"); +var SourceModifier = require("./source_modifier"); +var YUICompiler = function($__super) { + 'use strict'; + var $__proto = $__getProtoParent($__super); + var $YUICompiler = ($__createClass)({ + constructor: function() { + $__superCall(this, $__proto, "constructor", arguments); + }, + stringify: function() { + var string = this.string.toString(); + this.source = new SourceModifier(string); + var out = this.buildPreamble(); + this.buildImports(); + this.buildExports(); + out += (this.indentLines(" ") + "\n return __exports__;\n}, \"@VERSION@\", " + this.buildMetas() + ");"); + return out; + }, + buildPreamble: function() { + var name = this.moduleName || "@NAME@"; + return ("YUI.add(\"" + name + "\", function(Y, NAME, __imports__, __exports__) {\n \"use strict\";\n"); + }, + buildMetas: function() { + return JSON.stringify({ + es: true, + requires: this.dependencyNames + }); + }, + doModuleImport: function(name, dependencyName, idx) { + return ("var " + name + " = __imports__[\"" + dependencyName + "\"];\n"); + }, + doBareImport: function(name) { + return ""; + }, + doDefaultImport: function(name, dependencyName, idx) { + if (this.options.compatFix === true) { + return ("var " + name + " = __imports__[\"" + dependencyName + "\"][\"default\"] || __imports__[\"" + dependencyName + "\"];\n"); + } else { + return ("var " + name + " = __imports__[\"" + dependencyName + "\"][\"default\"];\n"); + } + }, + doNamedImport: function(name, dependencyName, alias) { + var member = (name === 'default' ? '["default"]': '.' + name); + return ("var " + alias + " = __imports__[\"" + dependencyName + "\"]" + member + ";\n"); + }, + doExportSpecifier: function(name, reexport) { + if (reexport) { + return ("__exports__." + name + " = __imports__[\"" + reexport + "\"]." + name + ";\n"); + } + return ("__exports__." + name + " = " + name + ";\n"); + }, + doExportDeclaration: function(name) { + return ("\n__exports__." + name + " = " + name + ";"); + }, + doDefaultExport: function() { + return "__exports__[\"default\"] = "; + }, + doImportSpecifiers: function(import_, idx) { + var dependencyName = import_.source.value; + var replacement = ""; + { + var $__1 = traceur.runtime.getIterator(import_.specifiers); + try { + while (true) { + var specifier = $__1.next(); + { + var alias = specifier.name ? specifier.name.name: specifier.id.name; + replacement += this.doNamedImport(specifier.id.name, dependencyName, alias); + } + } + } catch (e) { + if (!traceur.runtime.isStopIteration(e)) throw e; + } + } + return replacement; + } + }, {}, $__proto, $__super, false); + return $YUICompiler; +}(AbstractCompiler); +module.exports = YUICompiler; + + +},{"./abstract_compiler":2,"./source_modifier":10}]},{},[8]) +(8) +}); +; + + diff --git a/lib/es6_module_transpiler/support/es6_node_runner.js b/lib/es6_module_transpiler/support/es6_node_runner.js new file mode 100644 index 00000000000..ba1ea3424e7 --- /dev/null +++ b/lib/es6_module_transpiler/support/es6_node_runner.js @@ -0,0 +1,22 @@ +(function(program, execJS) { execJS(program) })(function(module, exports, console) { + #{source} +}, function(program) { + var output, print = function(string) { + process.stdout.write('' + string); + }; + try { + result = program(); + if (typeof result == 'undefined' && result !== null) { + print('["ok"]'); + } else { + try { + print(JSON.stringify(['ok', result])); + } catch (err) { + print('["err"]'); + } + } + } catch (err) { + print(JSON.stringify(['err', '' + err])); + } +}); + diff --git a/lib/es6_module_transpiler/tilt.rb b/lib/es6_module_transpiler/tilt.rb new file mode 100644 index 00000000000..a24df56661d --- /dev/null +++ b/lib/es6_module_transpiler/tilt.rb @@ -0,0 +1,4 @@ +require 'tilt' +require 'es6_module_transpiler/tilt/es6_module_transpiler_template' + +Tilt.register Tilt::ES6ModuleTranspilerTemplate, 'es6' diff --git a/lib/es6_module_transpiler/tilt/es6_module_transpiler_template.rb b/lib/es6_module_transpiler/tilt/es6_module_transpiler_template.rb new file mode 100644 index 00000000000..0c46b1a0caa --- /dev/null +++ b/lib/es6_module_transpiler/tilt/es6_module_transpiler_template.rb @@ -0,0 +1,109 @@ +require 'execjs' + +module Tilt + class ES6ModuleTranspilerTemplate < Tilt::Template + self.default_mime_type = 'application/javascript' + + @mutex = Mutex.new + @ctx_init = Mutex.new + + def prepare + # intentionally left empty + # Tilt requires this method to be defined + end + + def self.create_new_context + ctx = V8::Context.new(timeout: 5000) + ctx.eval("module = {}; exports = {};"); + ctx.load("#{Rails.root}/lib/es6_module_transpiler/support/es6-module-transpiler.js") + ctx + end + + def self.v8 + return @ctx if @ctx + + # ensure we only init one of these + @ctx_init.synchronize do + return @ctx if @ctx + @ctx = create_new_context + end + + @ctx + end + + class JavaScriptError < StandardError + attr_accessor :message, :backtrace + + def initialize(message, backtrace) + @message = message + @backtrace = backtrace + end + + end + + def self.protect + rval = nil + @mutex.synchronize do + begin + rval = yield + # This may seem a bit odd, but we don't want to leak out + # objects that require locks on the v8 vm, to get a backtrace + # you need a lock, if this happens in the wrong spot you can + # deadlock a process + rescue V8::Error => e + raise JavaScriptError.new(e.message, e.backtrace) + end + end + rval + end + + def evaluate(scope, locals, &block) + return @output if @output + + klass = self.class + klass.protect do + @output = klass.v8.eval(generate_source(scope)) + end + @output + end + + private + + def transpiler_path + File.expand_path('../../support/es6-module-transpiler.js', __FILE__) + end + + def generate_source(scope) + "new module.exports.Compiler(#{::JSON.generate(data, quirks_mode: true)}, '#{module_name(scope.root_path, scope.logical_path)}', #{compiler_options}).#{compiler_method}()" + end + + def module_name(root_path, logical_path) + path = '' + if prefix = ES6ModuleTranspiler.lookup_prefix(File.join(root_path, logical_path)) + path = File.join(prefix, logical_path) + else + path = logical_path + end + + if ES6ModuleTranspiler.transform + path = ES6ModuleTranspiler.transform.call(path) + end + + path + end + + def compiler_method + type = { + amd: 'AMD', + cjs: 'CJS', + globals: 'Globals' + }[ES6ModuleTranspiler.compile_to.to_sym] + + "to#{type}" + end + + def compiler_options + ::JSON.generate(ES6ModuleTranspiler.compiler_options, quirks_mode: true) + end + end +end