/* Rollup.js v0.25.8 Sun Apr 03 2016 10:31:30 GMT-0400 (EDT) - commit 49e9fac201793b7590f70e8ece9434fb71605ee3 https://github.com/rollup/rollup Released under the MIT License. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : factory((global.rollup = {})); }(this, function (exports) { 'use strict'; var babelHelpers = {}; babelHelpers.classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var Promise = window.Promise; // TODO does this all work on windows? var absolutePath = /^(?:\/|(?:[A-Za-z]:)?[\\|\/])/; var relativePath = /^\.?\.\//; function isAbsolute(path) { return absolutePath.test(path); } function isRelative(path) { return relativePath.test(path); } function _basename(path) { return path.split(/(\/|\\)/).pop(); } function dirname(path) { var match = /(\/|\\)[^\/\\]*$/.exec(path); if (!match) return '.'; var dir = path.slice(0, -match[0].length); // If `dir` is the empty string, we're at root. return dir ? dir : '/'; } function extname(path) { var match = /\.[^\.]+$/.exec(_basename(path)); if (!match) return ''; return match[0]; } function resolve() { for (var _len = arguments.length, paths = Array(_len), _key = 0; _key < _len; _key++) { paths[_key] = arguments[_key]; } var resolvedParts = paths.shift().split(/[\/\\]/); paths.forEach(function (path) { if (isAbsolute(path)) { resolvedParts = path.split(/[\/\\]/); } else { var parts = path.split(/[\/\\]/); while (parts[0] === '.' || parts[0] === '..') { var part = parts.shift(); if (part === '..') { resolvedParts.pop(); } } resolvedParts.push.apply(resolvedParts, parts); } }); return resolvedParts.join('/'); // TODO windows... } var nope = function (method) { return 'Cannot use fs.' + method + ' inside browser'; }; var isFile = function () { return false; }; var readdirSync = nope('readdirSync'); var readFileSync = nope('readFileSync'); var writeFile = nope('writeFile'); var keys = Object.keys; function blank() { return Object.create(null); } function forOwn(object, func) { Object.keys(object).forEach(function (key) { return func(object[key], key); }); } function validateKeys(object, allowedKeys) { var actualKeys = keys(object); var i = actualKeys.length; while (i--) { var key = actualKeys[i]; if (allowedKeys.indexOf(key) === -1) { return new Error('Unexpected key \'' + key + '\' found, expected one of: ' + allowedKeys.join(', ')); } } } // this looks ridiculous, but it prevents sourcemap tooling from mistaking // this for an actual sourceMappingURL var SOURCEMAPPING_URL = 'sourceMa'; SOURCEMAPPING_URL += 'ppingURL'; var SOURCEMAPPING_URL$1 = SOURCEMAPPING_URL; var charToInteger$1 = {}; var integerToChar$1 = {}; 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split( '' ).forEach( function ( char, i ) { charToInteger$1[ char ] = i; integerToChar$1[ i ] = char; }); function encode$1$1 ( value ) { var result, i; if ( typeof value === 'number' ) { result = encodeInteger$1( value ); } else { result = ''; for ( i = 0; i < value.length; i += 1 ) { result += encodeInteger$1( value[i] ); } } return result; } function encodeInteger$1 ( num ) { var result = '', clamped; if ( num < 0 ) { num = ( -num << 1 ) | 1; } else { num <<= 1; } do { clamped = num & 31; num >>= 5; if ( num > 0 ) { clamped |= 32; } result += integerToChar$1[ clamped ]; } while ( num > 0 ); return result; } function Patch(start, end, content, original, storeName) { this.start = start; this.end = end; this.content = content; this.original = original; this.storeName = storeName; } Patch.prototype = { clone: function clone() { return new Patch(this.start, this.end, this.content, this.original, this.storeName); } }; var _btoa = undefined; if (typeof window !== 'undefined' && typeof window.btoa === 'function') { _btoa = window.btoa; } else if (typeof Buffer === 'function') { /* global Buffer */ _btoa = function (str) { return new Buffer(str).toString('base64'); }; } else { throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.'); } var btoa = _btoa; function SourceMap(properties) { this.version = 3; this.file = properties.file; this.sources = properties.sources; this.sourcesContent = properties.sourcesContent; this.names = properties.names; this.mappings = properties.mappings; } SourceMap.prototype = { toString: function toString() { return JSON.stringify(this); }, toUrl: function toUrl() { return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString()); } }; function guessIndent(code) { var lines = code.split('\n'); var tabbed = lines.filter(function (line) { return (/^\t+/.test(line) ); }); var spaced = lines.filter(function (line) { return (/^ {2,}/.test(line) ); }); if (tabbed.length === 0 && spaced.length === 0) { return null; } // More lines tabbed than spaced? Assume tabs, and // default to tabs in the case of a tie (or nothing // to go on) if (tabbed.length >= spaced.length) { return '\t'; } // Otherwise, we need to guess the multiple var min = spaced.reduce(function (previous, current) { var numSpaces = /^ +/.exec(current)[0].length; return Math.min(numSpaces, previous); }, Infinity); return new Array(min + 1).join(' '); } function encodeMappings(original, intro, patches, hires, sourcemapLocations, sourceIndex, offsets, names) { var rawLines = []; var generatedCodeLine = intro.split('\n').length - 1; var rawSegments = rawLines[generatedCodeLine] = []; var originalCharIndex = 0; var generatedCodeColumn = 0; var sourceCodeLine = 0; var sourceCodeColumn = 0; function addSegmentsUntil(end) { var first = true; while (originalCharIndex < end) { if (hires || first || sourcemapLocations[originalCharIndex]) { rawSegments.push({ generatedCodeLine: generatedCodeLine, generatedCodeColumn: generatedCodeColumn, sourceCodeLine: sourceCodeLine, sourceCodeColumn: sourceCodeColumn, sourceCodeName: -1, sourceIndex: sourceIndex }); } if (original[originalCharIndex] === '\n') { sourceCodeLine += 1; sourceCodeColumn = 0; generatedCodeLine += 1; rawLines[generatedCodeLine] = rawSegments = []; generatedCodeColumn = 0; } else { sourceCodeColumn += 1; generatedCodeColumn += 1; } originalCharIndex += 1; first = false; } } for (var i = 0; i < patches.length; i += 1) { var patch = patches[i]; var addSegmentForPatch = patch.storeName || patch.start > originalCharIndex; addSegmentsUntil(patch.start); if (addSegmentForPatch) { rawSegments.push({ generatedCodeLine: generatedCodeLine, generatedCodeColumn: generatedCodeColumn, sourceCodeLine: sourceCodeLine, sourceCodeColumn: sourceCodeColumn, sourceCodeName: patch.storeName ? names.indexOf(patch.original) : -1, sourceIndex: sourceIndex }); } var lines = patch.content.split('\n'); var lastLine = lines.pop(); if (lines.length) { generatedCodeLine += lines.length; rawLines[generatedCodeLine] = rawSegments = []; generatedCodeColumn = lastLine.length; } else { generatedCodeColumn += lastLine.length; } lines = patch.original.split('\n'); lastLine = lines.pop(); if (lines.length) { sourceCodeLine += lines.length; sourceCodeColumn = lastLine.length; } else { sourceCodeColumn += lastLine.length; } originalCharIndex = patch.end; } addSegmentsUntil(original.length); offsets.sourceIndex = offsets.sourceIndex || 0; offsets.sourceCodeLine = offsets.sourceCodeLine || 0; offsets.sourceCodeColumn = offsets.sourceCodeColumn || 0; offsets.sourceCodeName = offsets.sourceCodeName || 0; var encoded = rawLines.map(function (segments) { var generatedCodeColumn = 0; return segments.map(function (segment) { var arr = [segment.generatedCodeColumn - generatedCodeColumn, segment.sourceIndex - offsets.sourceIndex, segment.sourceCodeLine - offsets.sourceCodeLine, segment.sourceCodeColumn - offsets.sourceCodeColumn]; generatedCodeColumn = segment.generatedCodeColumn; offsets.sourceIndex = segment.sourceIndex; offsets.sourceCodeLine = segment.sourceCodeLine; offsets.sourceCodeColumn = segment.sourceCodeColumn; if (~segment.sourceCodeName) { arr.push(segment.sourceCodeName - offsets.sourceCodeName); offsets.sourceCodeName = segment.sourceCodeName; } return encode$1$1(arr); }).join(','); }).join(';'); return encoded; } function getRelativePath(from, to) { var fromParts = from.split(/[\/\\]/); var toParts = to.split(/[\/\\]/); fromParts.pop(); // get dirname while (fromParts[0] === toParts[0]) { fromParts.shift(); toParts.shift(); } if (fromParts.length) { var i = fromParts.length; while (i--) { fromParts[i] = '..'; } } return fromParts.concat(toParts).join('/'); } var toString = Object.prototype.toString; function isObject(thing) { return toString.call(thing) === '[object Object]'; } var warned = false; function MagicString(string) { var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; Object.defineProperties(this, { original: { writable: true, value: string }, outro: { writable: true, value: '' }, intro: { writable: true, value: '' }, patches: { writable: true, value: [] }, filename: { writable: true, value: options.filename }, indentExclusionRanges: { writable: true, value: options.indentExclusionRanges }, sourcemapLocations: { writable: true, value: {} }, storedNames: { writable: true, value: {} }, indentStr: { writable: true, value: guessIndent(string) } }); } MagicString.prototype = { addSourcemapLocation: function addSourcemapLocation(char) { this.sourcemapLocations[char] = true; }, append: function append(content) { if (typeof content !== 'string') throw new TypeError('outro content must be a string'); this.outro += content; return this; }, clone: function clone() { var cloned = new MagicString(this.original, { filename: this.filename }); cloned.patches = this.patches.map(function (patch) { return patch.clone(); }); if (this.indentExclusionRanges) { cloned.indentExclusionRanges = typeof this.indentExclusionRanges[0] === 'number' ? [this.indentExclusionRanges[0], this.indentExclusionRanges[1]] : this.indentExclusionRanges.map(function (range) { return [range.start, range.end]; }); } Object.keys(this.sourcemapLocations).forEach(function (loc) { cloned.sourcemapLocations[loc] = true; }); return cloned; }, generateMap: function generateMap(options) { options = options || {}; var names = Object.keys(this.storedNames); return new SourceMap({ file: options.file ? options.file.split(/[\/\\]/).pop() : null, sources: [options.source ? getRelativePath(options.file || '', options.source) : null], sourcesContent: options.includeContent ? [this.original] : [null], names: names, mappings: this.getMappings(options.hires, 0, {}, names) }); }, getIndentString: function getIndentString() { return this.indentStr === null ? '\t' : this.indentStr; }, getMappings: function getMappings(hires, sourceIndex, offsets, names) { return encodeMappings(this.original, this.intro, this.patches, hires, this.sourcemapLocations, sourceIndex, offsets, names); }, indent: function indent(indentStr, options) { var _this = this; var pattern = /^[^\r\n]/gm; if (isObject(indentStr)) { options = indentStr; indentStr = undefined; } indentStr = indentStr !== undefined ? indentStr : this.indentStr || '\t'; if (indentStr === '') return this; // noop options = options || {}; // Process exclusion ranges var isExcluded = {}; if (options.exclude) { var exclusions = typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude; exclusions.forEach(function (exclusion) { for (var i = exclusion[0]; i < exclusion[1]; i += 1) { isExcluded[i] = true; } }); } var shouldIndentNextCharacter = options.indentStart !== false; var replacer = function replacer(match) { if (shouldIndentNextCharacter) return '' + indentStr + match; shouldIndentNextCharacter = true; return match; }; this.intro = this.intro.replace(pattern, replacer); var charIndex = 0; var patchIndex = 0; var indentUntil = function indentUntil(end) { while (charIndex < end) { if (!isExcluded[charIndex]) { var char = _this.original[charIndex]; if (char === '\n') { shouldIndentNextCharacter = true; } else if (char !== '\r' && shouldIndentNextCharacter) { _this.patches.splice(patchIndex, 0, new Patch(charIndex, charIndex, indentStr, '', false)); shouldIndentNextCharacter = false; patchIndex += 1; } } charIndex += 1; } }; for (; patchIndex < this.patches.length; patchIndex += 1) { // can't cache this.patches.length, it may change var patch = this.patches[patchIndex]; indentUntil(patch.start); if (!isExcluded[charIndex]) { patch.content = patch.content.replace(pattern, replacer); if (patch.content.length) { shouldIndentNextCharacter = patch.content[patch.content.length - 1] === '\n'; } } charIndex = patch.end; } indentUntil(this.original.length); this.outro = this.outro.replace(pattern, replacer); return this; }, insert: function insert(index, content) { if (typeof content !== 'string') { throw new TypeError('inserted content must be a string'); } this.patch(index, index, content); return this; }, // get current location of character in original string locate: function locate(character) { throw new Error('magicString.locate is deprecated'); }, locateOrigin: function locateOrigin(character) { throw new Error('magicString.locateOrigin is deprecated'); }, overwrite: function overwrite(start, end, content, storeName) { if (typeof content !== 'string') { throw new TypeError('replacement content must be a string'); } this.patch(start, end, content, storeName); return this; }, patch: function patch(start, end, content, storeName) { var original = this.original.slice(start, end); if (storeName) this.storedNames[original] = true; var i = this.patches.length; while (i--) { var previous = this.patches[i]; // TODO can we tidy this up? // if this completely covers previous patch, remove it if (start !== end && start <= previous.start && end >= previous.end) { // unless it's an insert at the start if (previous.start === previous.end && previous.start === start) break; // or it's an insert at the end if (previous.start === previous.end && previous.end === end) continue; this.patches.splice(i, 1); } // if it overlaps, throw error else if (start < previous.end && end > previous.start) { // special case – it's okay to remove overlapping ranges if (!previous.content.length && !content.length) { previous.start = Math.min(start, previous.start); previous.end = Math.max(end, previous.end); return; } throw new Error('Cannot overwrite the same content twice: \'' + original + '\''); } // if this precedes previous patch, stop search else if (start >= previous.end) { break; } } var patch = new Patch(start, end, content, original, storeName); this.patches.splice(i + 1, 0, patch); return patch; }, prepend: function prepend(content) { if (typeof content !== 'string') throw new TypeError('outro content must be a string'); this.intro = content + this.intro; return this; }, remove: function remove(start, end) { if (start < 0 || end > this.original.length) { throw new Error('Character is out of bounds'); } this.patch(start, end, ''); return this; }, replace: function replace(start, end, content) { if (!warned) { console.warn('magicString.replace(...) is deprecated. Use magicString.overwrite(...) instead'); warned = true; } return this.overwrite(start, end, content); }, slice: function slice(start) { var end = arguments.length <= 1 || arguments[1] === undefined ? this.original.length : arguments[1]; while (start < 0) { start += this.original.length; }while (end < 0) { end += this.original.length; }var firstPatchIndex = 0; var lastPatchIndex = this.patches.length; while (lastPatchIndex--) { var patch = this.patches[lastPatchIndex]; if (end >= patch.start && end < patch.end) throw new Error('Cannot use replaced characters (' + start + ', ' + end + ') as slice anchors'); // TODO this is weird, rewrite it if (patch.start > end) continue; break; } for (firstPatchIndex = 0; firstPatchIndex <= lastPatchIndex; firstPatchIndex += 1) { var patch = this.patches[firstPatchIndex]; if (start > patch.start && start <= patch.end) throw new Error('Cannot use replaced characters (' + start + ', ' + end + ') as slice anchors'); if (start <= patch.start) { break; } } var result = ''; var lastIndex = start; for (var i = firstPatchIndex; i <= lastPatchIndex; i += 1) { var patch = this.patches[i]; result += this.original.slice(lastIndex, patch.start); result += patch.content; lastIndex = patch.end; } result += this.original.slice(lastIndex, end); return result; }, snip: function snip(start, end) { var clone = this.clone(); clone.remove(0, start); clone.remove(end, clone.original.length); return clone; }, toString: function toString() { return this.intro + this.slice(0, this.original.length) + this.outro; }, trimLines: function trimLines() { return this.trim('[\\r\\n]'); }, trim: function trim(charType) { return this.trimStart(charType).trimEnd(charType); }, trimEnd: function trimEnd(charType) { var rx = new RegExp((charType || '\\s') + '+$'); this.outro = this.outro.replace(rx, ''); if (this.outro.length) return this; var charIndex = this.original.length; var i = this.patches.length; while (i--) { var patch = this.patches[i]; if (charIndex > patch.end) { var _slice = this.original.slice(patch.end, charIndex); var _match = rx.exec(_slice); if (_match) { this.patch(charIndex - _match[0].length, charIndex, ''); } if (!_match || _match[0].length < _slice.length) { // there is non-whitespace after the patch return this; } } patch.content = patch.content.replace(rx, ''); if (patch.content) return this; charIndex = patch.start; } var slice = this.original.slice(0, charIndex); var match = rx.exec(slice); if (match) this.patch(charIndex - match[0].length, charIndex, ''); return this; }, trimStart: function trimStart(charType) { var rx = new RegExp('^' + (charType || '\\s') + '+'); this.intro = this.intro.replace(rx, ''); if (this.intro.length) return this; var charIndex = 0; for (var i = 0; i < this.patches.length; i += 1) { var patch = this.patches[i]; if (charIndex < patch.start) { var _slice2 = this.original.slice(charIndex, patch.start); var _match2 = rx.exec(_slice2); if (_match2) this.patch(charIndex, charIndex + _match2[0].length, ''); if (!_match2 || _match2[0].length < _slice2.length) { // there is non-whitespace before the patch return this; } } patch.content = patch.content.replace(rx, ''); if (patch.content) return this; charIndex = patch.end; } var slice = this.original.slice(charIndex, this.original.length); var match = rx.exec(slice); if (match) this.patch(charIndex, charIndex + match[0].length, ''); return this; } }; var hasOwnProp = Object.prototype.hasOwnProperty; function Bundle$1() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; this.intro = options.intro || ''; this.separator = options.separator !== undefined ? options.separator : '\n'; this.sources = []; this.uniqueSources = []; this.uniqueSourceIndexByFilename = {}; } Bundle$1.prototype = { addSource: function addSource(source) { if (source instanceof MagicString) { return this.addSource({ content: source, filename: source.filename, separator: this.separator }); } if (!isObject(source) || !source.content) { throw new Error('bundle.addSource() takes an object with a `content` property, which should be an instance of MagicString, and an optional `filename`'); } ['filename', 'indentExclusionRanges', 'separator'].forEach(function (option) { if (!hasOwnProp.call(source, option)) source[option] = source.content[option]; }); if (source.separator === undefined) { // TODO there's a bunch of this sort of thing, needs cleaning up source.separator = this.separator; } if (source.filename) { if (!hasOwnProp.call(this.uniqueSourceIndexByFilename, source.filename)) { this.uniqueSourceIndexByFilename[source.filename] = this.uniqueSources.length; this.uniqueSources.push({ filename: source.filename, content: source.content.original }); } else { var uniqueSource = this.uniqueSources[this.uniqueSourceIndexByFilename[source.filename]]; if (source.content.original !== uniqueSource.content) { throw new Error('Illegal source: same filename (' + source.filename + '), different contents'); } } } this.sources.push(source); return this; }, append: function append(str, options) { this.addSource({ content: new MagicString(str), separator: options && options.separator || '' }); return this; }, clone: function clone() { var bundle = new Bundle$1({ intro: this.intro, separator: this.separator }); this.sources.forEach(function (source) { bundle.addSource({ filename: source.filename, content: source.content.clone(), separator: source.separator }); }); return bundle; }, generateMap: function generateMap(options) { var _this = this; var offsets = {}; var names = []; this.sources.forEach(function (source) { Object.keys(source.content.storedNames).forEach(function (name) { if (! ~names.indexOf(name)) names.push(name); }); }); var encoded = getSemis(this.intro) + this.sources.map(function (source, i) { var prefix = i > 0 ? getSemis(source.separator) || ',' : ''; var mappings = undefined; // we don't bother encoding sources without a filename if (!source.filename) { mappings = getSemis(source.content.toString()); } else { var sourceIndex = _this.uniqueSourceIndexByFilename[source.filename]; mappings = source.content.getMappings(options.hires, sourceIndex, offsets, names); } return prefix + mappings; }).join(''); return new SourceMap({ file: options.file ? options.file.split(/[\/\\]/).pop() : null, sources: this.uniqueSources.map(function (source) { return options.file ? getRelativePath(options.file, source.filename) : source.filename; }), sourcesContent: this.uniqueSources.map(function (source) { return options.includeContent ? source.content : null; }), names: names, mappings: encoded }); }, getIndentString: function getIndentString() { var indentStringCounts = {}; this.sources.forEach(function (source) { var indentStr = source.content.indentStr; if (indentStr === null) return; if (!indentStringCounts[indentStr]) indentStringCounts[indentStr] = 0; indentStringCounts[indentStr] += 1; }); return Object.keys(indentStringCounts).sort(function (a, b) { return indentStringCounts[a] - indentStringCounts[b]; })[0] || '\t'; }, indent: function indent(indentStr) { var _this2 = this; if (!arguments.length) { indentStr = this.getIndentString(); } if (indentStr === '') return this; // noop var trailingNewline = !this.intro || this.intro.slice(-1) === '\n'; this.sources.forEach(function (source, i) { var separator = source.separator !== undefined ? source.separator : _this2.separator; var indentStart = trailingNewline || i > 0 && /\r?\n$/.test(separator); source.content.indent(indentStr, { exclude: source.indentExclusionRanges, indentStart: indentStart //: trailingNewline || /\r?\n$/.test( separator ) //true///\r?\n/.test( separator ) }); // TODO this is a very slow way to determine this trailingNewline = source.content.toString().slice(0, -1) === '\n'; }); if (this.intro) { this.intro = indentStr + this.intro.replace(/^[^\n]/gm, function (match, index) { return index > 0 ? indentStr + match : match; }); } return this; }, prepend: function prepend(str) { this.intro = str + this.intro; return this; }, toString: function toString() { var _this3 = this; var body = this.sources.map(function (source, i) { var separator = source.separator !== undefined ? source.separator : _this3.separator; var str = (i > 0 ? separator : '') + source.content.toString(); return str; }).join(''); return this.intro + body; }, trimLines: function trimLines() { return this.trim('[\\r\\n]'); }, trim: function trim(charType) { return this.trimStart(charType).trimEnd(charType); }, trimStart: function trimStart(charType) { var rx = new RegExp('^' + (charType || '\\s') + '+'); this.intro = this.intro.replace(rx, ''); if (!this.intro) { var source = undefined; var i = 0; do { source = this.sources[i]; if (!source) { break; } source.content.trimStart(charType); i += 1; } while (source.content.toString() === ''); // TODO faster way to determine non-empty source? } return this; }, trimEnd: function trimEnd(charType) { var rx = new RegExp((charType || '\\s') + '+$'); var source = undefined; var i = this.sources.length - 1; do { source = this.sources[i]; if (!source) { this.intro = this.intro.replace(rx, ''); break; } source.content.trimEnd(charType); i -= 1; } while (source.content.toString() === ''); // TODO faster way to determine non-empty source? return this; } }; function getSemis(str) { return new Array(str.split('\n').length).join(';'); } MagicString.Bundle = Bundle$1; // Return the first non-falsy result from an array of // maybe-sync, maybe-promise-returning functions function first(candidates) { return function () { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return candidates.reduce(function (promise, candidate) { return promise.then(function (result) { return result != null ? result : Promise.resolve(candidate.apply(undefined, args)); }); }, Promise.resolve()); }; } // This is a trick taken from Esprima. It turns out that, on // non-Chrome browsers, to check whether a string is in a set, a // predicate containing a big ugly `switch` statement is faster than // a regular expression, and on Chrome the two are about on par. // This function uses `eval` (non-lexical) to produce such a // predicate from a space-separated string of words. // // It starts by sorting the words by length. // Reserved word lists for various dialects of the language var reservedWords$1 = { 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", 5: "class enum extends super const export import", 6: "enum", strict: "implements interface let package private protected public static yield", strictBind: "eval arguments" }; // And the keywords var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; var keywords = { 5: ecma5AndLessKeywords, 6: ecma5AndLessKeywords + " let const class extends export import yield super" }; // ## Character categories // Big ugly regular expressions that match characters in the // whitespace, identifier, and identifier-start categories. These // are only applied when a character is found to actually have a // code point above 128. // Generated by `bin/generate-identifier-regex.js`. var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\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-\u08b2\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\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-\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-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\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\u2118-\u211d\u2124\u2126\u2128\u212a-\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\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\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-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua7ad\ua7b0\ua7b1\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab5f\uab64\uab65\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"; var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19b0-\u19c0\u19c8\u19c9\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfc-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2d\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; // These are a run-length and offset encoded representation of the // >0xffff code points that are a valid part of identifiers. The // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by tools/generate-identifier-regex.js var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 17, 26, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 99, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 98, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 26, 45, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 955, 52, 76, 44, 33, 24, 27, 35, 42, 34, 4, 0, 13, 47, 15, 3, 22, 0, 38, 17, 2, 24, 133, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 32, 4, 287, 47, 21, 1, 2, 0, 185, 46, 82, 47, 21, 0, 60, 42, 502, 63, 32, 0, 449, 56, 1288, 920, 104, 110, 2962, 1070, 13266, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 881, 68, 12, 0, 67, 12, 16481, 1, 3071, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 4149, 196, 1340, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42710, 42, 4148, 12, 221, 16355, 541]; var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 1306, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 52, 0, 13, 2, 49, 13, 16, 9, 83, 11, 168, 11, 6, 9, 8, 2, 57, 0, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 316, 19, 13, 9, 214, 6, 3, 8, 112, 16, 16, 9, 82, 12, 9, 9, 535, 9, 20855, 9, 135, 4, 60, 6, 26, 9, 1016, 45, 17, 3, 19723, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 4305, 6, 792618, 239]; // This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is // rare. function isInAstralSet(code, set) { var pos = 0x10000; for (var i = 0; i < set.length; i += 2) { pos += set[i]; if (pos > code) return false; pos += set[i + 1]; if (pos >= code) return true; } } // Test whether a given character code starts an identifier. function isIdentifierStart(code, astral) { if (code < 65) return code === 36; if (code < 91) return true; if (code < 97) return code === 95; if (code < 123) return true; if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); if (astral === false) return false; return isInAstralSet(code, astralIdentifierStartCodes); } // Test whether a given character is part of an identifier. function isIdentifierChar(code, astral) { if (code < 48) return code === 36; if (code < 58) return true; if (code < 65) return false; if (code < 91) return true; if (code < 97) return code === 95; if (code < 123) return true; if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); if (astral === false) return false; return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); } // ## Token types // The assignment of fine-grained, information-carrying type objects // allows the tokenizer to store the information it has about a // token in a way that is very cheap for the parser to look up. // All token type variables start with an underscore, to make them // easy to recognize. // The `beforeExpr` property is used to disambiguate between regular // expressions and divisions. It is set on all token types that can // be followed by an expression (thus, a slash after them would be a // regular expression). // // The `startsExpr` property is used to check if the token ends a // `yield` expression. It is set on all token types that either can // directly start an expression (like a quotation mark) or can // continue an expression (like the body of a string). // // `isLoop` marks a keyword as starting a loop, which is important // to know when parsing a label, in order to allow or disallow // continue jumps to that label. var TokenType = function TokenType(label) { var conf = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; babelHelpers.classCallCheck(this, TokenType); this.label = label; this.keyword = conf.keyword; this.beforeExpr = !!conf.beforeExpr; this.startsExpr = !!conf.startsExpr; this.isLoop = !!conf.isLoop; this.isAssign = !!conf.isAssign; this.prefix = !!conf.prefix; this.postfix = !!conf.postfix; this.binop = conf.binop || null; this.updateContext = null; }; function binop(name, prec) { return new TokenType(name, { beforeExpr: true, binop: prec }); } var beforeExpr = { beforeExpr: true }; var startsExpr = { startsExpr: true }; var tt = { num: new TokenType("num", startsExpr), regexp: new TokenType("regexp", startsExpr), string: new TokenType("string", startsExpr), name: new TokenType("name", startsExpr), eof: new TokenType("eof"), // Punctuation token types. bracketL: new TokenType("[", { beforeExpr: true, startsExpr: true }), bracketR: new TokenType("]"), braceL: new TokenType("{", { beforeExpr: true, startsExpr: true }), braceR: new TokenType("}"), parenL: new TokenType("(", { beforeExpr: true, startsExpr: true }), parenR: new TokenType(")"), comma: new TokenType(",", beforeExpr), semi: new TokenType(";", beforeExpr), colon: new TokenType(":", beforeExpr), dot: new TokenType("."), question: new TokenType("?", beforeExpr), arrow: new TokenType("=>", beforeExpr), template: new TokenType("template"), ellipsis: new TokenType("...", beforeExpr), backQuote: new TokenType("`", startsExpr), dollarBraceL: new TokenType("${", { beforeExpr: true, startsExpr: true }), // Operators. These carry several kinds of properties to help the // parser use them properly (the presence of these properties is // what categorizes them as operators). // // `binop`, when present, specifies that this operator is a binary // operator, and will refer to its precedence. // // `prefix` and `postfix` mark the operator as a prefix or postfix // unary operator. // // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as // binary operators with a very low precedence, that should result // in AssignmentExpression nodes. eq: new TokenType("=", { beforeExpr: true, isAssign: true }), assign: new TokenType("_=", { beforeExpr: true, isAssign: true }), incDec: new TokenType("++/--", { prefix: true, postfix: true, startsExpr: true }), prefix: new TokenType("prefix", { beforeExpr: true, prefix: true, startsExpr: true }), logicalOR: binop("||", 1), logicalAND: binop("&&", 2), bitwiseOR: binop("|", 3), bitwiseXOR: binop("^", 4), bitwiseAND: binop("&", 5), equality: binop("==/!=", 6), relational: binop("", 7), bitShift: binop("<>", 8), plusMin: new TokenType("+/-", { beforeExpr: true, binop: 9, prefix: true, startsExpr: true }), modulo: binop("%", 10), star: binop("*", 10), slash: binop("/", 10) }; // Map keyword names to token types. var keywordTypes = {}; // Succinct definitions of keyword token types function kw(name) { var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; options.keyword = name; keywordTypes[name] = tt["_" + name] = new TokenType(name, options); } kw("break"); kw("case", beforeExpr); kw("catch"); kw("continue"); kw("debugger"); kw("default", beforeExpr); kw("do", { isLoop: true, beforeExpr: true }); kw("else", beforeExpr); kw("finally"); kw("for", { isLoop: true }); kw("function", startsExpr); kw("if"); kw("return", beforeExpr); kw("switch"); kw("throw", beforeExpr); kw("try"); kw("var"); kw("let"); kw("const"); kw("while", { isLoop: true }); kw("with"); kw("new", { beforeExpr: true, startsExpr: true }); kw("this", startsExpr); kw("super", startsExpr); kw("class"); kw("extends", beforeExpr); kw("export"); kw("import"); kw("yield", { beforeExpr: true, startsExpr: true }); kw("null", startsExpr); kw("true", startsExpr); kw("false", startsExpr); kw("in", { beforeExpr: true, binop: 7 }); kw("instanceof", { beforeExpr: true, binop: 7 }); kw("typeof", { beforeExpr: true, prefix: true, startsExpr: true }); kw("void", { beforeExpr: true, prefix: true, startsExpr: true }); kw("delete", { beforeExpr: true, prefix: true, startsExpr: true }); // Matches a whole line break (where CRLF is considered a single // line break). Used to count lines. var lineBreak = /\r\n?|\n|\u2028|\u2029/; var lineBreakG = new RegExp(lineBreak.source, "g"); function isNewLine(code) { return code === 10 || code === 13 || code === 0x2028 || code == 0x2029; } var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; function isArray$1(obj) { return Object.prototype.toString.call(obj) === "[object Array]"; } // Checks if an object has a property. function has(obj, propName) { return Object.prototype.hasOwnProperty.call(obj, propName); } // These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties. var Position = (function () { function Position(line, col) { babelHelpers.classCallCheck(this, Position); this.line = line; this.column = col; } Position.prototype.offset = function offset(n) { return new Position(this.line, this.column + n); }; return Position; })(); var SourceLocation = function SourceLocation(p, start, end) { babelHelpers.classCallCheck(this, SourceLocation); this.start = start; this.end = end; if (p.sourceFile !== null) this.source = p.sourceFile; } // The `getLineInfo` function is mostly useful when the // `locations` option is off (for performance reasons) and you // want to find the line/column position for a given character // offset. `input` should be the code string that the offset refers // into. ; function getLineInfo(input, offset) { for (var line = 1, cur = 0;;) { lineBreakG.lastIndex = cur; var match = lineBreakG.exec(input); if (match && match.index < offset) { ++line; cur = match.index + match[0].length; } else { return new Position(line, offset - cur); } } } // A second optional argument can be given to further configure // the parser process. These options are recognized: var defaultOptions = { // `ecmaVersion` indicates the ECMAScript version to parse. Must // be either 3, or 5, or 6. This influences support for strict // mode, the set of reserved words, support for getters and // setters and other features. ecmaVersion: 5, // Source type ("script" or "module") for different semantics sourceType: "script", // `onInsertedSemicolon` can be a callback that will be called // when a semicolon is automatically inserted. It will be passed // th position of the comma as an offset, and if `locations` is // enabled, it is given the location as a `{line, column}` object // as second argument. onInsertedSemicolon: null, // `onTrailingComma` is similar to `onInsertedSemicolon`, but for // trailing commas. onTrailingComma: null, // By default, reserved words are only enforced if ecmaVersion >= 5. // Set `allowReserved` to a boolean value to explicitly turn this on // an off. When this option has the value "never", reserved words // and keywords can also not be used as property names. allowReserved: null, // When enabled, a return at the top level is not considered an // error. allowReturnOutsideFunction: false, // When enabled, import/export statements are not constrained to // appearing at the top of the program. allowImportExportEverywhere: false, // When enabled, hashbang directive in the beginning of file // is allowed and treated as a line comment. allowHashBang: false, // When `locations` is on, `loc` properties holding objects with // `start` and `end` properties in `{line, column}` form (with // line being 1-based and column 0-based) will be attached to the // nodes. locations: false, // A function can be passed as `onToken` option, which will // cause Acorn to call that function with object in the same // format as tokens returned from `tokenizer().getToken()`. Note // that you are not allowed to call the parser from the // callback—that will corrupt its internal state. onToken: null, // A function can be passed as `onComment` option, which will // cause Acorn to call that function with `(block, text, start, // end)` parameters whenever a comment is skipped. `block` is a // boolean indicating whether this is a block (`/* */`) comment, // `text` is the content of the comment, and `start` and `end` are // character offsets that denote the start and end of the comment. // When the `locations` option is on, two more parameters are // passed, the full `{line, column}` locations of the start and // end of the comments. Note that you are not allowed to call the // parser from the callback—that will corrupt its internal state. onComment: null, // Nodes have their start and end characters offsets recorded in // `start` and `end` properties (directly on the node, rather than // the `loc` object, which holds line/column data. To also add a // [semi-standardized][range] `range` property holding a `[start, // end]` array with the same numbers, set the `ranges` option to // `true`. // // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 ranges: false, // It is possible to parse multiple files into a single AST by // passing the tree produced by parsing the first file as // `program` option in subsequent parses. This will add the // toplevel forms of the parsed file to the `Program` (top) node // of an existing parse tree. program: null, // When `locations` is on, you can pass this to record the source // file in every node's `loc` object. sourceFile: null, // This value, if given, is stored in every node, whether // `locations` is on or off. directSourceFile: null, // When enabled, parenthesized expressions are represented by // (non-standard) ParenthesizedExpression nodes preserveParens: false, plugins: {} }; // Interpret and default an options object function getOptions(opts) { var options = {}; for (var opt in defaultOptions) { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }if (options.allowReserved == null) options.allowReserved = options.ecmaVersion < 5; if (isArray$1(options.onToken)) { (function () { var tokens = options.onToken; options.onToken = function (token) { return tokens.push(token); }; })(); } if (isArray$1(options.onComment)) options.onComment = pushComment(options, options.onComment); return options; } function pushComment(options, array) { return function (block, text, start, end, startLoc, endLoc) { var comment = { type: block ? 'Block' : 'Line', value: text, start: start, end: end }; if (options.locations) comment.loc = new SourceLocation(this, startLoc, endLoc); if (options.ranges) comment.range = [start, end]; array.push(comment); }; } // Registered plugins var plugins = {}; function keywordRegexp(words) { return new RegExp("^(" + words.replace(/ /g, "|") + ")$"); } var Parser = (function () { function Parser(options, input, startPos) { babelHelpers.classCallCheck(this, Parser); this.options = options = getOptions(options); this.sourceFile = options.sourceFile; this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]); var reserved = options.allowReserved ? "" : reservedWords$1[options.ecmaVersion] + (options.sourceType == "module" ? " await" : ""); this.reservedWords = keywordRegexp(reserved); var reservedStrict = (reserved ? reserved + " " : "") + reservedWords$1.strict; this.reservedWordsStrict = keywordRegexp(reservedStrict); this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords$1.strictBind); this.input = String(input); // Used to signal to callers of `readWord1` whether the word // contained any escape sequences. This is needed because words with // escape sequences must not be interpreted as keywords. this.containsEsc = false; // Load plugins this.loadPlugins(options.plugins); // Set up token state // The current position of the tokenizer in the input. if (startPos) { this.pos = startPos; this.lineStart = Math.max(0, this.input.lastIndexOf("\n", startPos)); this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; } else { this.pos = this.lineStart = 0; this.curLine = 1; } // Properties of the current token: // Its type this.type = tt.eof; // For tokens that include more information than their type, the value this.value = null; // Its start and end offset this.start = this.end = this.pos; // And, if locations are used, the {line, column} object // corresponding to those offsets this.startLoc = this.endLoc = this.curPosition(); // Position information for the previous token this.lastTokEndLoc = this.lastTokStartLoc = null; this.lastTokStart = this.lastTokEnd = this.pos; // The context stack is used to superficially track syntactic // context to predict whether a regular expression is allowed in a // given position. this.context = this.initialContext(); this.exprAllowed = true; // Figure out if it's a module code. this.strict = this.inModule = options.sourceType === "module"; // Used to signify the start of a potential arrow function this.potentialArrowAt = -1; // Flags to track whether we are in a function, a generator. this.inFunction = this.inGenerator = false; // Labels in scope. this.labels = []; // If enabled, skip leading hashbang line. if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === '#!') this.skipLineComment(2); } // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them Parser.prototype.isKeyword = function isKeyword(word) { return this.keywords.test(word); }; Parser.prototype.isReservedWord = function isReservedWord(word) { return this.reservedWords.test(word); }; Parser.prototype.extend = function extend(name, f) { this[name] = f(this[name]); }; Parser.prototype.loadPlugins = function loadPlugins(pluginConfigs) { for (var _name in pluginConfigs) { var plugin = plugins[_name]; if (!plugin) throw new Error("Plugin '" + _name + "' not found"); plugin(this, pluginConfigs[_name]); } }; Parser.prototype.parse = function parse() { var node = this.options.program || this.startNode(); this.nextToken(); return this.parseTopLevel(node); }; return Parser; })(); var pp = Parser.prototype; // ## Parser utilities // Test whether a statement node is the string literal `"use strict"`. pp.isUseStrict = function (stmt) { return this.options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && stmt.expression.raw.slice(1, -1) === "use strict"; }; // Predicate that tests whether the next token is of the given // type, and if yes, consumes it as a side effect. pp.eat = function (type) { if (this.type === type) { this.next(); return true; } else { return false; } }; // Tests whether parsed token is a contextual keyword. pp.isContextual = function (name) { return this.type === tt.name && this.value === name; }; // Consumes contextual keyword if possible. pp.eatContextual = function (name) { return this.value === name && this.eat(tt.name); }; // Asserts that following token is given contextual keyword. pp.expectContextual = function (name) { if (!this.eatContextual(name)) this.unexpected(); }; // Test whether a semicolon can be inserted at the current position. pp.canInsertSemicolon = function () { return this.type === tt.eof || this.type === tt.braceR || lineBreak.test(this.input.slice(this.lastTokEnd, this.start)); }; pp.insertSemicolon = function () { if (this.canInsertSemicolon()) { if (this.options.onInsertedSemicolon) this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); return true; } }; // Consume a semicolon, or, failing that, see if we are allowed to // pretend that there is a semicolon at this position. pp.semicolon = function () { if (!this.eat(tt.semi) && !this.insertSemicolon()) this.unexpected(); }; pp.afterTrailingComma = function (tokType) { if (this.type == tokType) { if (this.options.onTrailingComma) this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); this.next(); return true; } }; // Expect a token of a given type. If found, consume it, otherwise, // raise an unexpected token error. pp.expect = function (type) { this.eat(type) || this.unexpected(); }; // Raise an unexpected token error. pp.unexpected = function (pos) { this.raise(pos != null ? pos : this.start, "Unexpected token"); }; pp.checkPatternErrors = function (refDestructuringErrors, andThrow) { var pos = refDestructuringErrors && refDestructuringErrors.trailingComma; if (!andThrow) return !!pos; if (pos) this.raise(pos, "Trailing comma is not permitted in destructuring patterns"); }; pp.checkExpressionErrors = function (refDestructuringErrors, andThrow) { var pos = refDestructuringErrors && refDestructuringErrors.shorthandAssign; if (!andThrow) return !!pos; if (pos) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns"); }; var pp$1 = Parser.prototype; // ### Statement parsing // Parse a program. Initializes the parser, reads any number of // statements, and wraps them in a Program node. Optionally takes a // `program` argument. If present, the statements will be appended // to its body instead of creating a new node. pp$1.parseTopLevel = function (node) { var first = true; if (!node.body) node.body = []; while (this.type !== tt.eof) { var stmt = this.parseStatement(true, true); node.body.push(stmt); if (first) { if (this.isUseStrict(stmt)) this.setStrict(true); first = false; } } this.next(); if (this.options.ecmaVersion >= 6) { node.sourceType = this.options.sourceType; } return this.finishNode(node, "Program"); }; var loopLabel = { kind: "loop" }; var switchLabel = { kind: "switch" }; // Parse a single statement. // // If expecting a statement and finding a slash operator, parse a // regular expression literal. This is to handle cases like // `if (foo) /blah/.exec(foo)`, where looking at the previous token // does not help. pp$1.parseStatement = function (declaration, topLevel) { var starttype = this.type, node = this.startNode(); // Most types of statements are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of // complexity. switch (starttype) { case tt._break:case tt._continue: return this.parseBreakContinueStatement(node, starttype.keyword); case tt._debugger: return this.parseDebuggerStatement(node); case tt._do: return this.parseDoStatement(node); case tt._for: return this.parseForStatement(node); case tt._function: if (!declaration && this.options.ecmaVersion >= 6) this.unexpected(); return this.parseFunctionStatement(node); case tt._class: if (!declaration) this.unexpected(); return this.parseClass(node, true); case tt._if: return this.parseIfStatement(node); case tt._return: return this.parseReturnStatement(node); case tt._switch: return this.parseSwitchStatement(node); case tt._throw: return this.parseThrowStatement(node); case tt._try: return this.parseTryStatement(node); case tt._let:case tt._const: if (!declaration) this.unexpected(); // NOTE: falls through to _var case tt._var: return this.parseVarStatement(node, starttype); case tt._while: return this.parseWhileStatement(node); case tt._with: return this.parseWithStatement(node); case tt.braceL: return this.parseBlock(); case tt.semi: return this.parseEmptyStatement(node); case tt._export: case tt._import: if (!this.options.allowImportExportEverywhere) { if (!topLevel) this.raise(this.start, "'import' and 'export' may only appear at the top level"); if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } return starttype === tt._import ? this.parseImport(node) : this.parseExport(node); // If the statement does not start with a statement keyword or a // brace, it's an ExpressionStatement or LabeledStatement. We // simply start parsing an expression, and afterwards, if the // next token is a colon and the expression was a simple // Identifier node, we switch to interpreting it as a label. default: var maybeName = this.value, expr = this.parseExpression(); if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) return this.parseLabeledStatement(node, maybeName, expr);else return this.parseExpressionStatement(node, expr); } }; pp$1.parseBreakContinueStatement = function (node, keyword) { var isBreak = keyword == "break"; this.next(); if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null;else if (this.type !== tt.name) this.unexpected();else { node.label = this.parseIdent(); this.semicolon(); } // Verify that there is an actual destination to break or // continue to. for (var i = 0; i < this.labels.length; ++i) { var lab = this.labels[i]; if (node.label == null || lab.name === node.label.name) { if (lab.kind != null && (isBreak || lab.kind === "loop")) break; if (node.label && isBreak) break; } } if (i === this.labels.length) this.raise(node.start, "Unsyntactic " + keyword); return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); }; pp$1.parseDebuggerStatement = function (node) { this.next(); this.semicolon(); return this.finishNode(node, "DebuggerStatement"); }; pp$1.parseDoStatement = function (node) { this.next(); this.labels.push(loopLabel); node.body = this.parseStatement(false); this.labels.pop(); this.expect(tt._while); node.test = this.parseParenExpression(); if (this.options.ecmaVersion >= 6) this.eat(tt.semi);else this.semicolon(); return this.finishNode(node, "DoWhileStatement"); }; // Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see // the second parameter to `parseExpression`), and then check // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop. pp$1.parseForStatement = function (node) { this.next(); this.labels.push(loopLabel); this.expect(tt.parenL); if (this.type === tt.semi) return this.parseFor(node, null); if (this.type === tt._var || this.type === tt._let || this.type === tt._const) { var _init = this.startNode(), varKind = this.type; this.next(); this.parseVar(_init, true, varKind); this.finishNode(_init, "VariableDeclaration"); if ((this.type === tt._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) && _init.declarations.length === 1 && !(varKind !== tt._var && _init.declarations[0].init)) return this.parseForIn(node, _init); return this.parseFor(node, _init); } var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }; var init = this.parseExpression(true, refDestructuringErrors); if (this.type === tt._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) { this.checkPatternErrors(refDestructuringErrors, true); this.toAssignable(init); this.checkLVal(init); return this.parseForIn(node, init); } else { this.checkExpressionErrors(refDestructuringErrors, true); } return this.parseFor(node, init); }; pp$1.parseFunctionStatement = function (node) { this.next(); return this.parseFunction(node, true); }; pp$1.parseIfStatement = function (node) { this.next(); node.test = this.parseParenExpression(); node.consequent = this.parseStatement(false); node.alternate = this.eat(tt._else) ? this.parseStatement(false) : null; return this.finishNode(node, "IfStatement"); }; pp$1.parseReturnStatement = function (node) { if (!this.inFunction && !this.options.allowReturnOutsideFunction) this.raise(this.start, "'return' outside of function"); this.next(); // In `return` (and `break`/`continue`), the keywords with // optional arguments, we eagerly look for a semicolon or the // possibility to insert one. if (this.eat(tt.semi) || this.insertSemicolon()) node.argument = null;else { node.argument = this.parseExpression();this.semicolon(); } return this.finishNode(node, "ReturnStatement"); }; pp$1.parseSwitchStatement = function (node) { this.next(); node.discriminant = this.parseParenExpression(); node.cases = []; this.expect(tt.braceL); this.labels.push(switchLabel); // Statements under must be grouped (by label) in SwitchCase // nodes. `cur` is used to keep the node that we are currently // adding statements to. for (var cur, sawDefault = false; this.type != tt.braceR;) { if (this.type === tt._case || this.type === tt._default) { var isCase = this.type === tt._case; if (cur) this.finishNode(cur, "SwitchCase"); node.cases.push(cur = this.startNode()); cur.consequent = []; this.next(); if (isCase) { cur.test = this.parseExpression(); } else { if (sawDefault) this.raise(this.lastTokStart, "Multiple default clauses"); sawDefault = true; cur.test = null; } this.expect(tt.colon); } else { if (!cur) this.unexpected(); cur.consequent.push(this.parseStatement(true)); } } if (cur) this.finishNode(cur, "SwitchCase"); this.next(); // Closing brace this.labels.pop(); return this.finishNode(node, "SwitchStatement"); }; pp$1.parseThrowStatement = function (node) { this.next(); if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) this.raise(this.lastTokEnd, "Illegal newline after throw"); node.argument = this.parseExpression(); this.semicolon(); return this.finishNode(node, "ThrowStatement"); }; // Reused empty array added for node fields that are always empty. var empty = []; pp$1.parseTryStatement = function (node) { this.next(); node.block = this.parseBlock(); node.handler = null; if (this.type === tt._catch) { var clause = this.startNode(); this.next(); this.expect(tt.parenL); clause.param = this.parseBindingAtom(); this.checkLVal(clause.param, true); this.expect(tt.parenR); clause.body = this.parseBlock(); node.handler = this.finishNode(clause, "CatchClause"); } node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null; if (!node.handler && !node.finalizer) this.raise(node.start, "Missing catch or finally clause"); return this.finishNode(node, "TryStatement"); }; pp$1.parseVarStatement = function (node, kind) { this.next(); this.parseVar(node, false, kind); this.semicolon(); return this.finishNode(node, "VariableDeclaration"); }; pp$1.parseWhileStatement = function (node) { this.next(); node.test = this.parseParenExpression(); this.labels.push(loopLabel); node.body = this.parseStatement(false); this.labels.pop(); return this.finishNode(node, "WhileStatement"); }; pp$1.parseWithStatement = function (node) { if (this.strict) this.raise(this.start, "'with' in strict mode"); this.next(); node.object = this.parseParenExpression(); node.body = this.parseStatement(false); return this.finishNode(node, "WithStatement"); }; pp$1.parseEmptyStatement = function (node) { this.next(); return this.finishNode(node, "EmptyStatement"); }; pp$1.parseLabeledStatement = function (node, maybeName, expr) { for (var i = 0; i < this.labels.length; ++i) { if (this.labels[i].name === maybeName) this.raise(expr.start, "Label '" + maybeName + "' is already declared"); }var kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null; for (var i = this.labels.length - 1; i >= 0; i--) { var label = this.labels[i]; if (label.statementStart == node.start) { label.statementStart = this.start; label.kind = kind; } else break; } this.labels.push({ name: maybeName, kind: kind, statementStart: this.start }); node.body = this.parseStatement(true); this.labels.pop(); node.label = expr; return this.finishNode(node, "LabeledStatement"); }; pp$1.parseExpressionStatement = function (node, expr) { node.expression = expr; this.semicolon(); return this.finishNode(node, "ExpressionStatement"); }; // Parse a semicolon-enclosed block of statements, handling `"use // strict"` declarations when `allowStrict` is true (used for // function bodies). pp$1.parseBlock = function (allowStrict) { var node = this.startNode(), first = true, oldStrict = undefined; node.body = []; this.expect(tt.braceL); while (!this.eat(tt.braceR)) { var stmt = this.parseStatement(true); node.body.push(stmt); if (first && allowStrict && this.isUseStrict(stmt)) { oldStrict = this.strict; this.setStrict(this.strict = true); } first = false; } if (oldStrict === false) this.setStrict(false); return this.finishNode(node, "BlockStatement"); }; // Parse a regular `for` loop. The disambiguation code in // `parseStatement` will already have parsed the init statement or // expression. pp$1.parseFor = function (node, init) { node.init = init; this.expect(tt.semi); node.test = this.type === tt.semi ? null : this.parseExpression(); this.expect(tt.semi); node.update = this.type === tt.parenR ? null : this.parseExpression(); this.expect(tt.parenR); node.body = this.parseStatement(false); this.labels.pop(); return this.finishNode(node, "ForStatement"); }; // Parse a `for`/`in` and `for`/`of` loop, which are almost // same from parser's perspective. pp$1.parseForIn = function (node, init) { var type = this.type === tt._in ? "ForInStatement" : "ForOfStatement"; this.next(); node.left = init; node.right = this.parseExpression(); this.expect(tt.parenR); node.body = this.parseStatement(false); this.labels.pop(); return this.finishNode(node, type); }; // Parse a list of variable declarations. pp$1.parseVar = function (node, isFor, kind) { node.declarations = []; node.kind = kind.keyword; for (;;) { var decl = this.startNode(); this.parseVarId(decl); if (this.eat(tt.eq)) { decl.init = this.parseMaybeAssign(isFor); } else if (kind === tt._const && !(this.type === tt._in || this.options.ecmaVersion >= 6 && this.isContextual("of"))) { this.unexpected(); } else if (decl.id.type != "Identifier" && !(isFor && (this.type === tt._in || this.isContextual("of")))) { this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); } else { decl.init = null; } node.declarations.push(this.finishNode(decl, "VariableDeclarator")); if (!this.eat(tt.comma)) break; } return node; }; pp$1.parseVarId = function (decl) { decl.id = this.parseBindingAtom(); this.checkLVal(decl.id, true); }; // Parse a function declaration or literal (depending on the // `isStatement` parameter). pp$1.parseFunction = function (node, isStatement, allowExpressionBody) { this.initFunction(node); if (this.options.ecmaVersion >= 6) node.generator = this.eat(tt.star); if (isStatement || this.type === tt.name) node.id = this.parseIdent(); this.parseFunctionParams(node); this.parseFunctionBody(node, allowExpressionBody); return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); }; pp$1.parseFunctionParams = function (node) { this.expect(tt.parenL); node.params = this.parseBindingList(tt.parenR, false, false, true); }; // Parse a class declaration or literal (depending on the // `isStatement` parameter). pp$1.parseClass = function (node, isStatement) { this.next(); this.parseClassId(node, isStatement); this.parseClassSuper(node); var classBody = this.startNode(); var hadConstructor = false; classBody.body = []; this.expect(tt.braceL); while (!this.eat(tt.braceR)) { if (this.eat(tt.semi)) continue; var method = this.startNode(); var isGenerator = this.eat(tt.star); var isMaybeStatic = this.type === tt.name && this.value === "static"; this.parsePropertyName(method); method.static = isMaybeStatic && this.type !== tt.parenL; if (method.static) { if (isGenerator) this.unexpected(); isGenerator = this.eat(tt.star); this.parsePropertyName(method); } method.kind = "method"; var isGetSet = false; if (!method.computed) { var key = method.key; if (!isGenerator && key.type === "Identifier" && this.type !== tt.parenL && (key.name === "get" || key.name === "set")) { isGetSet = true; method.kind = key.name; key = this.parsePropertyName(method); } if (!method.static && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) { if (hadConstructor) this.raise(key.start, "Duplicate constructor in the same class"); if (isGetSet) this.raise(key.start, "Constructor can't have get/set modifier"); if (isGenerator) this.raise(key.start, "Constructor can't be a generator"); method.kind = "constructor"; hadConstructor = true; } } this.parseClassMethod(classBody, method, isGenerator); if (isGetSet) { var paramCount = method.kind === "get" ? 0 : 1; if (method.value.params.length !== paramCount) { var start = method.value.start; if (method.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param"); } if (method.kind === "set" && method.value.params[0].type === "RestElement") this.raise(method.value.params[0].start, "Setter cannot use rest params"); } } node.body = this.finishNode(classBody, "ClassBody"); return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression"); }; pp$1.parseClassMethod = function (classBody, method, isGenerator) { method.value = this.parseMethod(isGenerator); classBody.body.push(this.finishNode(method, "MethodDefinition")); }; pp$1.parseClassId = function (node, isStatement) { node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null; }; pp$1.parseClassSuper = function (node) { node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null; }; // Parses module export declaration. pp$1.parseExport = function (node) { this.next(); // export * from '...' if (this.eat(tt.star)) { this.expectContextual("from"); node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected(); this.semicolon(); return this.finishNode(node, "ExportAllDeclaration"); } if (this.eat(tt._default)) { // export default ... var expr = this.parseMaybeAssign(); var needsSemi = true; if (expr.type == "FunctionExpression" || expr.type == "ClassExpression") { needsSemi = false; if (expr.id) { expr.type = expr.type == "FunctionExpression" ? "FunctionDeclaration" : "ClassDeclaration"; } } node.declaration = expr; if (needsSemi) this.semicolon(); return this.finishNode(node, "ExportDefaultDeclaration"); } // export var|const|let|function|class ... if (this.shouldParseExportStatement()) { node.declaration = this.parseStatement(true); node.specifiers = []; node.source = null; } else { // export { x, y as z } [from '...'] node.declaration = null; node.specifiers = this.parseExportSpecifiers(); if (this.eatContextual("from")) { node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected(); } else { // check for keywords used as local names for (var i = 0; i < node.specifiers.length; i++) { if (this.keywords.test(node.specifiers[i].local.name) || this.reservedWords.test(node.specifiers[i].local.name)) { this.unexpected(node.specifiers[i].local.start); } } node.source = null; } this.semicolon(); } return this.finishNode(node, "ExportNamedDeclaration"); }; pp$1.shouldParseExportStatement = function () { return this.type.keyword; }; // Parses a comma-separated list of module exports. pp$1.parseExportSpecifiers = function () { var nodes = [], first = true; // export { x, y as z } [from '...'] this.expect(tt.braceL); while (!this.eat(tt.braceR)) { if (!first) { this.expect(tt.comma); if (this.afterTrailingComma(tt.braceR)) break; } else first = false; var node = this.startNode(); node.local = this.parseIdent(this.type === tt._default); node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local; nodes.push(this.finishNode(node, "ExportSpecifier")); } return nodes; }; // Parses import declaration. pp$1.parseImport = function (node) { this.next(); // import '...' if (this.type === tt.string) { node.specifiers = empty; node.source = this.parseExprAtom(); } else { node.specifiers = this.parseImportSpecifiers(); this.expectContextual("from"); node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected(); } this.semicolon(); return this.finishNode(node, "ImportDeclaration"); }; // Parses a comma-separated list of module imports. pp$1.parseImportSpecifiers = function () { var nodes = [], first = true; if (this.type === tt.name) { // import defaultObj, { x, y as z } from '...' var node = this.startNode(); node.local = this.parseIdent(); this.checkLVal(node.local, true); nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); if (!this.eat(tt.comma)) return nodes; } if (this.type === tt.star) { var node = this.startNode(); this.next(); this.expectContextual("as"); node.local = this.parseIdent(); this.checkLVal(node.local, true); nodes.push(this.finishNode(node, "ImportNamespaceSpecifier")); return nodes; } this.expect(tt.braceL); while (!this.eat(tt.braceR)) { if (!first) { this.expect(tt.comma); if (this.afterTrailingComma(tt.braceR)) break; } else first = false; var node = this.startNode(); node.imported = this.parseIdent(true); if (this.eatContextual("as")) { node.local = this.parseIdent(); } else { node.local = node.imported; if (this.isKeyword(node.local.name)) this.unexpected(node.local.start); if (this.reservedWordsStrict.test(node.local.name)) this.raise(node.local.start, "The keyword '" + node.local.name + "' is reserved"); } this.checkLVal(node.local, true); nodes.push(this.finishNode(node, "ImportSpecifier")); } return nodes; }; var pp$2 = Parser.prototype; // Convert existing expression atom to assignable pattern // if possible. pp$2.toAssignable = function (node, isBinding) { if (this.options.ecmaVersion >= 6 && node) { switch (node.type) { case "Identifier": case "ObjectPattern": case "ArrayPattern": break; case "ObjectExpression": node.type = "ObjectPattern"; for (var i = 0; i < node.properties.length; i++) { var prop = node.properties[i]; if (prop.kind !== "init") this.raise(prop.key.start, "Object pattern can't contain getter or setter"); this.toAssignable(prop.value, isBinding); } break; case "ArrayExpression": node.type = "ArrayPattern"; this.toAssignableList(node.elements, isBinding); break; case "AssignmentExpression": if (node.operator === "=") { node.type = "AssignmentPattern"; delete node.operator; // falls through to AssignmentPattern } else { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); break; } case "AssignmentPattern": if (node.right.type === "YieldExpression") this.raise(node.right.start, "Yield expression cannot be a default value"); break; case "ParenthesizedExpression": node.expression = this.toAssignable(node.expression, isBinding); break; case "MemberExpression": if (!isBinding) break; default: this.raise(node.start, "Assigning to rvalue"); } } return node; }; // Convert list of expression atoms to binding list. pp$2.toAssignableList = function (exprList, isBinding) { var end = exprList.length; if (end) { var last = exprList[end - 1]; if (last && last.type == "RestElement") { --end; } else if (last && last.type == "SpreadElement") { last.type = "RestElement"; var arg = last.argument; this.toAssignable(arg, isBinding); if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") this.unexpected(arg.start); --end; } if (isBinding && last.type === "RestElement" && last.argument.type !== "Identifier") this.unexpected(last.argument.start); } for (var i = 0; i < end; i++) { var elt = exprList[i]; if (elt) this.toAssignable(elt, isBinding); } return exprList; }; // Parses spread element. pp$2.parseSpread = function (refDestructuringErrors) { var node = this.startNode(); this.next(); node.argument = this.parseMaybeAssign(refDestructuringErrors); return this.finishNode(node, "SpreadElement"); }; pp$2.parseRest = function (allowNonIdent) { var node = this.startNode(); this.next(); // RestElement inside of a function parameter must be an identifier if (allowNonIdent) node.argument = this.type === tt.name ? this.parseIdent() : this.unexpected();else node.argument = this.type === tt.name || this.type === tt.bracketL ? this.parseBindingAtom() : this.unexpected(); return this.finishNode(node, "RestElement"); }; // Parses lvalue (assignable) atom. pp$2.parseBindingAtom = function () { if (this.options.ecmaVersion < 6) return this.parseIdent(); switch (this.type) { case tt.name: return this.parseIdent(); case tt.bracketL: var node = this.startNode(); this.next(); node.elements = this.parseBindingList(tt.bracketR, true, true); return this.finishNode(node, "ArrayPattern"); case tt.braceL: return this.parseObj(true); default: this.unexpected(); } }; pp$2.parseBindingList = function (close, allowEmpty, allowTrailingComma, allowNonIdent) { var elts = [], first = true; while (!this.eat(close)) { if (first) first = false;else this.expect(tt.comma); if (allowEmpty && this.type === tt.comma) { elts.push(null); } else if (allowTrailingComma && this.afterTrailingComma(close)) { break; } else if (this.type === tt.ellipsis) { var rest = this.parseRest(allowNonIdent); this.parseBindingListItem(rest); elts.push(rest); this.expect(close); break; } else { var elem = this.parseMaybeDefault(this.start, this.startLoc); this.parseBindingListItem(elem); elts.push(elem); } } return elts; }; pp$2.parseBindingListItem = function (param) { return param; }; // Parses assignment pattern around given atom if possible. pp$2.parseMaybeDefault = function (startPos, startLoc, left) { left = left || this.parseBindingAtom(); if (this.options.ecmaVersion < 6 || !this.eat(tt.eq)) return left; var node = this.startNodeAt(startPos, startLoc); node.left = left; node.right = this.parseMaybeAssign(); return this.finishNode(node, "AssignmentPattern"); }; // Verify that a node is an lval — something that can be assigned // to. pp$2.checkLVal = function (expr, isBinding, checkClashes) { switch (expr.type) { case "Identifier": if (this.strict && this.reservedWordsStrictBind.test(expr.name)) this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); if (checkClashes) { if (has(checkClashes, expr.name)) this.raise(expr.start, "Argument name clash"); checkClashes[expr.name] = true; } break; case "MemberExpression": if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression"); break; case "ObjectPattern": for (var i = 0; i < expr.properties.length; i++) { this.checkLVal(expr.properties[i].value, isBinding, checkClashes); }break; case "ArrayPattern": for (var i = 0; i < expr.elements.length; i++) { var elem = expr.elements[i]; if (elem) this.checkLVal(elem, isBinding, checkClashes); } break; case "AssignmentPattern": this.checkLVal(expr.left, isBinding, checkClashes); break; case "RestElement": this.checkLVal(expr.argument, isBinding, checkClashes); break; case "ParenthesizedExpression": this.checkLVal(expr.expression, isBinding, checkClashes); break; default: this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue"); } }; var pp$3 = Parser.prototype; // Check if property name clashes with already added. // Object/class getters and setters are not allowed to clash — // either with each other or with an init property — and in // strict mode, init properties are also not allowed to be repeated. pp$3.checkPropClash = function (prop, propHash) { if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) return; var key = prop.key;var name = undefined; switch (key.type) { case "Identifier": name = key.name;break; case "Literal": name = String(key.value);break; default: return; } var kind = prop.kind; if (this.options.ecmaVersion >= 6) { if (name === "__proto__" && kind === "init") { if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); propHash.proto = true; } return; } name = "$" + name; var other = propHash[name]; if (other) { var isGetSet = kind !== "init"; if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) this.raise(key.start, "Redefinition of property"); } else { other = propHash[name] = { init: false, get: false, set: false }; } other[kind] = true; }; // ### Expression parsing // These nest, from the most general expression type at the top to // 'atomic', nondivisible expression types at the bottom. Most of // the functions will simply let the function(s) below them parse, // and, *if* the syntactic construct they handle is present, wrap // the AST node that the inner parser gave them in another node. // Parse a full expression. The optional arguments are used to // forbid the `in` operator (in for loops initalization expressions) // and provide reference for storing '=' operator inside shorthand // property assignment in contexts where both object expression // and object pattern might appear (so it's possible to raise // delayed syntax error at correct position). pp$3.parseExpression = function (noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); if (this.type === tt.comma) { var node = this.startNodeAt(startPos, startLoc); node.expressions = [expr]; while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); return this.finishNode(node, "SequenceExpression"); } return expr; }; // Parse an assignment expression. This includes applications of // operators like `+=`. pp$3.parseMaybeAssign = function (noIn, refDestructuringErrors, afterLeftParse) { if (this.type == tt._yield && this.inGenerator) return this.parseYield(); var validateDestructuring = false; if (!refDestructuringErrors) { refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }; validateDestructuring = true; } var startPos = this.start, startLoc = this.startLoc; if (this.type == tt.parenL || this.type == tt.name) this.potentialArrowAt = this.start; var left = this.parseMaybeConditional(noIn, refDestructuringErrors); if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc); if (this.type.isAssign) { if (validateDestructuring) this.checkPatternErrors(refDestructuringErrors, true); var node = this.startNodeAt(startPos, startLoc); node.operator = this.value; node.left = this.type === tt.eq ? this.toAssignable(left) : left; refDestructuringErrors.shorthandAssign = 0; // reset because shorthand default was used correctly this.checkLVal(left); this.next(); node.right = this.parseMaybeAssign(noIn); return this.finishNode(node, "AssignmentExpression"); } else { if (validateDestructuring) this.checkExpressionErrors(refDestructuringErrors, true); } return left; }; // Parse a ternary conditional (`?:`) operator. pp$3.parseMaybeConditional = function (noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseExprOps(noIn, refDestructuringErrors); if (this.checkExpressionErrors(refDestructuringErrors)) return expr; if (this.eat(tt.question)) { var node = this.startNodeAt(startPos, startLoc); node.test = expr; node.consequent = this.parseMaybeAssign(); this.expect(tt.colon); node.alternate = this.parseMaybeAssign(noIn); return this.finishNode(node, "ConditionalExpression"); } return expr; }; // Start the precedence parser. pp$3.parseExprOps = function (noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseMaybeUnary(refDestructuringErrors); if (this.checkExpressionErrors(refDestructuringErrors)) return expr; return this.parseExprOp(expr, startPos, startLoc, -1, noIn); }; // Parse binary operators with the operator precedence parsing // algorithm. `left` is the left-hand side of the operator. // `minPrec` provides context that allows the function to stop and // defer further parser to one of its callers when it encounters an // operator that has a lower precedence than the set it is parsing. pp$3.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, noIn) { var prec = this.type.binop; if (prec != null && (!noIn || this.type !== tt._in)) { if (prec > minPrec) { var node = this.startNodeAt(leftStartPos, leftStartLoc); node.left = left; node.operator = this.value; var op = this.type; this.next(); var startPos = this.start, startLoc = this.startLoc; node.right = this.parseExprOp(this.parseMaybeUnary(), startPos, startLoc, prec, noIn); this.finishNode(node, op === tt.logicalOR || op === tt.logicalAND ? "LogicalExpression" : "BinaryExpression"); return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn); } } return left; }; // Parse unary operators, both prefix and postfix. pp$3.parseMaybeUnary = function (refDestructuringErrors) { if (this.type.prefix) { var node = this.startNode(), update = this.type === tt.incDec; node.operator = this.value; node.prefix = true; this.next(); node.argument = this.parseMaybeUnary(); this.checkExpressionErrors(refDestructuringErrors, true); if (update) this.checkLVal(node.argument);else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") this.raise(node.start, "Deleting local variable in strict mode"); return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); } var startPos = this.start, startLoc = this.startLoc; var expr = this.parseExprSubscripts(refDestructuringErrors); if (this.checkExpressionErrors(refDestructuringErrors)) return expr; while (this.type.postfix && !this.canInsertSemicolon()) { var node = this.startNodeAt(startPos, startLoc); node.operator = this.value; node.prefix = false; node.argument = expr; this.checkLVal(expr); this.next(); expr = this.finishNode(node, "UpdateExpression"); } return expr; }; // Parse call, dot, and `[]`-subscript expressions. pp$3.parseExprSubscripts = function (refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseExprAtom(refDestructuringErrors); var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr; return this.parseSubscripts(expr, startPos, startLoc); }; pp$3.parseSubscripts = function (base, startPos, startLoc, noCalls) { for (;;) { if (this.eat(tt.dot)) { var node = this.startNodeAt(startPos, startLoc); node.object = base; node.property = this.parseIdent(true); node.computed = false; base = this.finishNode(node, "MemberExpression"); } else if (this.eat(tt.bracketL)) { var node = this.startNodeAt(startPos, startLoc); node.object = base; node.property = this.parseExpression(); node.computed = true; this.expect(tt.bracketR); base = this.finishNode(node, "MemberExpression"); } else if (!noCalls && this.eat(tt.parenL)) { var node = this.startNodeAt(startPos, startLoc); node.callee = base; node.arguments = this.parseExprList(tt.parenR, false); base = this.finishNode(node, "CallExpression"); } else if (this.type === tt.backQuote) { var node = this.startNodeAt(startPos, startLoc); node.tag = base; node.quasi = this.parseTemplate(); base = this.finishNode(node, "TaggedTemplateExpression"); } else { return base; } } }; // Parse an atomic expression — either a single token that is an // expression, an expression started by a keyword like `function` or // `new`, or an expression wrapped in punctuation like `()`, `[]`, // or `{}`. pp$3.parseExprAtom = function (refDestructuringErrors) { var node = undefined, canBeArrow = this.potentialArrowAt == this.start; switch (this.type) { case tt._super: if (!this.inFunction) this.raise(this.start, "'super' outside of function or class"); case tt._this: var type = this.type === tt._this ? "ThisExpression" : "Super"; node = this.startNode(); this.next(); return this.finishNode(node, type); case tt._yield: if (this.inGenerator) this.unexpected(); case tt.name: var startPos = this.start, startLoc = this.startLoc; var id = this.parseIdent(this.type !== tt.name); if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id]); return id; case tt.regexp: var value = this.value; node = this.parseLiteral(value.value); node.regex = { pattern: value.pattern, flags: value.flags }; return node; case tt.num:case tt.string: return this.parseLiteral(this.value); case tt._null:case tt._true:case tt._false: node = this.startNode(); node.value = this.type === tt._null ? null : this.type === tt._true; node.raw = this.type.keyword; this.next(); return this.finishNode(node, "Literal"); case tt.parenL: return this.parseParenAndDistinguishExpression(canBeArrow); case tt.bracketL: node = this.startNode(); this.next(); // check whether this is array comprehension or regular array if (this.options.ecmaVersion >= 7 && this.type === tt._for) { return this.parseComprehension(node, false); } node.elements = this.parseExprList(tt.bracketR, true, true, refDestructuringErrors); return this.finishNode(node, "ArrayExpression"); case tt.braceL: return this.parseObj(false, refDestructuringErrors); case tt._function: node = this.startNode(); this.next(); return this.parseFunction(node, false); case tt._class: return this.parseClass(this.startNode(), false); case tt._new: return this.parseNew(); case tt.backQuote: return this.parseTemplate(); default: this.unexpected(); } }; pp$3.parseLiteral = function (value) { var node = this.startNode(); node.value = value; node.raw = this.input.slice(this.start, this.end); this.next(); return this.finishNode(node, "Literal"); }; pp$3.parseParenExpression = function () { this.expect(tt.parenL); var val = this.parseExpression(); this.expect(tt.parenR); return val; }; pp$3.parseParenAndDistinguishExpression = function (canBeArrow) { var startPos = this.start, startLoc = this.startLoc, val = undefined; if (this.options.ecmaVersion >= 6) { this.next(); if (this.options.ecmaVersion >= 7 && this.type === tt._for) { return this.parseComprehension(this.startNodeAt(startPos, startLoc), true); } var innerStartPos = this.start, innerStartLoc = this.startLoc; var exprList = [], first = true; var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }, spreadStart = undefined, innerParenStart = undefined; while (this.type !== tt.parenR) { first ? first = false : this.expect(tt.comma); if (this.type === tt.ellipsis) { spreadStart = this.start; exprList.push(this.parseParenItem(this.parseRest())); break; } else { if (this.type === tt.parenL && !innerParenStart) { innerParenStart = this.start; } exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); } } var innerEndPos = this.start, innerEndLoc = this.startLoc; this.expect(tt.parenR); if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { this.checkPatternErrors(refDestructuringErrors, true); if (innerParenStart) this.unexpected(innerParenStart); return this.parseParenArrowList(startPos, startLoc, exprList); } if (!exprList.length) this.unexpected(this.lastTokStart); if (spreadStart) this.unexpected(spreadStart); this.checkExpressionErrors(refDestructuringErrors, true); if (exprList.length > 1) { val = this.startNodeAt(innerStartPos, innerStartLoc); val.expressions = exprList; this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); } else { val = exprList[0]; } } else { val = this.parseParenExpression(); } if (this.options.preserveParens) { var par = this.startNodeAt(startPos, startLoc); par.expression = val; return this.finishNode(par, "ParenthesizedExpression"); } else { return val; } }; pp$3.parseParenItem = function (item) { return item; }; pp$3.parseParenArrowList = function (startPos, startLoc, exprList) { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList); }; // New's precedence is slightly tricky. It must allow its argument to // be a `[]` or dot subscript expression, but not a call — at least, // not without wrapping it in parentheses. Thus, it uses the noCalls // argument to parseSubscripts to prevent it from consuming the // argument list. var empty$1 = []; pp$3.parseNew = function () { var node = this.startNode(); var meta = this.parseIdent(true); if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) { node.meta = meta; node.property = this.parseIdent(true); if (node.property.name !== "target") this.raise(node.property.start, "The only valid meta property for new is new.target"); if (!this.inFunction) this.raise(node.start, "new.target can only be used in functions"); return this.finishNode(node, "MetaProperty"); } var startPos = this.start, startLoc = this.startLoc; node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, false);else node.arguments = empty$1; return this.finishNode(node, "NewExpression"); }; // Parse template expression. pp$3.parseTemplateElement = function () { var elem = this.startNode(); elem.value = { raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'), cooked: this.value }; this.next(); elem.tail = this.type === tt.backQuote; return this.finishNode(elem, "TemplateElement"); }; pp$3.parseTemplate = function () { var node = this.startNode(); this.next(); node.expressions = []; var curElt = this.parseTemplateElement(); node.quasis = [curElt]; while (!curElt.tail) { this.expect(tt.dollarBraceL); node.expressions.push(this.parseExpression()); this.expect(tt.braceR); node.quasis.push(curElt = this.parseTemplateElement()); } this.next(); return this.finishNode(node, "TemplateLiteral"); }; // Parse an object literal or binding pattern. pp$3.parseObj = function (isPattern, refDestructuringErrors) { var node = this.startNode(), first = true, propHash = {}; node.properties = []; this.next(); while (!this.eat(tt.braceR)) { if (!first) { this.expect(tt.comma); if (this.afterTrailingComma(tt.braceR)) break; } else first = false; var prop = this.startNode(), isGenerator = undefined, startPos = undefined, startLoc = undefined; if (this.options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; if (isPattern || refDestructuringErrors) { startPos = this.start; startLoc = this.startLoc; } if (!isPattern) isGenerator = this.eat(tt.star); } this.parsePropertyName(prop); this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors); this.checkPropClash(prop, propHash); node.properties.push(this.finishNode(prop, "Property")); } return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression"); }; pp$3.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) { if (this.eat(tt.colon)) { prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); prop.kind = "init"; } else if (this.options.ecmaVersion >= 6 && this.type === tt.parenL) { if (isPattern) this.unexpected(); prop.kind = "init"; prop.method = true; prop.value = this.parseMethod(isGenerator); } else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && this.type != tt.comma && this.type != tt.braceR) { if (isGenerator || isPattern) this.unexpected(); prop.kind = prop.key.name; this.parsePropertyName(prop); prop.value = this.parseMethod(false); var paramCount = prop.kind === "get" ? 0 : 1; if (prop.value.params.length !== paramCount) { var start = prop.value.start; if (prop.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param"); } if (prop.kind === "set" && prop.value.params[0].type === "RestElement") this.raise(prop.value.params[0].start, "Setter cannot use rest params"); } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { prop.kind = "init"; if (isPattern) { if (this.keywords.test(prop.key.name) || (this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name)) this.raise(prop.key.start, "Binding " + prop.key.name); prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else if (this.type === tt.eq && refDestructuringErrors) { if (!refDestructuringErrors.shorthandAssign) refDestructuringErrors.shorthandAssign = this.start; prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else { prop.value = prop.key; } prop.shorthand = true; } else this.unexpected(); }; pp$3.parsePropertyName = function (prop) { if (this.options.ecmaVersion >= 6) { if (this.eat(tt.bracketL)) { prop.computed = true; prop.key = this.parseMaybeAssign(); this.expect(tt.bracketR); return prop.key; } else { prop.computed = false; } } return prop.key = this.type === tt.num || this.type === tt.string ? this.parseExprAtom() : this.parseIdent(true); }; // Initialize empty function node. pp$3.initFunction = function (node) { node.id = null; if (this.options.ecmaVersion >= 6) { node.generator = false; node.expression = false; } }; // Parse object or class method. pp$3.parseMethod = function (isGenerator) { var node = this.startNode(); this.initFunction(node); this.expect(tt.parenL); node.params = this.parseBindingList(tt.parenR, false, false); if (this.options.ecmaVersion >= 6) node.generator = isGenerator; this.parseFunctionBody(node, false); return this.finishNode(node, "FunctionExpression"); }; // Parse arrow function expression with given parameters. pp$3.parseArrowExpression = function (node, params) { this.initFunction(node); node.params = this.toAssignableList(params, true); this.parseFunctionBody(node, true); return this.finishNode(node, "ArrowFunctionExpression"); }; // Parse function body and check parameters. pp$3.parseFunctionBody = function (node, isArrowFunction) { var isExpression = isArrowFunction && this.type !== tt.braceL; if (isExpression) { node.body = this.parseMaybeAssign(); node.expression = true; } else { // Start a new scope with regard to labels and the `inFunction` // flag (restore them to their old value afterwards). var oldInFunc = this.inFunction, oldInGen = this.inGenerator, oldLabels = this.labels; this.inFunction = true;this.inGenerator = node.generator;this.labels = []; node.body = this.parseBlock(true); node.expression = false; this.inFunction = oldInFunc;this.inGenerator = oldInGen;this.labels = oldLabels; } // If this is a strict mode function, verify that argument names // are not repeated, and it does not try to bind the words `eval` // or `arguments`. if (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) { var oldStrict = this.strict; this.strict = true; if (node.id) this.checkLVal(node.id, true); this.checkParams(node); this.strict = oldStrict; } else if (isArrowFunction) { this.checkParams(node); } }; // Checks function params for various disallowed patterns such as using "eval" // or "arguments" and duplicate parameters. pp$3.checkParams = function (node) { var nameHash = {}; for (var i = 0; i < node.params.length; i++) { this.checkLVal(node.params[i], true, nameHash); } }; // Parses a comma-separated list of expressions, and returns them as // an array. `close` is the token type that ends the list, and // `allowEmpty` can be turned on to allow subsequent commas with // nothing in between them to be parsed as `null` (which is needed // for array literals). pp$3.parseExprList = function (close, allowTrailingComma, allowEmpty, refDestructuringErrors) { var elts = [], first = true; while (!this.eat(close)) { if (!first) { this.expect(tt.comma); if (this.type === close && refDestructuringErrors && !refDestructuringErrors.trailingComma) { refDestructuringErrors.trailingComma = this.lastTokStart; } if (allowTrailingComma && this.afterTrailingComma(close)) break; } else first = false; var elt = undefined; if (allowEmpty && this.type === tt.comma) elt = null;else if (this.type === tt.ellipsis) elt = this.parseSpread(refDestructuringErrors);else elt = this.parseMaybeAssign(false, refDestructuringErrors); elts.push(elt); } return elts; }; // Parse the next token as an identifier. If `liberal` is true (used // when parsing properties), it will also convert keywords into // identifiers. pp$3.parseIdent = function (liberal) { var node = this.startNode(); if (liberal && this.options.allowReserved == "never") liberal = false; if (this.type === tt.name) { if (!liberal && (this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) && (this.options.ecmaVersion >= 6 || this.input.slice(this.start, this.end).indexOf("\\") == -1)) this.raise(this.start, "The keyword '" + this.value + "' is reserved"); node.name = this.value; } else if (liberal && this.type.keyword) { node.name = this.type.keyword; } else { this.unexpected(); } this.next(); return this.finishNode(node, "Identifier"); }; // Parses yield expression inside generator. pp$3.parseYield = function () { var node = this.startNode(); this.next(); if (this.type == tt.semi || this.canInsertSemicolon() || this.type != tt.star && !this.type.startsExpr) { node.delegate = false; node.argument = null; } else { node.delegate = this.eat(tt.star); node.argument = this.parseMaybeAssign(); } return this.finishNode(node, "YieldExpression"); }; // Parses array and generator comprehensions. pp$3.parseComprehension = function (node, isGenerator) { node.blocks = []; while (this.type === tt._for) { var block = this.startNode(); this.next(); this.expect(tt.parenL); block.left = this.parseBindingAtom(); this.checkLVal(block.left, true); this.expectContextual("of"); block.right = this.parseExpression(); this.expect(tt.parenR); node.blocks.push(this.finishNode(block, "ComprehensionBlock")); } node.filter = this.eat(tt._if) ? this.parseParenExpression() : null; node.body = this.parseExpression(); this.expect(isGenerator ? tt.parenR : tt.bracketR); node.generator = isGenerator; return this.finishNode(node, "ComprehensionExpression"); }; var pp$4 = Parser.prototype; // This function is used to raise exceptions on parse errors. It // takes an offset integer (into the current `input`) to indicate // the location of the error, attaches the position to the end // of the error message, and then raises a `SyntaxError` with that // message. pp$4.raise = function (pos, message) { var loc = getLineInfo(this.input, pos); message += " (" + loc.line + ":" + loc.column + ")"; var err = new SyntaxError(message); err.pos = pos;err.loc = loc;err.raisedAt = this.pos; throw err; }; pp$4.curPosition = function () { if (this.options.locations) { return new Position(this.curLine, this.pos - this.lineStart); } }; var Node = function Node(parser, pos, loc) { babelHelpers.classCallCheck(this, Node); this.type = ""; this.start = pos; this.end = 0; if (parser.options.locations) this.loc = new SourceLocation(parser, loc); if (parser.options.directSourceFile) this.sourceFile = parser.options.directSourceFile; if (parser.options.ranges) this.range = [pos, 0]; } // Start an AST node, attaching a start offset. ; var pp$5 = Parser.prototype; pp$5.startNode = function () { return new Node(this, this.start, this.startLoc); }; pp$5.startNodeAt = function (pos, loc) { return new Node(this, pos, loc); }; // Finish an AST node, adding `type` and `end` properties. function finishNodeAt(node, type, pos, loc) { node.type = type; node.end = pos; if (this.options.locations) node.loc.end = loc; if (this.options.ranges) node.range[1] = pos; return node; } pp$5.finishNode = function (node, type) { return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc); }; // Finish node at given position pp$5.finishNodeAt = function (node, type, pos, loc) { return finishNodeAt.call(this, node, type, pos, loc); }; var TokContext = function TokContext(token, isExpr, preserveSpace, override) { babelHelpers.classCallCheck(this, TokContext); this.token = token; this.isExpr = !!isExpr; this.preserveSpace = !!preserveSpace; this.override = override; }; var types = { b_stat: new TokContext("{", false), b_expr: new TokContext("{", true), b_tmpl: new TokContext("${", true), p_stat: new TokContext("(", false), p_expr: new TokContext("(", true), q_tmpl: new TokContext("`", true, true, function (p) { return p.readTmplToken(); }), f_expr: new TokContext("function", true) }; var pp$6 = Parser.prototype; pp$6.initialContext = function () { return [types.b_stat]; }; pp$6.braceIsBlock = function (prevType) { if (prevType === tt.colon) { var _parent = this.curContext(); if (_parent === types.b_stat || _parent === types.b_expr) return !_parent.isExpr; } if (prevType === tt._return) return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)); if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR) return true; if (prevType == tt.braceL) return this.curContext() === types.b_stat; return !this.exprAllowed; }; pp$6.updateContext = function (prevType) { var update = undefined, type = this.type; if (type.keyword && prevType == tt.dot) this.exprAllowed = false;else if (update = type.updateContext) update.call(this, prevType);else this.exprAllowed = type.beforeExpr; }; // Token-specific context update code tt.parenR.updateContext = tt.braceR.updateContext = function () { if (this.context.length == 1) { this.exprAllowed = true; return; } var out = this.context.pop(); if (out === types.b_stat && this.curContext() === types.f_expr) { this.context.pop(); this.exprAllowed = false; } else if (out === types.b_tmpl) { this.exprAllowed = true; } else { this.exprAllowed = !out.isExpr; } }; tt.braceL.updateContext = function (prevType) { this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr); this.exprAllowed = true; }; tt.dollarBraceL.updateContext = function () { this.context.push(types.b_tmpl); this.exprAllowed = true; }; tt.parenL.updateContext = function (prevType) { var statementParens = prevType === tt._if || prevType === tt._for || prevType === tt._with || prevType === tt._while; this.context.push(statementParens ? types.p_stat : types.p_expr); this.exprAllowed = true; }; tt.incDec.updateContext = function () { // tokExprAllowed stays unchanged }; tt._function.updateContext = function () { if (this.curContext() !== types.b_stat) this.context.push(types.f_expr); this.exprAllowed = false; }; tt.backQuote.updateContext = function () { if (this.curContext() === types.q_tmpl) this.context.pop();else this.context.push(types.q_tmpl); this.exprAllowed = false; }; // Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer. var Token = function Token(p) { babelHelpers.classCallCheck(this, Token); this.type = p.type; this.value = p.value; this.start = p.start; this.end = p.end; if (p.options.locations) this.loc = new SourceLocation(p, p.startLoc, p.endLoc); if (p.options.ranges) this.range = [p.start, p.end]; } // ## Tokenizer ; var pp$7 = Parser.prototype; // Are we running under Rhino? var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]"; // Move to the next token pp$7.next = function () { if (this.options.onToken) this.options.onToken(new Token(this)); this.lastTokEnd = this.end; this.lastTokStart = this.start; this.lastTokEndLoc = this.endLoc; this.lastTokStartLoc = this.startLoc; this.nextToken(); }; pp$7.getToken = function () { this.next(); return new Token(this); }; // If we're in an ES6 environment, make parsers iterable if (typeof Symbol !== "undefined") pp$7[Symbol.iterator] = function () { var self = this; return { next: function () { var token = self.getToken(); return { done: token.type === tt.eof, value: token }; } }; }; // Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`"use strict"; 010;` should fail). pp$7.setStrict = function (strict) { this.strict = strict; if (this.type !== tt.num && this.type !== tt.string) return; this.pos = this.start; if (this.options.locations) { while (this.pos < this.lineStart) { this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1; --this.curLine; } } this.nextToken(); }; pp$7.curContext = function () { return this.context[this.context.length - 1]; }; // Read a single token, updating the parser object's token-related // properties. pp$7.nextToken = function () { var curContext = this.curContext(); if (!curContext || !curContext.preserveSpace) this.skipSpace(); this.start = this.pos; if (this.options.locations) this.startLoc = this.curPosition(); if (this.pos >= this.input.length) return this.finishToken(tt.eof); if (curContext.override) return curContext.override(this);else this.readToken(this.fullCharCodeAtPos()); }; pp$7.readToken = function (code) { // Identifier or keyword. '\uXXXX' sequences are allowed in // identifiers, so '\' also dispatches to that. if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) return this.readWord(); return this.getTokenFromCode(code); }; pp$7.fullCharCodeAtPos = function () { var code = this.input.charCodeAt(this.pos); if (code <= 0xd7ff || code >= 0xe000) return code; var next = this.input.charCodeAt(this.pos + 1); return (code << 10) + next - 0x35fdc00; }; pp$7.skipBlockComment = function () { var startLoc = this.options.onComment && this.curPosition(); var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); if (end === -1) this.raise(this.pos - 2, "Unterminated comment"); this.pos = end + 2; if (this.options.locations) { lineBreakG.lastIndex = start; var match = undefined; while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { ++this.curLine; this.lineStart = match.index + match[0].length; } } if (this.options.onComment) this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, startLoc, this.curPosition()); }; pp$7.skipLineComment = function (startSkip) { var start = this.pos; var startLoc = this.options.onComment && this.curPosition(); var ch = this.input.charCodeAt(this.pos += startSkip); while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { ++this.pos; ch = this.input.charCodeAt(this.pos); } if (this.options.onComment) this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, startLoc, this.curPosition()); }; // Called at the start of the parse and after every token. Skips // whitespace and comments, and. pp$7.skipSpace = function () { loop: while (this.pos < this.input.length) { var ch = this.input.charCodeAt(this.pos); switch (ch) { case 32:case 160: // ' ' ++this.pos; break; case 13: if (this.input.charCodeAt(this.pos + 1) === 10) { ++this.pos; } case 10:case 8232:case 8233: ++this.pos; if (this.options.locations) { ++this.curLine; this.lineStart = this.pos; } break; case 47: // '/' switch (this.input.charCodeAt(this.pos + 1)) { case 42: // '*' this.skipBlockComment(); break; case 47: this.skipLineComment(2); break; default: break loop; } break; default: if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { ++this.pos; } else { break loop; } } } }; // Called at the end of every token. Sets `end`, `val`, and // maintains `context` and `exprAllowed`, and skips the space after // the token, so that the next one's `start` will point at the // right position. pp$7.finishToken = function (type, val) { this.end = this.pos; if (this.options.locations) this.endLoc = this.curPosition(); var prevType = this.type; this.type = type; this.value = val; this.updateContext(prevType); }; // ### Token reading // This is the function that is called to fetch the next token. It // is somewhat obscure, because it works in character codes rather // than characters, and because operator parsing has been inlined // into it. // // All in the name of speed. // pp$7.readToken_dot = function () { var next = this.input.charCodeAt(this.pos + 1); if (next >= 48 && next <= 57) return this.readNumber(true); var next2 = this.input.charCodeAt(this.pos + 2); if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' this.pos += 3; return this.finishToken(tt.ellipsis); } else { ++this.pos; return this.finishToken(tt.dot); } }; pp$7.readToken_slash = function () { // '/' var next = this.input.charCodeAt(this.pos + 1); if (this.exprAllowed) { ++this.pos;return this.readRegexp(); } if (next === 61) return this.finishOp(tt.assign, 2); return this.finishOp(tt.slash, 1); }; pp$7.readToken_mult_modulo = function (code) { // '%*' var next = this.input.charCodeAt(this.pos + 1); if (next === 61) return this.finishOp(tt.assign, 2); return this.finishOp(code === 42 ? tt.star : tt.modulo, 1); }; pp$7.readToken_pipe_amp = function (code) { // '|&' var next = this.input.charCodeAt(this.pos + 1); if (next === code) return this.finishOp(code === 124 ? tt.logicalOR : tt.logicalAND, 2); if (next === 61) return this.finishOp(tt.assign, 2); return this.finishOp(code === 124 ? tt.bitwiseOR : tt.bitwiseAND, 1); }; pp$7.readToken_caret = function () { // '^' var next = this.input.charCodeAt(this.pos + 1); if (next === 61) return this.finishOp(tt.assign, 2); return this.finishOp(tt.bitwiseXOR, 1); }; pp$7.readToken_plus_min = function (code) { // '+-' var next = this.input.charCodeAt(this.pos + 1); if (next === code) { if (next == 45 && this.input.charCodeAt(this.pos + 2) == 62 && lineBreak.test(this.input.slice(this.lastTokEnd, this.pos))) { // A `-->` line comment this.skipLineComment(3); this.skipSpace(); return this.nextToken(); } return this.finishOp(tt.incDec, 2); } if (next === 61) return this.finishOp(tt.assign, 2); return this.finishOp(tt.plusMin, 1); }; pp$7.readToken_lt_gt = function (code) { // '<>' var next = this.input.charCodeAt(this.pos + 1); var size = 1; if (next === code) { size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1); return this.finishOp(tt.bitShift, size); } if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 && this.input.charCodeAt(this.pos + 3) == 45) { if (this.inModule) this.unexpected(); // `