From 91d00a46fd3917991e315b96ffee422fc23fea16 Mon Sep 17 00:00:00 2001 From: Fred Christensen Date: Fri, 26 Jan 2018 13:07:45 -0700 Subject: [PATCH 1/5] Possible suggestions for clarity --- src/neural-network.js | 204 +++++++++++++++++++++++++----------------- test/base/options.js | 14 --- 2 files changed, 124 insertions(+), 94 deletions(-) diff --git a/src/neural-network.js b/src/neural-network.js index b7e43a64d..f5b9b9aca 100644 --- a/src/neural-network.js +++ b/src/neural-network.js @@ -15,23 +15,23 @@ import Thaw from 'thaw.js'; export default class NeuralNetwork { static get trainDefaults() { return { - iterations: 20000, - errorThresh: 0.005, - log: false, - logPeriod: 10, - learningRate: 0.3, - callback: null, - callbackPeriod: 10 + iterations: 20000, // the maximum times to iterate the training data + errorThresh: 0.005, // the acceptable error percentage from training data + log: false, // true to use console.log, when a function is supplied it is used + logPeriod: 10, // iterations between logging out + learningRate: 0.3, // multiply's against the input and the delta then adds to momentum + momentum: 0.1, // multiply's against the specified "change" then adds to learning rate for change + callback: null, // a periodic call back that can be triggered while training + callbackPeriod: 10, // the number of iterations through the training data between callback calls + timeout: Infinity // the max number of milliseconds to train for }; } static get defaults() { return { - learningRate: 0.3, - momentum: 0.1, - binaryThresh: 0.5, - hiddenLayers: null, - activation: 'sigmoid' + binaryThresh: 0.5, // ¯\_(ツ)_/¯ + hiddenLayers: [3], // array of ints for the sizes of the hidden layers in the network + activation: 'sigmoid' // Supported activation types ['sigmoid', 'relu', 'leaky-relu', 'tanh'] }; } @@ -39,6 +39,11 @@ export default class NeuralNetwork { Object.assign(this, this.constructor.defaults, options); this.hiddenSizes = options.hiddenLayers; + let backCompat = {}; + if (options.learningRate) backCompat.learningRate = options.learningRate; + if (options.momentum) backCompat.momentum = options.momentum; + this.trainOpts = Object.assign({}, this.constructor.trainDefaults, backCompat); + this.sizes = null; this.outputLayer = null; this.biases = null; // weights for bias nodes @@ -60,10 +65,11 @@ export default class NeuralNetwork { /** * - * @param {Number[]} sizes + * Expects this.sizes to have been set */ - initialize(sizes) { - this.sizes = sizes; + _initialize() { + if (!this.sizes) throw new Error ('Sizes must be set before initializing') + this.outputLayer = this.sizes.length - 1; this.biases = []; // weights for bias nodes this.weights = []; @@ -96,6 +102,10 @@ export default class NeuralNetwork { this.setActivation(); } + /** + * + * @param supported input: ['sigmoid', 'relu', 'leaky-relu', 'tanh'] + */ setActivation() { switch (this.activation) { case 'sigmoid': @@ -255,26 +265,66 @@ export default class NeuralNetwork { /** * * @param data - * @returns sizes + * Verifies network sizes are initilaized + * If they are not it will initialize them based off the data set. */ - _getSizesFromData(data) { - let sizes = []; - let inputSize = data[0].input.length; - let outputSize = data[0].output.length; - let hiddenSizes = this.hiddenSizes; - if (!hiddenSizes) { - sizes.push(Math.max(3, Math.floor(inputSize / 2))); + _verifyIsInitialized(data) { + if (this.sizes) return; + + this.sizes = []; + this.sizes.push(data[0].input.length); + if (!this.hiddenSizes) { + this.sizes.push(Math.max(3, Math.floor(data[0].input.length / 2))); } else { - hiddenSizes.forEach(size => { - sizes.push(size); + this.hiddenSizes.forEach(size => { + this.sizes.push(size); }); } + this.sizes.push(data[0].output.length) - sizes.unshift(inputSize); - sizes.push(outputSize); - return sizes; + this._initialize(); } + /** + * + * @param options + * Supports all `trainDefaults` properties + * also supports: + * learningRate: (number), + * momentum: (number), + * activation: ['sigmoid', 'relu', 'leaky-relu', 'tanh'] + */ + _updateTrainingOptions(opts) { + if (opts.iterations) { this.trainOpts.iterations = opts.iterations; } + if (opts.errorThresh) { this.trainOpts.errorThresh = opts.errorThresh; } + if (opts.log) { this._setLogMethod(opts.log); } + if (opts.logPeriod) { this.trainOpts.logPeriod = opts.logPeriod; } + if (opts.learningRate) { this.trainOpts.learningRate = opts.learningRate; } + if (opts.momentum) { this.trainOpts.momentum = opts.momentum; } + if (opts.callback) { this.trainOpts.callback = opts.callback; } + if (opts.callbackPeriod) { this.trainOpts.callbackPeriod = opts.callbackPeriod; } + if (opts.timeout) { this.trainOpts.callbackPeriod = opts.timeout; } + if (opts.activation) { this.activation = opts.activation; } + } + + /** + * + * Gets JSON of trainOpts object + * NOTE: Activation is stored directly on JSON object and not in the training options + */ + _getTrainOptsJSON() { + let results = {} + if (this.trainOpts.iterations) { results.iterations = this.trainOpts.iterations; } + if (this.trainOpts.errorThresh) { results.errorThresh = this.trainOpts.errorThresh; } + if (this.trainOpts.logPeriod) { results.logPeriod = this.trainOpts.logPeriod; } + if (this.trainOpts.learningRate) { results.learningRate = this.trainOpts.learningRate; } + if (this.trainOpts.momentum) { results.momentum = this.trainOpts.momentum; } + if (this.trainOpts.callback) { results.callback = this.trainOpts.callback; } + if (this.trainOpts.callbackPeriod) { results.callbackPeriod = this.trainOpts.callbackPeriod; } + if (this.trainOpts.timeout) { results.timeout = this.trainOpts.timeout; } + if (this.trainOpts.log) { results.log = true; } + return results; + } /** * @@ -284,8 +334,13 @@ export default class NeuralNetwork { * @returns error */ _setLogMethod(log) { - if (log) return console.log; - return false; + if (typeof log === 'function'){ + this.trainOpts.log = log; + } else if (log) { + this.trainOpts.log = console.log; + } else { + this.trainOpts.log = false; + } } /** @@ -294,10 +349,10 @@ export default class NeuralNetwork { * @param learning Rate * @returns error */ - _calculateTrainingError(data, learningRate) { + _calculateTrainingError(data) { let sum = 0; for (let i = 0; i < data.length; ++i) { - sum += this.trainPattern(data[i].input, data[i].output, learningRate); + sum += this._trainPattern(data[i].input, data[i].output); } return sum / data.length; } @@ -307,42 +362,39 @@ export default class NeuralNetwork { * @param status { iterations: number, error: number} * @param options */ - _checkTrainingTick(data, status, options) { + _trainingTick(data, status) { status.iterations++; - status.error = this._calculateTrainingError(data, options.learningRate); + status.error = this._calculateTrainingError(data); - if (options.log && (status.iterations % options.logPeriod === 0)) { - options.log(`iterations: ${status.iterations}, training error: ${status.error}`); + if (this.trainOpts.log && (status.iterations % this.trainOpts.logPeriod === 0)) { + this.trainOpts.log(`iterations: ${status.iterations}, training error: ${status.error}`); } - if (options.callback && (status.iterations % options.callbackPeriod === 0)) { - options.callback(Object.assign(status)); + if (this.trainOpts.callback && (status.iterations % this.trainOpts.callbackPeriod === 0)) { + this.trainOpts.callback(Object.assign(status)); } } /** * * @param data - * @param _options + * @param options * @returns {{error: number, iterations: number}} */ - train(data, _options = {}) { - const options = Object.assign({}, this.constructor.trainDefaults, _options); + train(data, options = {}) { + this._updateTrainingOptions(options); data = this.formatData(data); - options.log = this._setLogMethod(options.log); - options.learningRate = _options.learningRate || this.learningRate || options.learningRate; - var status = { + const endTime = Date.now() + this.trainOpts.timeout; + + const status = { error: 1, iterations: 0 }; - if (this.sizes === null) { - let sizes = this._getSizesFromData(data); - this.initialize(sizes); - } + this._verifyIsInitialized(data); - while ( status.iterations < options.iterations && status.error > options.errorThresh) { - this._checkTrainingTick(data, status, options); + while (status.iterations < this.trainOpts.iterations && status.error > this.trainOpts.errorThresh && Date.now() < endTime) { + this._trainingTick(data, status); } return status; @@ -351,41 +403,33 @@ export default class NeuralNetwork { /** * * @param data - * @param _options + * @param options * @param cb * @returns {{error: number, iterations: number}} */ - trainAsync(data, _options = {}) { + trainAsync(data, options = {}) { return new Promise((resolve, reject) => { - const options = Object.assign({}, this.constructor.trainDefaults, _options); + this._updateTrainingOptions(options); data = this.formatData(data); - options.log = this._setLogMethod(options.log); - options.learningRate = _options.learningRate || this.learningRate || options.learningRate; - let endTime = Date.now() + options.trainTimeMs; + const endTime = Date.now() + this.trainOpts.timeout; - let status = { + const status = { error: 1, iterations: 0 }; - if (this.sizes === null) { - let sizes = this._getSizesFromData(data); - this.initialize(sizes); - } + this._verifyIsInitialized(data); - const items = new Array(options.iterations); + const items = new Array(this.trainOpts.iterations); const thaw = new Thaw(items, { delay: true, each: () => { - this._checkTrainingTick(data, status, options); - - if (status.error < options.errorThresh) { + this._trainingTick(data, status); + if (status.error < this.trainOpts.errorThresh || Date.now() > endTime) { thaw.stop(); } }, - done: () => { - resolve(status); - } + done: () => { resolve(status); } }); thaw.tick(); @@ -396,17 +440,15 @@ export default class NeuralNetwork { * * @param input * @param target - * @param learningRate */ - trainPattern(input, target, learningRate) { - learningRate = learningRate || this.learningRate; + _trainPattern(input, target) { // forward propagate this.runInput(input); // back propagate this.calculateDeltas(target); - this.adjustWeights(learningRate); + this.adjustWeights(); let error = mse(this.errors[this.outputLayer]); return error; @@ -514,9 +556,9 @@ export default class NeuralNetwork { /** * - * @param learningRate + * Changes weights of networks */ - adjustWeights(learningRate) { + adjustWeights() { for (let layer = 1; layer <= this.outputLayer; layer++) { let incoming = this.outputs[layer - 1]; @@ -526,13 +568,13 @@ export default class NeuralNetwork { for (let k = 0; k < incoming.length; k++) { let change = this.changes[layer][node][k]; - change = (learningRate * delta * incoming[k]) - + (this.momentum * change); + change = (this.trainOpts.learningRate * delta * incoming[k]) + + (this.trainOpts.momentum * change); this.changes[layer][node][k] = change; this.weights[layer][node][k] += change; } - this.biases[layer][node] += learningRate * delta; + this.biases[layer][node] += this.trainOpts.learningRate * delta; } } } @@ -735,7 +777,8 @@ export default class NeuralNetwork { layers, outputLookup:!!this.outputLookup, inputLookup:!!this.inputLookup, - activation: this.activation + activation: this.activation, + trainOpts: this._getTrainOptsJSON() }; } @@ -745,7 +788,8 @@ export default class NeuralNetwork { * @returns {NeuralNetwork} */ fromJSON (json) { - this.initialize (json.sizes); + this.sizes = json.sizes + this._initialize(); for (let i = 0; i <= this.outputLayer; i++) { let layer = json.layers[i]; @@ -765,7 +809,7 @@ export default class NeuralNetwork { } } } - + this._updateTrainingOptions(json.trainOpts) this.setActivation(); return this; } diff --git a/test/base/options.js b/test/base/options.js index 04eebbff0..7330f039b 100644 --- a/test/base/options.js +++ b/test/base/options.js @@ -125,29 +125,15 @@ describe('async neural network options', () => { }).catch(err => { assert.ok(false, err.toString()) }); - }).timeout(5000); }) describe('log', () => { let logCalled = false; - let oldLog; beforeEach(() => { logCalled = false; }); - before(() => { - oldLog = console.log; - console.log = () => { - oldLog(arguments); - logCalled = true; - } - }) - - after(() => { - console.log = oldLog; - }) - function logFunction(str) { logCalled = true; } From e9f1401e23c86f90580f207e0722092f90d68b24 Mon Sep 17 00:00:00 2001 From: Fred Christensen Date: Sat, 27 Jan 2018 21:24:33 -0700 Subject: [PATCH 2/5] Updates Made setActivation() accept a param to be more friendly for other users Created log test class Moved the options tests that were for training options into the training options tests made async training options tests. Updates some readme stuff --- README.md | 16 ++-- src/neural-network.js | 20 ++-- test/README.md | 2 +- test/base/hash.js | 2 +- test/base/json.js | 8 ++ test/base/log.js | 41 ++++++++ test/base/options.js | 210 +++++++++++++++-------------------------- test/base/trainopts.js | 147 +++++++++++++++++++++++++++-- 8 files changed, 286 insertions(+), 160 deletions(-) create mode 100644 test/base/log.js diff --git a/README.md b/README.md index dc93fd055..6a5bab927 100644 --- a/README.md +++ b/README.md @@ -129,11 +129,15 @@ var output = net.run({ r: 1, g: 0.4, b: 0 }); // { white: 0.81, black: 0.18 } ```javascript net.train(data, { - errorThresh: 0.005, // error threshold to reach - iterations: 20000, // maximum training iterations - log: true, // console.log() progress periodically - logPeriod: 10, // number of iterations between logging - learningRate: 0.3 // learning rate + iterations: 20000, // the maximum times to iterate the training data + errorThresh: 0.005, // the acceptable error percentage from training data + log: false, // true to use console.log, when a function is supplied it is used + logPeriod: 10, // iterations between logging out + learningRate: 0.3, // scales with delta to effect traiing rate + momentum: 0.1, // scales with next layer's change value + callback: null, // a periodic call back that can be triggered while training + callbackPeriod: 10, // the number of iterations through the training data between callback calls + timeout: Infinity // the max number of milliseconds to train for }); ``` @@ -143,6 +147,7 @@ By default training won't let you know how its doing until the end, but set `log The learning rate is a parameter that influences how quickly the network trains. It's a number from `0` to `1`. If the learning rate is close to `0` it will take longer to train. If the learning rate is closer to `1` it will train faster but it's in danger of training to a local minimum and performing badly on new data.(_Overfitting_) The default learning rate is `0.3`. +The momentum is similar to learning rate, expecting a value from `0` to `1` as well but it is multiplied against the next level's change value. The default value is `0.1` ### Async Training `trainAsync()` takes the same arguments as train (data and options). Instead of returning the results object from training it returns a promise that when resolved will return the training results object. @@ -156,7 +161,6 @@ The learning rate is a parameter that influences how quickly the network trains. }) .catch(handleError); ``` - With multiple networks you can train in parallel like this: ```javascript diff --git a/src/neural-network.js b/src/neural-network.js index f5b9b9aca..e348d36de 100644 --- a/src/neural-network.js +++ b/src/neural-network.js @@ -38,11 +38,8 @@ export default class NeuralNetwork { constructor(options = {}) { Object.assign(this, this.constructor.defaults, options); this.hiddenSizes = options.hiddenLayers; - - let backCompat = {}; - if (options.learningRate) backCompat.learningRate = options.learningRate; - if (options.momentum) backCompat.momentum = options.momentum; - this.trainOpts = Object.assign({}, this.constructor.trainDefaults, backCompat); + this.trainOpts = {}; + this.updateTrainingOptions(Object.assign({}, this.constructor.trainDefaults, options)); this.sizes = null; this.outputLayer = null; @@ -106,7 +103,8 @@ export default class NeuralNetwork { * * @param supported input: ['sigmoid', 'relu', 'leaky-relu', 'tanh'] */ - setActivation() { + setActivation(activation) { + this.activation = (activation) ? activation : this.activation; switch (this.activation) { case 'sigmoid': this.runInput = this.runInput || this.runInputSigmoid; @@ -294,7 +292,7 @@ export default class NeuralNetwork { * momentum: (number), * activation: ['sigmoid', 'relu', 'leaky-relu', 'tanh'] */ - _updateTrainingOptions(opts) { + updateTrainingOptions(opts) { if (opts.iterations) { this.trainOpts.iterations = opts.iterations; } if (opts.errorThresh) { this.trainOpts.errorThresh = opts.errorThresh; } if (opts.log) { this._setLogMethod(opts.log); } @@ -303,7 +301,7 @@ export default class NeuralNetwork { if (opts.momentum) { this.trainOpts.momentum = opts.momentum; } if (opts.callback) { this.trainOpts.callback = opts.callback; } if (opts.callbackPeriod) { this.trainOpts.callbackPeriod = opts.callbackPeriod; } - if (opts.timeout) { this.trainOpts.callbackPeriod = opts.timeout; } + if (opts.timeout) { this.trainOpts.timeout = opts.timeout; } if (opts.activation) { this.activation = opts.activation; } } @@ -382,7 +380,7 @@ export default class NeuralNetwork { * @returns {{error: number, iterations: number}} */ train(data, options = {}) { - this._updateTrainingOptions(options); + this.updateTrainingOptions(options); data = this.formatData(data); const endTime = Date.now() + this.trainOpts.timeout; @@ -409,7 +407,7 @@ export default class NeuralNetwork { */ trainAsync(data, options = {}) { return new Promise((resolve, reject) => { - this._updateTrainingOptions(options); + this.updateTrainingOptions(options); data = this.formatData(data); const endTime = Date.now() + this.trainOpts.timeout; @@ -809,7 +807,7 @@ export default class NeuralNetwork { } } } - this._updateTrainingOptions(json.trainOpts) + this.updateTrainingOptions(json.trainOpts) this.setActivation(); return this; } diff --git a/test/README.md b/test/README.md index d59a69bd8..f86b66967 100644 --- a/test/README.md +++ b/test/README.md @@ -12,7 +12,7 @@ Then you can run all tests using `npm test`. Run the unit tests with: ``` -npm test +npm run test ``` See [package.json](../package.json) for more testing examples. diff --git a/test/base/hash.js b/test/base/hash.js index ba6cad0ec..6632097d7 100644 --- a/test/base/hash.js +++ b/test/base/hash.js @@ -2,7 +2,7 @@ import assert from 'assert'; import brain from '../../src'; describe('hash input and output', () => { - it ('runs correctly with array input and output', () => { + it('runs correctly with array input and output', () => { let net = new brain.NeuralNetwork(); net.train([ diff --git a/test/base/json.js b/test/base/json.js index 8489767c8..48c685518 100644 --- a/test/base/json.js +++ b/test/base/json.js @@ -20,12 +20,14 @@ describe('JSON', () => { const input = {'0' : Math.random(), b: Math.random()}; describe('.toJSON()', () => { describe('.layers', () => { + it('layer count is correct', () => { assert.equal(serialized.layers.length, 3); originalNet.sizes.forEach((size, i) => { assert.equal(size, Object.keys(serialized.layers[i]).length); }); }); + describe('input layer', () => { const inputLayer = serialized.layers[0]; it('is empty, but describes input', () => { @@ -37,6 +39,7 @@ describe('JSON', () => { assert(Object.keys(inputLayer['b']).length === 0); }); }); + describe('hidden layers', () => { it('are populated exactly from original net', () => { assert.equal(serialized.layers[1][0].bias, originalNet.biases[1][0]); @@ -47,12 +50,14 @@ describe('JSON', () => { }); }); }); + describe('.activation', () => { it('exports correctly', () => { assert.equal(serialized.activation, originalNet.activation); }); }); }); + describe('.fromJSON()', () => { describe('importing values', () => { describe('.layers', () => { @@ -61,6 +66,7 @@ describe('JSON', () => { assert.equal(serializedNet.biases['1'].length, 3); assert.equal(serializedNet.weights.length, 3); }); + describe('hidden layers', () => { it('are populated exactly from serialized', () => { assert.equal(serializedNet.biases[1][0], serialized.layers[1][0].bias); @@ -71,12 +77,14 @@ describe('JSON', () => { }); }); }); + describe('.activation', () => { it('exports correctly', () => { assert.equal(serializedNet.activation, serialized.activation); }); }); }); + it('can run originalNet, and serializedNet, with same output', () => { const output1 = originalNet.run(input); const output2 = serializedNet.run(input); diff --git a/test/base/log.js b/test/base/log.js new file mode 100644 index 000000000..247d1abdf --- /dev/null +++ b/test/base/log.js @@ -0,0 +1,41 @@ +import assert from 'assert'; +import brain from '../../src'; + +describe('log', () => { + let logCalled = false; + + beforeEach(() => { logCalled = false; }); + + function logFunction(str) { + logCalled = true; + } + + function trainWithLog(log, expected) { + let net = new brain.NeuralNetwork(); + net.train( + [ { input: [0], output: [0] } ], + { log: log, logPeriod: 1, iterations: 1 } + ); + assert.equal(logCalled, expected) + } + + function trainWithLogAsync(log, expected, done) { + let net = new brain.NeuralNetwork(); + net + .trainAsync( + [ {input: [0], output: [0]} ], + { log: log, logPeriod: 1, iterations: 1 } + ) + .then(res => { + assert.equal(logCalled, expected); + done(); + }) + .catch(err => { assert.ok(false, err.toString()) }); + } + + it('should call log method', () => { trainWithLog(logFunction, true); }); + it('should not call log method', () => { trainWithLog(false, false); }); + + it('ASYNC should call log method', done => { trainWithLogAsync(logFunction, true, done); }).timeout(5000); + it('ASYNC should not call log method', done => { trainWithLogAsync(false, false, done); }).timeout(5000); +}); diff --git a/test/base/options.js b/test/base/options.js index 7330f039b..18a62fee7 100644 --- a/test/base/options.js +++ b/test/base/options.js @@ -5,7 +5,6 @@ describe('neural network options', () => { it('hiddenLayers', () => { let net = new brain.NeuralNetwork({ hiddenLayers: [8, 7] }); - net.train([ { input: [0, 0], output: [0] }, { input: [0, 1], output: [1] }, @@ -14,7 +13,6 @@ describe('neural network options', () => { ]); let json = net.toJSON(); - assert.equal(json.layers.length, 4); assert.equal(Object.keys(json.layers[1]).length, 8); assert.equal(Object.keys(json.layers[2]).length, 7); @@ -22,7 +20,6 @@ describe('neural network options', () => { it('hiddenLayers default expand to input size', () => { let net = new brain.NeuralNetwork(); - net.train([ { input: [0, 0, 1, 1, 1, 1, 1, 1, 1], output: [0]}, { input: [0, 1, 1, 1, 1, 1, 1, 1, 1], output: [1]}, @@ -31,141 +28,84 @@ describe('neural network options', () => { ]); let json = net.toJSON(); - assert.equal(json.layers.length, 3); assert.equal(Object.keys(json.layers[1]).length, 4, `9 input units should be 4 hidden not ${Object.keys(json.layers[1]).length}`); }); - - it('learningRate - higher learning rate should train faster', () => { - let data = [ - { input: [0, 0], output: [0] }, - { input: [0, 1], output: [1] }, - { input: [1, 0], output: [1] }, - { input: [1, 1], output: [1] } - ]; - - let net = new brain.NeuralNetwork(); - let res = net.train(data, { learningRate: 0.5 }); - - let net2 = new brain.NeuralNetwork(); - let res2 = net2.train(data, { learningRate: 0.8 }); - - assert.ok(res.iterations > (res2.iterations * 1.1), `${res.iterations} should be greater than ${res2.iterations * 1.1}`); - }); - - - it('momentum - higher momentum should train faster', () => { - let data = [ - { input: [0, 0], output: [0] }, - { input: [0, 1], output: [1] }, - { input: [1, 0], output: [1] }, - { input: [1, 1], output: [1] } - ]; - - let net = new brain.NeuralNetwork({ momentum: 0.1 }); - let res = net.train(data) - - let net2 = new brain.NeuralNetwork({ momentum: 0.5 }); - let res2 = net2.train(data) - - assert.ok(res.iterations > (res2.iterations * 1.1), `${res.iterations} !> ${res2.iterations * 1.1}`); - }); -}); - - - -describe('async neural network options', () => { - it('learningRate ASYNC - higher learning rate should train faster', (done) => { - let data = [ - { input: [0, 0], output: [0] }, - { input: [0, 1], output: [1] }, - { input: [1, 0], output: [1] }, - { input: [1, 1], output: [1] } - ]; - - let net = new brain.NeuralNetwork(); - let net2 = new brain.NeuralNetwork(); - - let p1 = net.trainAsync(data, { learningRate: 0.5 }); - let p2 = net2.trainAsync(data, { learningRate: 0.8 }); - - Promise - .all([p1, p2]) - .then(values => { - let res = values[0]; - let res2 = values[1]; - assert.ok(res.iterations > (res2.iterations * 1.1), `${res.iterations} !> ${res2.iterations * 1.1}`); - done(); - }) - .catch(err => { - assert.ok(false, err.toString()) - }); - }).timeout(5000); - - it('momentum ASYNC - higher momentum should train faster', (done) => { - let data = [ - { input: [0, 0], output: [0] }, - { input: [0, 1], output: [1] }, - { input: [1, 0], output: [1] }, - { input: [1, 1], output: [1] } - ]; - - let net = new brain.NeuralNetwork({ momentum: 0.1 }); - let net2 = new brain.NeuralNetwork({ momentum: 0.5 }); - - let p1 = net.trainAsync(data); - let p2 = net2.trainAsync(data); - - Promise.all([p1, p2]) - .then(values => { - let res = values[0]; - let res2 = values[1]; - assert.ok(res.iterations > (res2.iterations * 1.1), `${res.iterations} !> ${res2.iterations * 1.1}`); - done(); - }).catch(err => { - assert.ok(false, err.toString()) - }); - }).timeout(5000); }) -describe('log', () => { - let logCalled = false; - - beforeEach(() => { logCalled = false; }); - - function logFunction(str) { - logCalled = true; - } - - function trainWithLog(log, expected) { - let net = new brain.NeuralNetwork(); - net.train( - [ { input: [0], output: [0] } ], - { log: log, logPeriod: 1, iterations: 1 } - ); - assert.equal(logCalled, expected) - } - - function trainWithLogAsync(log, expected, done) { - let net = new brain.NeuralNetwork(); - net - .trainAsync( - [ {input: [0], output: [0]} ], - { log: log, logPeriod: 1, iterations: 1 } - ) - .then(res => { - assert.equal(logCalled, expected); - done(); - }) - .catch(err => { - assert.ok(false, err.toString()) - }); - } - - it('should call log method', () => { trainWithLog(logFunction, true); }); - it('should not call log method', () => { trainWithLog(false, false); }); - - it('ASYNC should call log method', done => { trainWithLogAsync(logFunction, true, done); }).timeout(5000); - it('ASYNC should not call log method', done => { trainWithLogAsync(false, false, done); }).timeout(5000); -}); +describe ('neural network constructor values', () => { + it('iterations should be settable in the constructor', () => { + let opts = { iterations: 5}; + var net = new brain.NeuralNetwork(opts); + assert.equal(opts.iterations, net.trainOpts.iterations, `iterations => ${net.trainOpts.iterations} but should be ${opts.iterations}`); + }) + + it('errorThresh should be settable in the constructor', () => { + let opts = { errorThresh: 0.1 }; + var net = new brain.NeuralNetwork(opts); + assert.equal(opts.errorThresh, net.trainOpts.errorThresh, `errorThresh => ${net.trainOpts.errorThresh} but should be ${opts.errorThresh}`); + }) + + it('log should allow setting the training options to the constructor', () => { + let log = function (res) {}; + let opts = { log: log }; + var net = new brain.NeuralNetwork(opts); + assert.ok(typeof net.trainOpts.log === 'function', `log => ${net.trainOpts.log} but should be ${opts.log}`); + }) + + it('logPeriod should be settable in the constructor', () => { + let opts = { logPeriod: 5 }; + var net = new brain.NeuralNetwork(opts); + assert.equal(opts.logPeriod, net.trainOpts.logPeriod, `logPeriod => ${net.trainOpts.logPeriod} but should be ${opts.logPeriod}`); + }) + + it('learningRate should be settable in the constructor', () => { + let opts = { learningRate: 0.5 }; + var net = new brain.NeuralNetwork(opts); + assert.equal(opts.learningRate, net.trainOpts.learningRate, `learningRate => ${net.trainOpts.learningRate} but should be ${opts.learningRate}`); + }) + + it('momentum should be settable in the constructor', () => { + let opts = { momentum: 0.2 }; + var net = new brain.NeuralNetwork(opts); + assert.equal(opts.momentum, net.trainOpts.momentum, `momentum => ${net.trainOpts.momentum} but should be ${opts.momentum}`); + }) + + it('callback should be settable in the constructor', () => { + let cb = function (res) {}; + let opts = { callback: cb }; + var net = new brain.NeuralNetwork(opts); + assert.ok(typeof net.trainOpts.callback === 'function', `callback => ${net.trainOpts.callback} but should be ${opts.callback}`); + }) + + it('callbackPeriod should be settable in the constructor', () => { + let opts = { callbackPeriod: 2 }; + var net = new brain.NeuralNetwork(opts); + assert.equal(opts.callbackPeriod, net.trainOpts.callbackPeriod, `callbackPeriod => ${net.trainOpts.callbackPeriod} but should be ${opts.callbackPeriod}`); + }) + + it('timeout should be settable in the constructor', () => { + let opts = { timeout: 1500 }; + var net = new brain.NeuralNetwork(opts); + assert.equal(opts.timeout, net.trainOpts.timeout, `timeout => ${net.trainOpts.timeout} but should be ${opts.timeout}`); + }) + + it('binaryThresh should be settable in the constructor', () => { + let opts = { binaryThresh: 0.2 }; + var net = new brain.NeuralNetwork(opts); + assert.equal(opts.binaryThresh, net.binaryThresh, `binaryThresh => ${net.binaryThresh} but should be ${opts.binaryThresh}`); + }) + + it('hiddenLayers should be settable in the constructor', () => { + let opts = { hiddenLayers: [2, 3, 4] }; + var net = new brain.NeuralNetwork(opts); + assert.equal(JSON.stringify(opts.hiddenLayers), JSON.stringify(net.hiddenLayers), `hiddenLayers => ${net.hiddenLayers} but should be ${opts.hiddenLayers}`); + }) + + it('activation should be settable in the constructor', () => { + let opts = { activation: 'relu' }; + var net = new brain.NeuralNetwork(opts); + assert.equal(opts.activation, net.activation, `activation => ${net.activation} but should be ${opts.activation}`); + }) +}); \ No newline at end of file diff --git a/test/base/trainopts.js b/test/base/trainopts.js index 31d18769d..e9baa0b75 100644 --- a/test/base/trainopts.js +++ b/test/base/trainopts.js @@ -6,20 +6,20 @@ let data = [{input: [0, 0], output: [0]}, {input: [1, 0], output: [1]}, {input: [1, 1], output: [1]}]; -describe('train() options', function () { - it('train until error threshold reached', function () { +describe('train() options', () => { + it('train until error threshold reached', () => { let net = new brain.NeuralNetwork(); - var res = net.train (data, { errorThresh: 0.2 }); + let res = net.train(data, { errorThresh: 0.2 }); assert.ok(res.error < 0.2, `[res.error, ${res.error}] should have been less then 0.2`); }); - it('train until max iterations reached', function () { + it('train until max iterations reached', () => { let net = new brain.NeuralNetwork(); - var res = net.train(data, { iterations: 25 }); + let res = net.train(data, { iterations: 25 }); assert.equal(res.iterations, 25, `[res.iterations, ${res.iterations}] should have been less then 25`); }); - it('training callback called with training stats', function () { + it('training callback called with training stats', () => { let iters = 100; let period = 20; let target = iters / period; @@ -37,4 +37,139 @@ describe('train() options', function () { }); assert.ok(target === calls, `[calls, ${calls}] should be the same as [target, ${target}]`); }); + + it('learningRate - higher learning rate should train faster', () => { + let data = [ + { input: [0, 0], output: [0] }, + { input: [0, 1], output: [1] }, + { input: [1, 0], output: [1] }, + { input: [1, 1], output: [1] } + ]; + + let net = new brain.NeuralNetwork(); + let res = net.train(data, { learningRate: 0.5 }); + + let net2 = new brain.NeuralNetwork(); + let res2 = net2.train(data, { learningRate: 0.8 }); + + assert.ok(res.iterations > (res2.iterations * 1.1), `${res.iterations} should be greater than ${res2.iterations * 1.1}`); + }); + + + it('momentum - higher momentum should train faster', () => { + let data = [ + { input: [0, 0], output: [0] }, + { input: [0, 1], output: [1] }, + { input: [1, 0], output: [1] }, + { input: [1, 1], output: [1] } + ]; + + let net = new brain.NeuralNetwork({ momentum: 0.1 }); + let res = net.train(data) + + let net2 = new brain.NeuralNetwork({ momentum: 0.5 }); + let res2 = net2.train(data) + + assert.ok(res.iterations > (res2.iterations * 1.1), `${res.iterations} !> ${res2.iterations * 1.1}`); + }); +}); + + +describe('async train() options', () => { + it('train until error threshold reached', (done) => { + let net = new brain.NeuralNetwork(); + let p1 = net + .trainAsync(data, { errorThresh: 0.2 }) + .then (res => { + assert.ok(res.error < 0.2, `[res.error, ${res.error}] should have been less then 0.2`); + done(); + }) + .catch(err => { assert.ok(false, err.toString()) }); + }); + + it('train until max iterations reached', (done) => { + let net = new brain.NeuralNetwork(); + let res = net + .trainAsync(data, { iterations: 25 }) + .then(res => { + assert.equal(res.iterations, 25, `[res.iterations, ${res.iterations}] should have been less then 25`); + done(); + }) + .catch(err => { assert.ok(false, err.toString()) }); + }); + + it('asyinc training callback called with training stats', (done) => { + let iters = 100; + let period = 20; + let target = iters / period; + + let calls = 0; + + let net = new brain.NeuralNetwork(); + net.trainAsync(data, { + iterations: iters, + callbackPeriod: period, + callback: (res) => { + assert.ok(res.iterations % period == 0); + calls++; + } + }) + .then (res => { + assert.ok(target === calls, `[calls, ${calls}] should be the same as [target, ${target}]`); + done(); + }) + .catch(err => { assert.ok(false, err.toString()) }); + }); + + it('learningRate ASYNC - higher learning rate should train faster', (done) => { + let data = [ + { input: [0, 0], output: [0] }, + { input: [0, 1], output: [1] }, + { input: [1, 0], output: [1] }, + { input: [1, 1], output: [1] } + ]; + + let net = new brain.NeuralNetwork(); + let net2 = new brain.NeuralNetwork(); + + let p1 = net.trainAsync(data, { learningRate: 0.5 }); + let p2 = net2.trainAsync(data, { learningRate: 0.8 }); + + Promise + .all([p1, p2]) + .then(values => { + let res = values[0]; + let res2 = values[1]; + assert.ok(res.iterations > (res2.iterations * 1.1), `${res.iterations} !> ${res2.iterations * 1.1}`); + done(); + }) + .catch(err => { + assert.ok(false, err.toString()) + }); + }).timeout(5000); + + it('momentum ASYNC - higher momentum should train faster', (done) => { + let data = [ + { input: [0, 0], output: [0] }, + { input: [0, 1], output: [1] }, + { input: [1, 0], output: [1] }, + { input: [1, 1], output: [1] } + ]; + + let net = new brain.NeuralNetwork({ momentum: 0.1 }); + let net2 = new brain.NeuralNetwork({ momentum: 0.5 }); + + let p1 = net.trainAsync(data); + let p2 = net2.trainAsync(data); + + Promise.all([p1, p2]) + .then(values => { + let res = values[0]; + let res2 = values[1]; + assert.ok(res.iterations > (res2.iterations * 1.1), `${res.iterations} !> ${res2.iterations * 1.1}`); + done(); + }).catch(err => { + assert.ok(false, err.toString()) + }); + }).timeout(5000); }); From 27755d73eec236c56b985f2be1dca553d251e574 Mon Sep 17 00:00:00 2001 From: Fred Christensen Date: Sat, 27 Jan 2018 22:29:06 -0700 Subject: [PATCH 3/5] Updating some things --- README.md | 2 + browser.js | 23090 ++++++++++++++++++----------------- browser.min.js | 123 +- dist/neural-network.js | 271 +- dist/neural-network.js.map | 2 +- test/base/json.js | 19 + 6 files changed, 11864 insertions(+), 11643 deletions(-) diff --git a/README.md b/README.md index 6a5bab927..a8346a1eb 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,8 @@ The learning rate is a parameter that influences how quickly the network trains. The momentum is similar to learning rate, expecting a value from `0` to `1` as well but it is multiplied against the next level's change value. The default value is `0.1` +Any of these training options can be passed into the constructor or passed into the `updateTrainingOptions(opts)` method and they will be saved on the network and used any time you trian. If you save your network to json, these training options are saved and restored as well (except for callback and if the log is set restored log will be console.log). + ### Async Training `trainAsync()` takes the same arguments as train (data and options). Instead of returning the results object from training it returns a promise that when resolved will return the training results object. diff --git a/browser.js b/browser.js index 020b8f248..29bf945cd 100644 --- a/browser.js +++ b/browser.js @@ -11,6 +11,7 @@ * acorn: * license: MIT (http://opensource.org/licenses/MIT) * maintainers: Marijn Haverbeke , Ingvar Stepanyan + * contributors: List of Acorn contributors. Updated before every release., Adrian Heine, Adrian Heine né Lang, Adrian Rakovsky, Alistair Braidwood, Amila Welihinda, Andres Suarez, Angelo, Aparajita Fishman, Arian Stolwijk, Artem Govorov, Bradley Heinz, Brandon Mills, Charles Hughes, Charmander, Conrad Irwin, Daniel Tschinder, David Bonnet, Domenico Matteo, ehmicky, Felix Maier, Forbes Lindesay, Gilad Peleg, impinball, Ingvar Stepanyan, Jackson Ray Hamilton, Jesse McCarthy, Jiaxing Wang, Joel Kemp, Johannes Herr, John-David Dalton, Jordan Klassen, Jürg Lehni, Kai Cataldo, keeyipchan, Keheliya Gallaba, Kevin Irish, Kevin Kwok, krator, laosb, Marek, Marijn Haverbeke, Martin Carlberg, Mat Garcia, Mathias Bynens, Mathieu 'p01' Henri, Matthew Bastien, Max Schaefer, Max Zerzouri, Mihai Bazon, Mike Rennie, naoh, Nicholas C. Zakas, Nick Fitzgerald, Olivier Thomann, Oskar Schöldström, Paul Harper, Peter Rust, PlNG, Prayag Verma, ReadmeCritic, r-e-d, Richard Gibson, Rich Harris, Sebastian McKenzie, Shahar Soel, Simen Bekkhus, Teddy Katz, Timothy Gu, Toru Nagashima, Victor Homyakov, Wexpo Lyu, zsjforcn * homepage: https://github.com/acornjs/acorn * version: 5.3.0 * @@ -29,12 +30,14 @@ * * core-util-is: * license: MIT (http://opensource.org/licenses/MIT) - * author: Isaac Z. Schlueter (http://blog.izs.me/) + * author: Isaac Z. Schlueter + * homepage: https://github.com/isaacs/core-util-is#readme * version: 1.0.2 * * events: * license: MIT (http://opensource.org/licenses/MIT) - * author: Irakli Gozalishvili (http://jeditoolkit.com) + * author: Irakli Gozalishvili + * homepage: https://github.com/Gozala/events#readme * version: 1.1.1 * * gpu.js: @@ -47,10 +50,12 @@ * license: BSD-3-Clause (http://opensource.org/licenses/BSD-3-Clause) * author: Feross Aboukhadijeh * contributors: Romain Beauxis + * homepage: https://github.com/feross/ieee754#readme * version: 1.1.8 * * inherits: * license: ISC (http://opensource.org/licenses/ISC) + * homepage: https://github.com/isaacs/inherits#readme * version: 2.0.3 * * isarray: @@ -62,6 +67,7 @@ * process: * license: MIT (http://opensource.org/licenses/MIT) * author: Roman Shtylman + * homepage: https://github.com/shtylman/node-process#readme * version: 0.11.10 * * process-nextick-args: @@ -71,6 +77,7 @@ * * readable-stream: * license: MIT (http://opensource.org/licenses/MIT) + * homepage: https://github.com/nodejs/readable-stream#readme * version: 2.3.3 * * safe-buffer: @@ -98,7 +105,7 @@ * * util-deprecate: * license: MIT (http://opensource.org/licenses/MIT) - * author: Nathan Rajlich (http://n8.io/) + * author: Nathan Rajlich * homepage: https://github.com/TooTallNate/util-deprecate * version: 1.0.2 * @@ -840,7 +847,7 @@ function mse(errors) { return sum / this.constants.size; } -},{"./lookup":3,"./neural-network":5,"gpu.js":75}],5:[function(require,module,exports){ +},{"./lookup":3,"./neural-network":5,"gpu.js":76}],5:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { @@ -900,24 +907,24 @@ var NeuralNetwork = function () { key: 'trainDefaults', get: function get() { return { - iterations: 20000, - errorThresh: 0.005, - log: false, - logPeriod: 10, - learningRate: 0.3, - callback: null, - callbackPeriod: 10 + iterations: 20000, // the maximum times to iterate the training data + errorThresh: 0.005, // the acceptable error percentage from training data + log: false, // true to use console.log, when a function is supplied it is used + logPeriod: 10, // iterations between logging out + learningRate: 0.3, // multiply's against the input and the delta then adds to momentum + momentum: 0.1, // multiply's against the specified "change" then adds to learning rate for change + callback: null, // a periodic call back that can be triggered while training + callbackPeriod: 10, // the number of iterations through the training data between callback calls + timeout: Infinity // the max number of milliseconds to train for }; } }, { key: 'defaults', get: function get() { return { - learningRate: 0.3, - momentum: 0.1, - binaryThresh: 0.5, - hiddenLayers: null, - activation: 'sigmoid' + binaryThresh: 0.5, // ¯\_(ツ)_/¯ + hiddenLayers: [3], // array of ints for the sizes of the hidden layers in the network + activation: 'sigmoid' // Supported activation types ['sigmoid', 'relu', 'leaky-relu', 'tanh'] }; } }]); @@ -929,6 +936,8 @@ var NeuralNetwork = function () { Object.assign(this, this.constructor.defaults, options); this.hiddenSizes = options.hiddenLayers; + this.trainOpts = {}; + this.updateTrainingOptions(Object.assign({}, this.constructor.trainDefaults, options)); this.sizes = null; this.outputLayer = null; @@ -951,14 +960,15 @@ var NeuralNetwork = function () { /** * - * @param {Number[]} sizes + * Expects this.sizes to have been set */ _createClass(NeuralNetwork, [{ - key: 'initialize', - value: function initialize(sizes) { - this.sizes = sizes; + key: '_initialize', + value: function _initialize() { + if (!this.sizes) throw new Error('Sizes must be set before initializing'); + this.outputLayer = this.sizes.length - 1; this.biases = []; // weights for bias nodes this.weights = []; @@ -990,9 +1000,16 @@ var NeuralNetwork = function () { this.setActivation(); } + + /** + * + * @param supported input: ['sigmoid', 'relu', 'leaky-relu', 'tanh'] + */ + }, { key: 'setActivation', - value: function setActivation() { + value: function setActivation(activation) { + this.activation = activation ? activation : this.activation; switch (this.activation) { case 'sigmoid': this.runInput = this.runInput || this.runInputSigmoid; @@ -1137,27 +1154,114 @@ var NeuralNetwork = function () { /** * * @param data - * @returns sizes + * Verifies network sizes are initilaized + * If they are not it will initialize them based off the data set. */ }, { - key: '_getSizesFromData', - value: function _getSizesFromData(data) { - var sizes = []; - var inputSize = data[0].input.length; - var outputSize = data[0].output.length; - var hiddenSizes = this.hiddenSizes; - if (!hiddenSizes) { - sizes.push(Math.max(3, Math.floor(inputSize / 2))); + key: '_verifyIsInitialized', + value: function _verifyIsInitialized(data) { + var _this = this; + + if (this.sizes) return; + + this.sizes = []; + this.sizes.push(data[0].input.length); + if (!this.hiddenSizes) { + this.sizes.push(Math.max(3, Math.floor(data[0].input.length / 2))); } else { - hiddenSizes.forEach(function (size) { - sizes.push(size); + this.hiddenSizes.forEach(function (size) { + _this.sizes.push(size); }); } + this.sizes.push(data[0].output.length); + + this._initialize(); + } + + /** + * + * @param options + * Supports all `trainDefaults` properties + * also supports: + * learningRate: (number), + * momentum: (number), + * activation: ['sigmoid', 'relu', 'leaky-relu', 'tanh'] + */ + + }, { + key: 'updateTrainingOptions', + value: function updateTrainingOptions(opts) { + if (opts.iterations) { + this.trainOpts.iterations = opts.iterations; + } + if (opts.errorThresh) { + this.trainOpts.errorThresh = opts.errorThresh; + } + if (opts.log) { + this._setLogMethod(opts.log); + } + if (opts.logPeriod) { + this.trainOpts.logPeriod = opts.logPeriod; + } + if (opts.learningRate) { + this.trainOpts.learningRate = opts.learningRate; + } + if (opts.momentum) { + this.trainOpts.momentum = opts.momentum; + } + if (opts.callback) { + this.trainOpts.callback = opts.callback; + } + if (opts.callbackPeriod) { + this.trainOpts.callbackPeriod = opts.callbackPeriod; + } + if (opts.timeout) { + this.trainOpts.timeout = opts.timeout; + } + if (opts.activation) { + this.activation = opts.activation; + } + } + + /** + * + * Gets JSON of trainOpts object + * NOTE: Activation is stored directly on JSON object and not in the training options + */ - sizes.unshift(inputSize); - sizes.push(outputSize); - return sizes; + }, { + key: '_getTrainOptsJSON', + value: function _getTrainOptsJSON() { + var results = {}; + if (this.trainOpts.iterations) { + results.iterations = this.trainOpts.iterations; + } + if (this.trainOpts.errorThresh) { + results.errorThresh = this.trainOpts.errorThresh; + } + if (this.trainOpts.logPeriod) { + results.logPeriod = this.trainOpts.logPeriod; + } + if (this.trainOpts.learningRate) { + results.learningRate = this.trainOpts.learningRate; + } + if (this.trainOpts.momentum) { + results.momentum = this.trainOpts.momentum; + } + if (this.trainOpts.callback) { + results.callback = this.trainOpts.callback; + } + if (this.trainOpts.callbackPeriod) { + results.callbackPeriod = this.trainOpts.callbackPeriod; + } + if (this.trainOpts.timeout) { + results.timeout = this.trainOpts.timeout; + } + if (this.trainOpts.log) { + results.log = true; + } + return results; } /** @@ -1171,8 +1275,13 @@ var NeuralNetwork = function () { }, { key: '_setLogMethod', value: function _setLogMethod(log) { - if (log) return console.log; - return false; + if (typeof log === 'function') { + this.trainOpts.log = log; + } else if (log) { + this.trainOpts.log = console.log; + } else { + this.trainOpts.log = false; + } } /** @@ -1184,10 +1293,10 @@ var NeuralNetwork = function () { }, { key: '_calculateTrainingError', - value: function _calculateTrainingError(data, learningRate) { + value: function _calculateTrainingError(data) { var sum = 0; for (var i = 0; i < data.length; ++i) { - sum += this.trainPattern(data[i].input, data[i].output, learningRate); + sum += this._trainPattern(data[i].input, data[i].output); } return sum / data.length; } @@ -1199,48 +1308,45 @@ var NeuralNetwork = function () { */ }, { - key: '_checkTrainingTick', - value: function _checkTrainingTick(data, status, options) { + key: '_trainingTick', + value: function _trainingTick(data, status) { status.iterations++; - status.error = this._calculateTrainingError(data, options.learningRate); + status.error = this._calculateTrainingError(data); - if (options.log && status.iterations % options.logPeriod === 0) { - options.log('iterations: ' + status.iterations + ', training error: ' + status.error); + if (this.trainOpts.log && status.iterations % this.trainOpts.logPeriod === 0) { + this.trainOpts.log('iterations: ' + status.iterations + ', training error: ' + status.error); } - if (options.callback && status.iterations % options.callbackPeriod === 0) { - options.callback(Object.assign(status)); + if (this.trainOpts.callback && status.iterations % this.trainOpts.callbackPeriod === 0) { + this.trainOpts.callback(Object.assign(status)); } } /** * * @param data - * @param _options + * @param options * @returns {{error: number, iterations: number}} */ }, { key: 'train', value: function train(data) { - var _options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - var options = Object.assign({}, this.constructor.trainDefaults, _options); + this.updateTrainingOptions(options); data = this.formatData(data); - options.log = this._setLogMethod(options.log); - options.learningRate = _options.learningRate || this.learningRate || options.learningRate; + var endTime = Date.now() + this.trainOpts.timeout; + var status = { error: 1, iterations: 0 }; - if (this.sizes === null) { - var sizes = this._getSizesFromData(data); - this.initialize(sizes); - } + this._verifyIsInitialized(data); - while (status.iterations < options.iterations && status.error > options.errorThresh) { - this._checkTrainingTick(data, status, options); + while (status.iterations < this.trainOpts.iterations && status.error > this.trainOpts.errorThresh && Date.now() < endTime) { + this._trainingTick(data, status); } return status; @@ -1249,7 +1355,7 @@ var NeuralNetwork = function () { /** * * @param data - * @param _options + * @param options * @param cb * @returns {{error: number, iterations: number}} */ @@ -1257,34 +1363,28 @@ var NeuralNetwork = function () { }, { key: 'trainAsync', value: function trainAsync(data) { - var _this = this; + var _this2 = this; - var _options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return new Promise(function (resolve, reject) { - var options = Object.assign({}, _this.constructor.trainDefaults, _options); - data = _this.formatData(data); - options.log = _this._setLogMethod(options.log); - options.learningRate = _options.learningRate || _this.learningRate || options.learningRate; - var endTime = Date.now() + options.trainTimeMs; + _this2.updateTrainingOptions(options); + data = _this2.formatData(data); + var endTime = Date.now() + _this2.trainOpts.timeout; var status = { error: 1, iterations: 0 }; - if (_this.sizes === null) { - var sizes = _this._getSizesFromData(data); - _this.initialize(sizes); - } + _this2._verifyIsInitialized(data); - var items = new Array(options.iterations); + var items = new Array(_this2.trainOpts.iterations); var thaw = new _thaw2.default(items, { delay: true, each: function each() { - _this._checkTrainingTick(data, status, options); - - if (status.error < options.errorThresh) { + _this2._trainingTick(data, status); + if (status.error < _this2.trainOpts.errorThresh || Date.now() > endTime) { thaw.stop(); } }, @@ -1301,20 +1401,18 @@ var NeuralNetwork = function () { * * @param input * @param target - * @param learningRate */ }, { - key: 'trainPattern', - value: function trainPattern(input, target, learningRate) { - learningRate = learningRate || this.learningRate; + key: '_trainPattern', + value: function _trainPattern(input, target) { // forward propagate this.runInput(input); // back propagate this.calculateDeltas(target); - this.adjustWeights(learningRate); + this.adjustWeights(); var error = (0, _mse2.default)(this.errors[this.outputLayer]); return error; @@ -1430,12 +1528,12 @@ var NeuralNetwork = function () { /** * - * @param learningRate + * Changes weights of networks */ }, { key: 'adjustWeights', - value: function adjustWeights(learningRate) { + value: function adjustWeights() { for (var layer = 1; layer <= this.outputLayer; layer++) { var incoming = this.outputs[layer - 1]; @@ -1445,12 +1543,12 @@ var NeuralNetwork = function () { for (var k = 0; k < incoming.length; k++) { var change = this.changes[layer][node][k]; - change = learningRate * delta * incoming[k] + this.momentum * change; + change = this.trainOpts.learningRate * delta * incoming[k] + this.trainOpts.momentum * change; this.changes[layer][node][k] = change; this.weights[layer][node][k] += change; } - this.biases[layer][node] += learningRate * delta; + this.biases[layer][node] += this.trainOpts.learningRate * delta; } } } @@ -1464,7 +1562,7 @@ var NeuralNetwork = function () { }, { key: 'formatData', value: function formatData(data) { - var _this2 = this; + var _this3 = this; if (!Array.isArray(data)) { // turn stream datum into array @@ -1481,7 +1579,7 @@ var NeuralNetwork = function () { })); } data = data.map(function (datum) { - var array = _lookup2.default.toArray(_this2.inputLookup, datum.input); + var array = _lookup2.default.toArray(_this3.inputLookup, datum.input); return Object.assign({}, datum, { input: array }); }, this); } @@ -1493,7 +1591,7 @@ var NeuralNetwork = function () { })); } data = data.map(function (datum) { - var array = _lookup2.default.toArray(_this2.outputLookup, datum.output); + var array = _lookup2.default.toArray(_this3.outputLookup, datum.output); return Object.assign({}, datum, { output: array }); }, this); } @@ -1514,7 +1612,7 @@ var NeuralNetwork = function () { }, { key: 'test', value: function test(data) { - var _this3 = this; + var _this4 = this; data = this.formatData(data); @@ -1533,13 +1631,13 @@ var NeuralNetwork = function () { var sum = 0; var _loop = function _loop(i) { - var output = _this3.runInput(data[i].input); + var output = _this4.runInput(data[i].input); var target = data[i].output; var actual = void 0, expected = void 0; if (isBinary) { - actual = output[0] > _this3.binaryThresh ? 1 : 0; + actual = output[0] > _this4.binaryThresh ? 1 : 0; expected = target[0]; } else { actual = output.indexOf((0, _max2.default)(output)); @@ -1674,7 +1772,8 @@ var NeuralNetwork = function () { layers: layers, outputLookup: !!this.outputLookup, inputLookup: !!this.inputLookup, - activation: this.activation + activation: this.activation, + trainOpts: this._getTrainOptsJSON() }; } @@ -1687,7 +1786,8 @@ var NeuralNetwork = function () { }, { key: 'fromJSON', value: function fromJSON(json) { - this.initialize(json.sizes); + this.sizes = json.sizes; + this._initialize(); for (var i = 0; i <= this.outputLayer; i++) { var layer = json.layers[i]; @@ -1706,7 +1806,7 @@ var NeuralNetwork = function () { } } } - + this.updateTrainingOptions(json.trainOpts); this.setActivation(); return this; } @@ -1784,7 +1884,7 @@ var NeuralNetwork = function () { }, { key: 'isRunnable', get: function get() { - var _this4 = this; + var _this5 = this; if (!this.runInput) { console.error('Activation function has not been initialized, did you run train()?'); @@ -1792,7 +1892,7 @@ var NeuralNetwork = function () { } var checkFns = ['sizes', 'outputLayer', 'biases', 'weights', 'outputs', 'deltas', 'changes', 'errors'].filter(function (c) { - return _this4[c] === null; + return _this5[c] === null; }); if (checkFns.length > 0) { @@ -4201,7 +4301,7 @@ function uniques(arr) { return [].concat(_toConsumableArray(new Set(arr))); } -},{"./lookup":3,"stream":98}],34:[function(require,module,exports){ +},{"./lookup":3,"stream":97}],34:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { @@ -4654,7864 +4754,7272 @@ if (typeof window !== 'undefined') { module.exports = brain; } },{"./dist/cross-validate":1,"./dist/likely":2,"./dist/lookup":3,"./dist/neural-network":5,"./dist/neural-network-gpu":4,"./dist/recurrent/gru":6,"./dist/recurrent/lstm":7,"./dist/recurrent/rnn":32,"./dist/train-stream":33,"./dist/utilities/data-formatter":34,"./dist/utilities/max":35,"./dist/utilities/mse":36,"./dist/utilities/ones":37,"./dist/utilities/random":39,"./dist/utilities/random-weight":38,"./dist/utilities/randos":40,"./dist/utilities/range":41,"./dist/utilities/to-array":42,"./dist/utilities/zeros":43}],45:[function(require,module,exports){ -'use strict' - -exports.byteLength = byteLength -exports.toByteArray = toByteArray -exports.fromByteArray = fromByteArray +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.acorn = {}))); +}(this, (function (exports) { 'use strict'; -var lookup = [] -var revLookup = [] -var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array +// Reserved word lists for various dialects of the language -var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -for (var i = 0, len = code.length; i < len; ++i) { - lookup[i] = code[i] - revLookup[code.charCodeAt(i)] = i -} +var reservedWords = { + 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" +}; -revLookup['-'.charCodeAt(0)] = 62 -revLookup['_'.charCodeAt(0)] = 63 +// And the keywords -function placeHoldersCount (b64) { - var len = b64.length - if (len % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } +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"; - // the number of equal signs (place holders) - // if there are two placeholders, than the two characters before it - // represent one byte - // if there is only one, then the three characters before it represent 2 bytes - // this is just a cheap hack to not do indexOf twice - return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 -} +var keywords = { + 5: ecma5AndLessKeywords, + 6: ecma5AndLessKeywords + " const class extends export import super" +}; -function byteLength (b64) { - // base64 is 4/3 + up to two characters of the original data - return (b64.length * 3 / 4) - placeHoldersCount(b64) -} +var keywordRelationalOperator = /^in(stanceof)?$/; -function toByteArray (b64) { - var i, l, tmp, placeHolders, arr - var len = b64.length - placeHolders = placeHoldersCount(b64) +// ## Character categories - arr = new Arr((len * 3 / 4) - placeHolders) +// 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`. - // if there are placeholders, only get up to the last complete 4 chars - l = placeHolders > 0 ? len - 4 : len +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-\u08b4\u08b6-\u08bd\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\u0af9\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-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\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-\u13f5\u13f8-\u13fd\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\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\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-\u9fd5\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\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-\uab65\uab70-\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\u08d4-\u08e1\u08e3-\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\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\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\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-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; - var L = 0 +var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); +var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); - for (i = 0; i < l; i += 4) { - tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] - arr[L++] = (tmp >> 16) & 0xFF - arr[L++] = (tmp >> 8) & 0xFF - arr[L++] = tmp & 0xFF - } +nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; - if (placeHolders === 2) { - tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[L++] = tmp & 0xFF - } else if (placeHolders === 1) { - tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[L++] = (tmp >> 8) & 0xFF - arr[L++] = tmp & 0xFF - } +// 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 bin/generate-identifier-regex.js - return arr -} +// eslint-disable-next-line comma-spacing +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,19,35,5,35,5,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,66,18,2,1,11,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,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,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,60,67,1213,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,3,5761,10591,541]; -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] -} +// eslint-disable-next-line comma-spacing +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,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,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,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239]; -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) - output.push(tripletToBase64(tmp)) +// 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 } } - return output.join('') } -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var output = '' - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 - - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) - } +// Test whether a given character code starts an identifier. - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - output += lookup[tmp >> 2] - output += lookup[(tmp << 4) & 0x3F] - output += '==' - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) - output += lookup[tmp >> 10] - output += lookup[(tmp >> 4) & 0x3F] - output += lookup[(tmp << 2) & 0x3F] - output += '=' - } +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) +} - parts.push(output) +// Test whether a given character is part of an identifier. - return parts.join('') +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) } -},{}],46:[function(require,module,exports){ +// ## Token types -},{}],47:[function(require,module,exports){ -(function (global){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -/* eslint-disable no-proto */ +// 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. -'use strict' +// All token type variables start with an underscore, to make them +// easy to recognize. -var base64 = require('base64-js') -var ieee754 = require('ieee754') -var isArray = require('isarray') +// 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. -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 +var TokenType = function TokenType(label, conf) { + if ( conf === void 0 ) conf = {}; -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * Due to various browser bugs, sometimes the Object implementation will be used even - * when the browser supports typed arrays. - * - * Note: - * - * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, - * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. - * - * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. - * - * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of - * incorrect length in some situations. + 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; +}; - * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they - * get the Object implementation, which is slower but behaves correctly. - */ -Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined - ? global.TYPED_ARRAY_SUPPORT - : typedArraySupport() +function binop(name, prec) { + return new TokenType(name, {beforeExpr: true, binop: prec}) +} +var beforeExpr = {beforeExpr: true}; +var startsExpr = {startsExpr: true}; -/* - * Export kMaxLength after typed array support is determined. - */ -exports.kMaxLength = kMaxLength() +// Map keyword names to token types. -function typedArraySupport () { - try { - var arr = new Uint8Array(1) - arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} - return arr.foo() === 42 && // typed array instances can be augmented - typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` - arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` - } catch (e) { - return false - } -} +var keywords$1 = {}; -function kMaxLength () { - return Buffer.TYPED_ARRAY_SUPPORT - ? 0x7fffffff - : 0x3fffffff +// Succinct definitions of keyword token types +function kw(name, options) { + if ( options === void 0 ) options = {}; + + options.keyword = name; + return keywords$1[name] = new TokenType(name, options) } -function createBuffer (that, length) { - if (kMaxLength() < length) { - throw new RangeError('Invalid typed array length') - } - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Return an augmented `Uint8Array` instance, for best performance - that = new Uint8Array(length) - that.__proto__ = Buffer.prototype - } else { - // Fallback: Return an object instance of the Buffer class - if (that === null) { - that = new Buffer(length) - } - that.length = length - } +var types = { + num: new TokenType("num", startsExpr), + regexp: new TokenType("regexp", startsExpr), + string: new TokenType("string", startsExpr), + name: new TokenType("name", startsExpr), + eof: new TokenType("eof"), - return that -} + // 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"), + invalidTemplate: new TokenType("invalidTemplate"), + ellipsis: new TokenType("...", beforeExpr), + backQuote: new TokenType("`", startsExpr), + dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), -/** - * The Buffer constructor returns instances of `Uint8Array` that have their - * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of - * `Uint8Array`, so the returned instances will have all the node `Buffer` methods - * and the `Uint8Array` methods. Square bracket notation works as expected -- it - * returns a single octet. - * - * The `Uint8Array` prototype remains unmodified. - */ + // 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. -function Buffer (arg, encodingOrOffset, length) { - if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { - return new Buffer(arg, encodingOrOffset, length) - } + 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("!/~", {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), + starstar: new TokenType("**", {beforeExpr: true}), - // Common case. - if (typeof arg === 'number') { - if (typeof encodingOrOffset === 'string') { - throw new Error( - 'If encoding is specified then the first argument must be a string' - ) - } - return allocUnsafe(this, arg) - } - return from(this, arg, encodingOrOffset, length) -} + // Keyword token types. + _break: kw("break"), + _case: kw("case", beforeExpr), + _catch: kw("catch"), + _continue: kw("continue"), + _debugger: kw("debugger"), + _default: kw("default", beforeExpr), + _do: kw("do", {isLoop: true, beforeExpr: true}), + _else: kw("else", beforeExpr), + _finally: kw("finally"), + _for: kw("for", {isLoop: true}), + _function: kw("function", startsExpr), + _if: kw("if"), + _return: kw("return", beforeExpr), + _switch: kw("switch"), + _throw: kw("throw", beforeExpr), + _try: kw("try"), + _var: kw("var"), + _const: kw("const"), + _while: kw("while", {isLoop: true}), + _with: kw("with"), + _new: kw("new", {beforeExpr: true, startsExpr: true}), + _this: kw("this", startsExpr), + _super: kw("super", startsExpr), + _class: kw("class", startsExpr), + _extends: kw("extends", beforeExpr), + _export: kw("export"), + _import: kw("import"), + _null: kw("null", startsExpr), + _true: kw("true", startsExpr), + _false: kw("false", startsExpr), + _in: kw("in", {beforeExpr: true, binop: 7}), + _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), + _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), + _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), + _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) +}; -Buffer.poolSize = 8192 // not used by this implementation +// Matches a whole line break (where CRLF is considered a single +// line break). Used to count lines. -// TODO: Legacy, not needed anymore. Remove in next major version. -Buffer._augment = function (arr) { - arr.__proto__ = Buffer.prototype - return arr +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 } -function from (that, value, encodingOrOffset, length) { - if (typeof value === 'number') { - throw new TypeError('"value" argument must not be a number') - } +var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; - if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { - return fromArrayBuffer(that, value, encodingOrOffset, length) - } +var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; - if (typeof value === 'string') { - return fromString(that, value, encodingOrOffset) - } +var ref = Object.prototype; +var hasOwnProperty = ref.hasOwnProperty; +var toString = ref.toString; - return fromObject(that, value) +// Checks if an object has a property. + +function has(obj, propName) { + return hasOwnProperty.call(obj, propName) } -/** - * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError - * if value is a number. - * Buffer.from(str[, encoding]) - * Buffer.from(array) - * Buffer.from(buffer) - * Buffer.from(arrayBuffer[, byteOffset[, length]]) - **/ -Buffer.from = function (value, encodingOrOffset, length) { - return from(null, value, encodingOrOffset, length) -} +var isArray = Array.isArray || (function (obj) { return ( + toString.call(obj) === "[object Array]" +); }); -if (Buffer.TYPED_ARRAY_SUPPORT) { - Buffer.prototype.__proto__ = Uint8Array.prototype - Buffer.__proto__ = Uint8Array - if (typeof Symbol !== 'undefined' && Symbol.species && - Buffer[Symbol.species] === Buffer) { - // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 - Object.defineProperty(Buffer, Symbol.species, { - value: null, - configurable: true - }) - } -} +// These are used when `options.locations` is on, for the +// `startLoc` and `endLoc` properties. -function assertSize (size) { - if (typeof size !== 'number') { - throw new TypeError('"size" argument must be a number') - } else if (size < 0) { - throw new RangeError('"size" argument must not be negative') - } -} +var Position = function Position(line, col) { + this.line = line; + this.column = col; +}; -function alloc (that, size, fill, encoding) { - assertSize(size) - if (size <= 0) { - return createBuffer(that, size) - } - if (fill !== undefined) { - // Only pay attention to encoding if it's a string. This - // prevents accidentally sending in a number that would - // be interpretted as a start offset. - return typeof encoding === 'string' - ? createBuffer(that, size).fill(fill, encoding) - : createBuffer(that, size).fill(fill) - } - return createBuffer(that, size) -} +Position.prototype.offset = function offset (n) { + return new Position(this.line, this.column + n) +}; -/** - * Creates a new filled Buffer instance. - * alloc(size[, fill[, encoding]]) - **/ -Buffer.alloc = function (size, fill, encoding) { - return alloc(null, size, fill, encoding) -} +var SourceLocation = function SourceLocation(p, start, end) { + this.start = start; + this.end = end; + if (p.sourceFile !== null) { this.source = p.sourceFile; } +}; -function allocUnsafe (that, size) { - assertSize(size) - that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) { - for (var i = 0; i < size; ++i) { - that[i] = 0 +// 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) } } - return that } -/** - * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. - * */ -Buffer.allocUnsafe = function (size) { - return allocUnsafe(null, size) -} -/** - * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. - */ -Buffer.allocUnsafeSlow = function (size) { - return allocUnsafe(null, size) -} +// A second optional argument can be given to further configure +// the parser process. These options are recognized: -function fromString (that, string, encoding) { - if (typeof encoding !== 'string' || encoding === '') { - encoding = 'utf8' - } +var defaultOptions = { + // `ecmaVersion` indicates the ECMAScript version to parse. Must + // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support + // for strict mode, the set of reserved words, and support for + // new syntax features. The default is 7. + ecmaVersion: 7, + // `sourceType` indicates the mode the code should be parsed in. + // Can be either `"script"` or `"module"`. This influences global + // strict mode and parsing of `import` and `export` declarations. + 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: {} +}; - if (!Buffer.isEncoding(encoding)) { - throw new TypeError('"encoding" must be a valid string encoding') - } +// Interpret and default an options object - var length = byteLength(string, encoding) | 0 - that = createBuffer(that, length) +function getOptions(opts) { + var options = {}; - var actual = that.write(string, encoding) + for (var opt in defaultOptions) + { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } - if (actual !== length) { - // Writing a hex string, for example, that contains invalid characters will - // cause everything after the first invalid character to be ignored. (e.g. - // 'abxxcd' will be treated as 'ab') - that = that.slice(0, actual) + if (options.ecmaVersion >= 2015) + { options.ecmaVersion -= 2009; } + + if (options.allowReserved == null) + { options.allowReserved = options.ecmaVersion < 5; } + + if (isArray(options.onToken)) { + var tokens = options.onToken; + options.onToken = function (token) { return tokens.push(token); }; } + if (isArray(options.onComment)) + { options.onComment = pushComment(options, options.onComment); } - return that + return options } -function fromArrayLike (that, array) { - var length = array.length < 0 ? 0 : checked(array.length) | 0 - that = createBuffer(that, length) - for (var i = 0; i < length; i += 1) { - that[i] = array[i] & 255 +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); } - return that } -function fromArrayBuffer (that, array, byteOffset, length) { - array.byteLength // this throws if `array` is not a valid ArrayBuffer +// Registered plugins +var plugins = {}; - if (byteOffset < 0 || array.byteLength < byteOffset) { - throw new RangeError('\'offset\' is out of bounds') - } +function keywordRegexp(words) { + return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") +} - if (array.byteLength < byteOffset + (length || 0)) { - throw new RangeError('\'length\' is out of bounds') - } - - if (byteOffset === undefined && length === undefined) { - array = new Uint8Array(array) - } else if (length === undefined) { - array = new Uint8Array(array, byteOffset) - } else { - array = new Uint8Array(array, byteOffset, length) +var Parser = function Parser(options, input, startPos) { + this.options = options = getOptions(options); + this.sourceFile = options.sourceFile; + this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]); + var reserved = ""; + if (!options.allowReserved) { + for (var v = options.ecmaVersion;; v--) + { if (reserved = reservedWords[v]) { break } } + if (options.sourceType == "module") { reserved += " await"; } } + this.reservedWords = keywordRegexp(reserved); + var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; + this.reservedWordsStrict = keywordRegexp(reservedStrict); + this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind); + this.input = String(input); - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Return an augmented `Uint8Array` instance, for best performance - that = array - that.__proto__ = Buffer.prototype - } else { - // Fallback: Return an object instance of the Buffer class - that = fromArrayLike(that, array) - } - return that -} + // 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; -function fromObject (that, obj) { - if (Buffer.isBuffer(obj)) { - var len = checked(obj.length) | 0 - that = createBuffer(that, len) + // Load plugins + this.loadPlugins(options.plugins); - if (that.length === 0) { - return that - } + // Set up token state - obj.copy(that, 0, 0, len) - return that + // The current position of the tokenizer in the input. + if (startPos) { + this.pos = startPos; + this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; + this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; + } else { + this.pos = this.lineStart = 0; + this.curLine = 1; } - if (obj) { - if ((typeof ArrayBuffer !== 'undefined' && - obj.buffer instanceof ArrayBuffer) || 'length' in obj) { - if (typeof obj.length !== 'number' || isnan(obj.length)) { - return createBuffer(that, 0) - } - return fromArrayLike(that, obj) - } + // Properties of the current token: + // Its type + this.type = types.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(); - if (obj.type === 'Buffer' && isArray(obj.data)) { - return fromArrayLike(that, obj.data) - } - } + // Position information for the previous token + this.lastTokEndLoc = this.lastTokStartLoc = null; + this.lastTokStart = this.lastTokEnd = this.pos; - throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') -} + // 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; -function checked (length) { - // Note: cannot use `length < kMaxLength()` here because that fails when - // length is NaN (which is otherwise coerced to zero.) - if (length >= kMaxLength()) { - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + kMaxLength().toString(16) + ' bytes') - } - return length | 0 -} + // Figure out if it's a module code. + this.inModule = options.sourceType === "module"; + this.strict = this.inModule || this.strictDirective(this.pos); -function SlowBuffer (length) { - if (+length != length) { // eslint-disable-line eqeqeq - length = 0 - } - return Buffer.alloc(+length) -} + // Used to signify the start of a potential arrow function + this.potentialArrowAt = -1; -Buffer.isBuffer = function isBuffer (b) { - return !!(b != null && b._isBuffer) -} + // Flags to track whether we are in a function, a generator, an async function. + this.inFunction = this.inGenerator = this.inAsync = false; + // Positions to delayed-check that yield/await does not exist in default parameters. + this.yieldPos = this.awaitPos = 0; + // Labels in scope. + this.labels = []; -Buffer.compare = function compare (a, b) { - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { - throw new TypeError('Arguments must be Buffers') - } + // If enabled, skip leading hashbang line. + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") + { this.skipLineComment(2); } - if (a === b) return 0 + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = []; + this.enterFunctionScope(); +}; - var x = a.length - var y = b.length +// 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) }; - for (var i = 0, len = Math.min(x, y); i < len; ++i) { - if (a[i] !== b[i]) { - x = a[i] - y = b[i] - break - } - } +Parser.prototype.extend = function extend (name, f) { + this[name] = f(this[name]); +}; - if (x < y) return -1 - if (y < x) return 1 - return 0 -} +Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) { + var this$1 = this; -Buffer.isEncoding = function isEncoding (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'latin1': - case 'binary': - case 'base64': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false + for (var name in pluginConfigs) { + var plugin = plugins[name]; + if (!plugin) { throw new Error("Plugin '" + name + "' not found") } + plugin(this$1, pluginConfigs[name]); } -} +}; -Buffer.concat = function concat (list, length) { - if (!isArray(list)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } +Parser.prototype.parse = function parse () { + var node = this.options.program || this.startNode(); + this.nextToken(); + return this.parseTopLevel(node) +}; - if (list.length === 0) { - return Buffer.alloc(0) - } +var pp = Parser.prototype; - var i - if (length === undefined) { - length = 0 - for (i = 0; i < list.length; ++i) { - length += list[i].length - } - } +// ## Parser utilities - var buffer = Buffer.allocUnsafe(length) - var pos = 0 - for (i = 0; i < list.length; ++i) { - var buf = list[i] - if (!Buffer.isBuffer(buf)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - buf.copy(buffer, pos) - pos += buf.length - } - return buffer -} +var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/; +pp.strictDirective = function(start) { + var this$1 = this; -function byteLength (string, encoding) { - if (Buffer.isBuffer(string)) { - return string.length - } - if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && - (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { - return string.byteLength - } - if (typeof string !== 'string') { - string = '' + string + for (;;) { + skipWhiteSpace.lastIndex = start; + start += skipWhiteSpace.exec(this$1.input)[0].length; + var match = literal.exec(this$1.input.slice(start)); + if (!match) { return false } + if ((match[1] || match[2]) == "use strict") { return true } + start += match[0].length; } +}; - var len = string.length - if (len === 0) return 0 +// Predicate that tests whether the next token is of the given +// type, and if yes, consumes it as a side effect. - // Use a for loop to avoid recursion - var loweredCase = false - for (;;) { - switch (encoding) { - case 'ascii': - case 'latin1': - case 'binary': - return len - case 'utf8': - case 'utf-8': - case undefined: - return utf8ToBytes(string).length - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return len * 2 - case 'hex': - return len >>> 1 - case 'base64': - return base64ToBytes(string).length - default: - if (loweredCase) return utf8ToBytes(string).length // assume utf8 - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } +pp.eat = function(type) { + if (this.type === type) { + this.next(); + return true + } else { + return false } -} -Buffer.byteLength = byteLength +}; -function slowToString (encoding, start, end) { - var loweredCase = false - - // No need to verify that "this.length <= MAX_UINT32" since it's a read-only - // property of a typed array. +// Tests whether parsed token is a contextual keyword. - // This behaves neither like String nor Uint8Array in that we set start/end - // to their upper/lower bounds if the value passed is out of range. - // undefined is handled specially as per ECMA-262 6th Edition, - // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. - if (start === undefined || start < 0) { - start = 0 - } - // Return early if start > this.length. Done here to prevent potential uint32 - // coercion fail below. - if (start > this.length) { - return '' - } +pp.isContextual = function(name) { + return this.type === types.name && this.value === name && !this.containsEsc +}; - if (end === undefined || end > this.length) { - end = this.length - } +// Consumes contextual keyword if possible. - if (end <= 0) { - return '' - } +pp.eatContextual = function(name) { + if (!this.isContextual(name)) { return false } + this.next(); + return true +}; - // Force coersion to uint32. This will also coerce falsey/NaN values to 0. - end >>>= 0 - start >>>= 0 +// Asserts that following token is given contextual keyword. - if (end <= start) { - return '' - } +pp.expectContextual = function(name) { + if (!this.eatContextual(name)) { this.unexpected(); } +}; - if (!encoding) encoding = 'utf8' +// Test whether a semicolon can be inserted at the current position. - while (true) { - switch (encoding) { - case 'hex': - return hexSlice(this, start, end) +pp.canInsertSemicolon = function() { + return this.type === types.eof || + this.type === types.braceR || + lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) +}; - case 'utf8': - case 'utf-8': - return utf8Slice(this, start, end) +pp.insertSemicolon = function() { + if (this.canInsertSemicolon()) { + if (this.options.onInsertedSemicolon) + { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } + return true + } +}; - case 'ascii': - return asciiSlice(this, start, end) +// Consume a semicolon, or, failing that, see if we are allowed to +// pretend that there is a semicolon at this position. - case 'latin1': - case 'binary': - return latin1Slice(this, start, end) +pp.semicolon = function() { + if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); } +}; - case 'base64': - return base64Slice(this, start, end) +pp.afterTrailingComma = function(tokType, notNext) { + if (this.type == tokType) { + if (this.options.onTrailingComma) + { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } + if (!notNext) + { this.next(); } + return true + } +}; - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return utf16leSlice(this, start, end) +// Expect a token of a given type. If found, consume it, otherwise, +// raise an unexpected token error. - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() - loweredCase = true - } - } -} +pp.expect = function(type) { + this.eat(type) || this.unexpected(); +}; -// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect -// Buffer instances. -Buffer.prototype._isBuffer = true +// Raise an unexpected token error. -function swap (b, n, m) { - var i = b[n] - b[n] = b[m] - b[m] = i -} +pp.unexpected = function(pos) { + this.raise(pos != null ? pos : this.start, "Unexpected token"); +}; -Buffer.prototype.swap16 = function swap16 () { - var len = this.length - if (len % 2 !== 0) { - throw new RangeError('Buffer size must be a multiple of 16-bits') - } - for (var i = 0; i < len; i += 2) { - swap(this, i, i + 1) - } - return this +function DestructuringErrors() { + this.shorthandAssign = + this.trailingComma = + this.parenthesizedAssign = + this.parenthesizedBind = + this.doubleProto = + -1; } -Buffer.prototype.swap32 = function swap32 () { - var len = this.length - if (len % 4 !== 0) { - throw new RangeError('Buffer size must be a multiple of 32-bits') - } - for (var i = 0; i < len; i += 4) { - swap(this, i, i + 3) - swap(this, i + 1, i + 2) - } - return this -} +pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { + if (!refDestructuringErrors) { return } + if (refDestructuringErrors.trailingComma > -1) + { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } + var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; + if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } +}; -Buffer.prototype.swap64 = function swap64 () { - var len = this.length - if (len % 8 !== 0) { - throw new RangeError('Buffer size must be a multiple of 64-bits') - } - for (var i = 0; i < len; i += 8) { - swap(this, i, i + 7) - swap(this, i + 1, i + 6) - swap(this, i + 2, i + 5) - swap(this, i + 3, i + 4) - } - return this -} +pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { + if (!refDestructuringErrors) { return false } + var shorthandAssign = refDestructuringErrors.shorthandAssign; + var doubleProto = refDestructuringErrors.doubleProto; + if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } + if (shorthandAssign >= 0) + { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } + if (doubleProto >= 0) + { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } +}; -Buffer.prototype.toString = function toString () { - var length = this.length | 0 - if (length === 0) return '' - if (arguments.length === 0) return utf8Slice(this, 0, length) - return slowToString.apply(this, arguments) -} +pp.checkYieldAwaitInDefaultParams = function() { + if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) + { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } + if (this.awaitPos) + { this.raise(this.awaitPos, "Await expression cannot be a default value"); } +}; -Buffer.prototype.equals = function equals (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - if (this === b) return true - return Buffer.compare(this, b) === 0 -} +pp.isSimpleAssignTarget = function(expr) { + if (expr.type === "ParenthesizedExpression") + { return this.isSimpleAssignTarget(expr.expression) } + return expr.type === "Identifier" || expr.type === "MemberExpression" +}; -Buffer.prototype.inspect = function inspect () { - var str = '' - var max = exports.INSPECT_MAX_BYTES - if (this.length > 0) { - str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') - if (this.length > max) str += ' ... ' - } - return '' -} +var pp$1 = Parser.prototype; -Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { - if (!Buffer.isBuffer(target)) { - throw new TypeError('Argument must be a Buffer') - } +// ### Statement parsing - if (start === undefined) { - start = 0 - } - if (end === undefined) { - end = target ? target.length : 0 - } - if (thisStart === undefined) { - thisStart = 0 - } - if (thisEnd === undefined) { - thisEnd = this.length - } +// 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. - if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { - throw new RangeError('out of range index') - } +pp$1.parseTopLevel = function(node) { + var this$1 = this; - if (thisStart >= thisEnd && start >= end) { - return 0 - } - if (thisStart >= thisEnd) { - return -1 + var exports = {}; + if (!node.body) { node.body = []; } + while (this.type !== types.eof) { + var stmt = this$1.parseStatement(true, true, exports); + node.body.push(stmt); } - if (start >= end) { - return 1 + this.adaptDirectivePrologue(node.body); + this.next(); + if (this.options.ecmaVersion >= 6) { + node.sourceType = this.options.sourceType; } + return this.finishNode(node, "Program") +}; - start >>>= 0 - end >>>= 0 - thisStart >>>= 0 - thisEnd >>>= 0 - - if (this === target) return 0 +var loopLabel = {kind: "loop"}; +var switchLabel = {kind: "switch"}; - var x = thisEnd - thisStart - var y = end - start - var len = Math.min(x, y) - - var thisCopy = this.slice(thisStart, thisEnd) - var targetCopy = target.slice(start, end) - - for (var i = 0; i < len; ++i) { - if (thisCopy[i] !== targetCopy[i]) { - x = thisCopy[i] - y = targetCopy[i] - break - } +pp$1.isLet = function() { + if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); + if (nextCh === 91 || nextCh == 123) { return true } // '{' and '[' + if (isIdentifierStart(nextCh, true)) { + var pos = next + 1; + while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; } + var ident = this.input.slice(next, pos); + if (!keywordRelationalOperator.test(ident)) { return true } } + return false +}; - if (x < y) return -1 - if (y < x) return 1 - return 0 -} +// check 'async [no LineTerminator here] function' +// - 'async /*foo*/ function' is OK. +// - 'async /*\n*/ function' is invalid. +pp$1.isAsyncFunction = function() { + if (this.options.ecmaVersion < 8 || !this.isContextual("async")) + { return false } -// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, -// OR the last index of `val` in `buffer` at offset <= `byteOffset`. + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length; + return !lineBreak.test(this.input.slice(this.pos, next)) && + this.input.slice(next, next + 8) === "function" && + (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) +}; + +// Parse a single statement. // -// Arguments: -// - buffer - a Buffer to search -// - val - a string, Buffer, or number -// - byteOffset - an index into `buffer`; will be clamped to an int32 -// - encoding - an optional encoding, relevant is val is a string -// - dir - true for indexOf, false for lastIndexOf -function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { - // Empty buffer means no match - if (buffer.length === 0) return -1 +// 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. - // Normalize byteOffset - if (typeof byteOffset === 'string') { - encoding = byteOffset - byteOffset = 0 - } else if (byteOffset > 0x7fffffff) { - byteOffset = 0x7fffffff - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000 - } - byteOffset = +byteOffset // Coerce to Number. - if (isNaN(byteOffset)) { - // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer - byteOffset = dir ? 0 : (buffer.length - 1) - } +pp$1.parseStatement = function(declaration, topLevel, exports) { + var starttype = this.type, node = this.startNode(), kind; - // Normalize byteOffset: negative offsets start from the end of the buffer - if (byteOffset < 0) byteOffset = buffer.length + byteOffset - if (byteOffset >= buffer.length) { - if (dir) return -1 - else byteOffset = buffer.length - 1 - } else if (byteOffset < 0) { - if (dir) byteOffset = 0 - else return -1 + if (this.isLet()) { + starttype = types._var; + kind = "let"; } - // Normalize val - if (typeof val === 'string') { - val = Buffer.from(val, encoding) - } + // Most types of statements are recognized by the keyword they + // start with. Many are trivial to parse, some require a bit of + // complexity. - // Finally, search either indexOf (if dir is true) or lastIndexOf - if (Buffer.isBuffer(val)) { - // Special case: looking for empty string/buffer always fails - if (val.length === 0) { - return -1 + switch (starttype) { + case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword) + case types._debugger: return this.parseDebuggerStatement(node) + case types._do: return this.parseDoStatement(node) + case types._for: return this.parseForStatement(node) + case types._function: + if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); } + return this.parseFunctionStatement(node, false) + case types._class: + if (!declaration) { this.unexpected(); } + return this.parseClass(node, true) + case types._if: return this.parseIfStatement(node) + case types._return: return this.parseReturnStatement(node) + case types._switch: return this.parseSwitchStatement(node) + case types._throw: return this.parseThrowStatement(node) + case types._try: return this.parseTryStatement(node) + case types._const: case types._var: + kind = kind || this.value; + if (!declaration && kind != "var") { this.unexpected(); } + return this.parseVarStatement(node, kind) + case types._while: return this.parseWhileStatement(node) + case types._with: return this.parseWithStatement(node) + case types.braceL: return this.parseBlock() + case types.semi: return this.parseEmptyStatement(node) + case types._export: + case types._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 arrayIndexOf(buffer, val, byteOffset, encoding, dir) - } else if (typeof val === 'number') { - val = val & 0xFF // Search for a byte value [0-255] - if (Buffer.TYPED_ARRAY_SUPPORT && - typeof Uint8Array.prototype.indexOf === 'function') { - if (dir) { - return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) - } else { - return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) - } + return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports) + + // 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: + if (this.isAsyncFunction()) { + if (!declaration) { this.unexpected(); } + this.next(); + return this.parseFunctionStatement(node, true) } - return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) - } - throw new TypeError('val must be string, number or Buffer') -} + var maybeName = this.value, expr = this.parseExpression(); + if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) + { return this.parseLabeledStatement(node, maybeName, expr) } + else { return this.parseExpressionStatement(node, expr) } + } +}; -function arrayIndexOf (arr, val, byteOffset, encoding, dir) { - var indexSize = 1 - var arrLength = arr.length - var valLength = val.length +pp$1.parseBreakContinueStatement = function(node, keyword) { + var this$1 = this; - if (encoding !== undefined) { - encoding = String(encoding).toLowerCase() - if (encoding === 'ucs2' || encoding === 'ucs-2' || - encoding === 'utf16le' || encoding === 'utf-16le') { - if (arr.length < 2 || val.length < 2) { - return -1 - } - indexSize = 2 - arrLength /= 2 - valLength /= 2 - byteOffset /= 2 - } + var isBreak = keyword == "break"; + this.next(); + if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; } + else if (this.type !== types.name) { this.unexpected(); } + else { + node.label = this.parseIdent(); + this.semicolon(); } - function read (buf, i) { - if (indexSize === 1) { - return buf[i] - } else { - return buf.readUInt16BE(i * indexSize) + // Verify that there is an actual destination to break or + // continue to. + var i = 0; + for (; i < this.labels.length; ++i) { + var lab = this$1.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") +}; - var i - if (dir) { - var foundIndex = -1 - for (i = byteOffset; i < arrLength; i++) { - if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { - if (foundIndex === -1) foundIndex = i - if (i - foundIndex + 1 === valLength) return foundIndex * indexSize - } else { - if (foundIndex !== -1) i -= i - foundIndex - foundIndex = -1 - } - } - } else { - if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength - for (i = byteOffset; i >= 0; i--) { - var found = true - for (var j = 0; j < valLength; j++) { - if (read(arr, i + j) !== read(val, j)) { - found = false - break - } - } - if (found) return i - } - } +pp$1.parseDebuggerStatement = function(node) { + this.next(); + this.semicolon(); + return this.finishNode(node, "DebuggerStatement") +}; - return -1 -} +pp$1.parseDoStatement = function(node) { + this.next(); + this.labels.push(loopLabel); + node.body = this.parseStatement(false); + this.labels.pop(); + this.expect(types._while); + node.test = this.parseParenExpression(); + if (this.options.ecmaVersion >= 6) + { this.eat(types.semi); } + else + { this.semicolon(); } + return this.finishNode(node, "DoWhileStatement") +}; -Buffer.prototype.includes = function includes (val, byteOffset, encoding) { - return this.indexOf(val, byteOffset, encoding) !== -1 -} +// 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. -Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, true) -} - -Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, false) -} - -function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - var remaining = buf.length - offset - if (!length) { - length = remaining +pp$1.parseForStatement = function(node) { + this.next(); + this.labels.push(loopLabel); + this.enterLexicalScope(); + this.expect(types.parenL); + if (this.type === types.semi) { return this.parseFor(node, null) } + var isLet = this.isLet(); + if (this.type === types._var || this.type === types._const || isLet) { + var init$1 = this.startNode(), kind = isLet ? "let" : this.value; + this.next(); + this.parseVar(init$1, true, kind); + this.finishNode(init$1, "VariableDeclaration"); + if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 && + !(kind !== "var" && init$1.declarations[0].init)) + { return this.parseForIn(node, init$1) } + return this.parseFor(node, init$1) + } + var refDestructuringErrors = new DestructuringErrors; + var init = this.parseExpression(true, refDestructuringErrors); + if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { + this.toAssignable(init, false, refDestructuringErrors); + this.checkLVal(init); + return this.parseForIn(node, init) } else { - length = Number(length) - if (length > remaining) { - length = remaining - } + this.checkExpressionErrors(refDestructuringErrors, true); } + return this.parseFor(node, init) +}; - // must be an even number of digits - var strLen = string.length - if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') +pp$1.parseFunctionStatement = function(node, isAsync) { + this.next(); + return this.parseFunction(node, true, false, isAsync) +}; - if (length > strLen / 2) { - length = strLen / 2 - } - for (var i = 0; i < length; ++i) { - var parsed = parseInt(string.substr(i * 2, 2), 16) - if (isNaN(parsed)) return i - buf[offset + i] = parsed - } - return i -} +pp$1.parseIfStatement = function(node) { + this.next(); + node.test = this.parseParenExpression(); + // allow function declarations in branches, but only in non-strict mode + node.consequent = this.parseStatement(!this.strict && this.type == types._function); + node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.type == types._function) : null; + return this.finishNode(node, "IfStatement") +}; -function utf8Write (buf, string, offset, length) { - return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) -} +pp$1.parseReturnStatement = function(node) { + if (!this.inFunction && !this.options.allowReturnOutsideFunction) + { this.raise(this.start, "'return' outside of function"); } + this.next(); -function asciiWrite (buf, string, offset, length) { - return blitBuffer(asciiToBytes(string), buf, offset, length) -} + // In `return` (and `break`/`continue`), the keywords with + // optional arguments, we eagerly look for a semicolon or the + // possibility to insert one. -function latin1Write (buf, string, offset, length) { - return asciiWrite(buf, string, offset, length) -} + if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; } + else { node.argument = this.parseExpression(); this.semicolon(); } + return this.finishNode(node, "ReturnStatement") +}; -function base64Write (buf, string, offset, length) { - return blitBuffer(base64ToBytes(string), buf, offset, length) -} +pp$1.parseSwitchStatement = function(node) { + var this$1 = this; -function ucs2Write (buf, string, offset, length) { - return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) -} + this.next(); + node.discriminant = this.parseParenExpression(); + node.cases = []; + this.expect(types.braceL); + this.labels.push(switchLabel); + this.enterLexicalScope(); -Buffer.prototype.write = function write (string, offset, length, encoding) { - // Buffer#write(string) - if (offset === undefined) { - encoding = 'utf8' - length = this.length - offset = 0 - // Buffer#write(string, encoding) - } else if (length === undefined && typeof offset === 'string') { - encoding = offset - length = this.length - offset = 0 - // Buffer#write(string, offset[, length][, encoding]) - } else if (isFinite(offset)) { - offset = offset | 0 - if (isFinite(length)) { - length = length | 0 - if (encoding === undefined) encoding = 'utf8' + // Statements under must be grouped (by label) in SwitchCase + // nodes. `cur` is used to keep the node that we are currently + // adding statements to. + + var cur; + for (var sawDefault = false; this.type != types.braceR;) { + if (this$1.type === types._case || this$1.type === types._default) { + var isCase = this$1.type === types._case; + if (cur) { this$1.finishNode(cur, "SwitchCase"); } + node.cases.push(cur = this$1.startNode()); + cur.consequent = []; + this$1.next(); + if (isCase) { + cur.test = this$1.parseExpression(); + } else { + if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); } + sawDefault = true; + cur.test = null; + } + this$1.expect(types.colon); } else { - encoding = length - length = undefined + if (!cur) { this$1.unexpected(); } + cur.consequent.push(this$1.parseStatement(true)); } - // legacy write(string, encoding, offset, length) - remove in v0.13 - } else { - throw new Error( - 'Buffer.write(string, encoding, offset[, length]) is no longer supported' - ) } + this.exitLexicalScope(); + if (cur) { this.finishNode(cur, "SwitchCase"); } + this.next(); // Closing brace + this.labels.pop(); + return this.finishNode(node, "SwitchStatement") +}; - var remaining = this.length - offset - if (length === undefined || length > remaining) length = remaining - - if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { - throw new RangeError('Attempt to write outside buffer bounds') - } +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") +}; - if (!encoding) encoding = 'utf8' +// Reused empty array added for node fields that are always empty. - var loweredCase = false - for (;;) { - switch (encoding) { - case 'hex': - return hexWrite(this, string, offset, length) +var empty = []; - case 'utf8': - case 'utf-8': - return utf8Write(this, string, offset, length) +pp$1.parseTryStatement = function(node) { + this.next(); + node.block = this.parseBlock(); + node.handler = null; + if (this.type === types._catch) { + var clause = this.startNode(); + this.next(); + this.expect(types.parenL); + clause.param = this.parseBindingAtom(); + this.enterLexicalScope(); + this.checkLVal(clause.param, "let"); + this.expect(types.parenR); + clause.body = this.parseBlock(false); + this.exitLexicalScope(); + node.handler = this.finishNode(clause, "CatchClause"); + } + node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; + if (!node.handler && !node.finalizer) + { this.raise(node.start, "Missing catch or finally clause"); } + return this.finishNode(node, "TryStatement") +}; - case 'ascii': - return asciiWrite(this, string, offset, length) +pp$1.parseVarStatement = function(node, kind) { + this.next(); + this.parseVar(node, false, kind); + this.semicolon(); + return this.finishNode(node, "VariableDeclaration") +}; - case 'latin1': - case 'binary': - return latin1Write(this, string, offset, length) +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") +}; - case 'base64': - // Warning: maxLength not taken into account in base64Write - return base64Write(this, string, offset, length) +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") +}; - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return ucs2Write(this, string, offset, length) +pp$1.parseEmptyStatement = function(node) { + this.next(); + return this.finishNode(node, "EmptyStatement") +}; - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} +pp$1.parseLabeledStatement = function(node, maybeName, expr) { + var this$1 = this; -Buffer.prototype.toJSON = function toJSON () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) - } -} + for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1) + { + var label = list[i$1]; -function base64Slice (buf, start, end) { - if (start === 0 && end === buf.length) { - return base64.fromByteArray(buf) - } else { - return base64.fromByteArray(buf.slice(start, end)) + if (label.name === maybeName) + { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared"); + } } + var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; + for (var i = this.labels.length - 1; i >= 0; i--) { + var label$1 = this$1.labels[i]; + if (label$1.statementStart == node.start) { + // Update information about previous labels on this node + label$1.statementStart = this$1.start; + label$1.kind = kind; + } else { break } } -} - -function utf8Slice (buf, start, end) { - end = Math.min(buf.length, end) - var res = [] - - var i = start - while (i < end) { - var firstByte = buf[i] - var codePoint = null - var bytesPerSequence = (firstByte > 0xEF) ? 4 - : (firstByte > 0xDF) ? 3 - : (firstByte > 0xBF) ? 2 - : 1 + this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); + node.body = this.parseStatement(true); + if (node.body.type == "ClassDeclaration" || + node.body.type == "VariableDeclaration" && node.body.kind != "var" || + node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) + { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); } + this.labels.pop(); + node.label = expr; + return this.finishNode(node, "LabeledStatement") +}; - if (i + bytesPerSequence <= end) { - var secondByte, thirdByte, fourthByte, tempCodePoint +pp$1.parseExpressionStatement = function(node, expr) { + node.expression = expr; + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") +}; - switch (bytesPerSequence) { - case 1: - if (firstByte < 0x80) { - codePoint = firstByte - } - break - case 2: - secondByte = buf[i + 1] - if ((secondByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) - if (tempCodePoint > 0x7F) { - codePoint = tempCodePoint - } - } - break - case 3: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) - if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { - codePoint = tempCodePoint - } - } - break - case 4: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - fourthByte = buf[i + 3] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) - if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { - codePoint = tempCodePoint - } - } - } - } +// Parse a semicolon-enclosed block of statements, handling `"use +// strict"` declarations when `allowStrict` is true (used for +// function bodies). - if (codePoint === null) { - // we did not generate a valid codePoint so insert a - // replacement char (U+FFFD) and advance only 1 byte - codePoint = 0xFFFD - bytesPerSequence = 1 - } else if (codePoint > 0xFFFF) { - // encode to utf16 (surrogate pair dance) - codePoint -= 0x10000 - res.push(codePoint >>> 10 & 0x3FF | 0xD800) - codePoint = 0xDC00 | codePoint & 0x3FF - } +pp$1.parseBlock = function(createNewLexicalScope) { + var this$1 = this; + if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; - res.push(codePoint) - i += bytesPerSequence + var node = this.startNode(); + node.body = []; + this.expect(types.braceL); + if (createNewLexicalScope) { + this.enterLexicalScope(); } - - return decodeCodePointsArray(res) -} - -// Based on http://stackoverflow.com/a/22747272/680742, the browser with -// the lowest limit is Chrome, with 0x10000 args. -// We go 1 magnitude less, for safety -var MAX_ARGUMENTS_LENGTH = 0x1000 - -function decodeCodePointsArray (codePoints) { - var len = codePoints.length - if (len <= MAX_ARGUMENTS_LENGTH) { - return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + while (!this.eat(types.braceR)) { + var stmt = this$1.parseStatement(true); + node.body.push(stmt); } - - // Decode in chunks to avoid "call stack size exceeded". - var res = '' - var i = 0 - while (i < len) { - res += String.fromCharCode.apply( - String, - codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) - ) + if (createNewLexicalScope) { + this.exitLexicalScope(); } - return res -} + return this.finishNode(node, "BlockStatement") +}; -function asciiSlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) +// Parse a regular `for` loop. The disambiguation code in +// `parseStatement` will already have parsed the init statement or +// expression. - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i] & 0x7F) - } - return ret -} +pp$1.parseFor = function(node, init) { + node.init = init; + this.expect(types.semi); + node.test = this.type === types.semi ? null : this.parseExpression(); + this.expect(types.semi); + node.update = this.type === types.parenR ? null : this.parseExpression(); + this.expect(types.parenR); + this.exitLexicalScope(); + node.body = this.parseStatement(false); + this.labels.pop(); + return this.finishNode(node, "ForStatement") +}; -function latin1Slice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) +// Parse a `for`/`in` and `for`/`of` loop, which are almost +// same from parser's perspective. - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i]) +pp$1.parseForIn = function(node, init) { + var type = this.type === types._in ? "ForInStatement" : "ForOfStatement"; + this.next(); + if (type == "ForInStatement") { + if (init.type === "AssignmentPattern" || + (init.type === "VariableDeclaration" && init.declarations[0].init != null && + (this.strict || init.declarations[0].id.type !== "Identifier"))) + { this.raise(init.start, "Invalid assignment in for-in loop head"); } } - return ret -} + node.left = init; + node.right = type == "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign(); + this.expect(types.parenR); + this.exitLexicalScope(); + node.body = this.parseStatement(false); + this.labels.pop(); + return this.finishNode(node, type) +}; -function hexSlice (buf, start, end) { - var len = buf.length +// Parse a list of variable declarations. - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len +pp$1.parseVar = function(node, isFor, kind) { + var this$1 = this; - var out = '' - for (var i = start; i < end; ++i) { - out += toHex(buf[i]) + node.declarations = []; + node.kind = kind; + for (;;) { + var decl = this$1.startNode(); + this$1.parseVarId(decl, kind); + if (this$1.eat(types.eq)) { + decl.init = this$1.parseMaybeAssign(isFor); + } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { + this$1.unexpected(); + } else if (decl.id.type != "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) { + this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value"); + } else { + decl.init = null; + } + node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")); + if (!this$1.eat(types.comma)) { break } } - return out -} + return node +}; -function utf16leSlice (buf, start, end) { - var bytes = buf.slice(start, end) - var res = '' - for (var i = 0; i < bytes.length; i += 2) { - res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) - } - return res -} +pp$1.parseVarId = function(decl, kind) { + decl.id = this.parseBindingAtom(kind); + this.checkLVal(decl.id, kind, false); +}; -Buffer.prototype.slice = function slice (start, end) { - var len = this.length - start = ~~start - end = end === undefined ? len : ~~end +// Parse a function declaration or literal (depending on the +// `isStatement` parameter). - if (start < 0) { - start += len - if (start < 0) start = 0 - } else if (start > len) { - start = len - } +pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { + this.initFunction(node); + if (this.options.ecmaVersion >= 6 && !isAsync) + { node.generator = this.eat(types.star); } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } - if (end < 0) { - end += len - if (end < 0) end = 0 - } else if (end > len) { - end = len + if (isStatement) { + node.id = isStatement === "nullableID" && this.type != types.name ? null : this.parseIdent(); + if (node.id) { + this.checkLVal(node.id, "var"); + } } - if (end < start) end = start + var oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; + this.inGenerator = node.generator; + this.inAsync = node.async; + this.yieldPos = 0; + this.awaitPos = 0; + this.inFunction = true; + this.enterFunctionScope(); - var newBuf - if (Buffer.TYPED_ARRAY_SUPPORT) { - newBuf = this.subarray(start, end) - newBuf.__proto__ = Buffer.prototype - } else { - var sliceLen = end - start - newBuf = new Buffer(sliceLen, undefined) - for (var i = 0; i < sliceLen; ++i) { - newBuf[i] = this[i + start] - } - } + if (!isStatement) + { node.id = this.type == types.name ? this.parseIdent() : null; } - return newBuf -} + this.parseFunctionParams(node); + this.parseFunctionBody(node, allowExpressionBody); -/* - * Need to make sure that buffer isn't trying to write out of bounds. - */ -function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') - if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') -} + this.inGenerator = oldInGen; + this.inAsync = oldInAsync; + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.inFunction = oldInFunc; + return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") +}; -Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) +pp$1.parseFunctionParams = function(node) { + this.expect(types.parenL); + node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); +}; - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } +// Parse a class declaration or literal (depending on the +// `isStatement` parameter). - return val -} +pp$1.parseClass = function(node, isStatement) { + var this$1 = this; -Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) { - checkOffset(offset, byteLength, this.length) - } + this.next(); - var val = this[offset + --byteLength] - var mul = 1 - while (byteLength > 0 && (mul *= 0x100)) { - val += this[offset + --byteLength] * mul + this.parseClassId(node, isStatement); + this.parseClassSuper(node); + var classBody = this.startNode(); + var hadConstructor = false; + classBody.body = []; + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + var member = this$1.parseClassMember(classBody); + if (member && member.type === "MethodDefinition" && member.kind === "constructor") { + if (hadConstructor) { this$1.raise(member.start, "Duplicate constructor in the same class"); } + hadConstructor = true; + } } + node.body = this.finishNode(classBody, "ClassBody"); + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") +}; - return val -} - -Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { - if (!noAssert) checkOffset(offset, 1, this.length) - return this[offset] -} +pp$1.parseClassMember = function(classBody) { + var this$1 = this; -Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - return this[offset] | (this[offset + 1] << 8) -} + if (this.eat(types.semi)) { return null } -Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - return (this[offset] << 8) | this[offset + 1] -} + var method = this.startNode(); + var tryContextual = function (k, noLineBreak) { + if ( noLineBreak === void 0 ) noLineBreak = false; -Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) + var start = this$1.start, startLoc = this$1.startLoc; + if (!this$1.eatContextual(k)) { return false } + if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true } + if (method.key) { this$1.unexpected(); } + method.computed = false; + method.key = this$1.startNodeAt(start, startLoc); + method.key.name = k; + this$1.finishNode(method.key, "Identifier"); + return false + }; - return ((this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16)) + - (this[offset + 3] * 0x1000000) -} + method.kind = "method"; + method.static = tryContextual("static"); + var isGenerator = this.eat(types.star); + var isAsync = false; + if (!isGenerator) { + if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) { + isAsync = true; + } else if (tryContextual("get")) { + method.kind = "get"; + } else if (tryContextual("set")) { + method.kind = "set"; + } + } + if (!method.key) { this.parsePropertyName(method); } + var key = method.key; + if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || + key.type === "Literal" && key.value === "constructor")) { + if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); } + if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } + if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } + method.kind = "constructor"; + } else if (method.static && key.type === "Identifier" && key.name === "prototype") { + this.raise(key.start, "Classes may not have a static property named prototype"); + } + this.parseClassMethod(classBody, method, isGenerator, isAsync); + if (method.kind === "get" && method.value.params.length !== 0) + { this.raiseRecoverable(method.value.start, "getter should have no params"); } + if (method.kind === "set" && method.value.params.length !== 1) + { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); } + if (method.kind === "set" && method.value.params[0].type === "RestElement") + { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); } + return method +}; -Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) +pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) { + method.value = this.parseMethod(isGenerator, isAsync); + classBody.body.push(this.finishNode(method, "MethodDefinition")); +}; - return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) -} +pp$1.parseClassId = function(node, isStatement) { + node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null; +}; -Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) +pp$1.parseClassSuper = function(node) { + node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; +}; - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - mul *= 0x80 +// Parses module export declaration. - if (val >= mul) val -= Math.pow(2, 8 * byteLength) +pp$1.parseExport = function(node, exports) { + var this$1 = this; - return val -} + this.next(); + // export * from '...' + if (this.eat(types.star)) { + this.expectContextual("from"); + if (this.type !== types.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(types._default)) { // export default ... + this.checkExport(exports, "default", this.lastTokStart); + var isAsync; + if (this.type === types._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync); + } else if (this.type === types._class) { + var cNode = this.startNode(); + node.declaration = this.parseClass(cNode, "nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); + } + return this.finishNode(node, "ExportDefaultDeclaration") + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseStatement(true); + if (node.declaration.type === "VariableDeclaration") + { this.checkVariableExport(exports, node.declaration.declarations); } + else + { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } + node.specifiers = []; + node.source = null; + } else { // export { x, y as z } [from '...'] + node.declaration = null; + node.specifiers = this.parseExportSpecifiers(exports); + if (this.eatContextual("from")) { + if (this.type !== types.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + } else { + // check for keywords used as local names + for (var i = 0, list = node.specifiers; i < list.length; i += 1) { + var spec = list[i]; -Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) + this$1.checkUnreserved(spec.local); + } - var i = byteLength - var mul = 1 - var val = this[offset + --i] - while (i > 0 && (mul *= 0x100)) { - val += this[offset + --i] * mul + node.source = null; + } + this.semicolon(); } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) + return this.finishNode(node, "ExportNamedDeclaration") +}; - return val -} - -Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { - if (!noAssert) checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) return (this[offset]) - return ((0xff - this[offset] + 1) * -1) -} - -Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset] | (this[offset + 1] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} +pp$1.checkExport = function(exports, name, pos) { + if (!exports) { return } + if (has(exports, name)) + { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } + exports[name] = true; +}; -Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset + 1] | (this[offset] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} +pp$1.checkPatternExport = function(exports, pat) { + var this$1 = this; -Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) + var type = pat.type; + if (type == "Identifier") + { this.checkExport(exports, pat.name, pat.start); } + else if (type == "ObjectPattern") + { for (var i = 0, list = pat.properties; i < list.length; i += 1) + { + var prop = list[i]; - return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) -} + this$1.checkPatternExport(exports, prop.value); + } } + else if (type == "ArrayPattern") + { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { + var elt = list$1[i$1]; -Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) + if (elt) { this$1.checkPatternExport(exports, elt); } + } } + else if (type == "AssignmentPattern") + { this.checkPatternExport(exports, pat.left); } + else if (type == "ParenthesizedExpression") + { this.checkPatternExport(exports, pat.expression); } +}; - return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) -} +pp$1.checkVariableExport = function(exports, decls) { + var this$1 = this; -Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, true, 23, 4) -} + if (!exports) { return } + for (var i = 0, list = decls; i < list.length; i += 1) + { + var decl = list[i]; -Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, false, 23, 4) -} + this$1.checkPatternExport(exports, decl.id); + } +}; -Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, true, 52, 8) -} +pp$1.shouldParseExportStatement = function() { + return this.type.keyword === "var" || + this.type.keyword === "const" || + this.type.keyword === "class" || + this.type.keyword === "function" || + this.isLet() || + this.isAsyncFunction() +}; -Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, false, 52, 8) -} +// Parses a comma-separated list of module exports. -function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') - if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') - if (offset + ext > buf.length) throw new RangeError('Index out of range') -} +pp$1.parseExportSpecifiers = function(exports) { + var this$1 = this; -Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } + var nodes = [], first = true; + // export { x, y as z } [from '...'] + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this$1.expect(types.comma); + if (this$1.afterTrailingComma(types.braceR)) { break } + } else { first = false; } - var mul = 1 - var i = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF + var node = this$1.startNode(); + node.local = this$1.parseIdent(true); + node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local; + this$1.checkExport(exports, node.exported.name, node.exported.start); + nodes.push(this$1.finishNode(node, "ExportSpecifier")); } + return nodes +}; - return offset + byteLength -} - -Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } +// Parses import declaration. - var i = byteLength - 1 - var mul = 1 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF +pp$1.parseImport = function(node) { + this.next(); + // import '...' + if (this.type === types.string) { + node.specifiers = empty; + node.source = this.parseExprAtom(); + } else { + node.specifiers = this.parseImportSpecifiers(); + this.expectContextual("from"); + node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration") +}; - return offset + byteLength -} +// Parses a comma-separated list of module imports. -Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - this[offset] = (value & 0xff) - return offset + 1 -} +pp$1.parseImportSpecifiers = function() { + var this$1 = this; -function objectWriteUInt16 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { - buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> - (littleEndian ? i : 1 - i) * 8 + var nodes = [], first = true; + if (this.type === types.name) { + // import defaultObj, { x, y as z } from '...' + var node = this.startNode(); + node.local = this.parseIdent(); + this.checkLVal(node.local, "let"); + nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); + if (!this.eat(types.comma)) { return nodes } } -} - -Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - } else { - objectWriteUInt16(this, value, offset, true) + if (this.type === types.star) { + var node$1 = this.startNode(); + this.next(); + this.expectContextual("as"); + node$1.local = this.parseIdent(); + this.checkLVal(node$1.local, "let"); + nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); + return nodes } - return offset + 2 -} + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this$1.expect(types.comma); + if (this$1.afterTrailingComma(types.braceR)) { break } + } else { first = false; } -Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - } else { - objectWriteUInt16(this, value, offset, false) + var node$2 = this$1.startNode(); + node$2.imported = this$1.parseIdent(true); + if (this$1.eatContextual("as")) { + node$2.local = this$1.parseIdent(); + } else { + this$1.checkUnreserved(node$2.imported); + node$2.local = node$2.imported; + } + this$1.checkLVal(node$2.local, "let"); + nodes.push(this$1.finishNode(node$2, "ImportSpecifier")); } - return offset + 2 -} + return nodes +}; -function objectWriteUInt32 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffffffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { - buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff +// Set `ExpressionStatement#directive` property for directive prologues. +pp$1.adaptDirectivePrologue = function(statements) { + for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { + statements[i].directive = statements[i].expression.raw.slice(1, -1); } -} +}; +pp$1.isDirectiveCandidate = function(statement) { + return ( + statement.type === "ExpressionStatement" && + statement.expression.type === "Literal" && + typeof statement.expression.value === "string" && + // Reject parenthesized strings. + (this.input[statement.start] === "\"" || this.input[statement.start] === "'") + ) +}; -Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, true) - } - return offset + 4 -} +var pp$2 = Parser.prototype; -Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, false) - } - return offset + 4 -} +// Convert existing expression atom to assignable pattern +// if possible. -Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) +pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) { + var this$1 = this; - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } + if (this.options.ecmaVersion >= 6 && node) { + switch (node.type) { + case "Identifier": + if (this.inAsync && node.name === "await") + { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); } + break - var i = 0 - var mul = 1 - var sub = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } + case "ObjectPattern": + case "ArrayPattern": + case "RestElement": + break - return offset + byteLength -} + case "ObjectExpression": + node.type = "ObjectPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + for (var i = 0, list = node.properties; i < list.length; i += 1) + { + var prop = list[i]; -Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) + this$1.toAssignable(prop, isBinding); + } + break - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } + case "Property": + // AssignmentProperty has type == "Property" + if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } + this.toAssignable(node.value, isBinding); + break - var i = byteLength - 1 - var mul = 1 - var sub = 0 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } + case "ArrayExpression": + node.type = "ArrayPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + this.toAssignableList(node.elements, isBinding); + break - return offset + byteLength -} + case "SpreadElement": + node.type = "RestElement"; + this.toAssignable(node.argument, isBinding); + if (node.argument.type === "AssignmentPattern") + { this.raise(node.argument.start, "Rest elements cannot have a default value"); } + break -Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - if (value < 0) value = 0xff + value + 1 - this[offset] = (value & 0xff) - return offset + 1 -} + case "AssignmentExpression": + if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } + node.type = "AssignmentPattern"; + delete node.operator; + this.toAssignable(node.left, isBinding); + // falls through to AssignmentPattern -Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - } else { - objectWriteUInt16(this, value, offset, true) - } - return offset + 2 -} + case "AssignmentPattern": + break -Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - } else { - objectWriteUInt16(this, value, offset, false) - } - return offset + 2 -} + case "ParenthesizedExpression": + this.toAssignable(node.expression, isBinding); + break -Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - } else { - objectWriteUInt32(this, value, offset, true) - } - return offset + 4 -} + case "MemberExpression": + if (!isBinding) { break } -Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, false) - } - return offset + 4 -} + default: + this.raise(node.start, "Assigning to rvalue"); + } + } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + return node +}; -function checkIEEE754 (buf, value, offset, ext, max, min) { - if (offset + ext > buf.length) throw new RangeError('Index out of range') - if (offset < 0) throw new RangeError('Index out of range') -} +// Convert list of expression atoms to binding list. -function writeFloat (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) +pp$2.toAssignableList = function(exprList, isBinding) { + var this$1 = this; + + var end = exprList.length; + for (var i = 0; i < end; i++) { + var elt = exprList[i]; + if (elt) { this$1.toAssignable(elt, isBinding); } } - ieee754.write(buf, value, offset, littleEndian, 23, 4) - return offset + 4 -} + if (end) { + var last = exprList[end - 1]; + if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") + { this.unexpected(last.argument.start); } + } + return exprList +}; -Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { - return writeFloat(this, value, offset, true, noAssert) -} +// Parses spread element. -Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { - return writeFloat(this, value, offset, false, noAssert) -} +pp$2.parseSpread = function(refDestructuringErrors) { + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeAssign(false, refDestructuringErrors); + return this.finishNode(node, "SpreadElement") +}; -function writeDouble (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - ieee754.write(buf, value, offset, littleEndian, 52, 8) - return offset + 8 -} +pp$2.parseRestBinding = function() { + var node = this.startNode(); + this.next(); -Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { - return writeDouble(this, value, offset, true, noAssert) -} + // RestElement inside of a function parameter must be an identifier + if (this.options.ecmaVersion === 6 && this.type !== types.name) + { this.unexpected(); } -Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { - return writeDouble(this, value, offset, false, noAssert) -} + node.argument = this.parseBindingAtom(); -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function copy (target, targetStart, start, end) { - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (targetStart >= target.length) targetStart = target.length - if (!targetStart) targetStart = 0 - if (end > 0 && end < start) end = start + return this.finishNode(node, "RestElement") +}; - // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || this.length === 0) return 0 +// Parses lvalue (assignable) atom. - // Fatal error conditions - if (targetStart < 0) { - throw new RangeError('targetStart out of bounds') - } - if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') - if (end < 0) throw new RangeError('sourceEnd out of bounds') +pp$2.parseBindingAtom = function() { + if (this.options.ecmaVersion >= 6) { + switch (this.type) { + case types.bracketL: + var node = this.startNode(); + this.next(); + node.elements = this.parseBindingList(types.bracketR, true, true); + return this.finishNode(node, "ArrayPattern") - // Are we oob? - if (end > this.length) end = this.length - if (target.length - targetStart < end - start) { - end = target.length - targetStart + start + case types.braceL: + return this.parseObj(true) + } } + return this.parseIdent() +}; - var len = end - start - var i +pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) { + var this$1 = this; - if (this === target && start < targetStart && targetStart < end) { - // descending copy from end - for (i = len - 1; i >= 0; --i) { - target[i + targetStart] = this[i + start] - } - } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { - // ascending copy from start - for (i = 0; i < len; ++i) { - target[i + targetStart] = this[i + start] + var elts = [], first = true; + while (!this.eat(close)) { + if (first) { first = false; } + else { this$1.expect(types.comma); } + if (allowEmpty && this$1.type === types.comma) { + elts.push(null); + } else if (allowTrailingComma && this$1.afterTrailingComma(close)) { + break + } else if (this$1.type === types.ellipsis) { + var rest = this$1.parseRestBinding(); + this$1.parseBindingListItem(rest); + elts.push(rest); + if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } + this$1.expect(close); + break + } else { + var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc); + this$1.parseBindingListItem(elem); + elts.push(elem); } - } else { - Uint8Array.prototype.set.call( - target, - this.subarray(start, start + len), - targetStart - ) } + return elts +}; - return len -} +pp$2.parseBindingListItem = function(param) { + return param +}; -// Usage: -// buffer.fill(number[, offset[, end]]) -// buffer.fill(buffer[, offset[, end]]) -// buffer.fill(string[, offset[, end]][, encoding]) -Buffer.prototype.fill = function fill (val, start, end, encoding) { - // Handle string cases: - if (typeof val === 'string') { - if (typeof start === 'string') { - encoding = start - start = 0 - end = this.length - } else if (typeof end === 'string') { - encoding = end - end = this.length +// 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(types.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. +// bindingType can be either: +// 'var' indicating that the lval creates a 'var' binding +// 'let' indicating that the lval creates a lexical ('let' or 'const') binding +// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references + +pp$2.checkLVal = function(expr, bindingType, checkClashes) { + var this$1 = this; + + switch (expr.type) { + case "Identifier": + if (this.strict && this.reservedWordsStrictBind.test(expr.name)) + { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } + if (checkClashes) { + if (has(checkClashes, expr.name)) + { this.raiseRecoverable(expr.start, "Argument name clash"); } + checkClashes[expr.name] = true; } - if (val.length === 1) { - var code = val.charCodeAt(0) - if (code < 256) { - val = code + if (bindingType && bindingType !== "none") { + if ( + bindingType === "var" && !this.canDeclareVarName(expr.name) || + bindingType !== "var" && !this.canDeclareLexicalName(expr.name) + ) { + this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared")); + } + if (bindingType === "var") { + this.declareVarName(expr.name); + } else { + this.declareLexicalName(expr.name); } } - if (encoding !== undefined && typeof encoding !== 'string') { - throw new TypeError('encoding must be a string') - } - if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) - } - } else if (typeof val === 'number') { - val = val & 255 - } + break - // Invalid ranges are not set to a default, so can range check early. - if (start < 0 || this.length < start || this.length < end) { - throw new RangeError('Out of range index') - } + case "MemberExpression": + if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); } + break - if (end <= start) { - return this + case "ObjectPattern": + for (var i = 0, list = expr.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this$1.checkLVal(prop, bindingType, checkClashes); } + break - start = start >>> 0 - end = end === undefined ? this.length : end >>> 0 + case "Property": + // AssignmentProperty has type == "Property" + this.checkLVal(expr.value, bindingType, checkClashes); + break - if (!val) val = 0 + case "ArrayPattern": + for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { + var elem = list$1[i$1]; - var i - if (typeof val === 'number') { - for (i = start; i < end; ++i) { - this[i] = val - } - } else { - var bytes = Buffer.isBuffer(val) - ? val - : utf8ToBytes(new Buffer(val, encoding).toString()) - var len = bytes.length - for (i = 0; i < end - start; ++i) { - this[i + start] = bytes[i % len] + if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); } } - } + break - return this -} + case "AssignmentPattern": + this.checkLVal(expr.left, bindingType, checkClashes); + break -// HELPER FUNCTIONS -// ================ + case "RestElement": + this.checkLVal(expr.argument, bindingType, checkClashes); + break -var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g + case "ParenthesizedExpression": + this.checkLVal(expr.expression, bindingType, checkClashes); + break -function base64clean (str) { - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = stringtrim(str).replace(INVALID_BASE64_RE, '') - // Node converts strings with length < 2 to '' - if (str.length < 2) return '' - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + '=' + default: + this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue"); } - return str -} - -function stringtrim (str) { - if (str.trim) return str.trim() - return str.replace(/^\s+|\s+$/g, '') -} +}; -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) -} +// A recursive descent parser operates by defining functions for all +// syntactic elements, and recursively calling those, each function +// advancing the input stream and returning an AST node. Precedence +// of constructs (for example, the fact that `!x[1]` means `!(x[1])` +// instead of `(!x)[1]` is handled by the fact that the parser +// function that parses unary prefix operators is called first, and +// in turn calls the function that parses `[]` subscripts — that +// way, it'll receive the node for `x[1]` already parsed, and wraps +// *that* in the unary operator node. +// +// Acorn uses an [operator precedence parser][opp] to handle binary +// operator precedence, because it is much more compact than using +// the technique outlined above, which uses different, nesting +// functions to specify precedence, for all of the ten binary +// precedence levels that JavaScript defines. +// +// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser -function utf8ToBytes (string, units) { - units = units || Infinity - var codePoint - var length = string.length - var leadSurrogate = null - var bytes = [] +var pp$3 = Parser.prototype; - for (var i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i) +// 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. - // is surrogate component - if (codePoint > 0xD7FF && codePoint < 0xE000) { - // last char was a lead - if (!leadSurrogate) { - // no lead yet - if (codePoint > 0xDBFF) { - // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } else if (i + 1 === length) { - // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } - - // valid lead - leadSurrogate = codePoint - - continue - } - - // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint - continue +pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) { + if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) + { return } + var key = prop.key; + var name; + 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) { + if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; } + // Backwards-compat kludge. Can be removed in version 6.0 + else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); } } - - // valid surrogate pair - codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 - } else if (leadSurrogate) { - // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + propHash.proto = true; } - - leadSurrogate = null - - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint) - } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break - bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) + return + } + name = "$" + name; + var other = propHash[name]; + if (other) { + var redefinition; + if (kind === "init") { + redefinition = this.strict && other.init || other.get || other.set; } else { - throw new Error('Invalid code point') + redefinition = other.init || other[kind]; } + if (redefinition) + { this.raiseRecoverable(key.start, "Redefinition of property"); } + } else { + other = propHash[name] = { + init: false, + get: false, + set: false + }; } + other[kind] = true; +}; - return bytes -} - -function asciiToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xFF) - } - return byteArray -} - -function utf16leToBytes (str, units) { - var c, hi, lo - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - if ((units -= 2) < 0) break +// ### Expression parsing - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } +// 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. - return byteArray -} +// 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). -function base64ToBytes (str) { - return base64.toByteArray(base64clean(str)) -} +pp$3.parseExpression = function(noIn, refDestructuringErrors) { + var this$1 = this; -function blitBuffer (src, dst, offset, length) { - for (var i = 0; i < length; ++i) { - if ((i + offset >= dst.length) || (i >= src.length)) break - dst[i + offset] = src[i] + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); + if (this.type === types.comma) { + var node = this.startNodeAt(startPos, startLoc); + node.expressions = [expr]; + while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); } + return this.finishNode(node, "SequenceExpression") } - return i -} + return expr +}; -function isnan (val) { - return val !== val // eslint-disable-line no-self-compare -} +// Parse an assignment expression. This includes applications of +// operators like `+=`. -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"base64-js":45,"ieee754":77,"isarray":80}],48:[function(require,module,exports){ -(function (Buffer){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. +pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { + if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() } -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. + var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1; + if (refDestructuringErrors) { + oldParenAssign = refDestructuringErrors.parenthesizedAssign; + oldTrailingComma = refDestructuringErrors.trailingComma; + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; + } else { + refDestructuringErrors = new DestructuringErrors; + ownDestructuringErrors = true; + } -function isArray(arg) { - if (Array.isArray) { - return Array.isArray(arg); + var startPos = this.start, startLoc = this.startLoc; + if (this.type == types.parenL || this.type == types.name) + { this.potentialArrowAt = this.start; } + var left = this.parseMaybeConditional(noIn, refDestructuringErrors); + if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } + if (this.type.isAssign) { + var node = this.startNodeAt(startPos, startLoc); + node.operator = this.value; + node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left; + if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); } + refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly + this.checkLVal(left); + this.next(); + node.right = this.parseMaybeAssign(noIn); + return this.finishNode(node, "AssignmentExpression") + } else { + if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } } - return objectToString(arg) === '[object Array]'; -} -exports.isArray = isArray; + if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } + if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } + return left +}; -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; +// Parse a ternary conditional (`?:`) operator. -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; +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(types.question)) { + var node = this.startNodeAt(startPos, startLoc); + node.test = expr; + node.consequent = this.parseMaybeAssign(); + this.expect(types.colon); + node.alternate = this.parseMaybeAssign(noIn); + return this.finishNode(node, "ConditionalExpression") + } + return expr +}; -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; +// Start the precedence parser. -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; +pp$3.parseExprOps = function(noIn, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeUnary(refDestructuringErrors, false); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) +}; -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; +// 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. -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; +pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { + var prec = this.type.binop; + if (prec != null && (!noIn || this.type !== types._in)) { + if (prec > minPrec) { + var logical = this.type === types.logicalOR || this.type === types.logicalAND; + var op = this.value; + this.next(); + var startPos = this.start, startLoc = this.startLoc; + var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); + var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical); + return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) + } + } + return left +}; -function isRegExp(re) { - return objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; +pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) { + var node = this.startNodeAt(startPos, startLoc); + node.left = left; + node.operator = op; + node.right = right; + return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") +}; -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; +// Parse unary operators, both prefix and postfix. -function isDate(d) { - return objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; +pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { + var this$1 = this; -function isError(e) { - return (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; + var startPos = this.start, startLoc = this.startLoc, expr; + if (this.inAsync && this.isContextual("await")) { + expr = this.parseAwait(); + sawUnary = true; + } else if (this.type.prefix) { + var node = this.startNode(), update = this.type === types.incDec; + node.operator = this.value; + node.prefix = true; + this.next(); + node.argument = this.parseMaybeUnary(null, true); + this.checkExpressionErrors(refDestructuringErrors, true); + if (update) { this.checkLVal(node.argument); } + else if (this.strict && node.operator === "delete" && + node.argument.type === "Identifier") + { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } + else { sawUnary = true; } + expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); + } else { + expr = this.parseExprSubscripts(refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + while (this.type.postfix && !this.canInsertSemicolon()) { + var node$1 = this$1.startNodeAt(startPos, startLoc); + node$1.operator = this$1.value; + node$1.prefix = false; + node$1.argument = expr; + this$1.checkLVal(expr); + this$1.next(); + expr = this$1.finishNode(node$1, "UpdateExpression"); + } + } -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; + if (!sawUnary && this.eat(types.starstar)) + { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) } + else + { return expr } +}; -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; +// Parse call, dot, and `[]`-subscript expressions. -exports.isBuffer = Buffer.isBuffer; +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 } + var result = this.parseSubscripts(expr, startPos, startLoc); + if (refDestructuringErrors && result.type === "MemberExpression") { + if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } + if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } + } + return result +}; -function objectToString(o) { - return Object.prototype.toString.call(o); -} +pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { + var this$1 = this; -}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) -},{"../../is-buffer/index.js":79}],49:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. + var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && + this.lastTokEnd == base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async"; + for (var computed = (void 0);;) { + if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) { + var node = this$1.startNodeAt(startPos, startLoc); + node.object = base; + node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true); + node.computed = !!computed; + if (computed) { this$1.expect(types.bracketR); } + base = this$1.finishNode(node, "MemberExpression"); + } else if (!noCalls && this$1.eat(types.parenL)) { + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos; + this$1.yieldPos = 0; + this$1.awaitPos = 0; + var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors); + if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) { + this$1.checkPatternErrors(refDestructuringErrors, false); + this$1.checkYieldAwaitInDefaultParams(); + this$1.yieldPos = oldYieldPos; + this$1.awaitPos = oldAwaitPos; + return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true) + } + this$1.checkExpressionErrors(refDestructuringErrors, true); + this$1.yieldPos = oldYieldPos || this$1.yieldPos; + this$1.awaitPos = oldAwaitPos || this$1.awaitPos; + var node$1 = this$1.startNodeAt(startPos, startLoc); + node$1.callee = base; + node$1.arguments = exprList; + base = this$1.finishNode(node$1, "CallExpression"); + } else if (this$1.type === types.backQuote) { + var node$2 = this$1.startNodeAt(startPos, startLoc); + node$2.tag = base; + node$2.quasi = this$1.parseTemplate({isTagged: true}); + base = this$1.finishNode(node$2, "TaggedTemplateExpression"); + } else { + return base + } + } +}; -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; +// 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 `{}`. -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; +pp$3.parseExprAtom = function(refDestructuringErrors) { + var node, canBeArrow = this.potentialArrowAt == this.start; + switch (this.type) { + case types._super: + if (!this.inFunction) + { this.raise(this.start, "'super' outside of function or class"); } + node = this.startNode(); + this.next(); + // The `super` keyword can appear at below: + // SuperProperty: + // super [ Expression ] + // super . IdentifierName + // SuperCall: + // super Arguments + if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) + { this.unexpected(); } + return this.finishNode(node, "Super") -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; + case types._this: + node = this.startNode(); + this.next(); + return this.finishNode(node, "ThisExpression") -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; + case types.name: + var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; + var id = this.parseIdent(this.type !== types.name); + if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)) + { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) } + if (canBeArrow && !this.canInsertSemicolon()) { + if (this.eat(types.arrow)) + { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) } + if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) { + id = this.parseIdent(); + if (this.canInsertSemicolon() || !this.eat(types.arrow)) + { this.unexpected(); } + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) + } + } + return id -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; + case types.regexp: + var value = this.value; + node = this.parseLiteral(value.value); + node.regex = {pattern: value.pattern, flags: value.flags}; + return node -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; + case types.num: case types.string: + return this.parseLiteral(this.value) - if (!this._events) - this._events = {}; + case types._null: case types._true: case types._false: + node = this.startNode(); + node.value = this.type === types._null ? null : this.type === types._true; + node.raw = this.type.keyword; + this.next(); + return this.finishNode(node, "Literal") - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - // At least give some kind of context to the user - var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); - err.context = er; - throw err; - } - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - args = Array.prototype.slice.call(arguments, 1); - handler.apply(this, args); + case types.parenL: + var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow); + if (refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) + { refDestructuringErrors.parenthesizedAssign = start; } + if (refDestructuringErrors.parenthesizedBind < 0) + { refDestructuringErrors.parenthesizedBind = start; } } - } else if (isObject(handler)) { - args = Array.prototype.slice.call(arguments, 1); - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; + return expr -EventEmitter.prototype.addListener = function(type, listener) { - var m; + case types.bracketL: + node = this.startNode(); + this.next(); + node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors); + return this.finishNode(node, "ArrayExpression") - if (!isFunction(listener)) - throw TypeError('listener must be a function'); + case types.braceL: + return this.parseObj(false, refDestructuringErrors) - if (!this._events) - this._events = {}; + case types._function: + node = this.startNode(); + this.next(); + return this.parseFunction(node, false) - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); + case types._class: + return this.parseClass(this.startNode(), false) - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; + case types._new: + return this.parseNew() - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } + case types.backQuote: + return this.parseTemplate() - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } + default: + this.unexpected(); } - - return this; }; -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; +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") }; -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; +pp$3.parseParenExpression = function() { + this.expect(types.parenL); + var val = this.parseExpression(); + this.expect(types.parenR); + return val +}; - list = this._events[type]; - length = list.length; - position = -1; +pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { + var this$1 = this; - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); + var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; + if (this.options.ecmaVersion >= 6) { + this.next(); - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; + var innerStartPos = this.start, innerStartLoc = this.startLoc; + var exprList = [], first = true, lastIsComma = false; + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; + this.yieldPos = 0; + this.awaitPos = 0; + while (this.type !== types.parenR) { + first ? first = false : this$1.expect(types.comma); + if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) { + lastIsComma = true; + break + } else if (this$1.type === types.ellipsis) { + spreadStart = this$1.start; + exprList.push(this$1.parseParenItem(this$1.parseRestBinding())); + if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } + break + } else { + exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem)); } } + var innerEndPos = this.start, innerEndLoc = this.startLoc; + this.expect(types.parenR); - if (position < 0) - return this; + if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + return this.parseParenArrowList(startPos, startLoc, exprList) + } - if (list.length === 1) { - list.length = 0; - delete this._events[type]; + if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } + if (spreadStart) { this.unexpected(spreadStart); } + this.checkExpressionErrors(refDestructuringErrors, true); + this.yieldPos = oldYieldPos || this.yieldPos; + this.awaitPos = oldAwaitPos || this.awaitPos; + + if (exprList.length > 1) { + val = this.startNodeAt(innerStartPos, innerStartLoc); + val.expressions = exprList; + this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); } else { - list.splice(position, 1); + val = exprList[0]; } + } else { + val = this.parseParenExpression(); + } - if (this._events.removeListener) - this.emit('removeListener', type, listener); + if (this.options.preserveParens) { + var par = this.startNodeAt(startPos, startLoc); + par.expression = val; + return this.finishNode(par, "ParenthesizedExpression") + } else { + return val } +}; - return this; +pp$3.parseParenItem = function(item) { + return item }; -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; +pp$3.parseParenArrowList = function(startPos, startLoc, exprList) { + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) +}; - if (!this._events) - return this; +// 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. - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } +var empty$1 = []; - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; +pp$3.parseNew = function() { + var node = this.startNode(); + var meta = this.parseIdent(true); + if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) { + node.meta = meta; + var containsEsc = this.containsEsc; + node.property = this.parseIdent(true); + if (node.property.name !== "target" || containsEsc) + { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); } + if (!this.inFunction) + { this.raiseRecoverable(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(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); } + else { node.arguments = empty$1; } + return this.finishNode(node, "NewExpression") +}; - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; +// Parse template expression. - return this; -}; +pp$3.parseTemplateElement = function(ref) { + var isTagged = ref.isTagged; -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; + var elem = this.startNode(); + if (this.type === types.invalidTemplate) { + if (!isTagged) { + this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); + } + elem.value = { + raw: this.value, + cooked: null + }; + } else { + elem.value = { + raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), + cooked: this.value + }; + } + this.next(); + elem.tail = this.type === types.backQuote; + return this.finishNode(elem, "TemplateElement") }; -EventEmitter.prototype.listenerCount = function(type) { - if (this._events) { - var evlistener = this._events[type]; +pp$3.parseTemplate = function(ref) { + var this$1 = this; + if ( ref === void 0 ) ref = {}; + var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; - if (isFunction(evlistener)) - return 1; - else if (evlistener) - return evlistener.length; + var node = this.startNode(); + this.next(); + node.expressions = []; + var curElt = this.parseTemplateElement({isTagged: isTagged}); + node.quasis = [curElt]; + while (!curElt.tail) { + this$1.expect(types.dollarBraceL); + node.expressions.push(this$1.parseExpression()); + this$1.expect(types.braceR); + node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged})); } - return 0; + this.next(); + return this.finishNode(node, "TemplateLiteral") }; -EventEmitter.listenerCount = function(emitter, type) { - return emitter.listenerCount(type); +pp$3.isAsyncProp = function(prop) { + return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && + (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword) && + !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }; -function isFunction(arg) { - return typeof arg === 'function'; -} +// Parse an object literal or binding pattern. -function isNumber(arg) { - return typeof arg === 'number'; -} +pp$3.parseObj = function(isPattern, refDestructuringErrors) { + var this$1 = this; -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} + var node = this.startNode(), first = true, propHash = {}; + node.properties = []; + this.next(); + while (!this.eat(types.braceR)) { + if (!first) { + this$1.expect(types.comma); + if (this$1.afterTrailingComma(types.braceR)) { break } + } else { first = false; } -function isUndefined(arg) { - return arg === void 0; -} + var prop = this$1.parseProperty(isPattern, refDestructuringErrors); + if (!isPattern) { this$1.checkPropClash(prop, propHash, refDestructuringErrors); } + node.properties.push(prop); + } + return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") +}; -},{}],50:[function(require,module,exports){ -'use strict'; +pp$3.parseProperty = function(isPattern, refDestructuringErrors) { + var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; + 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(types.star); } + } + var containsEsc = this.containsEsc; + this.parsePropertyName(prop); + if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { + isAsync = true; + this.parsePropertyName(prop, refDestructuringErrors); + } else { + isAsync = false; + } + this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); + return this.finishNode(prop, "Property") +}; -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); +pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { + if ((isGenerator || isAsync) && this.type === types.colon) + { this.unexpected(); } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + if (this.eat(types.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 === types.parenL) { + if (isPattern) { this.unexpected(); } + prop.kind = "init"; + prop.method = true; + prop.value = this.parseMethod(isGenerator, isAsync); + } else if (!isPattern && !containsEsc && + this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && + (prop.key.name === "get" || prop.key.name === "set") && + (this.type != types.comma && this.type != types.braceR)) { + if (isGenerator || isAsync) { 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.raiseRecoverable(start, "getter should have no params"); } + else + { this.raiseRecoverable(start, "setter should have exactly one param"); } + } else { + if (prop.kind === "set" && prop.value.params[0].type === "RestElement") + { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } + } + } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { + this.checkUnreserved(prop.key); + prop.kind = "init"; + if (isPattern) { + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); + } else if (this.type === types.eq && refDestructuringErrors) { + if (refDestructuringErrors.shorthandAssign < 0) + { refDestructuringErrors.shorthandAssign = this.start; } + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); + } else { + prop.value = prop.key; + } + prop.shorthand = true; + } else { this.unexpected(); } +}; -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } +pp$3.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(types.bracketL)) { + prop.computed = true; + prop.key = this.parseMaybeAssign(); + this.expect(types.bracketR); + return prop.key + } else { + prop.computed = false; + } + } + return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true) +}; -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +// Initialize empty function node. -var FunctionBuilderBase = require('../function-builder-base'); -var CPUFunctionNode = require('./function-node'); +pp$3.initFunction = function(node) { + node.id = null; + if (this.options.ecmaVersion >= 6) { + node.generator = false; + node.expression = false; + } + if (this.options.ecmaVersion >= 8) + { node.async = false; } +}; -/** - * @class CPUFunctionBuilder - * - * @extends FunctionBuilderBase - * - * @desc Builds functions to execute on CPU from JavaScript function Strings - * - */ -module.exports = function (_FunctionBuilderBase) { - _inherits(CPUFunctionBuilder, _FunctionBuilderBase); +// Parse object or class method. - function CPUFunctionBuilder() { - _classCallCheck(this, CPUFunctionBuilder); +pp$3.parseMethod = function(isGenerator, isAsync) { + var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; - var _this = _possibleConstructorReturn(this, (CPUFunctionBuilder.__proto__ || Object.getPrototypeOf(CPUFunctionBuilder)).call(this)); + this.initFunction(node); + if (this.options.ecmaVersion >= 6) + { node.generator = isGenerator; } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } - _this.Node = CPUFunctionNode; - return _this; - } + this.inGenerator = node.generator; + this.inAsync = node.async; + this.yieldPos = 0; + this.awaitPos = 0; + this.inFunction = true; + this.enterFunctionScope(); - _createClass(CPUFunctionBuilder, [{ - key: 'polyfillStandardFunctions', - value: function polyfillStandardFunctions() {} - }]); + this.expect(types.parenL); + node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); + this.parseFunctionBody(node, false); - return CPUFunctionBuilder; -}(FunctionBuilderBase); -},{"../function-builder-base":55,"./function-node":51}],51:[function(require,module,exports){ -'use strict'; + this.inGenerator = oldInGen; + this.inAsync = oldInAsync; + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.inFunction = oldInFunc; + return this.finishNode(node, "FunctionExpression") +}; -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); +// Parse arrow function expression with given parameters. -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +pp$3.parseArrowExpression = function(node, params, isAsync) { + var oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + this.enterFunctionScope(); + this.initFunction(node); + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + this.inGenerator = false; + this.inAsync = node.async; + this.yieldPos = 0; + this.awaitPos = 0; + this.inFunction = true; -var BaseFunctionNode = require('../function-node-base'); -var utils = require('../../core/utils'); + node.params = this.toAssignableList(params, true); + this.parseFunctionBody(node, true); -/** - * @class CPUFunctionNode - * - * @extends BaseFunctionNode - * - * @desc [INTERNAL] Represents a single function, inside JS - * - *

This handles all the raw state, converted state, etc. Of a single function.

- * - * @prop functionName - {String} Name of the function - * @prop jsFunction - {Function} The JS Function the node represents - * @prop jsFunctionString - {String} jsFunction.toString() - * @prop paramNames - {String[]} Parameter names of the function - * @prop paramTypes - {String[]} Shader land parameters type assumption - * @prop isRootKernel - {Boolean} Special indicator, for kernel function - * @prop webglFunctionString - {String} webgl converted function string - * @prop openglFunctionString - {String} opengl converted function string - * @prop calledFunctions - {String[]} List of all the functions called - * @prop initVariables - {String[]} List of variables initialized in the function - * @prop readVariables - {String[]} List of variables read operations occur - * @prop writeVariables - {String[]} List of variables write operations occur - * - */ -module.exports = function (_BaseFunctionNode) { - _inherits(CPUFunctionNode, _BaseFunctionNode); + this.inGenerator = oldInGen; + this.inAsync = oldInAsync; + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.inFunction = oldInFunc; + return this.finishNode(node, "ArrowFunctionExpression") +}; - function CPUFunctionNode() { - _classCallCheck(this, CPUFunctionNode); +// Parse function body and check parameters. - return _possibleConstructorReturn(this, (CPUFunctionNode.__proto__ || Object.getPrototypeOf(CPUFunctionNode)).apply(this, arguments)); - } +pp$3.parseFunctionBody = function(node, isArrowFunction) { + var isExpression = isArrowFunction && this.type !== types.braceL; + var oldStrict = this.strict, useStrict = false; - _createClass(CPUFunctionNode, [{ - key: 'generate', - value: function generate() { - if (this.debug) { - console.log(this); - } - this.functionStringArray = this.astGeneric(this.getJsAST(), [], this); - this.functionString = this.functionStringArray.join('').trim(); - return this.functionString; - } + if (isExpression) { + node.body = this.parseMaybeAssign(); + node.expression = true; + this.checkParams(node, false); + } else { + var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); + if (!oldStrict || nonSimple) { + useStrict = this.strictDirective(this.end); + // 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 (useStrict && nonSimple) + { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } + } + // Start a new scope with regard to labels and the `inFunction` + // flag (restore them to their old value afterwards). + var oldLabels = this.labels; + this.labels = []; + if (useStrict) { this.strict = true; } - /** - * @memberOf CPUFunctionNode# - * @function - * @name getFunctionPrototypeString - * - * @desc Returns the converted JS function - * - * @returns {String} function string, result is cached under this.getFunctionPrototypeString - * - */ + // Add the params to varDeclaredNames to ensure that an error is thrown + // if a let/const declaration in the function clashes with one of the params. + this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)); + node.body = this.parseBlock(false); + node.expression = false; + this.adaptDirectivePrologue(node.body.body); + this.labels = oldLabels; + } + this.exitFunctionScope(); - }, { - key: 'getFunctionPrototypeString', - value: function getFunctionPrototypeString() { - if (this.webGlFunctionPrototypeString) { - return this.webGlFunctionPrototypeString; - } - return this.webGlFunctionPrototypeString = this.generate(); - } + if (this.strict && node.id) { + // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' + this.checkLVal(node.id, "none"); + } + this.strict = oldStrict; +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astGeneric - * - * @desc Parses the abstract syntax tree for generically to its respective function - * - * @param {Object} ast - the AST object to parse - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the parsed cpu string array - */ +pp$3.isSimpleParamList = function(params) { + for (var i = 0, list = params; i < list.length; i += 1) + { + var param = list[i]; - }, { - key: 'astGeneric', - value: function astGeneric(ast, retArr, funcParam) { - if (ast === null) { - throw this.astErrorOutput('NULL ast', ast, funcParam); - } else { - if (Array.isArray(ast)) { - for (var i = 0; i < ast.length; i++) { - this.astGeneric(ast[i], retArr, funcParam); - } - return retArr; - } + if (param.type !== "Identifier") { return false + } } + return true +}; - switch (ast.type) { - case 'FunctionDeclaration': - return this.astFunctionDeclaration(ast, retArr, funcParam); - case 'FunctionExpression': - return this.astFunctionExpression(ast, retArr, funcParam); - case 'ReturnStatement': - return this.astReturnStatement(ast, retArr, funcParam); - case 'Literal': - return this.astLiteral(ast, retArr, funcParam); - case 'BinaryExpression': - return this.astBinaryExpression(ast, retArr, funcParam); - case 'Identifier': - return this.astIdentifierExpression(ast, retArr, funcParam); - case 'AssignmentExpression': - return this.astAssignmentExpression(ast, retArr, funcParam); - case 'ExpressionStatement': - return this.astExpressionStatement(ast, retArr, funcParam); - case 'EmptyStatement': - return this.astEmptyStatement(ast, retArr, funcParam); - case 'BlockStatement': - return this.astBlockStatement(ast, retArr, funcParam); - case 'IfStatement': - return this.astIfStatement(ast, retArr, funcParam); - case 'BreakStatement': - return this.astBreakStatement(ast, retArr, funcParam); - case 'ContinueStatement': - return this.astContinueStatement(ast, retArr, funcParam); - case 'ForStatement': - return this.astForStatement(ast, retArr, funcParam); - case 'WhileStatement': - return this.astWhileStatement(ast, retArr, funcParam); - case 'VariableDeclaration': - return this.astVariableDeclaration(ast, retArr, funcParam); - case 'VariableDeclarator': - return this.astVariableDeclarator(ast, retArr, funcParam); - case 'ThisExpression': - return this.astThisExpression(ast, retArr, funcParam); - case 'SequenceExpression': - return this.astSequenceExpression(ast, retArr, funcParam); - case 'UnaryExpression': - return this.astUnaryExpression(ast, retArr, funcParam); - case 'UpdateExpression': - return this.astUpdateExpression(ast, retArr, funcParam); - case 'LogicalExpression': - return this.astLogicalExpression(ast, retArr, funcParam); - case 'MemberExpression': - return this.astMemberExpression(ast, retArr, funcParam); - case 'CallExpression': - return this.astCallExpression(ast, retArr, funcParam); - case 'ArrayExpression': - return this.astArrayExpression(ast, retArr, funcParam); - case 'DebuggerStatement': - return this.astDebuggerStatement(ast, retArr, funcParam); - } +// Checks function params for various disallowed patterns such as using "eval" +// or "arguments" and duplicate parameters. - throw this.astErrorOutput('Unknown ast type : ' + ast.type, ast, funcParam); - } - } +pp$3.checkParams = function(node, allowDuplicates) { + var this$1 = this; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astFunctionDeclaration - * - * @desc Parses the abstract syntax tree for to its *named function declaration* - * - * @param {Object} ast - the AST object to parse - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ + var nameHash = {}; + for (var i = 0, list = node.params; i < list.length; i += 1) + { + var param = list[i]; - }, { - key: 'astFunctionDeclaration', - value: function astFunctionDeclaration(ast, retArr, funcParam) { - if (this.addFunction) { - this.addFunction(null, utils.getAstString(this.jsFunctionString, ast)); - } - return retArr; - } + this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash); + } +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astFunctionPrototype - * @static - * - * @desc Parses the abstract syntax tree for to its *named function prototype* - * - * @param {Object} ast - the AST object to parse - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +// 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). - }, { - key: 'astFunctionExpression', +pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { + var this$1 = this; + var elts = [], first = true; + while (!this.eat(close)) { + if (!first) { + this$1.expect(types.comma); + if (allowTrailingComma && this$1.afterTrailingComma(close)) { break } + } else { first = false; } - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astFunctionExpression - * - * @desc Parses the abstract syntax tree for to its *named function* - * - * @param {Object} ast - the AST object to parse - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ - value: function astFunctionExpression(ast, retArr, funcParam) { + var elt = (void 0); + if (allowEmpty && this$1.type === types.comma) + { elt = null; } + else if (this$1.type === types.ellipsis) { + elt = this$1.parseSpread(refDestructuringErrors); + if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0) + { refDestructuringErrors.trailingComma = this$1.start; } + } else { + elt = this$1.parseMaybeAssign(false, refDestructuringErrors); + } + elts.push(elt); + } + return elts +}; - // Setup function return type and name - if (!funcParam.isRootKernel) { - retArr.push('function'); - funcParam.kernalAst = ast; - retArr.push(' '); - retArr.push(funcParam.functionName); - retArr.push('('); +pp$3.checkUnreserved = function(ref) { + var start = ref.start; + var end = ref.end; + var name = ref.name; - // Arguments handling - for (var i = 0; i < funcParam.paramNames.length; ++i) { - var paramName = funcParam.paramNames[i]; + if (this.inGenerator && name === "yield") + { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); } + if (this.inAsync && name === "await") + { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); } + if (this.isKeyword(name)) + { this.raise(start, ("Unexpected keyword '" + name + "'")); } + if (this.options.ecmaVersion < 6 && + this.input.slice(start, end).indexOf("\\") != -1) { return } + var re = this.strict ? this.reservedWordsStrict : this.reservedWords; + if (re.test(name)) { + if (!this.inAsync && name === "await") + { this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function"); } + this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); + } +}; - if (i > 0) { - retArr.push(', '); - } +// Parse the next token as an identifier. If `liberal` is true (used +// when parsing properties), it will also convert keywords into +// identifiers. - retArr.push(' '); - retArr.push('user_'); - retArr.push(paramName); - } +pp$3.parseIdent = function(liberal, isBinding) { + var node = this.startNode(); + if (liberal && this.options.allowReserved == "never") { liberal = false; } + if (this.type === types.name) { + node.name = this.value; + } else if (this.type.keyword) { + node.name = this.type.keyword; - // Function opening - retArr.push(') {\n'); - } + // To fix https://github.com/acornjs/acorn/issues/575 + // `class` and `function` keywords push new context into this.context. + // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. + // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword + if ((node.name === "class" || node.name === "function") && + (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { + this.context.pop(); + } + } else { + this.unexpected(); + } + this.next(); + this.finishNode(node, "Identifier"); + if (!liberal) { this.checkUnreserved(node); } + return node +}; - // Body statement iteration - for (var _i = 0; _i < ast.body.body.length; ++_i) { - this.astGeneric(ast.body.body[_i], retArr, funcParam); - retArr.push('\n'); - } +// Parses yield expression inside generator. - if (!funcParam.isRootKernel) { - // Function closing - retArr.push('}\n'); - } - return retArr; - } +pp$3.parseYield = function() { + if (!this.yieldPos) { this.yieldPos = this.start; } - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astReturnStatement - * - * @desc Parses the abstract syntax tree for to *return* statement - * - * @param {Object} ast - the AST object to parse - * @param {Array} retArr - return array string - * @param {Object} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ + var node = this.startNode(); + this.next(); + if (this.type == types.semi || this.canInsertSemicolon() || (this.type != types.star && !this.type.startsExpr)) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = this.eat(types.star); + node.argument = this.parseMaybeAssign(); + } + return this.finishNode(node, "YieldExpression") +}; - }, { - key: 'astReturnStatement', - value: function astReturnStatement(ast, retArr, funcParam) { - if (funcParam.isRootKernel) { - retArr.push('kernelResult = '); - this.astGeneric(ast.argument, retArr, funcParam); - retArr.push(';'); - } else if (funcParam.isSubKernel) { - retArr.push(funcParam.functionName + 'Result = '); - this.astGeneric(ast.argument, retArr, funcParam); - retArr.push(';'); - retArr.push('return ' + funcParam.functionName + 'Result;'); - } else { - retArr.push('return '); - this.astGeneric(ast.argument, retArr, funcParam); - retArr.push(';'); - } +pp$3.parseAwait = function() { + if (!this.awaitPos) { this.awaitPos = this.start; } - //throw this.astErrorOutput( - // 'Non main function return, is not supported : '+funcParam.currentFunctionNamespace, - // ast, funcParam - //); + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeUnary(null, true); + return this.finishNode(node, "AwaitExpression") +}; - return retArr; - } +var pp$4 = Parser.prototype; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astLiteral - * - * @desc Parses the abstract syntax tree for *literal value* - * - * @param {Object} ast - the AST object to parse - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +// 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. - }, { - key: 'astLiteral', - value: function astLiteral(ast, retArr, funcParam) { +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 +}; - // Reject non numeric literals - if (isNaN(ast.value)) { - throw this.astErrorOutput('Non-numeric literal not supported : ' + ast.value, ast, funcParam); - } +pp$4.raiseRecoverable = pp$4.raise; - retArr.push(ast.value); +pp$4.curPosition = function() { + if (this.options.locations) { + return new Position(this.curLine, this.pos - this.lineStart) + } +}; - return retArr; - } +var pp$5 = Parser.prototype; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astBinaryExpression - * - * @desc Parses the abstract syntax tree for *binary* expression - * - * @param {Object} ast - the AST object to parse - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +// Object.assign polyfill +var assign = Object.assign || function(target) { + var sources = [], len = arguments.length - 1; + while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; - }, { - key: 'astBinaryExpression', - value: function astBinaryExpression(ast, retArr, funcParam) { - retArr.push('('); - this.astGeneric(ast.left, retArr, funcParam); - retArr.push(ast.operator); - this.astGeneric(ast.right, retArr, funcParam); - retArr.push(')'); - return retArr; - } - - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astIdentifierExpression - * - * @desc Parses the abstract syntax tree for *identifier* expression - * - * @param {Object} idtNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ + for (var i = 0, list = sources; i < list.length; i += 1) { + var source = list[i]; - }, { - key: 'astIdentifierExpression', - value: function astIdentifierExpression(idtNode, retArr, funcParam) { - if (idtNode.type !== 'Identifier') { - throw this.astErrorOutput('IdentifierExpression - not an Identifier', idtNode, funcParam); - } + for (var key in source) { + if (has(source, key)) { + target[key] = source[key]; + } + } + } + return target +}; - switch (idtNode.name) { - case 'gpu_threadX': - retArr.push('threadId.x'); - break; - case 'gpu_threadY': - retArr.push('threadId.y'); - break; - case 'gpu_threadZ': - retArr.push('threadId.z'); - break; - case 'gpu_outputX': - retArr.push('uOutputDim.x'); - break; - case 'gpu_outputY': - retArr.push('uOutputDim.y'); - break; - case 'gpu_outputZ': - retArr.push('uOutputDim.z'); - break; - default: - if (this.constants && this.constants.hasOwnProperty(idtNode.name)) { - retArr.push('constants_' + idtNode.name); - } else { - var userParamName = funcParam.getUserParamName(idtNode.name); - if (userParamName !== null) { - retArr.push('user_' + userParamName); - } else { - retArr.push('user_' + idtNode.name); - } - } - } +// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. - return retArr; - } +pp$5.enterFunctionScope = function() { + // var: a hash of var-declared names in the current lexical scope + // lexical: a hash of lexically-declared names in the current lexical scope + // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) + // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) + this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}); +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astForStatement - * - * @desc Parses the abstract syntax tree forfor *for-loop* expression - * - * @param {Object} forNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the parsed cpu string - */ +pp$5.exitFunctionScope = function() { + this.scopeStack.pop(); +}; - }, { - key: 'astForStatement', - value: function astForStatement(forNode, retArr, funcParam) { - if (forNode.type !== 'ForStatement') { - throw this.astErrorOutput('Invalid for statment', forNode, funcParam); - } +pp$5.enterLexicalScope = function() { + var parentScope = this.scopeStack[this.scopeStack.length - 1]; + var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}}; - if (forNode.test && forNode.test.type === 'BinaryExpression') { - if ((forNode.test.right.type === 'Identifier' || forNode.test.right.type === 'Literal') && forNode.test.operator === '<' && this.isIdentifierConstant(forNode.test.right.name) === false) { + this.scopeStack.push(childScope); + assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical); +}; - if (!this.loopMaxIterations) { - console.warn('Warning: loopMaxIterations is not set! Using default of 1000 which may result in unintended behavior.'); - console.warn('Set loopMaxIterations or use a for loop of fixed length to silence this message.'); - } +pp$5.exitLexicalScope = function() { + var childScope = this.scopeStack.pop(); + var parentScope = this.scopeStack[this.scopeStack.length - 1]; - retArr.push('for ('); - this.astGeneric(forNode.init, retArr, funcParam); - if (retArr[retArr.length - 1] !== ';') { - retArr.push(';'); - } - this.astGeneric(forNode.test.left, retArr, funcParam); - retArr.push(forNode.test.operator); - retArr.push('LOOP_MAX'); - retArr.push(';'); - this.astGeneric(forNode.update, retArr, funcParam); - retArr.push(')'); + assign(parentScope.childVar, childScope.var, childScope.childVar); +}; - retArr.push('{\n'); - retArr.push('if ('); - this.astGeneric(forNode.test.left, retArr, funcParam); - retArr.push(forNode.test.operator); - this.astGeneric(forNode.test.right, retArr, funcParam); - retArr.push(') {\n'); - if (forNode.body.type === 'BlockStatement') { - for (var i = 0; i < forNode.body.body.length; i++) { - this.astGeneric(forNode.body.body[i], retArr, funcParam); - } - } else { - this.astGeneric(forNode.body, retArr, funcParam); - } - retArr.push('} else {\n'); - retArr.push('break;\n'); - retArr.push('}\n'); - retArr.push('}\n'); +/** + * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` + * in the current lexical scope or any of the parent lexical scopes in this function. + */ +pp$5.canDeclareVarName = function(name) { + var currentScope = this.scopeStack[this.scopeStack.length - 1]; - return retArr; - } else if (forNode.init.declarations) { - var declarations = JSON.parse(JSON.stringify(forNode.init.declarations)); - var updateArgument = forNode.update.argument; - if (!Array.isArray(declarations) || declarations.length < 1) { - console.log(this.jsFunctionString); - throw new Error('Error: Incompatible for loop declaration'); - } + return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) +}; - if (declarations.length > 1) { - var initArgument = null; - for (var _i2 = 0; _i2 < declarations.length; _i2++) { - var declaration = declarations[_i2]; - if (declaration.id.name === updateArgument.name) { - initArgument = declaration; - declarations.splice(_i2, 1); - } else { - retArr.push('var '); - this.astGeneric(declaration, retArr, funcParam); - retArr.push(';'); - } - } +/** + * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` + * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in + * any child lexical scopes in this function. + */ +pp$5.canDeclareLexicalName = function(name) { + var currentScope = this.scopeStack[this.scopeStack.length - 1]; - retArr.push('for (let '); - this.astGeneric(initArgument, retArr, funcParam); - retArr.push(';'); - } else { - retArr.push('for ('); - this.astGeneric(forNode.init, retArr, funcParam); - } + return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) +}; - this.astGeneric(forNode.test, retArr, funcParam); - retArr.push(';'); - this.astGeneric(forNode.update, retArr, funcParam); - retArr.push(')'); - this.astGeneric(forNode.body, retArr, funcParam); - return retArr; - } - } +pp$5.declareVarName = function(name) { + this.scopeStack[this.scopeStack.length - 1].var[name] = true; +}; - throw this.astErrorOutput('Invalid for statement', forNode, funcParam); - } +pp$5.declareLexicalName = function(name) { + this.scopeStack[this.scopeStack.length - 1].lexical[name] = true; +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astWhileStatement - * - * @desc Parses the abstract syntax tree for *while* loop - * - * - * @param {Object} whileNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the parsed openclgl string - */ +var Node = function Node(parser, pos, loc) { + 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]; } +}; - }, { - key: 'astWhileStatement', - value: function astWhileStatement(whileNode, retArr, funcParam) { - if (whileNode.type !== 'WhileStatement') { - throw this.astErrorOutput('Invalid while statment', whileNode, funcParam); - } +// Start an AST node, attaching a start offset. - retArr.push('for (let i = 0; i < LOOP_MAX; i++) {'); - retArr.push('if ('); - this.astGeneric(whileNode.test, retArr, funcParam); - retArr.push(') {\n'); - this.astGeneric(whileNode.body, retArr, funcParam); - retArr.push('} else {\n'); - retArr.push('break;\n'); - retArr.push('}\n'); - retArr.push('}\n'); +var pp$6 = Parser.prototype; - return retArr; - } +pp$6.startNode = function() { + return new Node(this, this.start, this.startLoc) +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astAssignmentExpression - * - * @desc Parses the abstract syntax tree for *Assignment* Expression - * - * @param {Object} assNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +pp$6.startNodeAt = function(pos, loc) { + return new Node(this, pos, loc) +}; - }, { - key: 'astAssignmentExpression', - value: function astAssignmentExpression(assNode, retArr, funcParam) { - this.astGeneric(assNode.left, retArr, funcParam); - retArr.push(assNode.operator); - this.astGeneric(assNode.right, retArr, funcParam); - return retArr; - } +// Finish an AST node, adding `type` and `end` properties. - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astEmptyStatement - * - * @desc Parses the abstract syntax tree for an *Empty* Statement - * - * @param {Object} eNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +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 +} - }, { - key: 'astEmptyStatement', - value: function astEmptyStatement(eNode, retArr, funcParam) { - //retArr.push(';\n'); - return retArr; - } +pp$6.finishNode = function(node, type) { + return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astBlockStatement - * - * @desc Parses the abstract syntax tree for *Block* statement - * - * @param {Object} bNode - the AST object to parse - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +// Finish node at given position - }, { - key: 'astBlockStatement', - value: function astBlockStatement(bNode, retArr, funcParam) { - retArr.push('{\n'); - for (var i = 0; i < bNode.body.length; i++) { - this.astGeneric(bNode.body[i], retArr, funcParam); - } - retArr.push('}\n'); - return retArr; - } +pp$6.finishNodeAt = function(node, type, pos, loc) { + return finishNodeAt.call(this, node, type, pos, loc) +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astExpressionStatement - * - * @desc Parses the abstract syntax tree for *generic expression* statement - * - * @param {Object} esNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +// The algorithm used to determine whether a regexp can appear at a +// given point in the program is loosely based on sweet.js' approach. +// See https://github.com/mozilla/sweet.js/wiki/design - }, { - key: 'astExpressionStatement', - value: function astExpressionStatement(esNode, retArr, funcParam) { - this.astGeneric(esNode.expression, retArr, funcParam); - retArr.push(';\n'); - return retArr; - } +var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { + this.token = token; + this.isExpr = !!isExpr; + this.preserveSpace = !!preserveSpace; + this.override = override; + this.generator = !!generator; +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astVariableDeclaration - * - * @desc Parses the abstract syntax tree for *Variable Declaration* - * - * @param {Object} vardecNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +var types$1 = { + b_stat: new TokContext("{", false), + b_expr: new TokContext("{", true), + b_tmpl: new TokContext("${", false), + p_stat: new TokContext("(", false), + p_expr: new TokContext("(", true), + q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), + f_stat: new TokContext("function", false), + f_expr: new TokContext("function", true), + f_expr_gen: new TokContext("function", true, false, null, true), + f_gen: new TokContext("function", false, false, null, true) +}; - }, { - key: 'astVariableDeclaration', - value: function astVariableDeclaration(vardecNode, retArr, funcParam) { - retArr.push('var '); - for (var i = 0; i < vardecNode.declarations.length; i++) { - if (i > 0) { - retArr.push(','); - } - this.astGeneric(vardecNode.declarations[i], retArr, funcParam); - } - retArr.push(';'); - return retArr; - } +var pp$7 = Parser.prototype; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astVariableDeclarator - * - * @desc Parses the abstract syntax tree for *Variable Declarator* - * - * @param {Object} ivardecNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +pp$7.initialContext = function() { + return [types$1.b_stat] +}; - }, { - key: 'astVariableDeclarator', - value: function astVariableDeclarator(ivardecNode, retArr, funcParam) { - this.astGeneric(ivardecNode.id, retArr, funcParam); - if (ivardecNode.init !== null) { - retArr.push('='); - this.astGeneric(ivardecNode.init, retArr, funcParam); - } - return retArr; - } +pp$7.braceIsBlock = function(prevType) { + var parent = this.curContext(); + if (parent === types$1.f_expr || parent === types$1.f_stat) + { return true } + if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)) + { return !parent.isExpr } - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astIfStatement - * - * @desc Parses the abstract syntax tree for *If* Statement - * - * @param {Object} ifNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ + // The check for `tt.name && exprAllowed` detects whether we are + // after a `yield` or `of` construct. See the `updateContext` for + // `tt.name`. + if (prevType === types._return || prevType == types.name && this.exprAllowed) + { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } + if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType == types.arrow) + { return true } + if (prevType == types.braceL) + { return parent === types$1.b_stat } + if (prevType == types._var || prevType == types.name) + { return false } + return !this.exprAllowed +}; - }, { - key: 'astIfStatement', - value: function astIfStatement(ifNode, retArr, funcParam) { - retArr.push('if ('); - this.astGeneric(ifNode.test, retArr, funcParam); - retArr.push(')'); - if (ifNode.consequent.type === 'BlockStatement') { - this.astGeneric(ifNode.consequent, retArr, funcParam); - } else { - retArr.push(' {\n'); - this.astGeneric(ifNode.consequent, retArr, funcParam); - retArr.push('\n}\n'); - } +pp$7.inGeneratorContext = function() { + var this$1 = this; - if (ifNode.alternate) { - retArr.push('else '); - if (ifNode.alternate.type === 'BlockStatement') { - this.astGeneric(ifNode.alternate, retArr, funcParam); - } else { - retArr.push(' {\n'); - this.astGeneric(ifNode.alternate, retArr, funcParam); - retArr.push('\n}\n'); - } - } - return retArr; - } + for (var i = this.context.length - 1; i >= 1; i--) { + var context = this$1.context[i]; + if (context.token === "function") + { return context.generator } + } + return false +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astBreakStatement - * - * @desc Parses the abstract syntax tree for *Break* Statement - * - * @param {Object} brNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +pp$7.updateContext = function(prevType) { + var update, type = this.type; + if (type.keyword && prevType == types.dot) + { this.exprAllowed = false; } + else if (update = type.updateContext) + { update.call(this, prevType); } + else + { this.exprAllowed = type.beforeExpr; } +}; - }, { - key: 'astBreakStatement', - value: function astBreakStatement(brNode, retArr, funcParam) { - retArr.push('break;\n'); - return retArr; - } +// Token-specific context update code - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astContinueStatement - * - * @desc Parses the abstract syntax tree for *Continue* Statement - * - * @param {Object} crNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +types.parenR.updateContext = types.braceR.updateContext = function() { + if (this.context.length == 1) { + this.exprAllowed = true; + return + } + var out = this.context.pop(); + if (out === types$1.b_stat && this.curContext().token === "function") { + out = this.context.pop(); + } + this.exprAllowed = !out.isExpr; +}; - }, { - key: 'astContinueStatement', - value: function astContinueStatement(crNode, retArr, funcParam) { - retArr.push('continue;\n'); - return retArr; - } +types.braceL.updateContext = function(prevType) { + this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr); + this.exprAllowed = true; +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astLogicalExpression - * - * @desc Parses the abstract syntax tree for *Logical* Expression - * - * @param {Object} logNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +types.dollarBraceL.updateContext = function() { + this.context.push(types$1.b_tmpl); + this.exprAllowed = true; +}; - }, { - key: 'astLogicalExpression', - value: function astLogicalExpression(logNode, retArr, funcParam) { - retArr.push('('); - this.astGeneric(logNode.left, retArr, funcParam); - retArr.push(logNode.operator); - this.astGeneric(logNode.right, retArr, funcParam); - retArr.push(')'); - return retArr; - } +types.parenL.updateContext = function(prevType) { + var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; + this.context.push(statementParens ? types$1.p_stat : types$1.p_expr); + this.exprAllowed = true; +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astUpdateExpression - * - * @desc Parses the abstract syntax tree for *Update* Expression - * - * @param {Object} uNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +types.incDec.updateContext = function() { + // tokExprAllowed stays unchanged +}; - }, { - key: 'astUpdateExpression', - value: function astUpdateExpression(uNode, retArr, funcParam) { - if (uNode.prefix) { - retArr.push(uNode.operator); - this.astGeneric(uNode.argument, retArr, funcParam); - } else { - this.astGeneric(uNode.argument, retArr, funcParam); - retArr.push(uNode.operator); - } +types._function.updateContext = types._class.updateContext = function(prevType) { + if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && + !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)) + { this.context.push(types$1.f_expr); } + else + { this.context.push(types$1.f_stat); } + this.exprAllowed = false; +}; - return retArr; - } +types.backQuote.updateContext = function() { + if (this.curContext() === types$1.q_tmpl) + { this.context.pop(); } + else + { this.context.push(types$1.q_tmpl); } + this.exprAllowed = false; +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astUnaryExpression - * - * @desc Parses the abstract syntax tree for *Unary* Expression - * - * @param {Object} uNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +types.star.updateContext = function(prevType) { + if (prevType == types._function) { + var index = this.context.length - 1; + if (this.context[index] === types$1.f_expr) + { this.context[index] = types$1.f_expr_gen; } + else + { this.context[index] = types$1.f_gen; } + } + this.exprAllowed = true; +}; - }, { - key: 'astUnaryExpression', - value: function astUnaryExpression(uNode, retArr, funcParam) { - if (uNode.prefix) { - retArr.push(uNode.operator); - this.astGeneric(uNode.argument, retArr, funcParam); - } else { - this.astGeneric(uNode.argument, retArr, funcParam); - retArr.push(uNode.operator); - } +types.name.updateContext = function(prevType) { + var allowed = false; + if (this.options.ecmaVersion >= 6) { + if (this.value == "of" && !this.exprAllowed || + this.value == "yield" && this.inGeneratorContext()) + { allowed = true; } + } + this.exprAllowed = allowed; +}; - return retArr; - } +// 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. - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astThisExpression - * - * @desc Parses the abstract syntax tree for *This* expression - * - * @param {Object} tNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +var Token = function Token(p) { + 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]; } +}; - }, { - key: 'astThisExpression', - value: function astThisExpression(tNode, retArr, funcParam) { - retArr.push('_this'); - return retArr; - } +// ## Tokenizer - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astMemberExpression - * - * @desc Parses the abstract syntax tree for *Member* Expression - * - * @param {Object} mNode - An ast Node - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +var pp$8 = Parser.prototype; - }, { - key: 'astMemberExpression', - value: function astMemberExpression(mNode, retArr, funcParam) { - if (mNode.computed) { - if (mNode.object.type === 'Identifier') { - this.astGeneric(mNode.object, retArr, funcParam); - retArr.push('['); - this.astGeneric(mNode.property, retArr, funcParam); - retArr.push(']'); - } else { - this.astGeneric(mNode.object, retArr, funcParam); - var last = retArr.pop(); - retArr.push(']['); - this.astGeneric(mNode.property, retArr, funcParam); - retArr.push(last); - } - } else { - var unrolled = this.astMemberExpressionUnroll(mNode); - if (mNode.property.type === 'Identifier' && mNode.computed) { - unrolled = 'user_' + unrolled; - } +// Are we running under Rhino? +var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]"; - // Its a reference to `this`, add '_' before - if (unrolled.indexOf('this') === 0) { - unrolled = '_' + unrolled; - } +// Move to the next token - switch (unrolled) { - case '_this.output.x': - retArr.push(this.output[0]); - break; - case '_this.output.y': - retArr.push(this.output[1]); - break; - case '_this.output.z': - retArr.push(this.output[2]); - break; - default: - retArr.push(unrolled); - } - } - return retArr; - } - }, { - key: 'astSequenceExpression', - value: function astSequenceExpression(sNode, retArr, funcParam) { - for (var i = 0; i < sNode.expressions.length; i++) { - if (i > 0) { - retArr.push(','); - } - this.astGeneric(sNode.expressions, retArr, funcParam); - } - return retArr; - } - - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astCallExpression - * - * @desc Parses the abstract syntax tree for *call* expression - * - * @param {Object} ast - the AST object to parse - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ - - }, { - key: 'astCallExpression', - value: function astCallExpression(ast, retArr, funcParam) { - if (ast.callee) { - // Get the full function call, unrolled - var funcName = this.astMemberExpressionUnroll(ast.callee); - - // Register the function into the called registry - if (funcParam.calledFunctions.indexOf(funcName) < 0) { - funcParam.calledFunctions.push(funcName); - } - if (!funcParam.hasOwnProperty('funcName')) { - funcParam.calledFunctionsArguments[funcName] = []; - } - - var functionArguments = []; - funcParam.calledFunctionsArguments[funcName].push(functionArguments); - - // Call the function - retArr.push(funcName); - - // Open arguments space - retArr.push('('); - - // Add the vars - for (var i = 0; i < ast.arguments.length; ++i) { - var argument = ast.arguments[i]; - if (i > 0) { - retArr.push(', '); - } - this.astGeneric(argument, retArr, funcParam); - if (argument.type === 'Identifier') { - var paramIndex = funcParam.paramNames.indexOf(argument.name); - if (paramIndex === -1) { - functionArguments.push(null); - } else { - functionArguments.push({ - name: argument.name, - type: funcParam.paramTypes[paramIndex] - }); - } - } else { - functionArguments.push(null); - } - } - - // Close arguments space - retArr.push(')'); - - return retArr; - } +pp$8.next = function() { + if (this.options.onToken) + { this.options.onToken(new Token(this)); } - // Failure, unknown expression - throw this.astErrorOutput('Unknown CallExpression', ast, funcParam); + this.lastTokEnd = this.end; + this.lastTokStart = this.start; + this.lastTokEndLoc = this.endLoc; + this.lastTokStartLoc = this.startLoc; + this.nextToken(); +}; - return retArr; - } +pp$8.getToken = function() { + this.next(); + return new Token(this) +}; - /** - * @memberOf WebGLFunctionNode# - * @function - * @name astArrayExpression - * - * @desc Parses the abstract syntax tree for *Array* Expression - * - * @param {Object} arrNode - the AST object to parse - * @param {Array} retArr - return array string - * @param {Function} funcParam - FunctionNode, that tracks compilation state - * - * @returns {Array} the append retArr - */ +// If we're in an ES6 environment, make parsers iterable +if (typeof Symbol !== "undefined") + { pp$8[Symbol.iterator] = function() { + var this$1 = this; - }, { - key: 'astArrayExpression', - value: function astArrayExpression(arrNode, retArr, funcParam) { - var arrLen = arrNode.elements.length; + return { + next: function () { + var token = this$1.getToken(); + return { + done: token.type === types.eof, + value: token + } + } + } + }; } - retArr.push('new Float32Array('); - for (var i = 0; i < arrLen; ++i) { - if (i > 0) { - retArr.push(', '); - } - var subNode = arrNode.elements[i]; - this.astGeneric(subNode, retArr, funcParam); - } - retArr.push(')'); +// Toggle strict mode. Re-reads the next number or string to please +// pedantic tests (`"use strict"; 010;` should fail). - return retArr; +pp$8.curContext = function() { + return this.context[this.context.length - 1] +}; - // // Failure, unknown expression - // throw this.astErrorOutput( - // 'Unknown ArrayExpression', - // arrNode, funcParam - //); - } - }, { - key: 'astDebuggerStatement', - value: function astDebuggerStatement(arrNode, retArr, funcParam) { - retArr.push('debugger;'); - return retArr; - } - }], [{ - key: 'astFunctionPrototype', - value: function astFunctionPrototype(ast, retArr, funcParam) { - // Setup function return type and name - if (funcParam.isRootKernel || funcParam.isSubKernel) { - return retArr; - } +// Read a single token, updating the parser object's token-related +// properties. - retArr.push(funcParam.returnType); - retArr.push(' '); - retArr.push(funcParam.functionName); - retArr.push('('); +pp$8.nextToken = function() { + var curContext = this.curContext(); + if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } - // Arguments handling - for (var i = 0; i < funcParam.paramNames.length; ++i) { - if (i > 0) { - retArr.push(', '); - } + this.start = this.pos; + if (this.options.locations) { this.startLoc = this.curPosition(); } + if (this.pos >= this.input.length) { return this.finishToken(types.eof) } - retArr.push(funcParam.paramTypes[i]); - retArr.push(' '); - retArr.push('user_'); - retArr.push(funcParam.paramNames[i]); - } + if (curContext.override) { return curContext.override(this) } + else { this.readToken(this.fullCharCodeAtPos()); } +}; - retArr.push(');\n'); +pp$8.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 retArr; - } - }]); + return this.getTokenFromCode(code) +}; - return CPUFunctionNode; -}(BaseFunctionNode); -},{"../../core/utils":74,"../function-node-base":56}],52:[function(require,module,exports){ -'use strict'; +pp$8.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 +}; -var utils = require('../../core/utils'); -var kernelRunShortcut = require('../kernel-run-shortcut'); +pp$8.skipBlockComment = function() { + var this$1 = this; -module.exports = function (cpuKernel, name) { - return '() => {\n ' + kernelRunShortcut.toString() + ';\n const utils = {\n allPropertiesOf: function ' + utils.allPropertiesOf.toString() + ',\n clone: function ' + utils.clone.toString() + ',\n /*splitArray: function ' + utils.splitArray.toString() + ',\n getArgumentType: function ' + utils.getArgumentType.toString() + ',\n getOutput: function ' + utils.getOutput.toString() + ',\n dimToTexSize: function ' + utils.dimToTexSize.toString() + ',\n copyFlatten: function ' + utils.copyFlatten.toString() + ',\n flatten: function ' + utils.flatten.toString() + ',\n systemEndianness: \'' + utils.systemEndianness() + '\',\n initWebGl: function ' + utils.initWebGl.toString() + ',\n isArray: function ' + utils.isArray.toString() + '*/\n };\n class ' + (name || 'Kernel') + ' {\n constructor() { \n this.argumentsLength = 0;\n this._canvas = null;\n this._webGl = null;\n this.built = false;\n this.program = null;\n this.paramNames = ' + JSON.stringify(cpuKernel.paramNames) + ';\n this.paramTypes = ' + JSON.stringify(cpuKernel.paramTypes) + ';\n this.texSize = ' + JSON.stringify(cpuKernel.texSize) + ';\n this.output = ' + JSON.stringify(cpuKernel.output) + ';\n this._kernelString = `' + cpuKernel._kernelString + '`;\n this.output = ' + JSON.stringify(cpuKernel.output) + ';\n\t\t this.run = function() {\n this.run = null;\n this.build();\n return this.run.apply(this, arguments);\n }.bind(this);\n this.thread = {\n x: 0,\n y: 0,\n z: 0\n };\n }\n setCanvas(canvas) { this._canvas = canvas; return this; }\n setWebGl(webGl) { this._webGl = webGl; return this; }\n ' + cpuKernel.build.toString() + '\n run () { ' + cpuKernel.kernelString + ' }\n getKernelString() { return this._kernelString; }\n };\n return kernelRunShortcut(new Kernel());\n };'; + 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; + while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { + ++this$1.curLine; + this$1.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()); } }; -},{"../../core/utils":74,"../kernel-run-shortcut":58}],53:[function(require,module,exports){ -'use strict'; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +pp$8.skipLineComment = function(startSkip) { + var this$1 = this; -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + 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 && !isNewLine(ch)) { + ch = this$1.input.charCodeAt(++this$1.pos); + } + if (this.options.onComment) + { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, + startLoc, this.curPosition()); } +}; -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +// Called at the start of the parse and after every token. Skips +// whitespace and comments, and. -var KernelBase = require('../kernel-base'); -var utils = require('../../core/utils'); -var kernelString = require('./kernel-string'); +pp$8.skipSpace = function() { + var this$1 = this; -module.exports = function (_KernelBase) { - _inherits(CPUKernel, _KernelBase); + loop: while (this.pos < this.input.length) { + var ch = this$1.input.charCodeAt(this$1.pos); + switch (ch) { + case 32: case 160: // ' ' + ++this$1.pos; + break + case 13: + if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { + ++this$1.pos; + } + case 10: case 8232: case 8233: + ++this$1.pos; + if (this$1.options.locations) { + ++this$1.curLine; + this$1.lineStart = this$1.pos; + } + break + case 47: // '/' + switch (this$1.input.charCodeAt(this$1.pos + 1)) { + case 42: // '*' + this$1.skipBlockComment(); + break + case 47: + this$1.skipLineComment(2); + break + default: + break loop + } + break + default: + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this$1.pos; + } else { + break loop + } + } + } +}; - /** - * @constructor CPUKernel - * - * @desc Kernel Implementation for CPU. - * - *

Instantiates properties to the CPU Kernel.

- * - * @extends KernelBase - * - * @prop {Object} thread - The thread dimensions, x, y and z - * @prop {Object} output - The canvas dimensions - * @prop {Object} functionBuilder - Function Builder instance bound to this Kernel - * @prop {Function} run - Method to run the kernel - * - */ - function CPUKernel(fnString, settings) { - _classCallCheck(this, CPUKernel); +// 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. - var _this = _possibleConstructorReturn(this, (CPUKernel.__proto__ || Object.getPrototypeOf(CPUKernel)).call(this, fnString, settings)); +pp$8.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._fnBody = utils.getFunctionBodyFromString(fnString); - _this._fn = null; - _this.run = null; - _this._canvasCtx = null; - _this._imageData = null; - _this._colorData = null; - _this._kernelString = null; - _this.thread = { - x: 0, - y: 0, - z: 0 - }; + this.updateContext(prevType); +}; - _this.run = function () { - this.run = null; - this.build.apply(this, arguments); - return this.run.apply(this, arguments); - }.bind(_this); - return _this; - } +// ### Token reading - /** - * @memberOf CPUKernel# - * @function - * @name validateOptions - * - * @desc Validate options related to CPU Kernel, such as - * dimensions size, and auto dimension support. - * - */ +// 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$8.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(types.ellipsis) + } else { + ++this.pos; + return this.finishToken(types.dot) + } +}; +pp$8.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(types.assign, 2) } + return this.finishOp(types.slash, 1) +}; - _createClass(CPUKernel, [{ - key: 'validateOptions', - value: function validateOptions() { - if (!this.output || this.output.length === 0) { - if (arguments.length !== 1) { - throw 'Auto dimensions only supported for kernels with only one input'; - } +pp$8.readToken_mult_modulo_exp = function(code) { // '%*' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + var tokentype = code === 42 ? types.star : types.modulo; - var argType = utils.getArgumentType(arguments[0]); - if (argType === 'Array') { - this.output = utils.getDimensions(argType); - } else if (argType === 'Texture') { - this.output = arguments[0].output; - } else { - throw 'Auto dimensions not supported for input type: ' + argType; - } - } - } + // exponentiation operator ** and **= + if (this.options.ecmaVersion >= 7 && code == 42 && next === 42) { + ++size; + tokentype = types.starstar; + next = this.input.charCodeAt(this.pos + 2); + } - /** - * @memberOf CPUKernel# - * @function - * @name build - * - * @desc Builds the Kernel, by generating the kernel - * string using thread dimensions, and arguments - * supplied to the kernel. - * - *

If the graphical flag is enabled, canvas is used.

- * - */ + if (next === 61) { return this.finishOp(types.assign, size + 1) } + return this.finishOp(tokentype, size) +}; - }, { - key: 'build', - value: function build() { - this.setupParams(arguments); - var threadDim = this.threadDim = utils.clone(this.output); +pp$8.readToken_pipe_amp = function(code) { // '|&' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1) +}; - while (threadDim.length < 3) { - threadDim.push(1); - } +pp$8.readToken_caret = function() { // '^' + var next = this.input.charCodeAt(this.pos + 1); + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.bitwiseXOR, 1) +}; - if (this.graphical) { - var canvas = this.getCanvas(); - canvas.width = threadDim[0]; - canvas.height = threadDim[1]; - this._canvasCtx = canvas.getContext('2d'); - this._imageData = this._canvasCtx.createImageData(threadDim[0], threadDim[1]); - this._colorData = new Uint8ClampedArray(threadDim[0] * threadDim[1] * 4); - } +pp$8.readToken_plus_min = function(code) { // '+-' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { + if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 && + (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { + // A `-->` line comment + this.skipLineComment(3); + this.skipSpace(); + return this.nextToken() + } + return this.finishOp(types.incDec, 2) + } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.plusMin, 1) +}; - var kernelString = this.getKernelString(); +pp$8.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(types.assign, size + 1) } + return this.finishOp(types.bitShift, size) + } + if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 && + this.input.charCodeAt(this.pos + 3) == 45) { + // `` line comment - this.skipLineComment(3); - this.skipSpace(); - return this.nextToken() - } - return this.finishOp(types.incDec, 2) - } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.plusMin, 1) -}; +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var UtilsCore = require("./utils-core"); +var Input = require('./input'); +var Texture = require('./texture'); +// FUNCTION_NAME regex +var FUNCTION_NAME = /function ([^(]*)/; -pp$8.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(types.assign, size + 1) } - return this.finishOp(types.bitShift, size) - } - if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 && - this.input.charCodeAt(this.pos + 3) == 45) { - // `