Merge branch 'devel' into minifier_js_update

This commit is contained in:
BrianMulhall
2020-03-31 20:38:49 -05:00
56 changed files with 1996 additions and 3061 deletions

View File

@@ -279,6 +279,8 @@ N/A
See [this comment](https://github.com/meteor/meteor/pull/10522#issuecomment-535535056)
by [@SimonSimCity](https://github.com/SimonSimCity).
* `Plugin.fs` methods are now always sync and no longer accept a callback.
### Migration Steps
* Be sure to update the `@babel/runtime` npm package to its latest version

View File

@@ -1,5 +1,4 @@
import { Meteor } from 'meteor/meteor'
import { isModern } from "meteor/modern-browsers";
import { WebApp } from "meteor/webapp";
import crypto from 'crypto';
import fs from 'fs';
@@ -88,12 +87,12 @@ WebApp.connectHandlers.use((req, res, next) => {
}
const cacheInfo = {
modern: isModern(request.browser),
// Provided by WebApp.categorizeRequest.
modern: request.modern,
};
cacheInfo.arch = cacheInfo.modern
? "web.browser"
: "web.browser.legacy";
// Also provided by WebApp.categorizeRequest.
cacheInfo.arch = request.arch;
// The true hash of the client manifest for this arch, regardless of
// AUTOUPDATE_VERSION or Autoupdate.autoupdateVersion.

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Enable the application cache in the browser",
version: "1.2.5",
version: "1.2.7",
});
Package.onUse(api => {

View File

@@ -171,27 +171,16 @@ CachingCompilerBase = class CachingCompilerBase {
return hash.digest('hex');
}
// We want to write the file atomically. But we also don't want to block
// processing on the file write.
_writeFileAsync(filename, contents) {
// Write the file atomically.
_writeFile(filename, contents) {
const tempFilename = filename + '.tmp.' + Random.id();
if (this._cacheDebugEnabled) {
// Write cache file synchronously when cache debugging enabled.
try {
fs.writeFileSync(tempFilename, contents);
fs.renameSync(tempFilename, filename);
} catch (e) {
// ignore errors, it's just a cache
}
} else {
fs.writeFile(tempFilename, contents, writeError => {
if (writeError) return;
try {
fs.renameSync(tempFilename, filename);
} catch (renameError) {
// ignore errors, it's just a cache
}
});
try {
fs.writeFileSync(tempFilename, contents);
fs.renameSync(tempFilename, filename);
} catch (e) {
// ignore errors, it's just a cache
this._cacheDebug(e);
}
}
@@ -384,7 +373,7 @@ CachingCompiler = class CachingCompiler extends CachingCompilerBase {
return;
const cacheFilename = this._cacheFilename(cacheKey);
const cacheContents = this.stringifyCompileResult(compileResult);
this._writeFileAsync(cacheFilename, cacheContents);
this._writeFile(cacheFilename, cacheContents);
}
// Returns null if the file does not exist or can't be parsed; otherwise

View File

@@ -253,6 +253,6 @@ extends CachingCompilerBase {
const cacheContents =
JSON.stringify(cacheEntry.cacheKeys) + '\n' +
this.stringifyCompileResult(cacheEntry.compileResult);
this._writeFileAsync(cacheFilename, cacheContents);
this._writeFile(cacheFilename, cacheContents);
}
}

View File

@@ -1,6 +1,6 @@
Package.describe({
name: 'caching-compiler',
version: '1.2.1',
version: '1.2.2',
summary: 'An easy way to make compiler plugins cache',
documentation: 'README.md'
});

View File

@@ -1,6 +1,6 @@
Package.describe({
name: "dynamic-import",
version: "0.5.1",
version: "0.5.2",
summary: "Runtime support for Meteor 1.5 dynamic import(...) syntax",
documentation: "README.md"
});

View File

@@ -8,7 +8,6 @@ const {
} = require("path");
const { fetchURL } = require("./common.js");
const { Meteor } = require("meteor/meteor");
const { isModern } = require("meteor/modern-browsers");
const hasOwn = Object.prototype.hasOwnProperty;
require("./security.js");
@@ -112,27 +111,19 @@ function middleware(request, response) {
}
function getPlatform(request) {
const { identifyBrowser } = Package.webapp.WebAppInternals;
const browser = identifyBrowser(request.headers["user-agent"]);
let platform = isModern(browser)
? "web.browser"
: "web.browser.legacy";
// If the __dynamicImport request includes a secret key, and it matches
// dynamicImportInfo[platform].key, use platform instead of the default
// platform, web.browser.
const secretKey = request.query.key;
if (typeof secretKey === "string") {
Object.keys(dynamicImportInfo).some(p => {
for (const p of Object.keys(dynamicImportInfo)) {
if (secretKey === dynamicImportInfo[p].key) {
platform = p;
return true;
return p;
}
});
}
}
return platform;
return Package.webapp.WebApp.categorizeRequest(request).arch;
}
function readTree(tree, platform) {

View File

@@ -518,6 +518,8 @@ MongoConnection.prototype._update = function (collection_name, selector, mod,
try {
var collection = self.rawCollection(collection_name);
var mongoOpts = {safe: true};
// Add support for filtered positional operator
if (options.arrayFilters !== undefined) mongoOpts.arrayFilters = options.arrayFilters;
// explictly enumerate options that minimongo supports
if (options.upsert) mongoOpts.upsert = true;
if (options.multi) mongoOpts.multi = true;

View File

@@ -9,7 +9,7 @@
Package.describe({
summary: "Adaptor for using MongoDB and Minimongo over DDP",
version: '1.9.0'
version: '1.9.1'
});
Npm.depends({
@@ -38,8 +38,8 @@ Package.onUse(function (api) {
]);
// Make weak use of Decimal type on client
api.use('mongo-decimal', 'client', {weak: true});
api.use('mongo-decimal', 'server');
api.use('mongo-decimal@0.1.1', 'client', {weak: true});
api.use('mongo-decimal@0.1.1', 'server');
api.use('underscore', 'server');

View File

@@ -2,24 +2,19 @@
"lockfileVersion": 1,
"dependencies": {
"@babel/runtime": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz",
"integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA=="
"version": "7.9.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
"integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q=="
},
"ajv": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU="
},
"amdefine": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
"integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw=="
},
"asap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz",
"integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0="
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
},
"asn1": {
"version": "0.2.4",
@@ -42,9 +37,9 @@
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
@@ -56,15 +51,15 @@
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
"clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
},
"combined-stream": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg="
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="
},
"core-util-is": {
"version": "1.0.2",
@@ -102,14 +97,14 @@
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
"integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
},
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"forever-agent": {
"version": "0.6.1",
@@ -117,9 +112,9 @@
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk="
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ=="
},
"getpass": {
"version": "0.1.7",
@@ -127,9 +122,9 @@
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo="
},
"graceful-fs": {
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz",
"integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg="
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
},
"har-schema": {
"version": "2.0.0",
@@ -137,9 +132,9 @@
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
"integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA=="
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g=="
},
"http-signature": {
"version": "1.2.0",
@@ -147,9 +142,9 @@
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE="
},
"image-size": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.3.5.tgz",
"integrity": "sha1-gyQOqy+1sAsEqrjHSwRx6cunrYw="
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
"integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w="
},
"is-typedarray": {
"version": "1.0.0",
@@ -172,9 +167,9 @@
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stringify-safe": {
"version": "5.0.1",
@@ -187,8 +182,9 @@
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI="
},
"less": {
"version": "https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6",
"integrity": "sha512-514pMpzrABW11ploVaRcbHLf3MhollYYCJj9SyJmNT1O8ZeLCiIeqZ2SjZUM1uudohPlHgTRwmCZouzIJFJ7Jw=="
"version": "3.11.1",
"resolved": "https://registry.npmjs.org/less/-/less-3.11.1.tgz",
"integrity": "sha512-tlWX341RECuTOvoDIvtFqXsKj072hm3+9ymRBe76/mD6O5ZZecnlAOVDlWAleF2+aohFrxNidXhv2773f6kY7g=="
},
"mime": {
"version": "1.6.0",
@@ -196,29 +192,24 @@
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": {
"version": "1.36.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
"integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw=="
"version": "1.43.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
},
"mime-types": {
"version": "2.1.20",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
"integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A=="
"version": "2.1.26",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ=="
},
"minimist": {
"version": "0.0.8",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"mkdirp": {
"version": "0.5.1",
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM="
},
"natives": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz",
"integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg=="
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
"integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw=="
},
"oauth-sign": {
"version": "0.9.0",
@@ -231,9 +222,9 @@
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"promise": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz",
"integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY="
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="
},
"prr": {
"version": "1.0.1",
@@ -241,14 +232,14 @@
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
},
"psl": {
"version": "1.1.29",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
},
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"qs": {
"version": "6.5.2",
@@ -256,19 +247,19 @@
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
"regenerator-runtime": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
"version": "0.13.5",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
},
"request": {
"version": "2.88.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg=="
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw=="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
},
"safer-buffer": {
"version": "2.1.2",
@@ -276,19 +267,24 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"source-map": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s="
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"sshpk": {
"version": "1.14.2",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
"integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg="
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg=="
},
"tough-cookie": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ=="
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g=="
},
"tslib": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
"integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
},
"tunnel-agent": {
"version": "0.6.0",
@@ -300,10 +296,15 @@
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ=="
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"verror": {
"version": "1.10.0",

View File

@@ -1,10 +1,18 @@
# Less
[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/less) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/less)
[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/non-core/less) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/non-core/less)
***
The Less package provides a compiler build plugin for the Meteor build tool. It
handles the compilation of `*.less` files to CSS.
## Changelog
### 3.0.0
- Updated less to 3.11.1.
- Import files without ending as less files, according to less import rules.
- Add `javascriptEnabled` option to less, to be backwards compatible to previous version of this package.
## Usage
If you want to use it in your app, just run:

View File

@@ -1,20 +1,22 @@
Package.describe({
name: 'less',
version: '2.8.0',
version: '3.0.1',
summary: 'Leaner CSS language',
documentation: 'README.md'
});
Package.registerBuildPlugin({
name: "compileLessBatch",
use: ['caching-compiler', 'ecmascript', 'underscore'],
use: [
"caching-compiler@1.2.2",
"ecmascript@0.14.3",
],
sources: [
'plugin/compile-less.js'
],
npmDependencies: {
"@babel/runtime": "7.0.0",
// Fork of 2.5.0, deleted large unused files in dist directory.
"less": "https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6"
"@babel/runtime": "7.9.2",
"less": "3.11.1"
}
});

View File

@@ -62,6 +62,8 @@ class LessCompiler extends MultiFileCachingCompiler {
return less.render(inputFile.getContentsAsBuffer().toString('utf8'), {
filename: this.getAbsoluteImportPath(inputFile),
plugins: [importPlugin],
// Enabled as it was default true before less v3.0.0
javascriptEnabled: true,
// Generate a source map, and include the source files in the
// sourcesContent field. (Note that source files which don't
// themselves produce text (eg, are entirely variable definitions)
@@ -81,11 +83,11 @@ class LessCompiler extends MultiFileCachingCompiler {
};
const referencedImportPaths = [];
output.imports.forEach((path) => {
output.imports.forEach((outputPath) => {
// Some files that show up in output.imports are not actually files; for
// example @import url("...");
if (allFiles.has(path)) {
referencedImportPaths.push(path);
if (allFiles.has(outputPath)) {
referencedImportPaths.push(outputPath);
}
});
@@ -109,22 +111,18 @@ class LessCompiler extends MultiFileCachingCompiler {
addCompileResult(inputFile, compileResult) {
inputFile.addStylesheet({
data: compileResult.css,
path: inputFile.getPathInPackage() + '.css',
path: `${inputFile.getPathInPackage()}.css`,
sourceMap: compileResult.sourceMap
});
}
}
class MeteorImportLessPlugin {
constructor(allFiles) {
this.allFiles = allFiles;
this.minVersion = [2, 5, 0];
}
function MeteorImportLessPlugin(allFiles) {
this.minVersion = [3, 6, 0];
install(less, pluginManager) {
pluginManager.addFileManager(
new MeteorImportLessFileManager(this.allFiles));
}
this.install = (l, pluginManager) => {
pluginManager.addFileManager(new MeteorImportLessFileManager(allFiles));
};
}
class MeteorImportLessFileManager extends less.AbstractFileManager {
@@ -138,20 +136,17 @@ class MeteorImportLessFileManager extends less.AbstractFileManager {
// We shouldn't process files that start with `//` or a protocol because
// those are not relative to the app at all; they are probably native
// CSS imports
if (! filename.match(/^(https?:)?\/\//)) {
return true;
}
return false;
return !filename.match(/^(https?:)?\/\//);
}
loadFile(filename, currentDirectory, options, environment, cb) {
loadFile(filename, currentDirectory) {
const packageMatch = currentDirectory.match(/^(\{[^}]*\})/);
if (! packageMatch) {
if (!packageMatch) {
// shouldn't happen. all filenames less ever sees should involve this {}
// thing!
cb(new Error('file without Meteor context? ' + currentDirectory));
return;
return Promise.reject(
new Error(`file without Meteor context? ${currentDirectory}`)
);
}
const currentPackagePrefix = packageMatch[1];
@@ -164,28 +159,41 @@ class MeteorImportLessFileManager extends less.AbstractFileManager {
} else {
resolvedFilename = path.join(currentDirectory, filename);
}
// Import rule from less:
// If it does not have an extension, .less will be appended and it will be included as a imported Less file.
if (
!this.allFiles.has(resolvedFilename) &&
this.allFiles.has(`${resolvedFilename}.less`)
) {
resolvedFilename = `${resolvedFilename}.less`;
}
if (!this.allFiles.has(resolvedFilename)) {
cb({type: 'File', message: 'Unknown import: ' + filename});
return;
return Promise.reject(new Error(`Unknown import: ${filename}`));
}
cb(null, {
return Promise.resolve({
contents: this.allFiles.get(resolvedFilename)
.getContentsAsBuffer().toString('utf8'),
filename: resolvedFilename
filename: resolvedFilename,
});
}
}
function decodeFilePath (filePath) {
function decodeFilePath(filePath) {
const match = filePath.match(/^{(.*)}\/(.*)$/);
if (! match)
throw new Error('Failed to decode Less path: ' + filePath);
if (!match) {
// Sometimes a filePath may be an URL, such as when loading fonts from
// https://fonts.googleapis.com/css. Preserve those URLs instead of
// trying to rewrite them.
return filePath;
}
if (match[1] === '') {
// app
// Importing from the application, not from a Meteor package.
return match[2];
}
return 'packages/' + match[1] + '/' + match[2];
return `packages/${match[1]}/${match[2]}`;
}

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Serves a Meteor app over HTTP",
version: '1.9.0'
version: '1.9.1'
});
Npm.depends({"basic-auth-connect": "1.0.0",

View File

@@ -130,10 +130,63 @@ var identifyBrowser = function (userAgentString) {
WebAppInternals.identifyBrowser = identifyBrowser;
WebApp.categorizeRequest = function (req) {
return _.extend({
browser: identifyBrowser(req.headers['user-agent']),
url: parseUrl(req.url, true)
}, _.pick(req, 'dynamicHead', 'dynamicBody', 'headers', 'cookies'));
if (req.browser && req.arch && typeof req.modern === "boolean") {
// Already categorized.
return req;
}
const browser = identifyBrowser(req.headers["user-agent"]);
const modern = isModern(browser);
const path = typeof req.pathname === "string"
? req.pathname
: parseRequest(req).pathname;
const categorized = {
browser,
modern,
path,
arch: WebApp.defaultArch,
url: parseUrl(req.url, true),
dynamicHead: req.dynamicHead,
dynamicBody: req.dynamicBody,
headers: req.headers,
cookies: req.cookies,
};
const pathParts = path.split("/");
const archKey = pathParts[1];
if (archKey.startsWith("__")) {
const archCleaned = "web." + archKey.slice(2);
if (hasOwn.call(WebApp.clientPrograms, archCleaned)) {
pathParts.splice(1, 1); // Remove the archKey part.
return Object.assign(categorized, {
arch: archCleaned,
path: pathParts.join("/"),
});
}
}
// TODO Perhaps one day we could infer Cordova clients here, so that we
// wouldn't have to use prefixed "/__cordova/..." URLs.
const preferredArchOrder = isModern(browser)
? ["web.browser", "web.browser.legacy"]
: ["web.browser.legacy", "web.browser"];
for (const arch of preferredArchOrder) {
// If our preferred arch is not available, it's better to use another
// client arch that is available than to guarantee the site won't work
// by returning an unknown arch. For example, if web.browser.legacy is
// excluded using the --exclude-archs command-line option, legacy
// clients are better off receiving web.browser (which might actually
// work) than receiving an HTTP 404 response. If none of the archs in
// preferredArchOrder are defined, only then should we send a 404.
if (hasOwn.call(WebApp.clientPrograms, arch)) {
return Object.assign(categorized, { arch });
}
}
return categorized;
};
// HTML attribute hooks: functions to be called to determine any attributes to
@@ -399,10 +452,7 @@ WebAppInternals.staticFilesMiddleware = async function (
return;
}
const { arch, path } = getArchAndPath(
pathname,
identifyBrowser(req.headers["user-agent"]),
);
const { arch, path } = WebApp.categorizeRequest(req);
if (! hasOwn.call(WebApp.clientPrograms, arch)) {
// We could come here in case we run with some architectures excluded
@@ -525,7 +575,7 @@ function getStaticFileInfo(staticFilesByArch, originalPath, path, arch) {
return finalize(originalPath);
}
// If getArchAndPath returned an alternate path, try that instead.
// If categorizeRequest returned an alternate path, try that instead.
if (path !== originalPath &&
hasOwn.call(staticFiles, path)) {
return finalize(path);
@@ -535,37 +585,6 @@ function getStaticFileInfo(staticFilesByArch, originalPath, path, arch) {
return info;
}
function getArchAndPath(path, browser) {
const pathParts = path.split("/");
const archKey = pathParts[1];
if (archKey.startsWith("__")) {
const archCleaned = "web." + archKey.slice(2);
if (hasOwn.call(WebApp.clientPrograms, archCleaned)) {
pathParts.splice(1, 1); // Remove the archKey part.
return {
arch: archCleaned,
path: pathParts.join("/"),
};
}
}
// TODO Perhaps one day we could infer Cordova clients here, so that we
// wouldn't have to use prefixed "/__cordova/..." URLs.
const arch = isModern(browser)
? "web.browser"
: "web.browser.legacy";
if (hasOwn.call(WebApp.clientPrograms, arch)) {
return { arch, path };
}
return {
arch: WebApp.defaultArch,
path,
};
}
// Parse the passed in port value. Return the port as-is if it's a String
// (e.g. a Windows Server style named pipe), otherwise return the port as an
// integer.
@@ -886,7 +905,7 @@ function runWebAppServer() {
if (isPrefixOf(prefixParts, pathParts)) {
request.url = "/" + pathParts.slice(prefixParts.length).join("/");
if (search) {
request.url += search;
request.url += search;
}
return next();
}
@@ -991,10 +1010,8 @@ function runWebAppServer() {
return;
}
const { arch } = getArchAndPath(
parseRequest(req).pathname,
request.browser,
);
const { arch } = request;
assert.strictEqual(typeof arch, "string", { arch });
if (! hasOwn.call(WebApp.clientPrograms, arch)) {
// We could come here in case we run with some architectures excluded

View File

@@ -41,7 +41,7 @@ if (Test-Path $devbundle_zip) {
Write-Host "Extracting $TARBALL to the dev_bundle directory"
cmd /C "7z.exe x $devbundle_zip -so | 7z.exe x -aoa -si -ttar -o$CHECKOUT_DIR\dev_bundle_XXX" | out-null
cmd /C "7z.exe x `"$devbundle_zip`" -so | 7z.exe x -aoa -si -ttar -o`"$CHECKOUT_DIR\dev_bundle_XXX`"" | out-null
if ($LASTEXITCODE -ne 0) {
Exit 1
}

View File

@@ -5,18 +5,17 @@
# but you can also edit it by hand.
meteor-base@1.4.0 # Packages every Meteor app needs to have
mobile-experience@1.0.5 # Packages for a great mobile UX
mongo@1.6.2 # The database Meteor supports right now
mobile-experience@1.1.0 # Packages for a great mobile UX
mongo@1.9.0 # The database Meteor supports right now
blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views
reactive-var@1.0.11 # Reactive variable for tracker
jquery # Helpful client-side library
tracker@1.2.0 # Meteor's client-side reactive programming library
standard-minifier-css@1.5.3 # CSS minifier run for production mode
standard-minifier-js@2.4.1 # JS minifier run for production mode
standard-minifier-css@1.6.0 # CSS minifier run for production mode
standard-minifier-js@2.6.0 # JS minifier run for production mode
es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers.
ecmascript@0.12.4 # Enable ECMAScript2015+ syntax in app code
shell-server@0.4.0 # Server-side component of the `meteor shell` command
ecmascript@0.14.2 # Enable ECMAScript2015+ syntax in app code
shell-server@0.5.0 # Server-side component of the `meteor shell` command
autopublish@1.0.7 # Publish all data to the clients (for prototyping)
insecure@1.0.7 # Allow all DB writes from clients (for prototyping)
@@ -26,3 +25,4 @@ helper-package
user:colon-name
underscore@1.0.10
fetch@0.1.1
jquery

View File

@@ -1 +1 @@
METEOR@1.8.1
METEOR@1.10.1

View File

@@ -1,32 +1,32 @@
allow-deny@1.1.0
autopublish@1.0.7
autoupdate@1.6.0
babel-compiler@7.3.4
babel-runtime@1.3.0
base64@1.0.11
babel-compiler@7.5.3
babel-runtime@1.5.0
base64@1.0.12
binary-heap@1.0.11
blaze@2.3.3
blaze@2.3.4
blaze-html-templates@1.1.2
blaze-tools@1.0.10
boilerplate-generator@1.6.0
boilerplate-generator@1.7.0
caching-compiler@1.2.1
caching-html-compiler@1.1.3
callback-hook@1.1.0
callback-hook@1.3.0
check@1.3.1
coffeescript@2.3.2_1
coffeescript-compiler@2.3.2_1
coffeescript@2.4.1
coffeescript-compiler@2.4.1
ddp@1.4.0
ddp-client@2.3.3
ddp-common@1.4.0
ddp-server@2.3.0
ddp-server@2.3.1
deps@1.0.12
diff-sequence@1.1.1
dynamic-import@0.5.1
ecmascript@0.12.7
ecmascript@0.14.3
ecmascript-runtime@0.7.0
ecmascript-runtime-client@0.8.0
ecmascript-runtime-server@0.7.1
ejson@1.1.0
ecmascript-runtime-client@0.10.0
ecmascript-runtime-server@0.9.0
ejson@1.1.1
es5-shim@4.8.0
fetch@0.1.1
geojson-utils@1.0.10
@@ -36,41 +36,41 @@ html-tools@1.0.11
htmljs@1.0.11
id-map@1.1.0
insecure@1.0.7
inter-process-messaging@0.1.0
jquery@1.11.11
launch-screen@1.1.1
inter-process-messaging@0.1.1
jquery@3.0.0
launch-screen@1.2.0
lazy-test-package@0.0.1
livedata@1.0.18
logging@1.1.20
meteor@1.9.3
meteor-base@1.4.0
minifier-css@1.4.2
minifier-js@2.4.1
minimongo@1.4.5
mobile-experience@1.0.5
mobile-status-bar@1.0.14
modern-browsers@0.1.4
modules@0.13.0
modules-runtime@0.10.3
mongo@1.6.2
minifier-css@1.5.0
minifier-js@2.6.0
minimongo@1.5.0
mobile-experience@1.1.0
mobile-status-bar@1.1.0
modern-browsers@0.1.5
modules@0.15.0
modules-runtime@0.12.0
mongo@1.9.1
mongo-decimal@0.1.1
mongo-dev-server@1.1.0
mongo-id@1.0.7
npm-mongo@3.1.2
npm-mongo@3.7.0
observe-sequence@1.0.16
ordered-dict@1.1.0
promise@0.11.2
random@1.1.0
random@1.2.0
reactive-var@1.0.11
reload@1.3.0
retry@1.1.0
routepolicy@1.1.0
shell-server@0.4.0
socket-stream-client@0.2.2
shell-server@0.5.0
socket-stream-client@0.2.3
spacebars@1.0.15
spacebars-compiler@1.1.3
standard-minifier-css@1.5.3
standard-minifier-js@2.4.1
standard-minifier-css@1.6.0
standard-minifier-js@2.6.0
templating@1.3.2
templating-compiler@1.3.3
templating-runtime@1.3.2
@@ -79,5 +79,5 @@ tracker@1.2.0
ui@1.0.13
underscore@1.0.10
user:colon-name@0.0.1
webapp@1.7.4
webapp@1.9.0
webapp-hashing@1.0.9

View File

@@ -4,39 +4,35 @@
"lockfileVersion": 1,
"dependencies": {
"@babel/runtime": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.0.tgz",
"integrity": "sha512-2xsuyZ0R0RBFwjgae5NpXk8FcfH4qovj5cEM5VEeB7KXnKqzaisIu2HSV/mCEISolJJuR4wkViUGYujA8MH9tw==",
"version": "7.9.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
"integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
"requires": {
"regenerator-runtime": "^0.13.2"
"regenerator-runtime": "^0.13.4"
}
},
"@types/node": {
"version": "12.0.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.12.tgz",
"integrity": "sha512-Uy0PN4R5vgBUXFoJrKryf5aTk3kJ8Rv3PdlHjl6UaX+Cqp1QE0yPQ68MPXGrZOfG7gZVNDIJZYyot0B9ubXUrQ=="
"@types/mime-types": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz",
"integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM="
},
"@wry/context": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/@wry/context/-/context-0.4.4.tgz",
"integrity": "sha512-LrKVLove/zw6h2Md/KZyWxIkFM6AoyKp71OqpH9Hiip1csjPVoD3tPxlbQUNxEnHENks3UGgNpSBCAfq9KWuag==",
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@wry/context/-/context-0.5.1.tgz",
"integrity": "sha512-VfPjm79RbzEYZigvZFk7DdvYX+8Qb57xOZw8m2iaAmgmBMNhGDN5yKGiplubX958oFAQMXfaftgTa/VFnu2CsQ==",
"requires": {
"@types/node": ">=6",
"tslib": "^1.9.3"
}
},
"acorn": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz",
"integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw=="
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
"integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg=="
},
"agent-base": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
"integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
"requires": {
"es6-promisify": "^5.0.0"
}
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz",
"integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g=="
},
"arson": {
"version": "0.2.6",
@@ -44,9 +40,9 @@
"integrity": "sha512-wVRnIfjOaCWu3jrf3j1CU/eotDf7tuM34cBswo32EwyLPaMiaWgETfROdYVv47VWEbWSOaZaDnkypGQtQduLbw=="
},
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
},
"balanced-match": {
"version": "1.0.0",
@@ -62,6 +58,11 @@
"concat-map": "0.0.1"
}
},
"buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@@ -96,28 +97,15 @@
"ms": "^2.1.1"
}
},
"es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"es6-promisify": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
"requires": {
"es6-promise": "^4.0.3"
}
},
"extract-zip": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz",
"integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=",
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
"integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
"requires": {
"concat-stream": "1.6.2",
"debug": "2.6.9",
"mkdirp": "0.5.1",
"yauzl": "2.4.1"
"concat-stream": "^1.6.2",
"debug": "^2.6.9",
"mkdirp": "^0.5.4",
"yauzl": "^2.10.0"
},
"dependencies": {
"debug": {
@@ -136,9 +124,9 @@
}
},
"fd-slicer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
"integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
"requires": {
"pend": "~1.2.0"
}
@@ -149,9 +137,9 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"glob": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -162,22 +150,12 @@
}
},
"https-proxy-agent": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
"integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz",
"integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==",
"requires": {
"agent-base": "^4.1.0",
"debug": "^3.1.0"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
}
"agent-base": "5",
"debug": "4"
}
},
"inflight": {
@@ -199,6 +177,11 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"jquery": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
"integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -778,6 +761,19 @@
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
},
"mime-db": {
"version": "1.43.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
},
"mime-types": {
"version": "2.1.26",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
"requires": {
"mime-db": "1.43.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -787,16 +783,16 @@
}
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
"integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
"requires": {
"minimist": "0.0.8"
"minimist": "^1.2.5"
}
},
"moment": {
@@ -823,11 +819,11 @@
}
},
"optimism": {
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/optimism/-/optimism-0.10.2.tgz",
"integrity": "sha512-zPfBIxFFWMmQboM9+Z4MSJqc1PXp82v1PFq/GfQaufI69mHKlup7ykGNnfuGIGssXJQkmhSodQ/k9EWwjd8O8A==",
"version": "0.11.5",
"resolved": "https://registry.npmjs.org/optimism/-/optimism-0.11.5.tgz",
"integrity": "sha512-twCHmBb64DYzEZ8A3O+TLCuF/RmZPBhXPQYv4agoiALRLlW9SidMzd7lwUP9mL0jOZhzhnBmb8ajqA00ECo/7g==",
"requires": {
"@wry/context": "^0.4.0"
"@wry/context": "^0.5.0"
}
},
"path-is-absolute": {
@@ -866,19 +862,21 @@
}
},
"proxy-from-env": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
"integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4="
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"puppeteer": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.18.1.tgz",
"integrity": "sha512-luUy0HPSuWPsPZ1wAp6NinE0zgetWtudf5zwZ6dHjMWfYpTQcmKveFRox7VBNhQ98OjNA9PQ9PzQyX8k/KrxTg==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-2.1.1.tgz",
"integrity": "sha512-LWzaDVQkk1EPiuYeTOj+CZRIjda4k2s5w4MK4xoH2+kgWV/SDlkYHmxatDdtYrciHUKSXTsGgPgPP8ILVdBsxg==",
"requires": {
"@types/mime-types": "^2.1.0",
"debug": "^4.1.0",
"extract-zip": "^1.6.6",
"https-proxy-agent": "^2.2.1",
"https-proxy-agent": "^4.0.0",
"mime": "^2.0.3",
"mime-types": "^2.1.25",
"progress": "^2.0.1",
"proxy-from-env": "^1.0.0",
"rimraf": "^2.6.1",
@@ -886,25 +884,24 @@
}
},
"react": {
"version": "16.8.6",
"resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz",
"integrity": "sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==",
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
"integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.13.6"
"prop-types": "^15.6.2"
}
},
"react-is": {
"version": "16.8.6",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz",
"integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA=="
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -916,14 +913,14 @@
}
},
"regenerator-runtime": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
"integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA=="
"version": "0.13.5",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
},
"rimraf": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"requires": {
"glob": "^7.1.3"
}
@@ -933,15 +930,6 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"scheduler": {
"version": "0.13.6",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz",
"integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -951,9 +939,9 @@
}
},
"tslib": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
"integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
},
"typedarray": {
"version": "0.0.6",
@@ -966,9 +954,9 @@
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz",
"integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw=="
},
"wrappy": {
"version": "1.0.2",
@@ -984,11 +972,12 @@
}
},
"yauzl": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
"integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
"requires": {
"fd-slicer": "~1.0.1"
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
}
}

View File

@@ -6,17 +6,17 @@
"test": "TEST_BROWSER_DRIVER=puppeteer meteor test --full-app --driver-package meteortesting:mocha"
},
"dependencies": {
"@babel/runtime": "^7.5.0",
"acorn": "^6.2.0",
"@babel/runtime": "^7.9.2",
"acorn": "^7.1.1",
"arson": "^0.2.6",
"jquery": "^3.4.1",
"meteor-node-stubs": "^1.0.0",
"moment": "^2.24.0",
"optimism": "^0.10.2",
"optimism": "^0.11.5",
"private": "^0.1.8",
"puppeteer": "^1.18.1",
"react": "^16.8.6",
"regenerator-runtime": "^0.13.2",
"uuid": "^3.3.2"
"puppeteer": "^2.1.1",
"react": "^16.13.1",
"regenerator-runtime": "^0.13.5",
"uuid": "^7.0.2"
}
}

View File

@@ -247,15 +247,15 @@ describe("dynamic import(...)", function () {
});
it('should support object-valued package.json "browser" fields', () => {
return import("uuid").then(({ default: uuid }) => {
return import("uuid").then(({ v4: uuid }) => {
const id = uuid();
assert.strictEqual(typeof id, "string");
assert.strictEqual(id.split("-").length, 5);
if (Meteor.isClient) {
assert.strictEqual(
require.resolve("uuid/lib/rng.js"),
"/node_modules/uuid/lib/rng-browser.js"
require.resolve("uuid/dist/esm-node/index.js"),
"/node_modules/uuid/dist/esm-browser/index.js"
);
const uuidPkgJsonId = ["uuid", "package.json"].join("/");
const { browser } = require(uuidPkgJsonId);

View File

@@ -5,15 +5,15 @@
# but you can also edit it by hand.
meteor-base@1.4.0 # Packages every Meteor app needs to have
mobile-experience@1.0.5 # Packages for a great mobile UX
mongo@1.8.0 # The database Meteor supports right now
mobile-experience@1.1.0 # Packages for a great mobile UX
mongo@1.9.0 # The database Meteor supports right now
blaze-html-templates # Compile .html files into Meteor Blaze views
session@1.2.0 # Client-side reactive dictionary for your app
jquery # Helpful client-side library
tracker@1.2.0 # Meteor's client-side reactive programming library
es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers.
ecmascript@0.14.0 # Enable ECMAScript2015+ syntax in app code
ecmascript@0.14.2 # Enable ECMAScript2015+ syntax in app code
coffeescript
modules-test-package
@@ -21,10 +21,10 @@ standard-minifier-css@1.6.0
standard-minifier-js@2.6.0
client-only-ecmascript
modules-test-plugin
shell-server@0.4.0
shell-server@0.5.0
dynamic-import@0.5.1
underscore@1.0.10
import-local-json-module
akryum:vue-component
dummy-compiler
typescript@3.7.2
typescript@3.7.5

View File

@@ -1 +1 @@
METEOR@1.9
METEOR@1.10.1

View File

@@ -0,0 +1,3 @@
.tern-*
/rollup.config.*
/src

View File

@@ -0,0 +1,580 @@
## 6.4.1 (2020-03-09)
### Bug fixes
More carefully check for valid UTF16 surrogate pairs in regexp validator.
## 7.1.1 (2020-03-01)
### Bug fixes
Treat `\8` and `\9` as invalid escapes in template strings.
Allow unicode escapes in property names that are keywords.
Don't error on an exponential operator expression as argument to `await`.
More carefully check for valid UTF16 surrogate pairs in regexp validator.
## 7.1.0 (2019-09-24)
### Bug fixes
Disallow trailing object literal commas when ecmaVersion is less than 5.
### New features
Add a static `acorn` property to the `Parser` class that contains the entire module interface, to allow plugins to access the instance of the library that they are acting on.
## 7.0.0 (2019-08-13)
### Breaking changes
Changes the node format for dynamic imports to use the `ImportExpression` node type, as defined in [ESTree](https://github.com/estree/estree/blob/master/es2020.md#importexpression).
Makes 10 (ES2019) the default value for the `ecmaVersion` option.
## 6.3.0 (2019-08-12)
### New features
`sourceType: "module"` can now be used even when `ecmaVersion` is less than 6, to parse module-style code that otherwise conforms to an older standard.
## 6.2.1 (2019-07-21)
### Bug fixes
Fix bug causing Acorn to treat some characters as identifier characters that shouldn't be treated as such.
Fix issue where setting the `allowReserved` option to `"never"` allowed reserved words in some circumstances.
## 6.2.0 (2019-07-04)
### Bug fixes
Improve valid assignment checking in `for`/`in` and `for`/`of` loops.
Disallow binding `let` in patterns.
### New features
Support bigint syntax with `ecmaVersion` >= 11.
Support dynamic `import` syntax with `ecmaVersion` >= 11.
Upgrade to Unicode version 12.
## 6.1.1 (2019-02-27)
### Bug fixes
Fix bug that caused parsing default exports of with names to fail.
## 6.1.0 (2019-02-08)
### Bug fixes
Fix scope checking when redefining a `var` as a lexical binding.
### New features
Split up `parseSubscripts` to use an internal `parseSubscript` method to make it easier to extend with plugins.
## 6.0.7 (2019-02-04)
### Bug fixes
Check that exported bindings are defined.
Don't treat `\u180e` as a whitespace character.
Check for duplicate parameter names in methods.
Don't allow shorthand properties when they are generators or async methods.
Forbid binding `await` in async arrow function's parameter list.
## 6.0.6 (2019-01-30)
### Bug fixes
The content of class declarations and expressions is now always parsed in strict mode.
Don't allow `let` or `const` to bind the variable name `let`.
Treat class declarations as lexical.
Don't allow a generator function declaration as the sole body of an `if` or `else`.
Ignore `"use strict"` when after an empty statement.
Allow string line continuations with special line terminator characters.
Treat `for` bodies as part of the `for` scope when checking for conflicting bindings.
Fix bug with parsing `yield` in a `for` loop initializer.
Implement special cases around scope checking for functions.
## 6.0.5 (2019-01-02)
### Bug fixes
Fix TypeScript type for `Parser.extend` and add `allowAwaitOutsideFunction` to options type.
Don't treat `let` as a keyword when the next token is `{` on the next line.
Fix bug that broke checking for parentheses around an object pattern in a destructuring assignment when `preserveParens` was on.
## 6.0.4 (2018-11-05)
### Bug fixes
Further improvements to tokenizing regular expressions in corner cases.
## 6.0.3 (2018-11-04)
### Bug fixes
Fix bug in tokenizing an expression-less return followed by a function followed by a regular expression.
Remove stray symlink in the package tarball.
## 6.0.2 (2018-09-26)
### Bug fixes
Fix bug where default expressions could fail to parse inside an object destructuring assignment expression.
## 6.0.1 (2018-09-14)
### Bug fixes
Fix wrong value in `version` export.
## 6.0.0 (2018-09-14)
### Bug fixes
Better handle variable-redefinition checks for catch bindings and functions directly under if statements.
Forbid `new.target` in top-level arrow functions.
Fix issue with parsing a regexp after `yield` in some contexts.
### New features
The package now comes with TypeScript definitions.
### Breaking changes
The default value of the `ecmaVersion` option is now 9 (2018).
Plugins work differently, and will have to be rewritten to work with this version.
The loose parser and walker have been moved into separate packages (`acorn-loose` and `acorn-walk`).
## 5.7.3 (2018-09-10)
### Bug fixes
Fix failure to tokenize regexps after expressions like `x.of`.
Better error message for unterminated template literals.
## 5.7.2 (2018-08-24)
### Bug fixes
Properly handle `allowAwaitOutsideFunction` in for statements.
Treat function declarations at the top level of modules like let bindings.
Don't allow async function declarations as the only statement under a label.
## 5.7.0 (2018-06-15)
### New features
Upgraded to Unicode 11.
## 5.6.0 (2018-05-31)
### New features
Allow U+2028 and U+2029 in string when ECMAVersion >= 10.
Allow binding-less catch statements when ECMAVersion >= 10.
Add `allowAwaitOutsideFunction` option for parsing top-level `await`.
## 5.5.3 (2018-03-08)
### Bug fixes
A _second_ republish of the code in 5.5.1, this time with yarn, to hopefully get valid timestamps.
## 5.5.2 (2018-03-08)
### Bug fixes
A republish of the code in 5.5.1 in an attempt to solve an issue with the file timestamps in the npm package being 0.
## 5.5.1 (2018-03-06)
### Bug fixes
Fix misleading error message for octal escapes in template strings.
## 5.5.0 (2018-02-27)
### New features
The identifier character categorization is now based on Unicode version 10.
Acorn will now validate the content of regular expressions, including new ES9 features.
## 5.4.0 (2018-02-01)
### Bug fixes
Disallow duplicate or escaped flags on regular expressions.
Disallow octal escapes in strings in strict mode.
### New features
Add support for async iteration.
Add support for object spread and rest.
## 5.3.0 (2017-12-28)
### Bug fixes
Fix parsing of floating point literals with leading zeroes in loose mode.
Allow duplicate property names in object patterns.
Don't allow static class methods named `prototype`.
Disallow async functions directly under `if` or `else`.
Parse right-hand-side of `for`/`of` as an assignment expression.
Stricter parsing of `for`/`in`.
Don't allow unicode escapes in contextual keywords.
### New features
Parsing class members was factored into smaller methods to allow plugins to hook into it.
## 5.2.1 (2017-10-30)
### Bug fixes
Fix a token context corruption bug.
## 5.2.0 (2017-10-30)
### Bug fixes
Fix token context tracking for `class` and `function` in property-name position.
Make sure `%*` isn't parsed as a valid operator.
Allow shorthand properties `get` and `set` to be followed by default values.
Disallow `super` when not in callee or object position.
### New features
Support [`directive` property](https://github.com/estree/estree/compare/b3de58c9997504d6fba04b72f76e6dd1619ee4eb...1da8e603237144f44710360f8feb7a9977e905e0) on directive expression statements.
## 5.1.2 (2017-09-04)
### Bug fixes
Disable parsing of legacy HTML-style comments in modules.
Fix parsing of async methods whose names are keywords.
## 5.1.1 (2017-07-06)
### Bug fixes
Fix problem with disambiguating regexp and division after a class.
## 5.1.0 (2017-07-05)
### Bug fixes
Fix tokenizing of regexps in an object-desctructuring `for`/`of` loop and after `yield`.
Parse zero-prefixed numbers with non-octal digits as decimal.
Allow object/array patterns in rest parameters.
Don't error when `yield` is used as a property name.
Allow `async` as a shorthand object property.
### New features
Implement the [template literal revision proposal](https://github.com/tc39/proposal-template-literal-revision) for ES9.
## 5.0.3 (2017-04-01)
### Bug fixes
Fix spurious duplicate variable definition errors for named functions.
## 5.0.2 (2017-03-30)
### Bug fixes
A binary operator after a parenthesized arrow expression is no longer incorrectly treated as an error.
## 5.0.0 (2017-03-28)
### Bug fixes
Raise an error for duplicated lexical bindings.
Fix spurious error when an assignement expression occurred after a spread expression.
Accept regular expressions after `of` (in `for`/`of`), `yield` (in a generator), and braced arrow functions.
Allow labels in front or `var` declarations, even in strict mode.
### Breaking changes
Parse declarations following `export default` as declaration nodes, not expressions. This means that class and function declarations nodes can now have `null` as their `id`.
## 4.0.11 (2017-02-07)
### Bug fixes
Allow all forms of member expressions to be parenthesized as lvalue.
## 4.0.10 (2017-02-07)
### Bug fixes
Don't expect semicolons after default-exported functions or classes, even when they are expressions.
Check for use of `'use strict'` directives in non-simple parameter functions, even when already in strict mode.
## 4.0.9 (2017-02-06)
### Bug fixes
Fix incorrect error raised for parenthesized simple assignment targets, so that `(x) = 1` parses again.
## 4.0.8 (2017-02-03)
### Bug fixes
Solve spurious parenthesized pattern errors by temporarily erring on the side of accepting programs that our delayed errors don't handle correctly yet.
## 4.0.7 (2017-02-02)
### Bug fixes
Accept invalidly rejected code like `(x).y = 2` again.
Don't raise an error when a function _inside_ strict code has a non-simple parameter list.
## 4.0.6 (2017-02-02)
### Bug fixes
Fix exponential behavior (manifesting itself as a complete hang for even relatively small source files) introduced by the new 'use strict' check.
## 4.0.5 (2017-02-02)
### Bug fixes
Disallow parenthesized pattern expressions.
Allow keywords as export names.
Don't allow the `async` keyword to be parenthesized.
Properly raise an error when a keyword contains a character escape.
Allow `"use strict"` to appear after other string literal expressions.
Disallow labeled declarations.
## 4.0.4 (2016-12-19)
### Bug fixes
Fix crash when `export` was followed by a keyword that can't be
exported.
## 4.0.3 (2016-08-16)
### Bug fixes
Allow regular function declarations inside single-statement `if` branches in loose mode. Forbid them entirely in strict mode.
Properly parse properties named `async` in ES2017 mode.
Fix bug where reserved words were broken in ES2017 mode.
## 4.0.2 (2016-08-11)
### Bug fixes
Don't ignore period or 'e' characters after octal numbers.
Fix broken parsing for call expressions in default parameter values of arrow functions.
## 4.0.1 (2016-08-08)
### Bug fixes
Fix false positives in duplicated export name errors.
## 4.0.0 (2016-08-07)
### Breaking changes
The default `ecmaVersion` option value is now 7.
A number of internal method signatures changed, so plugins might need to be updated.
### Bug fixes
The parser now raises errors on duplicated export names.
`arguments` and `eval` can now be used in shorthand properties.
Duplicate parameter names in non-simple argument lists now always produce an error.
### New features
The `ecmaVersion` option now also accepts year-style version numbers
(2015, etc).
Support for `async`/`await` syntax when `ecmaVersion` is >= 8.
Support for trailing commas in call expressions when `ecmaVersion` is >= 8.
## 3.3.0 (2016-07-25)
### Bug fixes
Fix bug in tokenizing of regexp operator after a function declaration.
Fix parser crash when parsing an array pattern with a hole.
### New features
Implement check against complex argument lists in functions that enable strict mode in ES7.
## 3.2.0 (2016-06-07)
### Bug fixes
Improve handling of lack of unicode regexp support in host
environment.
Properly reject shorthand properties whose name is a keyword.
### New features
Visitors created with `visit.make` now have their base as _prototype_, rather than copying properties into a fresh object.
## 3.1.0 (2016-04-18)
### Bug fixes
Properly tokenize the division operator directly after a function expression.
Allow trailing comma in destructuring arrays.
## 3.0.4 (2016-02-25)
### Fixes
Allow update expressions as left-hand-side of the ES7 exponential operator.
## 3.0.2 (2016-02-10)
### Fixes
Fix bug that accidentally made `undefined` a reserved word when parsing ES7.
## 3.0.0 (2016-02-10)
### Breaking changes
The default value of the `ecmaVersion` option is now 6 (used to be 5).
Support for comprehension syntax (which was dropped from the draft spec) has been removed.
### Fixes
`let` and `yield` are now “contextual keywords”, meaning you can mostly use them as identifiers in ES5 non-strict code.
A parenthesized class or function expression after `export default` is now parsed correctly.
### New features
When `ecmaVersion` is set to 7, Acorn will parse the exponentiation operator (`**`).
The identifier character ranges are now based on Unicode 8.0.0.
Plugins can now override the `raiseRecoverable` method to override the way non-critical errors are handled.
## 2.7.0 (2016-01-04)
### Fixes
Stop allowing rest parameters in setters.
Disallow `y` rexexp flag in ES5.
Disallow `\00` and `\000` escapes in strict mode.
Raise an error when an import name is a reserved word.
## 2.6.2 (2015-11-10)
### Fixes
Don't crash when no options object is passed.
## 2.6.0 (2015-11-09)
### Fixes
Add `await` as a reserved word in module sources.
Disallow `yield` in a parameter default value for a generator.
Forbid using a comma after a rest pattern in an array destructuring.
### New features
Support parsing stdin in command-line tool.
## 2.5.0 (2015-10-27)
### Fixes
Fix tokenizer support in the command-line tool.
Stop allowing `new.target` outside of functions.
Remove legacy `guard` and `guardedHandler` properties from try nodes.
Stop allowing multiple `__proto__` properties on an object literal in strict mode.
Don't allow rest parameters to be non-identifier patterns.
Check for duplicate paramter names in arrow functions.

View File

@@ -0,0 +1,270 @@
# Acorn
A tiny, fast JavaScript parser written in JavaScript.
## Community
Acorn is open source software released under an
[MIT license](https://github.com/acornjs/acorn/blob/master/acorn/LICENSE).
You are welcome to
[report bugs](https://github.com/acornjs/acorn/issues) or create pull
requests on [github](https://github.com/acornjs/acorn). For questions
and discussion, please use the
[Tern discussion forum](https://discuss.ternjs.net).
## Installation
The easiest way to install acorn is from [`npm`](https://www.npmjs.com/):
```sh
npm install acorn
```
Alternately, you can download the source and build acorn yourself:
```sh
git clone https://github.com/acornjs/acorn.git
cd acorn
npm install
```
## Interface
**parse**`(input, options)` is the main interface to the library. The
`input` parameter is a string, `options` can be undefined or an object
setting some of the options listed below. The return value will be an
abstract syntax tree object as specified by the [ESTree
spec](https://github.com/estree/estree).
```javascript
let acorn = require("acorn");
console.log(acorn.parse("1 + 1"));
```
When encountering a syntax error, the parser will raise a
`SyntaxError` object with a meaningful message. The error object will
have a `pos` property that indicates the string offset at which the
error occurred, and a `loc` object that contains a `{line, column}`
object referring to that same position.
Options can be provided by passing a second argument, which should be
an object containing any of these fields:
- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be
either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), 10 (2019) or 11
(2020, partial support). This influences support for strict mode,
the set of reserved words, and support for new syntax features.
Default is 10.
**NOTE**: Only 'stage 4' (finalized) ECMAScript features are being
implemented by Acorn. Other proposed new features can be implemented
through plugins.
- **sourceType**: Indicate 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.
**NOTE**: If set to `"module"`, then static `import` / `export` syntax
will be valid, even if `ecmaVersion` is less than 6.
- **onInsertedSemicolon**: If given a callback, that callback will be
called whenever a missing semicolon is inserted by the parser. The
callback will be given the character offset of the point where the
semicolon is inserted as argument, and if `locations` is on, also a
`{line, column}` object representing this position.
- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing
commas.
- **allowReserved**: If `false`, using a reserved word will generate
an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher
versions. When given the value `"never"`, reserved words and
keywords can also not be used as property names (as in Internet
Explorer's old parser).
- **allowReturnOutsideFunction**: By default, a return statement at
the top level raises an error. Set this to `true` to accept such
code.
- **allowImportExportEverywhere**: By default, `import` and `export`
declarations can only appear at a program's top level. Setting this
option to `true` allows them anywhere where a statement is allowed.
- **allowAwaitOutsideFunction**: By default, `await` expressions can
only appear inside `async` functions. Setting this option to
`true` allows to have top-level `await` expressions. They are
still not allowed in non-`async` functions, though.
- **allowHashBang**: When this is enabled (off by default), if the
code starts with the characters `#!` (as in a shellscript), the
first line will be treated as a comment.
- **locations**: When `true`, each node has a `loc` object attached
with `start` and `end` subobjects, each of which contains the
one-based line and zero-based column numbers in `{line, column}`
form. Default is `false`.
- **onToken**: If a function is passed for this option, each found
token will be passed in same format as tokens returned from
`tokenizer().getToken()`.
If array is passed, each found token is pushed to it.
Note that you are not allowed to call the parser from the
callback—that will corrupt its internal state.
- **onComment**: If a function is passed for this option, whenever a
comment is encountered the function will be called with the
following parameters:
- `block`: `true` if the comment is a block comment, false if it
is a line comment.
- `text`: The content of the comment.
- `start`: Character offset of the start of the comment.
- `end`: Character offset of the end of the comment.
When the `locations` options is on, the `{line, column}` locations
of the comments start and end are passed as two additional
parameters.
If array is passed for this option, each found comment is pushed
to it as object in Esprima format:
```javascript
{
"type": "Line" | "Block",
"value": "comment text",
"start": Number,
"end": Number,
// If `locations` option is on:
"loc": {
"start": {line: Number, column: Number}
"end": {line: Number, column: Number}
},
// If `ranges` option is on:
"range": [Number, Number]
}
```
Note that you are not allowed to call the parser from the
callback—that will corrupt its internal state.
- **ranges**: 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](https://bugzilla.mozilla.org/show_bug.cgi?id=745678)
`range` property holding a `[start, end]` array with the same
numbers, set the `ranges` option to `true`.
- **program**: It is possible to parse multiple files into a single
AST by passing the tree produced by parsing the first file as the
`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.
- **sourceFile**: When the `locations` option is `true`, you can pass
this option to add a `source` attribute in every nodes `loc`
object. Note that the contents of this option are not examined or
processed in any way; you are free to use whatever format you
choose.
- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property
will be added (regardless of the `location` option) directly to the
nodes, rather than the `loc` object.
- **preserveParens**: If this option is `true`, parenthesized expressions
are represented by (non-standard) `ParenthesizedExpression` nodes
that have a single `expression` property containing the expression
inside parentheses.
**parseExpressionAt**`(input, offset, options)` will parse a single
expression in a string, and return its AST. It will not complain if
there is more of the string left after the expression.
**tokenizer**`(input, options)` returns an object with a `getToken`
method that can be called repeatedly to get the next token, a `{start,
end, type, value}` object (with added `loc` property when the
`locations` option is enabled and `range` property when the `ranges`
option is enabled). When the token's type is `tokTypes.eof`, you
should stop calling the method, since it will keep returning that same
token forever.
In ES6 environment, returned result can be used as any other
protocol-compliant iterable:
```javascript
for (let token of acorn.tokenizer(str)) {
// iterate over the tokens
}
// transform code to array of tokens:
var tokens = [...acorn.tokenizer(str)];
```
**tokTypes** holds an object mapping names to the token type objects
that end up in the `type` properties of tokens.
**getLineInfo**`(input, offset)` can be used to get a `{line,
column}` object for a given program string and offset.
### The `Parser` class
Instances of the **`Parser`** class contain all the state and logic
that drives a parse. It has static methods `parse`,
`parseExpressionAt`, and `tokenizer` that match the top-level
functions by the same name.
When extending the parser with plugins, you need to call these methods
on the extended version of the class. To extend a parser with plugins,
you can use its static `extend` method.
```javascript
var acorn = require("acorn");
var jsx = require("acorn-jsx");
var JSXParser = acorn.Parser.extend(jsx());
JSXParser.parse("foo(<bar/>)");
```
The `extend` method takes any number of plugin values, and returns a
new `Parser` class that includes the extra parser logic provided by
the plugins.
## Command line interface
The `bin/acorn` utility can be used to parse a file from the command
line. It accepts as arguments its input file and the following
options:
- `--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|--ecma10`: Sets the ECMAScript version
to parse. Default is version 9.
- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise.
- `--locations`: Attaches a "loc" object to each node with "start" and
"end" subobjects, each of which contains the one-based line and
zero-based column numbers in `{line, column}` form.
- `--allow-hash-bang`: If the code starts with the characters #! (as
in a shellscript), the first line will be treated as a comment.
- `--compact`: No whitespace is used in the AST output.
- `--silent`: Do not output the AST, just return the exit status.
- `--help`: Print the usage information and quit.
The utility spits out the syntax tree as JSON data.
## Existing plugins
- [`acorn-jsx`](https://github.com/RReverser/acorn-jsx): Parse [Facebook JSX syntax extensions](https://github.com/facebook/jsx)
Plugins for ECMAScript proposals:
- [`acorn-stage3`](https://github.com/acornjs/acorn-stage3): Parse most stage 3 proposals, bundling:
- [`acorn-class-fields`](https://github.com/acornjs/acorn-class-fields): Parse [class fields proposal](https://github.com/tc39/proposal-class-fields)
- [`acorn-import-meta`](https://github.com/acornjs/acorn-import-meta): Parse [import.meta proposal](https://github.com/tc39/proposal-import-meta)
- [`acorn-numeric-separator`](https://github.com/acornjs/acorn-numeric-separator): Parse [numeric separator proposal](https://github.com/tc39/proposal-numeric-separator)
- [`acorn-private-methods`](https://github.com/acornjs/acorn-private-methods): parse [private methods, getters and setters proposal](https://github.com/tc39/proposal-private-methods)n

View File

@@ -2,50 +2,28 @@
"name": "acorn",
"description": "ECMAScript parser",
"homepage": "https://github.com/acornjs/acorn",
"main": "src/index.js",
"version": "5.5.3",
"engines": {
"node": ">=0.4.0"
},
"module": "src/index.js",
"version": "7.1.1",
"engines": {"node": ">=0.4.0"},
"maintainers": [
{
"name": "Marijn Haverbeke",
"email": "marijnh@gmail.com",
"web": "http://marijnhaverbeke.nl"
"web": "https://marijnhaverbeke.nl"
},
{
"name": "Ingvar Stepanyan",
"email": "me@rreverser.com",
"web": "http://rreverser.com/"
"web": "https://rreverser.com/"
},
{
"name": "Adrian Heine",
"web": "http://adrianheine.de"
}
],
"repository": {
"type": "git",
"url": "https://github.com/acornjs/acorn.git"
},
"license": "MIT",
"scripts": {
"prepare": "npm test",
"test": "node test/run.js && node test/lint.js",
"pretest": "npm run build:main && npm run build:loose",
"test:test262": "node bin/run_test262.js",
"build": "npm run build:main && npm run build:walk && npm run build:loose && npm run build:bin",
"build:main": "rollup -c rollup/config.main.js",
"build:walk": "rollup -c rollup/config.walk.js",
"build:loose": "rollup -c rollup/config.loose.js && rollup -c rollup/config.loose_es.js",
"lint": "eslint src/"
},
"devDependencies": {
"eslint": "^4.10.0",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-node": "^5.2.1",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1",
"rollup": "^0.45.0",
"rollup-plugin-buble": "^0.16.0",
"test262": "git+https://github.com/tc39/test262.git#18c1e799a01cc976695983b61e225ce7959bdd91",
"test262-parser-runner": "^0.3.1",
"unicode-10.0.0": "^0.7.5"
}
"license": "MIT"
}

View File

@@ -7,8 +7,8 @@
],
"rules": {
"curly": "off",
"eqeqeq": "off",
"indent": ["error", 2, { "SwitchCase": 0, "VariableDeclarator": 2, "CallExpression": { arguments: "off" } }],
"eqeqeq": ["error", "always", { "null": "ignore" }],
"indent": ["error", 2, { "SwitchCase": 0, "VariableDeclarator": 2, "CallExpression": { "arguments": "off" } }],
"new-parens": "off",
"no-case-declarations": "off",
"no-cond-assign": "off",
@@ -25,7 +25,8 @@
"space-before-function-paren": ["error", "never"]
},
"globals": {
"Packages": false
"Packages": false,
"BigInt": false
},
"plugins": [
"import"

View File

@@ -6,7 +6,7 @@ let infile, forceFile, silent = false, compact = false, tokenize = false
const options = {}
function help(status) {
const print = (status == 0) ? console.log : console.error
const print = (status === 0) ? console.log : console.error
print("usage: " + basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|...|--ecma2015|--ecma2016|--ecma2017|--ecma2018|...]")
print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]")
process.exit(status)
@@ -14,15 +14,15 @@ function help(status) {
for (let i = 2; i < process.argv.length; ++i) {
const arg = process.argv[i]
if ((arg == "-" || arg[0] != "-") && !infile) infile = arg
else if (arg == "--" && !infile && i + 2 == process.argv.length) forceFile = infile = process.argv[++i]
else if (arg == "--locations") options.locations = true
else if (arg == "--allow-hash-bang") options.allowHashBang = true
else if (arg == "--silent") silent = true
else if (arg == "--compact") compact = true
else if (arg == "--help") help(0)
else if (arg == "--tokenize") tokenize = true
else if (arg == "--module") options.sourceType = "module"
if ((arg === "-" || arg[0] !== "-") && !infile) infile = arg
else if (arg === "--" && !infile && i + 2 === process.argv.length) forceFile = infile = process.argv[++i]
else if (arg === "--locations") options.locations = true
else if (arg === "--allow-hash-bang") options.allowHashBang = true
else if (arg === "--silent") silent = true
else if (arg === "--compact") compact = true
else if (arg === "--help") help(0)
else if (arg === "--tokenize") tokenize = true
else if (arg === "--module") options.sourceType = "module"
else {
let match = arg.match(/^--ecma(\d+)$/)
if (match)
@@ -43,16 +43,16 @@ function run(code) {
do {
token = tokenizer.getToken()
result.push(token)
} while (token.type != acorn.tokTypes.eof)
} while (token.type !== acorn.tokTypes.eof)
}
} catch (e) {
console.error(e.message)
console.error(infile && infile !== "-" ? e.message.replace(/\(\d+:\d+\)$/, m => m.slice(0, 1) + infile + " " + m.slice(1)) : e.message)
process.exit(1)
}
if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2))
}
if (forceFile || infile && infile != "-") {
if (forceFile || infile && infile !== "-") {
run(readFile(infile, "utf8"))
} else {
let code = ""

View File

@@ -20,6 +20,7 @@ import {types as tt} from "./tokentype"
import {Parser} from "./state"
import {DestructuringErrors} from "./parseutil"
import {lineBreak} from "./whitespace"
import {functionFlags, SCOPE_ARROW, SCOPE_SUPER, SCOPE_DIRECT_SUPER, BIND_OUTSIDE, BIND_VAR} from "./scopeflags"
const pp = Parser.prototype
@@ -43,9 +44,11 @@ pp.checkPropClash = function(prop, propHash, refDestructuringErrors) {
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")
if (refDestructuringErrors) {
if (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")
}
propHash.proto = true
}
@@ -103,7 +106,12 @@ pp.parseExpression = function(noIn, refDestructuringErrors) {
// operators like `+=`.
pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
if (this.inGenerator && this.isContextual("yield")) return this.parseYield()
if (this.isContextual("yield")) {
if (this.inGenerator) return this.parseYield(noIn)
// The tokenizer will assume an expression is allowed after
// `yield`, but this isn't that kind of yield
else this.exprAllowed = false
}
let ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1
if (refDestructuringErrors) {
@@ -116,7 +124,7 @@ pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
}
let startPos = this.start, startLoc = this.startLoc
if (this.type == tt.parenL || this.type == tt.name)
if (this.type === tt.parenL || this.type === tt.name)
this.potentialArrowAt = this.start
let left = this.parseMaybeConditional(noIn, refDestructuringErrors)
if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc)
@@ -124,8 +132,11 @@ pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
let node = this.startNodeAt(startPos, startLoc)
node.operator = this.value
node.left = this.type === tt.eq ? this.toAssignable(left, false, refDestructuringErrors) : left
if (!ownDestructuringErrors) DestructuringErrors.call(refDestructuringErrors)
refDestructuringErrors.shorthandAssign = -1 // reset because shorthand default was used correctly
if (!ownDestructuringErrors) {
refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1
}
if (refDestructuringErrors.shorthandAssign >= node.left.start)
refDestructuringErrors.shorthandAssign = -1 // reset because shorthand default was used correctly
this.checkLVal(left)
this.next()
node.right = this.parseMaybeAssign(noIn)
@@ -161,7 +172,7 @@ pp.parseExprOps = function(noIn, refDestructuringErrors) {
let startPos = this.start, startLoc = this.startLoc
let 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)
return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
}
// Parse binary operators with the operator precedence parsing
@@ -198,7 +209,7 @@ pp.buildBinary = function(startPos, startLoc, left, right, op, logical) {
pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
let startPos = this.start, startLoc = this.startLoc, expr
if (this.inAsync && this.isContextual("await")) {
if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) {
expr = this.parseAwait()
sawUnary = true
} else if (this.type.prefix) {
@@ -239,8 +250,8 @@ pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
pp.parseExprSubscripts = function(refDestructuringErrors) {
let startPos = this.start, startLoc = this.startLoc
let expr = this.parseExprAtom(refDestructuringErrors)
let skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"
if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr
if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
return expr
let result = this.parseSubscripts(expr, startPos, startLoc)
if (refDestructuringErrors && result.type === "MemberExpression") {
if (refDestructuringErrors.parenthesizedAssign >= result.start) refDestructuringErrors.parenthesizedAssign = -1
@@ -251,64 +262,82 @@ pp.parseExprSubscripts = function(refDestructuringErrors) {
pp.parseSubscripts = function(base, startPos, startLoc, noCalls) {
let 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 (let computed;;) {
if ((computed = this.eat(tt.bracketL)) || this.eat(tt.dot)) {
let node = this.startNodeAt(startPos, startLoc)
node.object = base
node.property = computed ? this.parseExpression() : this.parseIdent(true)
node.computed = !!computed
if (computed) this.expect(tt.bracketR)
base = this.finishNode(node, "MemberExpression")
} else if (!noCalls && this.eat(tt.parenL)) {
let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos
this.yieldPos = 0
this.awaitPos = 0
let exprList = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors)
if (maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
this.checkPatternErrors(refDestructuringErrors, false)
this.checkYieldAwaitInDefaultParams()
this.yieldPos = oldYieldPos
this.awaitPos = oldAwaitPos
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true)
}
this.checkExpressionErrors(refDestructuringErrors, true)
this.yieldPos = oldYieldPos || this.yieldPos
this.awaitPos = oldAwaitPos || this.awaitPos
let node = this.startNodeAt(startPos, startLoc)
node.callee = base
node.arguments = exprList
base = this.finishNode(node, "CallExpression")
} else if (this.type === tt.backQuote) {
let node = this.startNodeAt(startPos, startLoc)
node.tag = base
node.quasi = this.parseTemplate({isTagged: true})
base = this.finishNode(node, "TaggedTemplateExpression")
} else {
return base
}
this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 &&
this.potentialArrowAt === base.start
while (true) {
let element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow)
if (element === base || element.type === "ArrowFunctionExpression") return element
base = element
}
}
pp.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow) {
let computed = this.eat(tt.bracketL)
if (computed || this.eat(tt.dot)) {
let node = this.startNodeAt(startPos, startLoc)
node.object = base
node.property = computed ? this.parseExpression() : this.parseIdent(this.options.allowReserved !== "never")
node.computed = !!computed
if (computed) this.expect(tt.bracketR)
base = this.finishNode(node, "MemberExpression")
} else if (!noCalls && this.eat(tt.parenL)) {
let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos
this.yieldPos = 0
this.awaitPos = 0
this.awaitIdentPos = 0
let exprList = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors)
if (maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
this.checkPatternErrors(refDestructuringErrors, false)
this.checkYieldAwaitInDefaultParams()
if (this.awaitIdentPos > 0)
this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function")
this.yieldPos = oldYieldPos
this.awaitPos = oldAwaitPos
this.awaitIdentPos = oldAwaitIdentPos
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true)
}
this.checkExpressionErrors(refDestructuringErrors, true)
this.yieldPos = oldYieldPos || this.yieldPos
this.awaitPos = oldAwaitPos || this.awaitPos
this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos
let node = this.startNodeAt(startPos, startLoc)
node.callee = base
node.arguments = exprList
base = this.finishNode(node, "CallExpression")
} else if (this.type === tt.backQuote) {
let node = this.startNodeAt(startPos, startLoc)
node.tag = base
node.quasi = this.parseTemplate({isTagged: true})
base = this.finishNode(node, "TaggedTemplateExpression")
}
return base
}
// Parse an atomic expression — either a single token that is an
// expression, an expression started by a keyword like `function` or
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
// or `{}`.
pp.parseExprAtom = function(refDestructuringErrors) {
let node, canBeArrow = this.potentialArrowAt == this.start
// If a division operator appears in an expression position, the
// tokenizer got confused, and we force it to read a regexp instead.
if (this.type === tt.slash) this.readRegexp()
let node, canBeArrow = this.potentialArrowAt === this.start
switch (this.type) {
case tt._super:
if (!this.inFunction)
this.raise(this.start, "'super' outside of function or class")
if (!this.allowSuper)
this.raise(this.start, "'super' keyword outside a method")
node = this.startNode()
this.next()
if (this.type === tt.parenL && !this.allowDirectSuper)
this.raise(node.start, "super() call outside constructor of a subclass")
// The `super` keyword can appear at below:
// SuperProperty:
// super [ Expression ]
// super . IdentifierName
// SuperCall:
// super Arguments
// super ( Arguments )
if (this.type !== tt.dot && this.type !== tt.bracketL && this.type !== tt.parenL)
this.unexpected()
return this.finishNode(node, "Super")
@@ -320,14 +349,14 @@ pp.parseExprAtom = function(refDestructuringErrors) {
case tt.name:
let startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc
let id = this.parseIdent(this.type !== tt.name)
let id = this.parseIdent(false)
if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(tt._function))
return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true)
return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true)
if (canBeArrow && !this.canInsertSemicolon()) {
if (this.eat(tt.arrow))
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false)
if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === tt.name && !containsEsc) {
id = this.parseIdent()
id = this.parseIdent(false)
if (this.canInsertSemicolon() || !this.eat(tt.arrow))
this.unexpected()
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
@@ -373,7 +402,7 @@ pp.parseExprAtom = function(refDestructuringErrors) {
case tt._function:
node = this.startNode()
this.next()
return this.parseFunction(node, false)
return this.parseFunction(node, 0)
case tt._class:
return this.parseClass(this.startNode(), false)
@@ -384,15 +413,53 @@ pp.parseExprAtom = function(refDestructuringErrors) {
case tt.backQuote:
return this.parseTemplate()
case tt._import:
if (this.options.ecmaVersion >= 11) {
return this.parseExprImport()
} else {
return this.unexpected()
}
default:
this.unexpected()
}
}
pp.parseExprImport = function() {
const node = this.startNode()
this.next() // skip `import`
switch (this.type) {
case tt.parenL:
return this.parseDynamicImport(node)
default:
this.unexpected()
}
}
pp.parseDynamicImport = function(node) {
this.next() // skip `(`
// Parse node.source.
node.source = this.parseMaybeAssign()
// Verify ending.
if (!this.eat(tt.parenR)) {
const errorPos = this.start
if (this.eat(tt.comma) && this.eat(tt.parenR)) {
this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()")
} else {
this.unexpected(errorPos)
}
}
return this.finishNode(node, "ImportExpression")
}
pp.parseLiteral = function(value) {
let node = this.startNode()
node.value = value
node.raw = this.input.slice(this.start, this.end)
if (node.raw.charCodeAt(node.raw.length - 1) === 110) node.bigint = node.raw.slice(0, -1)
this.next()
return this.finishNode(node, "Literal")
}
@@ -414,6 +481,7 @@ pp.parseParenAndDistinguishExpression = function(canBeArrow) {
let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart
this.yieldPos = 0
this.awaitPos = 0
// Do not save awaitIdentPos to allow checking awaits nested in parameters
while (this.type !== tt.parenR) {
first ? first = false : this.expect(tt.comma)
if (allowTrailingComma && this.afterTrailingComma(tt.parenR, true)) {
@@ -482,6 +550,7 @@ pp.parseParenArrowList = function(startPos, startLoc, exprList) {
const empty = []
pp.parseNew = function() {
if (this.containsEsc) this.raiseRecoverable(this.start, "Escape sequence in keyword new")
let node = this.startNode()
let meta = this.parseIdent(true)
if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) {
@@ -490,12 +559,15 @@ pp.parseNew = function() {
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)
if (!this.inNonArrowFunction())
this.raiseRecoverable(node.start, "new.target can only be used in functions")
return this.finishNode(node, "MetaProperty")
}
let startPos = this.start, startLoc = this.startLoc
let startPos = this.start, startLoc = this.startLoc, isImport = this.type === tt._import
node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true)
if (isImport && node.callee.type === "ImportExpression") {
this.raise(startPos, "Cannot use new with import()")
}
if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false)
else node.arguments = empty
return this.finishNode(node, "NewExpression")
@@ -531,6 +603,7 @@ pp.parseTemplate = function({isTagged = false} = {}) {
let curElt = this.parseTemplateElement({isTagged})
node.quasis = [curElt]
while (!curElt.tail) {
if (this.type === tt.eof) this.raise(this.pos, "Unterminated template literal")
this.expect(tt.dollarBraceL)
node.expressions.push(this.parseExpression())
this.expect(tt.braceR)
@@ -555,7 +628,7 @@ pp.parseObj = function(isPattern, refDestructuringErrors) {
while (!this.eat(tt.braceR)) {
if (!first) {
this.expect(tt.comma)
if (this.afterTrailingComma(tt.braceR)) break
if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(tt.braceR)) break
} else first = false
const prop = this.parseProperty(isPattern, refDestructuringErrors)
@@ -631,7 +704,7 @@ pp.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos
} else if (!isPattern && !containsEsc &&
this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
(prop.key.name === "get" || prop.key.name === "set") &&
(this.type != tt.comma && this.type != tt.braceR)) {
(this.type !== tt.comma && this.type !== tt.braceR)) {
if (isGenerator || isAsync) this.unexpected()
prop.kind = prop.key.name
this.parsePropertyName(prop)
@@ -648,7 +721,10 @@ pp.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos
this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params")
}
} else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
if (isGenerator || isAsync) this.unexpected()
this.checkUnreserved(prop.key)
if (prop.key.name === "await" && !this.awaitIdentPos)
this.awaitIdentPos = startPos
prop.kind = "init"
if (isPattern) {
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key)
@@ -674,26 +750,21 @@ pp.parsePropertyName = function(prop) {
prop.computed = false
}
}
return prop.key = this.type === tt.num || this.type === tt.string ? this.parseExprAtom() : this.parseIdent(true)
return prop.key = this.type === tt.num || this.type === tt.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never")
}
// Initialize empty function node.
pp.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
if (this.options.ecmaVersion >= 6) node.generator = node.expression = false
if (this.options.ecmaVersion >= 8) node.async = false
}
// Parse object or class method.
pp.parseMethod = function(isGenerator, isAsync) {
let node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync,
oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction
pp.parseMethod = function(isGenerator, isAsync, allowDirectSuper) {
let node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos
this.initFunction(node)
if (this.options.ecmaVersion >= 6)
@@ -701,57 +772,47 @@ pp.parseMethod = function(isGenerator, isAsync) {
if (this.options.ecmaVersion >= 8)
node.async = !!isAsync
this.inGenerator = node.generator
this.inAsync = node.async
this.yieldPos = 0
this.awaitPos = 0
this.inFunction = true
this.enterFunctionScope()
this.awaitIdentPos = 0
this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0))
this.expect(tt.parenL)
node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8)
this.checkYieldAwaitInDefaultParams()
this.parseFunctionBody(node, false)
this.parseFunctionBody(node, false, true)
this.inGenerator = oldInGen
this.inAsync = oldInAsync
this.yieldPos = oldYieldPos
this.awaitPos = oldAwaitPos
this.inFunction = oldInFunc
this.awaitIdentPos = oldAwaitIdentPos
return this.finishNode(node, "FunctionExpression")
}
// Parse arrow function expression with given parameters.
pp.parseArrowExpression = function(node, params, isAsync) {
let oldInGen = this.inGenerator, oldInAsync = this.inAsync,
oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction
let oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos
this.enterFunctionScope()
this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW)
this.initFunction(node)
if (this.options.ecmaVersion >= 8)
node.async = !!isAsync
if (this.options.ecmaVersion >= 8) node.async = !!isAsync
this.inGenerator = false
this.inAsync = node.async
this.yieldPos = 0
this.awaitPos = 0
this.inFunction = true
this.awaitIdentPos = 0
node.params = this.toAssignableList(params, true)
this.parseFunctionBody(node, true)
this.parseFunctionBody(node, true, false)
this.inGenerator = oldInGen
this.inAsync = oldInAsync
this.yieldPos = oldYieldPos
this.awaitPos = oldAwaitPos
this.inFunction = oldInFunc
this.awaitIdentPos = oldAwaitIdentPos
return this.finishNode(node, "ArrowFunctionExpression")
}
// Parse function body and check parameters.
pp.parseFunctionBody = function(node, isArrowFunction) {
pp.parseFunctionBody = function(node, isArrowFunction, isMethod) {
let isExpression = isArrowFunction && this.type !== tt.braceL
let oldStrict = this.strict, useStrict = false
@@ -777,19 +838,15 @@ pp.parseFunctionBody = function(node, isArrowFunction) {
// 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)
this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params))
// Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
if (this.strict && node.id) this.checkLVal(node.id, BIND_OUTSIDE)
node.body = this.parseBlock(false, undefined, useStrict && !oldStrict)
node.expression = false
this.adaptDirectivePrologue(node.body.body)
this.labels = oldLabels
}
this.exitFunctionScope()
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
this.exitScope()
}
pp.isSimpleParamList = function(params) {
@@ -804,7 +861,7 @@ pp.isSimpleParamList = function(params) {
pp.checkParams = function(node, allowDuplicates) {
let nameHash = {}
for (let param of node.params)
this.checkLVal(param, "var", allowDuplicates ? null : nameHash)
this.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash)
}
// Parses a comma-separated list of expressions, and returns them as
@@ -838,17 +895,17 @@ pp.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructur
pp.checkUnreserved = function({start, end, name}) {
if (this.inGenerator && name === "yield")
this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator")
this.raiseRecoverable(start, "Cannot 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.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function")
if (this.keywords.test(name))
this.raise(start, `Unexpected keyword '${name}'`)
if (this.options.ecmaVersion < 6 &&
this.input.slice(start, end).indexOf("\\") != -1) return
this.input.slice(start, end).indexOf("\\") !== -1) return
const 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, "Cannot use keyword 'await' outside an async function")
this.raiseRecoverable(start, `The keyword '${name}' is reserved`)
}
}
@@ -859,7 +916,6 @@ pp.checkUnreserved = function({start, end, name}) {
pp.parseIdent = function(liberal, isBinding) {
let node = this.startNode()
if (liberal && this.options.allowReserved == "never") liberal = false
if (this.type === tt.name) {
node.name = this.value
} else if (this.type.keyword) {
@@ -876,25 +932,29 @@ pp.parseIdent = function(liberal, isBinding) {
} else {
this.unexpected()
}
this.next()
this.next(!!liberal)
this.finishNode(node, "Identifier")
if (!liberal) this.checkUnreserved(node)
if (!liberal) {
this.checkUnreserved(node)
if (node.name === "await" && !this.awaitIdentPos)
this.awaitIdentPos = node.start
}
return node
}
// Parses yield expression inside generator.
pp.parseYield = function() {
pp.parseYield = function(noIn) {
if (!this.yieldPos) this.yieldPos = this.start
let node = this.startNode()
this.next()
if (this.type == tt.semi || this.canInsertSemicolon() || (this.type != tt.star && !this.type.startsExpr)) {
if (this.type === tt.semi || this.canInsertSemicolon() || (this.type !== tt.star && !this.type.startsExpr)) {
node.delegate = false
node.argument = null
} else {
node.delegate = this.eat(tt.star)
node.argument = this.parseMaybeAssign()
node.argument = this.parseMaybeAssign(noIn)
}
return this.finishNode(node, "YieldExpression")
}
@@ -904,6 +964,6 @@ pp.parseAwait = function() {
let node = this.startNode()
this.next()
node.argument = this.parseMaybeUnary(null, true)
node.argument = this.parseMaybeUnary(null, false)
return this.finishNode(node, "AwaitExpression")
}

View File

@@ -14,6 +14,7 @@ const ecma5AndLessKeywords = "break case catch continue debugger default do else
export const keywords = {
5: ecma5AndLessKeywords,
"5module": ecma5AndLessKeywords + " export import",
6: ecma5AndLessKeywords + " const class extends export import super"
}
@@ -26,9 +27,8 @@ export const keywordRelationalOperator = /^in(stanceof)?$/
// are only applied when a character is found to actually have a
// code point above 128.
// Generated by `bin/generate-identifier-regex.js`.
let 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\u0860-\u086a\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\u09fc\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-\u312e\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fea\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"
let 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\u0afa-\u0aff\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\u0d00-\u0d03\u0d3b\u0d3c\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\u1cf7-\u1cf9\u1dc0-\u1df9\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"
let 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\u0560-\u0588\u05d0-\u05ea\u05ef-\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\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\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\u09fc\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\u0d04-\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\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\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-\u1878\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\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\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-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\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-\uab69\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"
let 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\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\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\u09fe\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\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\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\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\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\u1abf\u1ac0\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\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\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\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\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"
const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]")
const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]")
@@ -42,10 +42,10 @@ nonASCIIidentifierStartChars = nonASCIIidentifierChars = null
// generated by bin/generate-identifier-regex.js
// eslint-disable-next-line comma-spacing
const astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,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,257,0,11,39,8,0,22,0,12,39,3,3,55,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,698,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,1,31,6124,20,754,9486,286,82,395,2309,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,15,7472,3104,541]
const astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,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,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,349,41,7,1,79,28,11,0,9,21,107,20,28,22,13,52,76,44,33,24,27,35,30,0,3,0,9,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,21,2,31,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,7,3,0,3,7,2,1,2,23,16,0,2,0,95,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,190,0,80,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,1237,43,8,8952,286,50,2,18,3,9,395,2309,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,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,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,42717,35,4148,12,221,3,5761,15,7472,3104,541,1507,4938]
// eslint-disable-next-line comma-spacing
const 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,280,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,19719,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]
const astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,370,1,154,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,2,11,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,71,5,2,1,3,3,2,0,2,1,13,9,120,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,82,0,12,1,19628,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,262,6,10,9,419,13,1495,6,110,6,6,9,4759,9,787719,239]
// This has a complexity linear to the value of the code. The
// assumption is that looking up astral identifier characters is

View File

@@ -12,11 +12,6 @@
//
// [ghbt]: https://github.com/acornjs/acorn/issues
//
// This file defines the main parser interface. The library also comes
// with a [error-tolerant parser][dammit] and an
// [abstract syntax tree walker][walk], defined in other files.
//
// [dammit]: acorn_loose.js
// [walk]: util/walk.js
import {Parser} from "./state"
@@ -27,17 +22,58 @@ import "./expression"
import "./location"
import "./scope"
export {Parser, plugins} from "./state"
export {defaultOptions} from "./options"
export {Position, SourceLocation, getLineInfo} from "./locutil"
export {Node} from "./node"
export {TokenType, types as tokTypes, keywords as keywordTypes} from "./tokentype"
export {TokContext, types as tokContexts} from "./tokencontext"
export {isIdentifierChar, isIdentifierStart} from "./identifier"
export {Token} from "./tokenize"
export {isNewLine, lineBreak, lineBreakG, nonASCIIwhitespace} from "./whitespace"
import {defaultOptions} from "./options"
import {Position, SourceLocation, getLineInfo} from "./locutil"
import {Node} from "./node"
import {TokenType, types as tokTypes, keywords as keywordTypes} from "./tokentype"
import {TokContext, types as tokContexts} from "./tokencontext"
import {isIdentifierChar, isIdentifierStart} from "./identifier"
import {Token} from "./tokenize"
import {isNewLine, lineBreak, lineBreakG, nonASCIIwhitespace} from "./whitespace"
export const version = "5.5.3"
export const version = "7.1.0"
export {
Parser,
defaultOptions,
Position,
SourceLocation,
getLineInfo,
Node,
TokenType,
tokTypes,
keywordTypes,
TokContext,
tokContexts,
isIdentifierChar,
isIdentifierStart,
Token,
isNewLine,
lineBreak,
lineBreakG,
nonASCIIwhitespace
}
Parser.acorn = {
Parser,
version,
defaultOptions,
Position,
SourceLocation,
getLineInfo,
Node,
TokenType,
tokTypes,
keywordTypes,
TokContext,
tokContexts,
isIdentifierChar,
isIdentifierStart,
Token,
isNewLine,
lineBreak,
lineBreakG,
nonASCIIwhitespace
}
// The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and
@@ -47,7 +83,7 @@ export const version = "5.5.3"
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
export function parse(input, options) {
return new Parser(options, input).parse()
return Parser.parse(input, options)
}
// This function tries to parse a single expression at a given
@@ -55,24 +91,12 @@ export function parse(input, options) {
// that embed JavaScript expressions.
export function parseExpressionAt(input, pos, options) {
let p = new Parser(options, input, pos)
p.nextToken()
return p.parseExpression()
return Parser.parseExpressionAt(input, pos, options)
}
// Acorn is organized as a tokenizer and a recursive-descent parser.
// The `tokenizer` export provides an interface to the tokenizer.
export function tokenizer(input, options) {
return new Parser(options, input)
}
// This is a terrible kludge to support the existing, pre-ES6
// interface where the loose parser module retroactively adds exports
// to this module.
export let parse_dammit, LooseParser, pluginsLoose // eslint-disable-line camelcase
export function addLooseExports(parse, Parser, plugins) {
parse_dammit = parse // eslint-disable-line camelcase
LooseParser = Parser
pluginsLoose = plugins
return Parser.tokenizer(input, options)
}

View File

@@ -1,582 +0,0 @@
import {LooseParser} from "./state"
import {isDummy} from "./parseutil"
import {tokTypes as tt} from "../index"
const lp = LooseParser.prototype
lp.checkLVal = function(expr) {
if (!expr) return expr
switch (expr.type) {
case "Identifier":
case "MemberExpression":
return expr
case "ParenthesizedExpression":
expr.expression = this.checkLVal(expr.expression)
return expr
default:
return this.dummyIdent()
}
}
lp.parseExpression = function(noIn) {
let start = this.storeCurrentPos()
let expr = this.parseMaybeAssign(noIn)
if (this.tok.type === tt.comma) {
let node = this.startNodeAt(start)
node.expressions = [expr]
while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn))
return this.finishNode(node, "SequenceExpression")
}
return expr
}
lp.parseParenExpression = function() {
this.pushCx()
this.expect(tt.parenL)
let val = this.parseExpression()
this.popCx()
this.expect(tt.parenR)
return val
}
lp.parseMaybeAssign = function(noIn) {
if (this.toks.isContextual("yield")) {
let node = this.startNode()
this.next()
if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type != tt.star && !this.tok.type.startsExpr)) {
node.delegate = false
node.argument = null
} else {
node.delegate = this.eat(tt.star)
node.argument = this.parseMaybeAssign()
}
return this.finishNode(node, "YieldExpression")
}
let start = this.storeCurrentPos()
let left = this.parseMaybeConditional(noIn)
if (this.tok.type.isAssign) {
let node = this.startNodeAt(start)
node.operator = this.tok.value
node.left = this.tok.type === tt.eq ? this.toAssignable(left) : this.checkLVal(left)
this.next()
node.right = this.parseMaybeAssign(noIn)
return this.finishNode(node, "AssignmentExpression")
}
return left
}
lp.parseMaybeConditional = function(noIn) {
let start = this.storeCurrentPos()
let expr = this.parseExprOps(noIn)
if (this.eat(tt.question)) {
let node = this.startNodeAt(start)
node.test = expr
node.consequent = this.parseMaybeAssign()
node.alternate = this.expect(tt.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent()
return this.finishNode(node, "ConditionalExpression")
}
return expr
}
lp.parseExprOps = function(noIn) {
let start = this.storeCurrentPos()
let indent = this.curIndent, line = this.curLineStart
return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line)
}
lp.parseExprOp = function(left, start, minPrec, noIn, indent, line) {
if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) return left
let prec = this.tok.type.binop
if (prec != null && (!noIn || this.tok.type !== tt._in)) {
if (prec > minPrec) {
let node = this.startNodeAt(start)
node.left = left
node.operator = this.tok.value
this.next()
if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) {
node.right = this.dummyIdent()
} else {
let rightStart = this.storeCurrentPos()
node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line)
}
this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression")
return this.parseExprOp(node, start, minPrec, noIn, indent, line)
}
}
return left
}
lp.parseMaybeUnary = function(sawUnary) {
let start = this.storeCurrentPos(), expr
if (this.options.ecmaVersion >= 8 && this.inAsync && this.toks.isContextual("await")) {
expr = this.parseAwait()
sawUnary = true
} else if (this.tok.type.prefix) {
let node = this.startNode(), update = this.tok.type === tt.incDec
if (!update) sawUnary = true
node.operator = this.tok.value
node.prefix = true
this.next()
node.argument = this.parseMaybeUnary(true)
if (update) node.argument = this.checkLVal(node.argument)
expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression")
} else if (this.tok.type === tt.ellipsis) {
let node = this.startNode()
this.next()
node.argument = this.parseMaybeUnary(sawUnary)
expr = this.finishNode(node, "SpreadElement")
} else {
expr = this.parseExprSubscripts()
while (this.tok.type.postfix && !this.canInsertSemicolon()) {
let node = this.startNodeAt(start)
node.operator = this.tok.value
node.prefix = false
node.argument = this.checkLVal(expr)
this.next()
expr = this.finishNode(node, "UpdateExpression")
}
}
if (!sawUnary && this.eat(tt.starstar)) {
let node = this.startNodeAt(start)
node.operator = "**"
node.left = expr
node.right = this.parseMaybeUnary(false)
return this.finishNode(node, "BinaryExpression")
}
return expr
}
lp.parseExprSubscripts = function() {
let start = this.storeCurrentPos()
return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart)
}
lp.parseSubscripts = function(base, start, noCalls, startIndent, line) {
for (;;) {
if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine()) {
if (this.tok.type == tt.dot && this.curIndent == startIndent)
--startIndent
else
return base
}
let maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon()
if (this.eat(tt.dot)) {
let node = this.startNodeAt(start)
node.object = base
if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine())
node.property = this.dummyIdent()
else
node.property = this.parsePropertyAccessor() || this.dummyIdent()
node.computed = false
base = this.finishNode(node, "MemberExpression")
} else if (this.tok.type == tt.bracketL) {
this.pushCx()
this.next()
let node = this.startNodeAt(start)
node.object = base
node.property = this.parseExpression()
node.computed = true
this.popCx()
this.expect(tt.bracketR)
base = this.finishNode(node, "MemberExpression")
} else if (!noCalls && this.tok.type == tt.parenL) {
let exprList = this.parseExprList(tt.parenR)
if (maybeAsyncArrow && this.eat(tt.arrow))
return this.parseArrowExpression(this.startNodeAt(start), exprList, true)
let node = this.startNodeAt(start)
node.callee = base
node.arguments = exprList
base = this.finishNode(node, "CallExpression")
} else if (this.tok.type == tt.backQuote) {
let node = this.startNodeAt(start)
node.tag = base
node.quasi = this.parseTemplate()
base = this.finishNode(node, "TaggedTemplateExpression")
} else {
return base
}
}
}
lp.parseExprAtom = function() {
let node
switch (this.tok.type) {
case tt._this:
case tt._super:
let type = this.tok.type === tt._this ? "ThisExpression" : "Super"
node = this.startNode()
this.next()
return this.finishNode(node, type)
case tt.name:
let start = this.storeCurrentPos()
let id = this.parseIdent()
let isAsync = false
if (id.name === "async" && !this.canInsertSemicolon()) {
if (this.eat(tt._function))
return this.parseFunction(this.startNodeAt(start), false, true)
if (this.tok.type === tt.name) {
id = this.parseIdent()
isAsync = true
}
}
return this.eat(tt.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id
case tt.regexp:
node = this.startNode()
let val = this.tok.value
node.regex = {pattern: val.pattern, flags: val.flags}
node.value = val.value
node.raw = this.input.slice(this.tok.start, this.tok.end)
this.next()
return this.finishNode(node, "Literal")
case tt.num: case tt.string:
node = this.startNode()
node.value = this.tok.value
node.raw = this.input.slice(this.tok.start, this.tok.end)
this.next()
return this.finishNode(node, "Literal")
case tt._null: case tt._true: case tt._false:
node = this.startNode()
node.value = this.tok.type === tt._null ? null : this.tok.type === tt._true
node.raw = this.tok.type.keyword
this.next()
return this.finishNode(node, "Literal")
case tt.parenL:
let parenStart = this.storeCurrentPos()
this.next()
let inner = this.parseExpression()
this.expect(tt.parenR)
if (this.eat(tt.arrow)) {
// (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy.
let params = inner.expressions || [inner]
if (params.length && isDummy(params[params.length - 1]))
params.pop()
return this.parseArrowExpression(this.startNodeAt(parenStart), params)
}
if (this.options.preserveParens) {
let par = this.startNodeAt(parenStart)
par.expression = inner
inner = this.finishNode(par, "ParenthesizedExpression")
}
return inner
case tt.bracketL:
node = this.startNode()
node.elements = this.parseExprList(tt.bracketR, true)
return this.finishNode(node, "ArrayExpression")
case tt.braceL:
return this.parseObj()
case tt._class:
return this.parseClass(false)
case tt._function:
node = this.startNode()
this.next()
return this.parseFunction(node, false)
case tt._new:
return this.parseNew()
case tt.backQuote:
return this.parseTemplate()
default:
return this.dummyIdent()
}
}
lp.parseNew = function() {
let node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart
let meta = this.parseIdent(true)
if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) {
node.meta = meta
node.property = this.parseIdent(true)
return this.finishNode(node, "MetaProperty")
}
let start = this.storeCurrentPos()
node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line)
if (this.tok.type == tt.parenL) {
node.arguments = this.parseExprList(tt.parenR)
} else {
node.arguments = []
}
return this.finishNode(node, "NewExpression")
}
lp.parseTemplateElement = function() {
let elem = this.startNode()
// The loose parser accepts invalid unicode escapes even in untagged templates.
if (this.tok.type === tt.invalidTemplate) {
elem.value = {
raw: this.tok.value,
cooked: null
}
} else {
elem.value = {
raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"),
cooked: this.tok.value
}
}
this.next()
elem.tail = this.tok.type === tt.backQuote
return this.finishNode(elem, "TemplateElement")
}
lp.parseTemplate = function() {
let node = this.startNode()
this.next()
node.expressions = []
let curElt = this.parseTemplateElement()
node.quasis = [curElt]
while (!curElt.tail) {
this.next()
node.expressions.push(this.parseExpression())
if (this.expect(tt.braceR)) {
curElt = this.parseTemplateElement()
} else {
curElt = this.startNode()
curElt.value = {cooked: "", raw: ""}
curElt.tail = true
this.finishNode(curElt, "TemplateElement")
}
node.quasis.push(curElt)
}
this.expect(tt.backQuote)
return this.finishNode(node, "TemplateLiteral")
}
lp.parseObj = function() {
let node = this.startNode()
node.properties = []
this.pushCx()
let indent = this.curIndent + 1, line = this.curLineStart
this.eat(tt.braceL)
if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart }
while (!this.closes(tt.braceR, indent, line)) {
let prop = this.startNode(), isGenerator, isAsync, start
if (this.options.ecmaVersion >= 9 && this.eat(tt.ellipsis)) {
prop.argument = this.parseMaybeAssign()
node.properties.push(this.finishNode(prop, "SpreadElement"))
this.eat(tt.comma)
continue
}
if (this.options.ecmaVersion >= 6) {
start = this.storeCurrentPos()
prop.method = false
prop.shorthand = false
isGenerator = this.eat(tt.star)
}
this.parsePropertyName(prop)
if (this.toks.isAsyncProp(prop)) {
isAsync = true
isGenerator = this.options.ecmaVersion >= 9 && this.eat(tt.star)
this.parsePropertyName(prop)
} else {
isAsync = false
}
if (isDummy(prop.key)) { if (isDummy(this.parseMaybeAssign())) this.next(); this.eat(tt.comma); continue }
if (this.eat(tt.colon)) {
prop.kind = "init"
prop.value = this.parseMaybeAssign()
} else if (this.options.ecmaVersion >= 6 && (this.tok.type === tt.parenL || this.tok.type === tt.braceL)) {
prop.kind = "init"
prop.method = true
prop.value = this.parseMethod(isGenerator, isAsync)
} else if (this.options.ecmaVersion >= 5 && prop.key.type === "Identifier" &&
!prop.computed && (prop.key.name === "get" || prop.key.name === "set") &&
(this.tok.type != tt.comma && this.tok.type != tt.braceR && this.tok.type != tt.eq)) {
prop.kind = prop.key.name
this.parsePropertyName(prop)
prop.value = this.parseMethod(false)
} else {
prop.kind = "init"
if (this.options.ecmaVersion >= 6) {
if (this.eat(tt.eq)) {
let assign = this.startNodeAt(start)
assign.operator = "="
assign.left = prop.key
assign.right = this.parseMaybeAssign()
prop.value = this.finishNode(assign, "AssignmentExpression")
} else {
prop.value = prop.key
}
} else {
prop.value = this.dummyIdent()
}
prop.shorthand = true
}
node.properties.push(this.finishNode(prop, "Property"))
this.eat(tt.comma)
}
this.popCx()
if (!this.eat(tt.braceR)) {
// If there is no closing brace, make the node span to the start
// of the next token (this is useful for Tern)
this.last.end = this.tok.start
if (this.options.locations) this.last.loc.end = this.tok.loc.start
}
return this.finishNode(node, "ObjectExpression")
}
lp.parsePropertyName = function(prop) {
if (this.options.ecmaVersion >= 6) {
if (this.eat(tt.bracketL)) {
prop.computed = true
prop.key = this.parseExpression()
this.expect(tt.bracketR)
return
} else {
prop.computed = false
}
}
let key = (this.tok.type === tt.num || this.tok.type === tt.string) ? this.parseExprAtom() : this.parseIdent()
prop.key = key || this.dummyIdent()
}
lp.parsePropertyAccessor = function() {
if (this.tok.type === tt.name || this.tok.type.keyword) return this.parseIdent()
}
lp.parseIdent = function() {
let name = this.tok.type === tt.name ? this.tok.value : this.tok.type.keyword
if (!name) return this.dummyIdent()
let node = this.startNode()
this.next()
node.name = name
return this.finishNode(node, "Identifier")
}
lp.initFunction = function(node) {
node.id = null
node.params = []
if (this.options.ecmaVersion >= 6) {
node.generator = false
node.expression = false
}
if (this.options.ecmaVersion >= 8)
node.async = false
}
// Convert existing expression atom to assignable pattern
// if possible.
lp.toAssignable = function(node, binding) {
if (!node || node.type == "Identifier" || (node.type == "MemberExpression" && !binding)) {
// Okay
} else if (node.type == "ParenthesizedExpression") {
this.toAssignable(node.expression, binding)
} else if (this.options.ecmaVersion < 6) {
return this.dummyIdent()
} else if (node.type == "ObjectExpression") {
node.type = "ObjectPattern"
for (let prop of node.properties)
this.toAssignable(prop, binding)
} else if (node.type == "ArrayExpression") {
node.type = "ArrayPattern"
this.toAssignableList(node.elements, binding)
} else if (node.type == "Property") {
this.toAssignable(node.value, binding)
} else if (node.type == "SpreadElement") {
node.type = "RestElement"
this.toAssignable(node.argument, binding)
} else if (node.type == "AssignmentExpression") {
node.type = "AssignmentPattern"
delete node.operator
} else {
return this.dummyIdent()
}
return node
}
lp.toAssignableList = function(exprList, binding) {
for (let expr of exprList)
this.toAssignable(expr, binding)
return exprList
}
lp.parseFunctionParams = function(params) {
params = this.parseExprList(tt.parenR)
return this.toAssignableList(params, true)
}
lp.parseMethod = function(isGenerator, isAsync) {
let node = this.startNode(), oldInAsync = this.inAsync
this.initFunction(node)
if (this.options.ecmaVersion >= 6)
node.generator = !!isGenerator
if (this.options.ecmaVersion >= 8)
node.async = !!isAsync
this.inAsync = node.async
node.params = this.parseFunctionParams()
node.body = this.parseBlock()
this.toks.adaptDirectivePrologue(node.body.body)
this.inAsync = oldInAsync
return this.finishNode(node, "FunctionExpression")
}
lp.parseArrowExpression = function(node, params, isAsync) {
let oldInAsync = this.inAsync
this.initFunction(node)
if (this.options.ecmaVersion >= 8)
node.async = !!isAsync
this.inAsync = node.async
node.params = this.toAssignableList(params, true)
node.expression = this.tok.type !== tt.braceL
if (node.expression) {
node.body = this.parseMaybeAssign()
} else {
node.body = this.parseBlock()
this.toks.adaptDirectivePrologue(node.body.body)
}
this.inAsync = oldInAsync
return this.finishNode(node, "ArrowFunctionExpression")
}
lp.parseExprList = function(close, allowEmpty) {
this.pushCx()
let indent = this.curIndent, line = this.curLineStart, elts = []
this.next() // Opening bracket
while (!this.closes(close, indent + 1, line)) {
if (this.eat(tt.comma)) {
elts.push(allowEmpty ? null : this.dummyIdent())
continue
}
let elt = this.parseMaybeAssign()
if (isDummy(elt)) {
if (this.closes(close, indent, line)) break
this.next()
} else {
elts.push(elt)
}
this.eat(tt.comma)
}
this.popCx()
if (!this.eat(close)) {
// If there is no closing brace, make the node span to the start
// of the next token (this is useful for Tern)
this.last.end = this.tok.start
if (this.options.locations) this.last.loc.end = this.tok.loc.start
}
return elts
}
lp.parseAwait = function() {
let node = this.startNode()
this.next()
node.argument = this.parseMaybeUnary()
return this.finishNode(node, "AwaitExpression")
}

View File

@@ -1,47 +0,0 @@
// Acorn: Loose parser
//
// This module provides an alternative parser (`parse_dammit`) that
// exposes that same interface as `parse`, but will try to parse
// anything as JavaScript, repairing syntax error the best it can.
// There are circumstances in which it will raise an error and give
// up, but they are very rare. The resulting AST will be a mostly
// valid JavaScript AST (as per the [Mozilla parser API][api], except
// that:
//
// - Return outside functions is allowed
//
// - Label consistency (no conflicts, break only to existing labels)
// is not enforced.
//
// - Bogus Identifier nodes with a name of `"✖"` are inserted whenever
// the parser got too confused to return anything meaningful.
//
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
//
// The expected use for this is to *first* try `acorn.parse`, and only
// if that fails switch to `parse_dammit`. The loose parser might
// parse badly indented code incorrectly, so **don't** use it as
// your default parser.
//
// Quite a lot of acorn.js is duplicated here. The alternative was to
// add a *lot* of extra cruft to that file, making it less readable
// and slower. Copying and editing the code allowed me to make
// invasive changes and simplifications without creating a complicated
// tangle.
import {addLooseExports, defaultOptions} from "../index"
import {LooseParser, pluginsLoose} from "./state"
import "./tokenize"
import "./statement"
import "./expression"
export {LooseParser, pluginsLoose} from "./state"
defaultOptions.tabSize = 4
// eslint-disable-next-line camelcase
export function parse_dammit(input, options) {
return new LooseParser(input, options).parse()
}
addLooseExports(parse_dammit, LooseParser, pluginsLoose)

View File

@@ -1 +0,0 @@
export function isDummy(node) { return node.name == "✖" }

View File

@@ -1,170 +0,0 @@
import {tokenizer, SourceLocation, tokTypes as tt, Node, lineBreak, isNewLine} from "../index"
function noop() {}
// Registered plugins
export const pluginsLoose = {}
export class LooseParser {
constructor(input, options = {}) {
this.toks = tokenizer(input, options)
this.options = this.toks.options
this.input = this.toks.input
this.tok = this.last = {type: tt.eof, start: 0, end: 0}
this.tok.validateRegExpFlags = noop
this.tok.validateRegExpPattern = noop
if (this.options.locations) {
let here = this.toks.curPosition()
this.tok.loc = new SourceLocation(this.toks, here, here)
}
this.ahead = [] // Tokens ahead
this.context = [] // Indentation contexted
this.curIndent = 0
this.curLineStart = 0
this.nextLineStart = this.lineEnd(this.curLineStart) + 1
this.inAsync = false
// Load plugins
this.options.pluginsLoose = options.pluginsLoose || {}
this.loadPlugins(this.options.pluginsLoose)
}
startNode() {
return new Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null)
}
storeCurrentPos() {
return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start
}
startNodeAt(pos) {
if (this.options.locations) {
return new Node(this.toks, pos[0], pos[1])
} else {
return new Node(this.toks, pos)
}
}
finishNode(node, type) {
node.type = type
node.end = this.last.end
if (this.options.locations)
node.loc.end = this.last.loc.end
if (this.options.ranges)
node.range[1] = this.last.end
return node
}
dummyNode(type) {
let dummy = this.startNode()
dummy.type = type
dummy.end = dummy.start
if (this.options.locations)
dummy.loc.end = dummy.loc.start
if (this.options.ranges)
dummy.range[1] = dummy.start
this.last = {type: tt.name, start: dummy.start, end: dummy.start, loc: dummy.loc}
return dummy
}
dummyIdent() {
let dummy = this.dummyNode("Identifier")
dummy.name = "✖"
return dummy
}
dummyString() {
let dummy = this.dummyNode("Literal")
dummy.value = dummy.raw = "✖"
return dummy
}
eat(type) {
if (this.tok.type === type) {
this.next()
return true
} else {
return false
}
}
isContextual(name) {
return this.tok.type === tt.name && this.tok.value === name
}
eatContextual(name) {
return this.tok.value === name && this.eat(tt.name)
}
canInsertSemicolon() {
return this.tok.type === tt.eof || this.tok.type === tt.braceR ||
lineBreak.test(this.input.slice(this.last.end, this.tok.start))
}
semicolon() {
return this.eat(tt.semi)
}
expect(type) {
if (this.eat(type)) return true
for (let i = 1; i <= 2; i++) {
if (this.lookAhead(i).type == type) {
for (let j = 0; j < i; j++) this.next()
return true
}
}
}
pushCx() {
this.context.push(this.curIndent)
}
popCx() {
this.curIndent = this.context.pop()
}
lineEnd(pos) {
while (pos < this.input.length && !isNewLine(this.input.charCodeAt(pos))) ++pos
return pos
}
indentationAfter(pos) {
for (let count = 0;; ++pos) {
let ch = this.input.charCodeAt(pos)
if (ch === 32) ++count
else if (ch === 9) count += this.options.tabSize
else return count
}
}
closes(closeTok, indent, line, blockHeuristic) {
if (this.tok.type === closeTok || this.tok.type === tt.eof) return true
return line != this.curLineStart && this.curIndent < indent && this.tokenStartsLine() &&
(!blockHeuristic || this.nextLineStart >= this.input.length ||
this.indentationAfter(this.nextLineStart) < indent)
}
tokenStartsLine() {
for (let p = this.tok.start - 1; p >= this.curLineStart; --p) {
let ch = this.input.charCodeAt(p)
if (ch !== 9 && ch !== 32) return false
}
return true
}
extend(name, f) {
this[name] = f(this[name])
}
loadPlugins(pluginConfigs) {
for (let name in pluginConfigs) {
let plugin = pluginsLoose[name]
if (!plugin) throw new Error("Plugin '" + name + "' not found")
plugin(this, pluginConfigs[name])
}
}
parse() {
this.next()
return this.parseTopLevel()
}
}

View File

@@ -1,459 +0,0 @@
import {LooseParser} from "./state"
import {isDummy} from "./parseutil"
import {getLineInfo, tokTypes as tt} from "../index"
const lp = LooseParser.prototype
lp.parseTopLevel = function() {
let node = this.startNodeAt(this.options.locations ? [0, getLineInfo(this.input, 0)] : 0)
node.body = []
while (this.tok.type !== tt.eof) node.body.push(this.parseStatement())
this.toks.adaptDirectivePrologue(node.body)
this.last = this.tok
if (this.options.ecmaVersion >= 6) {
node.sourceType = this.options.sourceType
}
return this.finishNode(node, "Program")
}
lp.parseStatement = function() {
let starttype = this.tok.type, node = this.startNode(), kind
if (this.toks.isLet()) {
starttype = tt._var
kind = "let"
}
switch (starttype) {
case tt._break: case tt._continue:
this.next()
let isBreak = starttype === tt._break
if (this.semicolon() || this.canInsertSemicolon()) {
node.label = null
} else {
node.label = this.tok.type === tt.name ? this.parseIdent() : null
this.semicolon()
}
return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
case tt._debugger:
this.next()
this.semicolon()
return this.finishNode(node, "DebuggerStatement")
case tt._do:
this.next()
node.body = this.parseStatement()
node.test = this.eat(tt._while) ? this.parseParenExpression() : this.dummyIdent()
this.semicolon()
return this.finishNode(node, "DoWhileStatement")
case tt._for:
this.next() // `for` keyword
let isAwait = this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await")
this.pushCx()
this.expect(tt.parenL)
if (this.tok.type === tt.semi) return this.parseFor(node, null)
let isLet = this.toks.isLet()
if (isLet || this.tok.type === tt._var || this.tok.type === tt._const) {
let init = this.parseVar(true, isLet ? "let" : this.tok.value)
if (init.declarations.length === 1 && (this.tok.type === tt._in || this.isContextual("of"))) {
if (this.options.ecmaVersion >= 9 && this.tok.type !== tt._in) {
node.await = isAwait
}
return this.parseForIn(node, init)
}
return this.parseFor(node, init)
}
let init = this.parseExpression(true)
if (this.tok.type === tt._in || this.isContextual("of")) {
if (this.options.ecmaVersion >= 9 && this.tok.type !== tt._in) {
node.await = isAwait
}
return this.parseForIn(node, this.toAssignable(init))
}
return this.parseFor(node, init)
case tt._function:
this.next()
return this.parseFunction(node, true)
case tt._if:
this.next()
node.test = this.parseParenExpression()
node.consequent = this.parseStatement()
node.alternate = this.eat(tt._else) ? this.parseStatement() : null
return this.finishNode(node, "IfStatement")
case tt._return:
this.next()
if (this.eat(tt.semi) || this.canInsertSemicolon()) node.argument = null
else { node.argument = this.parseExpression(); this.semicolon() }
return this.finishNode(node, "ReturnStatement")
case tt._switch:
let blockIndent = this.curIndent, line = this.curLineStart
this.next()
node.discriminant = this.parseParenExpression()
node.cases = []
this.pushCx()
this.expect(tt.braceL)
let cur
while (!this.closes(tt.braceR, blockIndent, line, true)) {
if (this.tok.type === tt._case || this.tok.type === tt._default) {
let isCase = this.tok.type === tt._case
if (cur) this.finishNode(cur, "SwitchCase")
node.cases.push(cur = this.startNode())
cur.consequent = []
this.next()
if (isCase) cur.test = this.parseExpression()
else cur.test = null
this.expect(tt.colon)
} else {
if (!cur) {
node.cases.push(cur = this.startNode())
cur.consequent = []
cur.test = null
}
cur.consequent.push(this.parseStatement())
}
}
if (cur) this.finishNode(cur, "SwitchCase")
this.popCx()
this.eat(tt.braceR)
return this.finishNode(node, "SwitchStatement")
case tt._throw:
this.next()
node.argument = this.parseExpression()
this.semicolon()
return this.finishNode(node, "ThrowStatement")
case tt._try:
this.next()
node.block = this.parseBlock()
node.handler = null
if (this.tok.type === tt._catch) {
let clause = this.startNode()
this.next()
this.expect(tt.parenL)
clause.param = this.toAssignable(this.parseExprAtom(), true)
this.expect(tt.parenR)
clause.body = this.parseBlock()
node.handler = this.finishNode(clause, "CatchClause")
}
node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null
if (!node.handler && !node.finalizer) return node.block
return this.finishNode(node, "TryStatement")
case tt._var:
case tt._const:
return this.parseVar(false, kind || this.tok.value)
case tt._while:
this.next()
node.test = this.parseParenExpression()
node.body = this.parseStatement()
return this.finishNode(node, "WhileStatement")
case tt._with:
this.next()
node.object = this.parseParenExpression()
node.body = this.parseStatement()
return this.finishNode(node, "WithStatement")
case tt.braceL:
return this.parseBlock()
case tt.semi:
this.next()
return this.finishNode(node, "EmptyStatement")
case tt._class:
return this.parseClass(true)
case tt._import:
return this.parseImport()
case tt._export:
return this.parseExport()
default:
if (this.toks.isAsyncFunction()) {
this.next()
this.next()
return this.parseFunction(node, true, true)
}
let expr = this.parseExpression()
if (isDummy(expr)) {
this.next()
if (this.tok.type === tt.eof) return this.finishNode(node, "EmptyStatement")
return this.parseStatement()
} else if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) {
node.body = this.parseStatement()
node.label = expr
return this.finishNode(node, "LabeledStatement")
} else {
node.expression = expr
this.semicolon()
return this.finishNode(node, "ExpressionStatement")
}
}
}
lp.parseBlock = function() {
let node = this.startNode()
this.pushCx()
this.expect(tt.braceL)
let blockIndent = this.curIndent, line = this.curLineStart
node.body = []
while (!this.closes(tt.braceR, blockIndent, line, true))
node.body.push(this.parseStatement())
this.popCx()
this.eat(tt.braceR)
return this.finishNode(node, "BlockStatement")
}
lp.parseFor = function(node, init) {
node.init = init
node.test = node.update = null
if (this.eat(tt.semi) && this.tok.type !== tt.semi) node.test = this.parseExpression()
if (this.eat(tt.semi) && this.tok.type !== tt.parenR) node.update = this.parseExpression()
this.popCx()
this.expect(tt.parenR)
node.body = this.parseStatement()
return this.finishNode(node, "ForStatement")
}
lp.parseForIn = function(node, init) {
let type = this.tok.type === tt._in ? "ForInStatement" : "ForOfStatement"
this.next()
node.left = init
node.right = this.parseExpression()
this.popCx()
this.expect(tt.parenR)
node.body = this.parseStatement()
return this.finishNode(node, type)
}
lp.parseVar = function(noIn, kind) {
let node = this.startNode()
node.kind = kind
this.next()
node.declarations = []
do {
let decl = this.startNode()
decl.id = this.options.ecmaVersion >= 6 ? this.toAssignable(this.parseExprAtom(), true) : this.parseIdent()
decl.init = this.eat(tt.eq) ? this.parseMaybeAssign(noIn) : null
node.declarations.push(this.finishNode(decl, "VariableDeclarator"))
} while (this.eat(tt.comma))
if (!node.declarations.length) {
let decl = this.startNode()
decl.id = this.dummyIdent()
node.declarations.push(this.finishNode(decl, "VariableDeclarator"))
}
if (!noIn) this.semicolon()
return this.finishNode(node, "VariableDeclaration")
}
lp.parseClass = function(isStatement) {
let node = this.startNode()
this.next()
if (this.tok.type === tt.name) node.id = this.parseIdent()
else if (isStatement === true) node.id = this.dummyIdent()
else node.id = null
node.superClass = this.eat(tt._extends) ? this.parseExpression() : null
node.body = this.startNode()
node.body.body = []
this.pushCx()
let indent = this.curIndent + 1, line = this.curLineStart
this.eat(tt.braceL)
if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart }
while (!this.closes(tt.braceR, indent, line)) {
if (this.semicolon()) continue
let method = this.startNode(), isGenerator, isAsync
if (this.options.ecmaVersion >= 6) {
method.static = false
isGenerator = this.eat(tt.star)
}
this.parsePropertyName(method)
if (isDummy(method.key)) { if (isDummy(this.parseMaybeAssign())) this.next(); this.eat(tt.comma); continue }
if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" &&
(this.tok.type != tt.parenL && this.tok.type != tt.braceL)) {
method.static = true
isGenerator = this.eat(tt.star)
this.parsePropertyName(method)
} else {
method.static = false
}
if (!method.computed &&
method.key.type === "Identifier" && method.key.name === "async" && this.tok.type !== tt.parenL &&
!this.canInsertSemicolon()) {
isAsync = true
isGenerator = this.options.ecmaVersion >= 9 && this.eat(tt.star)
this.parsePropertyName(method)
} else {
isAsync = false
}
if (this.options.ecmaVersion >= 5 && method.key.type === "Identifier" &&
!method.computed && (method.key.name === "get" || method.key.name === "set") &&
this.tok.type !== tt.parenL && this.tok.type !== tt.braceL) {
method.kind = method.key.name
this.parsePropertyName(method)
method.value = this.parseMethod(false)
} else {
if (!method.computed && !method.static && !isGenerator && !isAsync && (
method.key.type === "Identifier" && method.key.name === "constructor" ||
method.key.type === "Literal" && method.key.value === "constructor")) {
method.kind = "constructor"
} else {
method.kind = "method"
}
method.value = this.parseMethod(isGenerator, isAsync)
}
node.body.body.push(this.finishNode(method, "MethodDefinition"))
}
this.popCx()
if (!this.eat(tt.braceR)) {
// If there is no closing brace, make the node span to the start
// of the next token (this is useful for Tern)
this.last.end = this.tok.start
if (this.options.locations) this.last.loc.end = this.tok.loc.start
}
this.semicolon()
this.finishNode(node.body, "ClassBody")
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
}
lp.parseFunction = function(node, isStatement, isAsync) {
let oldInAsync = this.inAsync
this.initFunction(node)
if (this.options.ecmaVersion >= 6) {
node.generator = this.eat(tt.star)
}
if (this.options.ecmaVersion >= 8) {
node.async = !!isAsync
}
if (this.tok.type === tt.name) node.id = this.parseIdent()
else if (isStatement === true) node.id = this.dummyIdent()
this.inAsync = node.async
node.params = this.parseFunctionParams()
node.body = this.parseBlock()
this.toks.adaptDirectivePrologue(node.body.body)
this.inAsync = oldInAsync
return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
}
lp.parseExport = function() {
let node = this.startNode()
this.next()
if (this.eat(tt.star)) {
node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString()
return this.finishNode(node, "ExportAllDeclaration")
}
if (this.eat(tt._default)) {
// export default (function foo() {}) // This is FunctionExpression.
let isAsync
if (this.tok.type === tt._function || (isAsync = this.toks.isAsyncFunction())) {
let fNode = this.startNode()
this.next()
if (isAsync) this.next()
node.declaration = this.parseFunction(fNode, "nullableID", isAsync)
} else if (this.tok.type === tt._class) {
node.declaration = this.parseClass("nullableID")
} else {
node.declaration = this.parseMaybeAssign()
this.semicolon()
}
return this.finishNode(node, "ExportDefaultDeclaration")
}
if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) {
node.declaration = this.parseStatement()
node.specifiers = []
node.source = null
} else {
node.declaration = null
node.specifiers = this.parseExportSpecifierList()
node.source = this.eatContextual("from") ? this.parseExprAtom() : null
this.semicolon()
}
return this.finishNode(node, "ExportNamedDeclaration")
}
lp.parseImport = function() {
let node = this.startNode()
this.next()
if (this.tok.type === tt.string) {
node.specifiers = []
node.source = this.parseExprAtom()
} else {
let elt
if (this.tok.type === tt.name && this.tok.value !== "from") {
elt = this.startNode()
elt.local = this.parseIdent()
this.finishNode(elt, "ImportDefaultSpecifier")
this.eat(tt.comma)
}
node.specifiers = this.parseImportSpecifierList()
node.source = this.eatContextual("from") && this.tok.type == tt.string ? this.parseExprAtom() : this.dummyString()
if (elt) node.specifiers.unshift(elt)
}
this.semicolon()
return this.finishNode(node, "ImportDeclaration")
}
lp.parseImportSpecifierList = function() {
let elts = []
if (this.tok.type === tt.star) {
let elt = this.startNode()
this.next()
elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent()
elts.push(this.finishNode(elt, "ImportNamespaceSpecifier"))
} else {
let indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart
this.pushCx()
this.eat(tt.braceL)
if (this.curLineStart > continuedLine) continuedLine = this.curLineStart
while (!this.closes(tt.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
let elt = this.startNode()
if (this.eat(tt.star)) {
elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent()
this.finishNode(elt, "ImportNamespaceSpecifier")
} else {
if (this.isContextual("from")) break
elt.imported = this.parseIdent()
if (isDummy(elt.imported)) break
elt.local = this.eatContextual("as") ? this.parseIdent() : elt.imported
this.finishNode(elt, "ImportSpecifier")
}
elts.push(elt)
this.eat(tt.comma)
}
this.eat(tt.braceR)
this.popCx()
}
return elts
}
lp.parseExportSpecifierList = function() {
let elts = []
let indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart
this.pushCx()
this.eat(tt.braceL)
if (this.curLineStart > continuedLine) continuedLine = this.curLineStart
while (!this.closes(tt.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
if (this.isContextual("from")) break
let elt = this.startNode()
elt.local = this.parseIdent()
if (isDummy(elt.local)) break
elt.exported = this.eatContextual("as") ? this.parseIdent() : elt.local
this.finishNode(elt, "ExportSpecifier")
elts.push(elt)
this.eat(tt.comma)
}
this.eat(tt.braceR)
this.popCx()
return elts
}

View File

@@ -1,111 +0,0 @@
import {tokTypes as tt, Token, isNewLine, SourceLocation, getLineInfo, lineBreakG} from "../index"
import {LooseParser} from "./state"
const lp = LooseParser.prototype
function isSpace(ch) {
return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || isNewLine(ch)
}
lp.next = function() {
this.last = this.tok
if (this.ahead.length)
this.tok = this.ahead.shift()
else
this.tok = this.readToken()
if (this.tok.start >= this.nextLineStart) {
while (this.tok.start >= this.nextLineStart) {
this.curLineStart = this.nextLineStart
this.nextLineStart = this.lineEnd(this.curLineStart) + 1
}
this.curIndent = this.indentationAfter(this.curLineStart)
}
}
lp.readToken = function() {
for (;;) {
try {
this.toks.next()
if (this.toks.type === tt.dot &&
this.input.substr(this.toks.end, 1) === "." &&
this.options.ecmaVersion >= 6) {
this.toks.end++
this.toks.type = tt.ellipsis
}
return new Token(this.toks)
} catch (e) {
if (!(e instanceof SyntaxError)) throw e
// Try to skip some text, based on the error message, and then continue
let msg = e.message, pos = e.raisedAt, replace = true
if (/unterminated/i.test(msg)) {
pos = this.lineEnd(e.pos + 1)
if (/string/.test(msg)) {
replace = {start: e.pos, end: pos, type: tt.string, value: this.input.slice(e.pos + 1, pos)}
} else if (/regular expr/i.test(msg)) {
let re = this.input.slice(e.pos, pos)
try { re = new RegExp(re) } catch (e) { /* ignore compilation error due to new syntax */ }
replace = {start: e.pos, end: pos, type: tt.regexp, value: re}
} else if (/template/.test(msg)) {
replace = {
start: e.pos,
end: pos,
type: tt.template,
value: this.input.slice(e.pos, pos)
}
} else {
replace = false
}
} else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) {
while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) ++pos
} else if (/character escape|expected hexadecimal/i.test(msg)) {
while (pos < this.input.length) {
let ch = this.input.charCodeAt(pos++)
if (ch === 34 || ch === 39 || isNewLine(ch)) break
}
} else if (/unexpected character/i.test(msg)) {
pos++
replace = false
} else if (/regular expression/i.test(msg)) {
replace = true
} else {
throw e
}
this.resetTo(pos)
if (replace === true) replace = {start: pos, end: pos, type: tt.name, value: "✖"}
if (replace) {
if (this.options.locations)
replace.loc = new SourceLocation(
this.toks,
getLineInfo(this.input, replace.start),
getLineInfo(this.input, replace.end))
return replace
}
}
}
}
lp.resetTo = function(pos) {
this.toks.pos = pos
let ch = this.input.charAt(pos - 1)
this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) ||
/[enwfd]/.test(ch) &&
/\b(case|else|return|throw|new|in|(instance|type)?of|delete|void)$/.test(this.input.slice(pos - 10, pos))
if (this.options.locations) {
this.toks.curLine = 1
this.toks.lineStart = lineBreakG.lastIndex = 0
let match
while ((match = lineBreakG.exec(this.input)) && match.index < pos) {
++this.toks.curLine
this.toks.lineStart = match.index + match[0].length
}
}
}
lp.lookAhead = function(n) {
while (n > this.ahead.length)
this.ahead.push(this.readToken())
return this.ahead[n - 1]
}

View File

@@ -1,6 +1,7 @@
import {types as tt} from "./tokentype"
import {Parser} from "./state"
import {has} from "./util"
import {BIND_NONE, BIND_OUTSIDE, BIND_LEXICAL} from "./scopeflags"
const pp = Parser.prototype
@@ -12,7 +13,7 @@ pp.toAssignable = function(node, isBinding, refDestructuringErrors) {
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")
this.raise(node.start, "Cannot use 'await' as identifier inside an async function")
break
case "ObjectPattern":
@@ -40,7 +41,7 @@ pp.toAssignable = function(node, isBinding, refDestructuringErrors) {
break
case "Property":
// AssignmentProperty has type == "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
@@ -69,7 +70,7 @@ pp.toAssignable = function(node, isBinding, refDestructuringErrors) {
break
case "ParenthesizedExpression":
this.toAssignable(node.expression, isBinding)
this.toAssignable(node.expression, isBinding, refDestructuringErrors)
break
case "MemberExpression":
@@ -185,9 +186,11 @@ pp.parseMaybeDefault = function(startPos, startLoc, left) {
// '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.checkLVal = function(expr, bindingType, checkClashes) {
pp.checkLVal = function(expr, bindingType = BIND_NONE, checkClashes) {
switch (expr.type) {
case "Identifier":
if (bindingType === BIND_LEXICAL && expr.name === "let")
this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name")
if (this.strict && this.reservedWordsStrictBind.test(expr.name))
this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode")
if (checkClashes) {
@@ -195,19 +198,7 @@ pp.checkLVal = function(expr, bindingType, checkClashes) {
this.raiseRecoverable(expr.start, "Argument name clash")
checkClashes[expr.name] = true
}
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 (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) this.declareName(expr.name, bindingType, expr.start)
break
case "MemberExpression":
@@ -220,7 +211,7 @@ pp.checkLVal = function(expr, bindingType, checkClashes) {
break
case "Property":
// AssignmentProperty has type == "Property"
// AssignmentProperty has type === "Property"
this.checkLVal(expr.value, bindingType, checkClashes)
break

View File

@@ -5,18 +5,19 @@ import {SourceLocation} from "./locutil"
// the parser process. These options are recognized:
export const 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,
// `ecmaVersion` indicates the ECMAScript version to parse. Must be
// either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10
// (2019). This influences support for strict mode, the set of
// reserved words, and support for new syntax features. The default
// is 10.
ecmaVersion: 10,
// `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
// the 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,
@@ -34,6 +35,9 @@ export const defaultOptions = {
// When enabled, import/export statements are not constrained to
// appearing at the top of the program.
allowImportExportEverywhere: false,
// When enabled, await identifiers are allowed to appear at the top-level scope,
// but they are still not allowed in non-async functions.
allowAwaitOutsideFunction: false,
// When enabled, hashbang directive in the beginning of file
// is allowed and treated as a line comment.
allowHashBang: false,
@@ -82,8 +86,7 @@ export const defaultOptions = {
directSourceFile: null,
// When enabled, parenthesized expressions are represented by
// (non-standard) ParenthesizedExpression nodes
preserveParens: false,
plugins: {}
preserveParens: false
}
// Interpret and default an options object

View File

@@ -6,15 +6,29 @@ const pp = Parser.prototype
// ## Parser utilities
const literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/
const literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)")/
pp.strictDirective = function(start) {
for (;;) {
// Try to find string literal.
skipWhiteSpace.lastIndex = start
start += skipWhiteSpace.exec(this.input)[0].length
let match = literal.exec(this.input.slice(start))
if (!match) return false
if ((match[1] || match[2]) == "use strict") return true
if ((match[1] || match[2]) === "use strict") {
skipWhiteSpace.lastIndex = start + match[0].length
let spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length
let next = this.input.charAt(end)
return next === ";" || next === "}" ||
(lineBreak.test(spaceAfter[0]) &&
!(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "="))
}
start += match[0].length
// Skip semicolon, if any.
skipWhiteSpace.lastIndex = start
start += skipWhiteSpace.exec(this.input)[0].length
if (this.input[start] === ";")
start++
}
}
@@ -74,7 +88,7 @@ pp.semicolon = function() {
}
pp.afterTrailingComma = function(tokType, notNext) {
if (this.type == tokType) {
if (this.type === tokType) {
if (this.options.onTrailingComma)
this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc)
if (!notNext)

View File

@@ -1,6 +1,7 @@
import {isIdentifierStart, isIdentifierChar} from "./identifier.js"
import {Parser} from "./state.js"
import UNICODE_PROPERTY_VALUES from "./unicode-property-data.js"
import {has} from "./util.js"
const pp = Parser.prototype
@@ -8,6 +9,7 @@ export class RegExpValidationState {
constructor(parser) {
this.parser = parser
this.validFlags = `gim${parser.options.ecmaVersion >= 6 ? "uy" : ""}${parser.options.ecmaVersion >= 9 ? "s" : ""}`
this.unicodeProperties = UNICODE_PROPERTY_VALUES[parser.options.ecmaVersion >= 11 ? 11 : parser.options.ecmaVersion]
this.source = ""
this.flags = ""
this.start = 0
@@ -48,7 +50,8 @@ export class RegExpValidationState {
if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
return c
}
return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00
const next = s.charCodeAt(i + 1)
return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c
}
nextIndex(i) {
@@ -57,8 +60,9 @@ export class RegExpValidationState {
if (i >= l) {
return l
}
const c = s.charCodeAt(i)
if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
let c = s.charCodeAt(i), next
if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l ||
(next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
return i + 1
}
return i + 2
@@ -103,7 +107,7 @@ pp.validateRegExpFlags = function(state) {
for (let i = 0; i < flags.length; i++) {
const flag = flags.charAt(i)
if (validFlags.indexOf(flag) == -1) {
if (validFlags.indexOf(flag) === -1) {
this.raise(state.start, "Invalid regular expression flag")
}
if (flags.indexOf(flag, i + 1) > -1) {
@@ -150,7 +154,7 @@ pp.regexp_pattern = function(state) {
if (state.eat(0x29 /* ) */)) {
state.raise("Unmatched ')'")
}
if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) {
if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) {
state.raise("Lone quantifier brackets")
}
}
@@ -784,14 +788,14 @@ pp.regexp_eatUnicodePropertyValueExpression = function(state) {
return false
}
pp.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
if (!UNICODE_PROPERTY_VALUES.hasOwnProperty(name) || UNICODE_PROPERTY_VALUES[name].indexOf(value) === -1) {
if (!has(state.unicodeProperties.nonBinary, name))
state.raise("Invalid property name")
}
if (!state.unicodeProperties.nonBinary[name].test(value))
state.raise("Invalid property value")
}
pp.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
if (UNICODE_PROPERTY_VALUES.$LONE.indexOf(nameOrValue) === -1) {
if (!state.unicodeProperties.binary.test(nameOrValue))
state.raise("Invalid property name")
}
}
// UnicodePropertyName ::
@@ -835,7 +839,7 @@ pp.regexp_eatCharacterClass = function(state) {
if (state.eat(0x5B /* [ */)) {
state.eat(0x5E /* ^ */)
this.regexp_classRanges(state)
if (state.eat(0x5D /* [ */)) {
if (state.eat(0x5D /* ] */)) {
return true
}
// Unreachable since it threw "unterminated regular expression" error before.
@@ -883,7 +887,7 @@ pp.regexp_eatClassAtom = function(state) {
}
const ch = state.current()
if (ch !== 0x5D /* [ */) {
if (ch !== 0x5D /* ] */) {
state.lastIntValue = ch
state.advance()
return true

View File

@@ -1,74 +1,95 @@
import {Parser} from "./state"
import {has} from "./util"
import {SCOPE_VAR, SCOPE_FUNCTION, SCOPE_TOP, SCOPE_ARROW, SCOPE_SIMPLE_CATCH, BIND_LEXICAL, BIND_SIMPLE_CATCH, BIND_FUNCTION} from "./scopeflags"
const pp = Parser.prototype
// Object.assign polyfill
const assign = Object.assign || function(target, ...sources) {
for (let source of sources) {
for (const key in source) {
if (has(source, key)) {
target[key] = source[key]
}
}
class Scope {
constructor(flags) {
this.flags = flags
// A list of var-declared names in the current lexical scope
this.var = []
// A list of lexically-declared names in the current lexical scope
this.lexical = []
// A list of lexically-declared FunctionDeclaration names in the current lexical scope
this.functions = []
}
return target
}
// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
pp.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: {}})
pp.enterScope = function(flags) {
this.scopeStack.push(new Scope(flags))
}
pp.exitFunctionScope = function() {
pp.exitScope = function() {
this.scopeStack.pop()
}
pp.enterLexicalScope = function() {
const parentScope = this.scopeStack[this.scopeStack.length - 1]
const childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}}
this.scopeStack.push(childScope)
assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical)
// The spec says:
// > At the top level of a function, or script, function declarations are
// > treated like var declarations rather than like lexical declarations.
pp.treatFunctionsAsVarInScope = function(scope) {
return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP)
}
pp.exitLexicalScope = function() {
const childScope = this.scopeStack.pop()
const parentScope = this.scopeStack[this.scopeStack.length - 1]
assign(parentScope.childVar, childScope.var, childScope.childVar)
pp.declareName = function(name, bindingType, pos) {
let redeclared = false
if (bindingType === BIND_LEXICAL) {
const scope = this.currentScope()
redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1
scope.lexical.push(name)
if (this.inModule && (scope.flags & SCOPE_TOP))
delete this.undefinedExports[name]
} else if (bindingType === BIND_SIMPLE_CATCH) {
const scope = this.currentScope()
scope.lexical.push(name)
} else if (bindingType === BIND_FUNCTION) {
const scope = this.currentScope()
if (this.treatFunctionsAsVar)
redeclared = scope.lexical.indexOf(name) > -1
else
redeclared = scope.lexical.indexOf(name) > -1 || scope.var.indexOf(name) > -1
scope.functions.push(name)
} else {
for (let i = this.scopeStack.length - 1; i >= 0; --i) {
const scope = this.scopeStack[i]
if (scope.lexical.indexOf(name) > -1 && !((scope.flags & SCOPE_SIMPLE_CATCH) && scope.lexical[0] === name) ||
!this.treatFunctionsAsVarInScope(scope) && scope.functions.indexOf(name) > -1) {
redeclared = true
break
}
scope.var.push(name)
if (this.inModule && (scope.flags & SCOPE_TOP))
delete this.undefinedExports[name]
if (scope.flags & SCOPE_VAR) break
}
}
if (redeclared) this.raiseRecoverable(pos, `Identifier '${name}' has already been declared`)
}
/**
* 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.canDeclareVarName = function(name) {
const currentScope = this.scopeStack[this.scopeStack.length - 1]
return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name)
pp.checkLocalExport = function(id) {
// scope.functions must be empty as Module code is always strict.
if (this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
this.scopeStack[0].var.indexOf(id.name) === -1) {
this.undefinedExports[id.name] = id
}
}
/**
* 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.canDeclareLexicalName = function(name) {
const currentScope = this.scopeStack[this.scopeStack.length - 1]
return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name)
pp.currentScope = function() {
return this.scopeStack[this.scopeStack.length - 1]
}
pp.declareVarName = function(name) {
this.scopeStack[this.scopeStack.length - 1].var[name] = true
pp.currentVarScope = function() {
for (let i = this.scopeStack.length - 1;; i--) {
let scope = this.scopeStack[i]
if (scope.flags & SCOPE_VAR) return scope
}
}
pp.declareLexicalName = function(name) {
this.scopeStack[this.scopeStack.length - 1].lexical[name] = true
// Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
pp.currentThisScope = function() {
for (let i = this.scopeStack.length - 1;; i--) {
let scope = this.scopeStack[i]
if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) return scope
}
}

View File

@@ -0,0 +1,24 @@
// Each scope gets a bitset that may contain these flags
export const
SCOPE_TOP = 1,
SCOPE_FUNCTION = 2,
SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION,
SCOPE_ASYNC = 4,
SCOPE_GENERATOR = 8,
SCOPE_ARROW = 16,
SCOPE_SIMPLE_CATCH = 32,
SCOPE_SUPER = 64,
SCOPE_DIRECT_SUPER = 128
export function functionFlags(async, generator) {
return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0)
}
// Used in checkLVal and declareName to determine the type of a binding
export const
BIND_NONE = 0, // Not a binding
BIND_VAR = 1, // Var-style binding
BIND_LEXICAL = 2, // Let- or const-style binding
BIND_FUNCTION = 3, // Function declaration
BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
BIND_OUTSIDE = 5 // Special case for function names as bound inside the function

View File

@@ -2,29 +2,24 @@ import {reservedWords, keywords} from "./identifier"
import {types as tt} from "./tokentype"
import {lineBreak} from "./whitespace"
import {getOptions} from "./options"
// Registered plugins
export const plugins = {}
function keywordRegexp(words) {
return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
}
import {wordsRegexp} from "./util"
import {SCOPE_TOP, SCOPE_FUNCTION, SCOPE_ASYNC, SCOPE_GENERATOR, SCOPE_SUPER, SCOPE_DIRECT_SUPER} from "./scopeflags"
export class Parser {
constructor(options, input, startPos) {
this.options = options = getOptions(options)
this.sourceFile = options.sourceFile
this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5])
this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5])
let reserved = ""
if (!options.allowReserved) {
if (options.allowReserved !== true) {
for (let v = options.ecmaVersion;; v--)
if (reserved = reservedWords[v]) break
if (options.sourceType == "module") reserved += " await"
if (options.sourceType === "module") reserved += " await"
}
this.reservedWords = keywordRegexp(reserved)
this.reservedWords = wordsRegexp(reserved)
let reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict
this.reservedWordsStrict = keywordRegexp(reservedStrict)
this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind)
this.reservedWordsStrict = wordsRegexp(reservedStrict)
this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind)
this.input = String(input)
// Used to signal to callers of `readWord1` whether the word
@@ -32,9 +27,6 @@ export class Parser {
// escape sequences must not be interpreted as keywords.
this.containsEsc = false
// Load plugins
this.loadPlugins(options.plugins)
// Set up token state
// The current position of the tokenizer in the input.
@@ -75,12 +67,12 @@ export class Parser {
// Used to signify the start of a potential arrow function
this.potentialArrowAt = -1
// 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
this.yieldPos = this.awaitPos = this.awaitIdentPos = 0
// Labels in scope.
this.labels = []
// Thus-far undefined exports.
this.undefinedExports = {}
// If enabled, skip leading hashbang line.
if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
@@ -88,31 +80,45 @@ export class Parser {
// Scope tracking for duplicate variable names (see scope.js)
this.scopeStack = []
this.enterFunctionScope()
this.enterScope(SCOPE_TOP)
// For RegExp validation
this.regexpState = null
}
// DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them
isKeyword(word) { return this.keywords.test(word) }
isReservedWord(word) { return this.reservedWords.test(word) }
extend(name, f) {
this[name] = f(this[name])
}
loadPlugins(pluginConfigs) {
for (let name in pluginConfigs) {
let plugin = plugins[name]
if (!plugin) throw new Error("Plugin '" + name + "' not found")
plugin(this, pluginConfigs[name])
}
}
parse() {
let node = this.options.program || this.startNode()
this.nextToken()
return this.parseTopLevel(node)
}
get inFunction() { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }
get inGenerator() { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 }
get inAsync() { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 }
get allowSuper() { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 }
get allowDirectSuper() { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }
get treatFunctionsAsVar() { return this.treatFunctionsAsVarInScope(this.currentScope()) }
// Switch to a getter for 7.0.0.
inNonArrowFunction() { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 }
static extend(...plugins) {
let cls = this
for (let i = 0; i < plugins.length; i++) cls = plugins[i](cls)
return cls
}
static parse(input, options) {
return new this(options, input).parse()
}
static parseExpressionAt(input, pos, options) {
let parser = new this(options, input, pos)
parser.nextToken()
return parser.parseExpression()
}
static tokenizer(input, options) {
return new this(options, input)
}
}

View File

@@ -4,6 +4,7 @@ import {lineBreak, skipWhiteSpace} from "./whitespace"
import {isIdentifierStart, isIdentifierChar, keywordRelationalOperator} from "./identifier"
import {has} from "./util"
import {DestructuringErrors} from "./parseutil"
import {functionFlags, SCOPE_SIMPLE_CATCH, BIND_SIMPLE_CATCH, BIND_LEXICAL, BIND_VAR, BIND_FUNCTION} from "./scopeflags"
const pp = Parser.prototype
@@ -18,25 +19,33 @@ pp.parseTopLevel = function(node) {
let exports = {}
if (!node.body) node.body = []
while (this.type !== tt.eof) {
let stmt = this.parseStatement(true, true, exports)
let stmt = this.parseStatement(null, true, exports)
node.body.push(stmt)
}
if (this.inModule)
for (let name of Object.keys(this.undefinedExports))
this.raiseRecoverable(this.undefinedExports[name].start, `Export '${name}' is not defined`)
this.adaptDirectivePrologue(node.body)
this.next()
if (this.options.ecmaVersion >= 6) {
node.sourceType = this.options.sourceType
}
node.sourceType = this.options.sourceType
return this.finishNode(node, "Program")
}
const loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}
pp.isLet = function() {
pp.isLet = function(context) {
if (this.options.ecmaVersion < 6 || !this.isContextual("let")) return false
skipWhiteSpace.lastIndex = this.pos
let skip = skipWhiteSpace.exec(this.input)
let next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next)
if (nextCh === 91 || nextCh == 123) return true // '{' and '['
// For ambiguous cases, determine if a LexicalDeclaration (or only a
// Statement) is allowed here. If context is not empty then only a Statement
// is allowed. However, `let [` is an explicit negative lookahead for
// ExpressionStatement, so special-case it first.
if (nextCh === 91) return true // '['
if (context) return false
if (nextCh === 123) return true // '{'
if (isIdentifierStart(nextCh, true)) {
let pos = next + 1
while (isIdentifierChar(this.input.charCodeAt(pos), true)) ++pos
@@ -58,7 +67,7 @@ pp.isAsyncFunction = function() {
let 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)))
(next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
}
// Parse a single statement.
@@ -68,10 +77,10 @@ pp.isAsyncFunction = function() {
// `if (foo) /blah/.exec(foo)`, where looking at the previous token
// does not help.
pp.parseStatement = function(declaration, topLevel, exports) {
pp.parseStatement = function(context, topLevel, exports) {
let starttype = this.type, node = this.startNode(), kind
if (this.isLet()) {
if (this.isLet(context)) {
starttype = tt._var
kind = "let"
}
@@ -86,10 +95,13 @@ pp.parseStatement = function(declaration, topLevel, exports) {
case tt._do: return this.parseDoStatement(node)
case tt._for: return this.parseForStatement(node)
case tt._function:
if (!declaration && this.options.ecmaVersion >= 6) this.unexpected()
return this.parseFunctionStatement(node, false)
// Function as sole body of either an if statement or a labeled statement
// works, but not when it is part of a labeled statement that is the sole
// body of an if statement.
if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) this.unexpected()
return this.parseFunctionStatement(node, false, !context)
case tt._class:
if (!declaration) this.unexpected()
if (context) this.unexpected()
return this.parseClass(node, true)
case tt._if: return this.parseIfStatement(node)
case tt._return: return this.parseReturnStatement(node)
@@ -98,14 +110,22 @@ pp.parseStatement = function(declaration, topLevel, exports) {
case tt._try: return this.parseTryStatement(node)
case tt._const: case tt._var:
kind = kind || this.value
if (!declaration && kind != "var") this.unexpected()
if (context && kind !== "var") this.unexpected()
return this.parseVarStatement(node, kind)
case tt._while: return this.parseWhileStatement(node)
case tt._with: return this.parseWithStatement(node)
case tt.braceL: return this.parseBlock()
case tt.braceL: return this.parseBlock(true, node)
case tt.semi: return this.parseEmptyStatement(node)
case tt._export:
case tt._import:
if (this.options.ecmaVersion > 10 && starttype === tt._import) {
skipWhiteSpace.lastIndex = this.pos
let skip = skipWhiteSpace.exec(this.input)
let next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next)
if (nextCh === 40) // '('
return this.parseExpressionStatement(node, this.parseExpression())
}
if (!this.options.allowImportExportEverywhere) {
if (!topLevel)
this.raise(this.start, "'import' and 'export' may only appear at the top level")
@@ -121,20 +141,20 @@ pp.parseStatement = function(declaration, topLevel, exports) {
// Identifier node, we switch to interpreting it as a label.
default:
if (this.isAsyncFunction()) {
if (!declaration) this.unexpected()
if (context) this.unexpected()
this.next()
return this.parseFunctionStatement(node, true)
return this.parseFunctionStatement(node, true, !context)
}
let maybeName = this.value, expr = this.parseExpression()
if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon))
return this.parseLabeledStatement(node, maybeName, expr)
return this.parseLabeledStatement(node, maybeName, expr, context)
else return this.parseExpressionStatement(node, expr)
}
}
pp.parseBreakContinueStatement = function(node, keyword) {
let isBreak = keyword == "break"
let isBreak = keyword === "break"
this.next()
if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null
else if (this.type !== tt.name) this.unexpected()
@@ -166,7 +186,7 @@ pp.parseDebuggerStatement = function(node) {
pp.parseDoStatement = function(node) {
this.next()
this.labels.push(loopLabel)
node.body = this.parseStatement(false)
node.body = this.parseStatement("do")
this.labels.pop()
this.expect(tt._while)
node.test = this.parseParenExpression()
@@ -187,9 +207,9 @@ pp.parseDoStatement = function(node) {
pp.parseForStatement = function(node) {
this.next()
let awaitAt = (this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await")) ? this.lastTokStart : -1
let awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1
this.labels.push(loopLabel)
this.enterLexicalScope()
this.enterScope(0)
this.expect(tt.parenL)
if (this.type === tt.semi) {
if (awaitAt > -1) this.unexpected(awaitAt)
@@ -201,8 +221,7 @@ pp.parseForStatement = function(node) {
this.next()
this.parseVar(init, true, kind)
this.finishNode(init, "VariableDeclaration")
if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1 &&
!(kind !== "var" && init.declarations[0].init)) {
if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1) {
if (this.options.ecmaVersion >= 9) {
if (this.type === tt._in) {
if (awaitAt > -1) this.unexpected(awaitAt)
@@ -231,17 +250,17 @@ pp.parseForStatement = function(node) {
return this.parseFor(node, init)
}
pp.parseFunctionStatement = function(node, isAsync) {
pp.parseFunctionStatement = function(node, isAsync, declarationPosition) {
this.next()
return this.parseFunction(node, true, false, isAsync)
return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync)
}
pp.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 == tt._function)
node.alternate = this.eat(tt._else) ? this.parseStatement(!this.strict && this.type == tt._function) : null
node.consequent = this.parseStatement("if")
node.alternate = this.eat(tt._else) ? this.parseStatement("if") : null
return this.finishNode(node, "IfStatement")
}
@@ -265,14 +284,14 @@ pp.parseSwitchStatement = function(node) {
node.cases = []
this.expect(tt.braceL)
this.labels.push(switchLabel)
this.enterLexicalScope()
this.enterScope(0)
// Statements under must be grouped (by label) in SwitchCase
// nodes. `cur` is used to keep the node that we are currently
// adding statements to.
let cur
for (let sawDefault = false; this.type != tt.braceR;) {
for (let sawDefault = false; this.type !== tt.braceR;) {
if (this.type === tt._case || this.type === tt._default) {
let isCase = this.type === tt._case
if (cur) this.finishNode(cur, "SwitchCase")
@@ -289,10 +308,10 @@ pp.parseSwitchStatement = function(node) {
this.expect(tt.colon)
} else {
if (!cur) this.unexpected()
cur.consequent.push(this.parseStatement(true))
cur.consequent.push(this.parseStatement(null))
}
}
this.exitLexicalScope()
this.exitScope()
if (cur) this.finishNode(cur, "SwitchCase")
this.next() // Closing brace
this.labels.pop()
@@ -319,13 +338,19 @@ pp.parseTryStatement = function(node) {
if (this.type === tt._catch) {
let clause = this.startNode()
this.next()
this.expect(tt.parenL)
clause.param = this.parseBindingAtom()
this.enterLexicalScope()
this.checkLVal(clause.param, "let")
this.expect(tt.parenR)
if (this.eat(tt.parenL)) {
clause.param = this.parseBindingAtom()
let simple = clause.param.type === "Identifier"
this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0)
this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL)
this.expect(tt.parenR)
} else {
if (this.options.ecmaVersion < 10) this.unexpected()
clause.param = null
this.enterScope(0)
}
clause.body = this.parseBlock(false)
this.exitLexicalScope()
this.exitScope()
node.handler = this.finishNode(clause, "CatchClause")
}
node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null
@@ -345,7 +370,7 @@ pp.parseWhileStatement = function(node) {
this.next()
node.test = this.parseParenExpression()
this.labels.push(loopLabel)
node.body = this.parseStatement(false)
node.body = this.parseStatement("while")
this.labels.pop()
return this.finishNode(node, "WhileStatement")
}
@@ -354,7 +379,7 @@ pp.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)
node.body = this.parseStatement("with")
return this.finishNode(node, "WithStatement")
}
@@ -363,25 +388,21 @@ pp.parseEmptyStatement = function(node) {
return this.finishNode(node, "EmptyStatement")
}
pp.parseLabeledStatement = function(node, maybeName, expr) {
pp.parseLabeledStatement = function(node, maybeName, expr, context) {
for (let label of this.labels)
if (label.name === maybeName)
this.raise(expr.start, "Label '" + maybeName + "' is already declared")
let kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null
for (let i = this.labels.length - 1; i >= 0; i--) {
let label = this.labels[i]
if (label.statementStart == node.start) {
if (label.statementStart === node.start) {
// Update information about previous labels on this node
label.statementStart = this.start
label.kind = kind
} else break
}
this.labels.push({name: maybeName, 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")
node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label")
this.labels.pop()
node.label = expr
return this.finishNode(node, "LabeledStatement")
@@ -397,20 +418,17 @@ pp.parseExpressionStatement = function(node, expr) {
// strict"` declarations when `allowStrict` is true (used for
// function bodies).
pp.parseBlock = function(createNewLexicalScope = true) {
let node = this.startNode()
pp.parseBlock = function(createNewLexicalScope = true, node = this.startNode(), exitStrict) {
node.body = []
this.expect(tt.braceL)
if (createNewLexicalScope) {
this.enterLexicalScope()
}
while (!this.eat(tt.braceR)) {
let stmt = this.parseStatement(true)
if (createNewLexicalScope) this.enterScope(0)
while (this.type !== tt.braceR) {
let stmt = this.parseStatement(null)
node.body.push(stmt)
}
if (createNewLexicalScope) {
this.exitLexicalScope()
}
if (exitStrict) this.strict = false
this.next()
if (createNewLexicalScope) this.exitScope()
return this.finishNode(node, "BlockStatement")
}
@@ -425,8 +443,8 @@ pp.parseFor = function(node, init) {
this.expect(tt.semi)
node.update = this.type === tt.parenR ? null : this.parseExpression()
this.expect(tt.parenR)
this.exitLexicalScope()
node.body = this.parseStatement(false)
node.body = this.parseStatement("for")
this.exitScope()
this.labels.pop()
return this.finishNode(node, "ForStatement")
}
@@ -435,21 +453,36 @@ pp.parseFor = function(node, init) {
// same from parser's perspective.
pp.parseForIn = function(node, init) {
let type = this.type === tt._in ? "ForInStatement" : "ForOfStatement"
const isForIn = this.type === tt._in
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")
if (
init.type === "VariableDeclaration" &&
init.declarations[0].init != null &&
(
!isForIn ||
this.options.ecmaVersion < 8 ||
this.strict ||
init.kind !== "var" ||
init.declarations[0].id.type !== "Identifier"
)
) {
this.raise(
init.start,
`${
isForIn ? "for-in" : "for-of"
} loop variable declaration may not have an initializer`
)
} else if (init.type === "AssignmentPattern") {
this.raise(init.start, "Invalid left-hand side in for-loop")
}
node.left = init
node.right = type == "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign()
node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign()
this.expect(tt.parenR)
this.exitLexicalScope()
node.body = this.parseStatement(false)
node.body = this.parseStatement("for")
this.exitScope()
this.labels.pop()
return this.finishNode(node, type)
return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement")
}
// Parse a list of variable declarations.
@@ -464,7 +497,7 @@ pp.parseVar = function(node, isFor, kind) {
decl.init = this.parseMaybeAssign(isFor)
} else if (kind === "const" && !(this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
this.unexpected()
} else if (decl.id.type != "Identifier" && !(isFor && (this.type === tt._in || this.isContextual("of")))) {
} else if (decl.id.type !== "Identifier" && !(isFor && (this.type === tt._in || this.isContextual("of")))) {
this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value")
} else {
decl.init = null
@@ -476,48 +509,52 @@ pp.parseVar = function(node, isFor, kind) {
}
pp.parseVarId = function(decl, kind) {
decl.id = this.parseBindingAtom(kind)
this.checkLVal(decl.id, kind, false)
decl.id = this.parseBindingAtom()
this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false)
}
// Parse a function declaration or literal (depending on the
// `isStatement` parameter).
const FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4
pp.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) {
// Parse a function declaration or literal (depending on the
// `statement & FUNC_STATEMENT`).
// Remove `allowExpressionBody` for 7.0.0, as it is only called with false
pp.parseFunction = function(node, statement, allowExpressionBody, isAsync) {
this.initFunction(node)
if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync)
if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) {
if (this.type === tt.star && (statement & FUNC_HANGING_STATEMENT))
this.unexpected()
node.generator = this.eat(tt.star)
}
if (this.options.ecmaVersion >= 8)
node.async = !!isAsync
if (isStatement) {
node.id = isStatement === "nullableID" && this.type != tt.name ? null : this.parseIdent()
if (node.id) {
this.checkLVal(node.id, "var")
}
if (statement & FUNC_STATEMENT) {
node.id = (statement & FUNC_NULLABLE_ID) && this.type !== tt.name ? null : this.parseIdent()
if (node.id && !(statement & FUNC_HANGING_STATEMENT))
// If it is a regular function declaration in sloppy mode, then it is
// subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
// mode depends on properties of the current scope (see
// treatFunctionsAsVar).
this.checkLVal(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION)
}
let oldInGen = this.inGenerator, oldInAsync = this.inAsync,
oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction
this.inGenerator = node.generator
this.inAsync = node.async
let oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos
this.yieldPos = 0
this.awaitPos = 0
this.inFunction = true
this.enterFunctionScope()
this.awaitIdentPos = 0
this.enterScope(functionFlags(node.async, node.generator))
if (!isStatement)
node.id = this.type == tt.name ? this.parseIdent() : null
if (!(statement & FUNC_STATEMENT))
node.id = this.type === tt.name ? this.parseIdent() : null
this.parseFunctionParams(node)
this.parseFunctionBody(node, allowExpressionBody)
this.parseFunctionBody(node, allowExpressionBody, false)
this.inGenerator = oldInGen
this.inAsync = oldInAsync
this.yieldPos = oldYieldPos
this.awaitPos = oldAwaitPos
this.inFunction = oldInFunc
return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
this.awaitIdentPos = oldAwaitIdentPos
return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression")
}
pp.parseFunctionParams = function(node) {
@@ -532,24 +569,34 @@ pp.parseFunctionParams = function(node) {
pp.parseClass = function(node, isStatement) {
this.next()
// ecma-262 14.6 Class Definitions
// A class definition is always strict mode code.
const oldStrict = this.strict
this.strict = true
this.parseClassId(node, isStatement)
this.parseClassSuper(node)
let classBody = this.startNode()
let hadConstructor = false
classBody.body = []
this.expect(tt.braceL)
while (!this.eat(tt.braceR)) {
const member = this.parseClassMember(classBody)
if (member && member.type === "MethodDefinition" && member.kind === "constructor") {
if (hadConstructor) this.raise(member.start, "Duplicate constructor in the same class")
hadConstructor = true
while (this.type !== tt.braceR) {
const element = this.parseClassElement(node.superClass !== null)
if (element) {
classBody.body.push(element)
if (element.type === "MethodDefinition" && element.kind === "constructor") {
if (hadConstructor) this.raise(element.start, "Duplicate constructor in the same class")
hadConstructor = true
}
}
}
this.strict = oldStrict
this.next()
node.body = this.finishNode(classBody, "ClassBody")
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
}
pp.parseClassMember = function(classBody) {
pp.parseClassElement = function(constructorAllowsSuper) {
if (this.eat(tt.semi)) return null
let method = this.startNode()
@@ -581,16 +628,18 @@ pp.parseClassMember = function(classBody) {
}
if (!method.key) this.parsePropertyName(method)
let {key} = method
let allowsDirectSuper = false
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"
allowsDirectSuper = constructorAllowsSuper
} 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)
this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper)
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)
@@ -600,13 +649,21 @@ pp.parseClassMember = function(classBody) {
return method
}
pp.parseClassMethod = function(classBody, method, isGenerator, isAsync) {
method.value = this.parseMethod(isGenerator, isAsync)
classBody.body.push(this.finishNode(method, "MethodDefinition"))
pp.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) {
method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper)
return this.finishNode(method, "MethodDefinition")
}
pp.parseClassId = function(node, isStatement) {
node.id = this.type === tt.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null
if (this.type === tt.name) {
node.id = this.parseIdent()
if (isStatement)
this.checkLVal(node.id, BIND_LEXICAL, false)
} else {
if (isStatement === true)
this.unexpected()
node.id = null
}
}
pp.parseClassSuper = function(node) {
@@ -619,6 +676,14 @@ pp.parseExport = function(node, exports) {
this.next()
// export * from '...'
if (this.eat(tt.star)) {
if (this.options.ecmaVersion >= 11) {
if (this.eatContextual("as")) {
node.exported = this.parseIdent(true)
this.checkExport(exports, node.exported.name, this.lastTokStart)
} else {
node.exported = null
}
}
this.expectContextual("from")
if (this.type !== tt.string) this.unexpected()
node.source = this.parseExprAtom()
@@ -632,7 +697,7 @@ pp.parseExport = function(node, exports) {
let fNode = this.startNode()
this.next()
if (isAsync) this.next()
node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync)
node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync)
} else if (this.type === tt._class) {
let cNode = this.startNode()
node.declaration = this.parseClass(cNode, "nullableID")
@@ -644,7 +709,7 @@ pp.parseExport = function(node, exports) {
}
// export var|const|let|function|class ...
if (this.shouldParseExportStatement()) {
node.declaration = this.parseStatement(true)
node.declaration = this.parseStatement(null)
if (node.declaration.type === "VariableDeclaration")
this.checkVariableExport(exports, node.declaration.declarations)
else
@@ -658,9 +723,11 @@ pp.parseExport = function(node, exports) {
if (this.type !== tt.string) this.unexpected()
node.source = this.parseExprAtom()
} else {
// check for keywords used as local names
for (let spec of node.specifiers) {
// check for keywords used as local names
this.checkUnreserved(spec.local)
// check if export is defined
this.checkLocalExport(spec.local)
}
node.source = null
@@ -679,22 +746,22 @@ pp.checkExport = function(exports, name, pos) {
pp.checkPatternExport = function(exports, pat) {
let type = pat.type
if (type == "Identifier")
if (type === "Identifier")
this.checkExport(exports, pat.name, pat.start)
else if (type == "ObjectPattern")
else if (type === "ObjectPattern")
for (let prop of pat.properties)
this.checkPatternExport(exports, prop)
else if (type == "ArrayPattern")
else if (type === "ArrayPattern")
for (let elt of pat.elements) {
if (elt) this.checkPatternExport(exports, elt)
}
else if (type == "Property")
else if (type === "Property")
this.checkPatternExport(exports, pat.value)
else if (type == "AssignmentPattern")
else if (type === "AssignmentPattern")
this.checkPatternExport(exports, pat.left)
else if (type == "RestElement")
else if (type === "RestElement")
this.checkPatternExport(exports, pat.argument)
else if (type == "ParenthesizedExpression")
else if (type === "ParenthesizedExpression")
this.checkPatternExport(exports, pat.expression)
}
@@ -759,7 +826,7 @@ pp.parseImportSpecifiers = function() {
// import defaultObj, { x, y as z } from '...'
let node = this.startNode()
node.local = this.parseIdent()
this.checkLVal(node.local, "let")
this.checkLVal(node.local, BIND_LEXICAL)
nodes.push(this.finishNode(node, "ImportDefaultSpecifier"))
if (!this.eat(tt.comma)) return nodes
}
@@ -768,7 +835,7 @@ pp.parseImportSpecifiers = function() {
this.next()
this.expectContextual("as")
node.local = this.parseIdent()
this.checkLVal(node.local, "let")
this.checkLVal(node.local, BIND_LEXICAL)
nodes.push(this.finishNode(node, "ImportNamespaceSpecifier"))
return nodes
}
@@ -787,7 +854,7 @@ pp.parseImportSpecifiers = function() {
this.checkUnreserved(node.imported)
node.local = node.imported
}
this.checkLVal(node.local, "let")
this.checkLVal(node.local, BIND_LEXICAL)
nodes.push(this.finishNode(node, "ImportSpecifier"))
}
return nodes

View File

@@ -45,13 +45,13 @@ pp.braceIsBlock = function(prevType) {
// The check for `tt.name && exprAllowed` detects whether we are
// after a `yield` or `of` construct. See the `updateContext` for
// `tt.name`.
if (prevType === tt._return || prevType == tt.name && this.exprAllowed)
if (prevType === tt._return || prevType === tt.name && this.exprAllowed)
return lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR || prevType == tt.arrow)
if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR || prevType === tt.arrow)
return true
if (prevType == tt.braceL)
if (prevType === tt.braceL)
return parent === types.b_stat
if (prevType == tt._var || prevType == tt.name)
if (prevType === tt._var || prevType === tt._const || prevType === tt.name)
return false
return !this.exprAllowed
}
@@ -67,7 +67,7 @@ pp.inGeneratorContext = function() {
pp.updateContext = function(prevType) {
let update, type = this.type
if (type.keyword && prevType == tt.dot)
if (type.keyword && prevType === tt.dot)
this.exprAllowed = false
else if (update = type.updateContext)
update.call(this, prevType)
@@ -78,7 +78,7 @@ pp.updateContext = function(prevType) {
// Token-specific context update code
tt.parenR.updateContext = tt.braceR.updateContext = function() {
if (this.context.length == 1) {
if (this.context.length === 1) {
this.exprAllowed = true
return
}
@@ -111,6 +111,7 @@ tt.incDec.updateContext = function() {
tt._function.updateContext = tt._class.updateContext = function(prevType) {
if (prevType.beforeExpr && prevType !== tt.semi && prevType !== tt._else &&
!(prevType === tt._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) &&
!((prevType === tt.colon || prevType === tt.braceL) && this.curContext() === types.b_stat))
this.context.push(types.f_expr)
else
@@ -127,7 +128,7 @@ tt.backQuote.updateContext = function() {
}
tt.star.updateContext = function(prevType) {
if (prevType == tt._function) {
if (prevType === tt._function) {
let index = this.context.length - 1
if (this.context[index] === types.f_expr)
this.context[index] = types.f_expr_gen
@@ -139,9 +140,9 @@ tt.star.updateContext = function(prevType) {
tt.name.updateContext = function(prevType) {
let allowed = false
if (this.options.ecmaVersion >= 6) {
if (this.value == "of" && !this.exprAllowed ||
this.value == "yield" && this.inGeneratorContext())
if (this.options.ecmaVersion >= 6 && prevType !== tt.dot) {
if (this.value === "of" && !this.exprAllowed ||
this.value === "yield" && this.inGeneratorContext())
allowed = true
}
this.exprAllowed = allowed

View File

@@ -28,7 +28,9 @@ const pp = Parser.prototype
// Move to the next token
pp.next = function() {
pp.next = function(ignoreEscapeSequenceInKeyword) {
if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc)
this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword)
if (this.options.onToken)
this.options.onToken(new Token(this))
@@ -219,7 +221,7 @@ pp.readToken_mult_modulo_exp = function(code) { // '%*'
let tokentype = code === 42 ? tt.star : tt.modulo
// exponentiation operator ** and **=
if (this.options.ecmaVersion >= 7 && code == 42 && next === 42) {
if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
++size
tokentype = tt.starstar
next = this.input.charCodeAt(this.pos + 2)
@@ -245,7 +247,7 @@ pp.readToken_caret = function() { // '^'
pp.readToken_plus_min = function(code) { // '+-'
let next = this.input.charCodeAt(this.pos + 1)
if (next === code) {
if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 &&
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)
@@ -266,8 +268,8 @@ pp.readToken_lt_gt = function(code) { // '<>'
if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1)
return this.finishOp(tt.bitShift, size)
}
if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 &&
this.input.charCodeAt(this.pos + 3) == 45) {
if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
this.input.charCodeAt(this.pos + 3) === 45) {
// `<!--`, an XML-style comment that should be interpreted as a line comment
this.skipLineComment(4)
this.skipSpace()
@@ -427,10 +429,14 @@ pp.readInt = function(radix, len) {
}
pp.readRadixNumber = function(radix) {
let start = this.pos
this.pos += 2 // 0x
let val = this.readInt(radix)
if (val == null) this.raise(this.start + 2, "Expected number in radix " + radix)
if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.pos, "Identifier directly after number")
if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
val = typeof BigInt !== "undefined" ? BigInt(this.input.slice(start, this.pos)) : null
++this.pos
} else if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.pos, "Identifier directly after number")
return this.finishToken(tt.num, val)
}
@@ -441,8 +447,15 @@ pp.readNumber = function(startsWithDot) {
if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number")
let octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48
if (octal && this.strict) this.raise(start, "Invalid number")
if (octal && /[89]/.test(this.input.slice(start, this.pos))) octal = false
let next = this.input.charCodeAt(this.pos)
if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
let str = this.input.slice(start, this.pos)
let val = typeof BigInt !== "undefined" ? BigInt(str) : null
++this.pos
if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.pos, "Identifier directly after number")
return this.finishToken(tt.num, val)
}
if (octal && /[89]/.test(this.input.slice(start, this.pos))) octal = false
if (next === 46 && !octal) { // '.'
++this.pos
this.readInt(10)
@@ -495,7 +508,7 @@ pp.readString = function(quote) {
out += this.readEscapedChar(false)
chunkStart = this.pos
} else {
if (isNewLine(ch)) this.raise(this.start, "Unterminated string constant")
if (isNewLine(ch, this.options.ecmaVersion >= 10)) this.raise(this.start, "Unterminated string constant")
++this.pos
}
}
@@ -617,6 +630,18 @@ pp.readEscapedChar = function(inTemplate) {
case 10: // ' \n'
if (this.options.locations) { this.lineStart = this.pos; ++this.curLine }
return ""
case 56:
case 57:
if (inTemplate) {
const codePos = this.pos - 1
this.invalidStringToken(
codePos,
"Invalid escape sequence in template string"
)
return null
}
default:
if (ch >= 48 && ch <= 55) {
let octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0]
@@ -627,7 +652,7 @@ pp.readEscapedChar = function(inTemplate) {
}
this.pos += octalStr.length - 1
ch = this.input.charCodeAt(this.pos)
if ((octalStr !== "0" || ch == 56 || ch == 57) && (this.strict || inTemplate)) {
if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
this.invalidStringToken(
this.pos - 1 - octalStr.length,
inTemplate
@@ -637,6 +662,11 @@ pp.readEscapedChar = function(inTemplate) {
}
return String.fromCharCode(octal)
}
if (isNewLine(ch)) {
// Unicode new line characters after \ get removed from output in both
// template literals and strings
return ""
}
return String.fromCharCode(ch)
}
}
@@ -668,7 +698,7 @@ pp.readWord1 = function() {
this.containsEsc = true
word += this.input.slice(chunkStart, this.pos)
let escStart = this.pos
if (this.input.charCodeAt(++this.pos) != 117) // "u"
if (this.input.charCodeAt(++this.pos) !== 117) // "u"
this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX")
++this.pos
let esc = this.readCodePoint()
@@ -691,7 +721,6 @@ pp.readWord = function() {
let word = this.readWord1()
let type = tt.name
if (this.keywords.test(word)) {
if (this.containsEsc) this.raiseRecoverable(this.start, "Escape sequence in keyword " + word)
type = keywordTypes[word]
}
return this.finishToken(type, word)

View File

@@ -136,7 +136,7 @@ export const types = {
_class: kw("class", startsExpr),
_extends: kw("extends", beforeExpr),
_export: kw("export"),
_import: kw("import"),
_import: kw("import", startsExpr),
_null: kw("null", startsExpr),
_true: kw("true", startsExpr),
_false: kw("false", startsExpr),

View File

@@ -1,463 +1,49 @@
const data = {
"$LONE": [
"ASCII",
"ASCII_Hex_Digit",
"AHex",
"Alphabetic",
"Alpha",
"Any",
"Assigned",
"Bidi_Control",
"Bidi_C",
"Bidi_Mirrored",
"Bidi_M",
"Case_Ignorable",
"CI",
"Cased",
"Changes_When_Casefolded",
"CWCF",
"Changes_When_Casemapped",
"CWCM",
"Changes_When_Lowercased",
"CWL",
"Changes_When_NFKC_Casefolded",
"CWKCF",
"Changes_When_Titlecased",
"CWT",
"Changes_When_Uppercased",
"CWU",
"Dash",
"Default_Ignorable_Code_Point",
"DI",
"Deprecated",
"Dep",
"Diacritic",
"Dia",
"Emoji",
"Emoji_Component",
"Emoji_Modifier",
"Emoji_Modifier_Base",
"Emoji_Presentation",
"Extender",
"Ext",
"Grapheme_Base",
"Gr_Base",
"Grapheme_Extend",
"Gr_Ext",
"Hex_Digit",
"Hex",
"IDS_Binary_Operator",
"IDSB",
"IDS_Trinary_Operator",
"IDST",
"ID_Continue",
"IDC",
"ID_Start",
"IDS",
"Ideographic",
"Ideo",
"Join_Control",
"Join_C",
"Logical_Order_Exception",
"LOE",
"Lowercase",
"Lower",
"Math",
"Noncharacter_Code_Point",
"NChar",
"Pattern_Syntax",
"Pat_Syn",
"Pattern_White_Space",
"Pat_WS",
"Quotation_Mark",
"QMark",
"Radical",
"Regional_Indicator",
"RI",
"Sentence_Terminal",
"STerm",
"Soft_Dotted",
"SD",
"Terminal_Punctuation",
"Term",
"Unified_Ideograph",
"UIdeo",
"Uppercase",
"Upper",
"Variation_Selector",
"VS",
"White_Space",
"space",
"XID_Continue",
"XIDC",
"XID_Start",
"XIDS"
],
"General_Category": [
"Cased_Letter",
"LC",
"Close_Punctuation",
"Pe",
"Connector_Punctuation",
"Pc",
"Control",
"Cc",
"cntrl",
"Currency_Symbol",
"Sc",
"Dash_Punctuation",
"Pd",
"Decimal_Number",
"Nd",
"digit",
"Enclosing_Mark",
"Me",
"Final_Punctuation",
"Pf",
"Format",
"Cf",
"Initial_Punctuation",
"Pi",
"Letter",
"L",
"Letter_Number",
"Nl",
"Line_Separator",
"Zl",
"Lowercase_Letter",
"Ll",
"Mark",
"M",
"Combining_Mark",
"Math_Symbol",
"Sm",
"Modifier_Letter",
"Lm",
"Modifier_Symbol",
"Sk",
"Nonspacing_Mark",
"Mn",
"Number",
"N",
"Open_Punctuation",
"Ps",
"Other",
"C",
"Other_Letter",
"Lo",
"Other_Number",
"No",
"Other_Punctuation",
"Po",
"Other_Symbol",
"So",
"Paragraph_Separator",
"Zp",
"Private_Use",
"Co",
"Punctuation",
"P",
"punct",
"Separator",
"Z",
"Space_Separator",
"Zs",
"Spacing_Mark",
"Mc",
"Surrogate",
"Cs",
"Symbol",
"S",
"Titlecase_Letter",
"Lt",
"Unassigned",
"Cn",
"Uppercase_Letter",
"Lu"
],
"Script": [
"Adlam",
"Adlm",
"Ahom",
"Anatolian_Hieroglyphs",
"Hluw",
"Arabic",
"Arab",
"Armenian",
"Armn",
"Avestan",
"Avst",
"Balinese",
"Bali",
"Bamum",
"Bamu",
"Bassa_Vah",
"Bass",
"Batak",
"Batk",
"Bengali",
"Beng",
"Bhaiksuki",
"Bhks",
"Bopomofo",
"Bopo",
"Brahmi",
"Brah",
"Braille",
"Brai",
"Buginese",
"Bugi",
"Buhid",
"Buhd",
"Canadian_Aboriginal",
"Cans",
"Carian",
"Cari",
"Caucasian_Albanian",
"Aghb",
"Chakma",
"Cakm",
"Cham",
"Cherokee",
"Cher",
"Common",
"Zyyy",
"Coptic",
"Copt",
"Qaac",
"Cuneiform",
"Xsux",
"Cypriot",
"Cprt",
"Cyrillic",
"Cyrl",
"Deseret",
"Dsrt",
"Devanagari",
"Deva",
"Duployan",
"Dupl",
"Egyptian_Hieroglyphs",
"Egyp",
"Elbasan",
"Elba",
"Ethiopic",
"Ethi",
"Georgian",
"Geor",
"Glagolitic",
"Glag",
"Gothic",
"Goth",
"Grantha",
"Gran",
"Greek",
"Grek",
"Gujarati",
"Gujr",
"Gurmukhi",
"Guru",
"Han",
"Hani",
"Hangul",
"Hang",
"Hanunoo",
"Hano",
"Hatran",
"Hatr",
"Hebrew",
"Hebr",
"Hiragana",
"Hira",
"Imperial_Aramaic",
"Armi",
"Inherited",
"Zinh",
"Qaai",
"Inscriptional_Pahlavi",
"Phli",
"Inscriptional_Parthian",
"Prti",
"Javanese",
"Java",
"Kaithi",
"Kthi",
"Kannada",
"Knda",
"Katakana",
"Kana",
"Kayah_Li",
"Kali",
"Kharoshthi",
"Khar",
"Khmer",
"Khmr",
"Khojki",
"Khoj",
"Khudawadi",
"Sind",
"Lao",
"Laoo",
"Latin",
"Latn",
"Lepcha",
"Lepc",
"Limbu",
"Limb",
"Linear_A",
"Lina",
"Linear_B",
"Linb",
"Lisu",
"Lycian",
"Lyci",
"Lydian",
"Lydi",
"Mahajani",
"Mahj",
"Malayalam",
"Mlym",
"Mandaic",
"Mand",
"Manichaean",
"Mani",
"Marchen",
"Marc",
"Masaram_Gondi",
"Gonm",
"Meetei_Mayek",
"Mtei",
"Mende_Kikakui",
"Mend",
"Meroitic_Cursive",
"Merc",
"Meroitic_Hieroglyphs",
"Mero",
"Miao",
"Plrd",
"Modi",
"Mongolian",
"Mong",
"Mro",
"Mroo",
"Multani",
"Mult",
"Myanmar",
"Mymr",
"Nabataean",
"Nbat",
"New_Tai_Lue",
"Talu",
"Newa",
"Nko",
"Nkoo",
"Nushu",
"Nshu",
"Ogham",
"Ogam",
"Ol_Chiki",
"Olck",
"Old_Hungarian",
"Hung",
"Old_Italic",
"Ital",
"Old_North_Arabian",
"Narb",
"Old_Permic",
"Perm",
"Old_Persian",
"Xpeo",
"Old_South_Arabian",
"Sarb",
"Old_Turkic",
"Orkh",
"Oriya",
"Orya",
"Osage",
"Osge",
"Osmanya",
"Osma",
"Pahawh_Hmong",
"Hmng",
"Palmyrene",
"Palm",
"Pau_Cin_Hau",
"Pauc",
"Phags_Pa",
"Phag",
"Phoenician",
"Phnx",
"Psalter_Pahlavi",
"Phlp",
"Rejang",
"Rjng",
"Runic",
"Runr",
"Samaritan",
"Samr",
"Saurashtra",
"Saur",
"Sharada",
"Shrd",
"Shavian",
"Shaw",
"Siddham",
"Sidd",
"SignWriting",
"Sgnw",
"Sinhala",
"Sinh",
"Sora_Sompeng",
"Sora",
"Soyombo",
"Soyo",
"Sundanese",
"Sund",
"Syloti_Nagri",
"Sylo",
"Syriac",
"Syrc",
"Tagalog",
"Tglg",
"Tagbanwa",
"Tagb",
"Tai_Le",
"Tale",
"Tai_Tham",
"Lana",
"Tai_Viet",
"Tavt",
"Takri",
"Takr",
"Tamil",
"Taml",
"Tangut",
"Tang",
"Telugu",
"Telu",
"Thaana",
"Thaa",
"Thai",
"Tibetan",
"Tibt",
"Tifinagh",
"Tfng",
"Tirhuta",
"Tirh",
"Ugaritic",
"Ugar",
"Vai",
"Vaii",
"Warang_Citi",
"Wara",
"Yi",
"Yiii",
"Zanabazar_Square",
"Zanb"
]
import {wordsRegexp} from "./util.js"
// This file contains Unicode properties extracted from the ECMAScript
// specification. The lists are extracted like so:
// $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText)
// #table-binary-unicode-properties
const ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS"
const ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic"
const ecma11BinaryProperties = ecma10BinaryProperties
const unicodeBinaryProperties = {
9: ecma9BinaryProperties,
10: ecma10BinaryProperties,
11: ecma11BinaryProperties
}
Array.prototype.push.apply(data.$LONE, data.General_Category)
data.gc = data.General_Category
data.sc = data.Script_Extensions = data.scx = data.Script
// #table-unicode-general-category-values
const unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"
// #table-unicode-script-values
const ecma9ScriptValues = "Adlam Adlm Ahom Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb"
const ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd"
const ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho"
const unicodeScriptValues = {
9: ecma9ScriptValues,
10: ecma10ScriptValues,
11: ecma11ScriptValues
}
const data = {}
function buildUnicodeData(ecmaVersion) {
let d = data[ecmaVersion] = {
binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),
nonBinary: {
General_Category: wordsRegexp(unicodeGeneralCategoryValues),
Script: wordsRegexp(unicodeScriptValues[ecmaVersion])
}
}
d.nonBinary.Script_Extensions = d.nonBinary.Script
d.nonBinary.gc = d.nonBinary.General_Category
d.nonBinary.sc = d.nonBinary.Script
d.nonBinary.scx = d.nonBinary.Script_Extensions
}
buildUnicodeData(9)
buildUnicodeData(10)
buildUnicodeData(11)
export default data

View File

@@ -9,3 +9,7 @@ export function has(obj, propName) {
export const isArray = Array.isArray || ((obj) => (
toString.call(obj) === "[object Array]"
))
export function wordsRegexp(words) {
return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
}

View File

@@ -1,370 +0,0 @@
// AST walker module for Mozilla Parser API compatible trees
// A simple walk is one where you simply specify callbacks to be
// called on specific nodes. The last two arguments are optional. A
// simple use would be
//
// walk.simple(myTree, {
// Expression: function(node) { ... }
// });
//
// to do something with all expressions. All Parser API node types
// can be used to identify node types, as well as Expression,
// Statement, and ScopeBody, which denote categories of nodes.
//
// The base argument can be used to pass a custom (recursive)
// walker, and state can be used to give this walked an initial
// state.
export function simple(node, visitors, baseVisitor = base, state, override) {
(function c(node, st, override) {
let type = override || node.type, found = visitors[type]
baseVisitor[type](node, st, c)
if (found) found(node, st)
})(node, state, override)
}
// An ancestor walk keeps an array of ancestor nodes (including the
// current node) and passes them to the callback as third parameter
// (and also as state parameter when no other state is present).
export function ancestor(node, visitors, baseVisitor = base, state) {
let ancestors = []
;(function c(node, st, override) {
let type = override || node.type, found = visitors[type]
let isNew = node != ancestors[ancestors.length - 1]
if (isNew) ancestors.push(node)
baseVisitor[type](node, st, c)
if (found) found(node, st || ancestors, ancestors)
if (isNew) ancestors.pop()
})(node, state)
}
// A recursive walk is one where your functions override the default
// walkers. They can modify and replace the state parameter that's
// threaded through the walk, and can opt how and whether to walk
// their child nodes (by calling their third argument on these
// nodes).
export function recursive(node, state, funcs, baseVisitor, override) {
let visitor = funcs ? exports.make(funcs, baseVisitor) : baseVisitor
;(function c(node, st, override) {
visitor[override || node.type](node, st, c)
})(node, state, override)
}
function makeTest(test) {
if (typeof test == "string")
return type => type == test
else if (!test)
return () => true
else
return test
}
class Found {
constructor(node, state) { this.node = node; this.state = state }
}
// A full walk triggers the callback on each node
export function full(node, callback, baseVisitor = base, state, override) {
(function c(node, st, override) {
let type = override || node.type
baseVisitor[type](node, st, c)
if (!override) callback(node, st, type)
})(node, state, override)
}
// An fullAncestor walk is like an ancestor walk, but triggers
// the callback on each node
export function fullAncestor(node, callback, baseVisitor = base, state) {
let ancestors = []
;(function c(node, st, override) {
let type = override || node.type
let isNew = node != ancestors[ancestors.length - 1]
if (isNew) ancestors.push(node)
baseVisitor[type](node, st, c)
if (!override) callback(node, st || ancestors, ancestors, type)
if (isNew) ancestors.pop()
})(node, state)
}
// Find a node with a given start, end, and type (all are optional,
// null can be used as wildcard). Returns a {node, state} object, or
// undefined when it doesn't find a matching node.
export function findNodeAt(node, start, end, test, baseVisitor = base, state) {
test = makeTest(test)
try {
(function c(node, st, override) {
let type = override || node.type
if ((start == null || node.start <= start) &&
(end == null || node.end >= end))
baseVisitor[type](node, st, c)
if ((start == null || node.start == start) &&
(end == null || node.end == end) &&
test(type, node))
throw new Found(node, st)
})(node, state)
} catch (e) {
if (e instanceof Found) return e
throw e
}
}
// Find the innermost node of a given type that contains the given
// position. Interface similar to findNodeAt.
export function findNodeAround(node, pos, test, baseVisitor = base, state) {
test = makeTest(test)
try {
(function c(node, st, override) {
let type = override || node.type
if (node.start > pos || node.end < pos) return
baseVisitor[type](node, st, c)
if (test(type, node)) throw new Found(node, st)
})(node, state)
} catch (e) {
if (e instanceof Found) return e
throw e
}
}
// Find the outermost matching node after a given position.
export function findNodeAfter(node, pos, test, baseVisitor = base, state) {
test = makeTest(test)
try {
(function c(node, st, override) {
if (node.end < pos) return
let type = override || node.type
if (node.start >= pos && test(type, node)) throw new Found(node, st)
baseVisitor[type](node, st, c)
})(node, state)
} catch (e) {
if (e instanceof Found) return e
throw e
}
}
// Find the outermost matching node before a given position.
export function findNodeBefore(node, pos, test, baseVisitor = base, state) {
test = makeTest(test)
let max
;(function c(node, st, override) {
if (node.start > pos) return
let type = override || node.type
if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))
max = new Found(node, st)
baseVisitor[type](node, st, c)
})(node, state)
return max
}
// Fallback to an Object.create polyfill for older environments.
const create = Object.create || function(proto) {
function Ctor() {}
Ctor.prototype = proto
return new Ctor
}
// Used to create a custom walker. Will fill in all missing node
// type properties with the defaults.
export function make(funcs, baseVisitor = base) {
let visitor = create(baseVisitor)
for (let type in funcs) visitor[type] = funcs[type]
return visitor
}
function skipThrough(node, st, c) { c(node, st) }
function ignore(_node, _st, _c) {}
// Node walkers.
export const base = {}
base.Program = base.BlockStatement = (node, st, c) => {
for (let stmt of node.body)
c(stmt, st, "Statement")
}
base.Statement = skipThrough
base.EmptyStatement = ignore
base.ExpressionStatement = base.ParenthesizedExpression =
(node, st, c) => c(node.expression, st, "Expression")
base.IfStatement = (node, st, c) => {
c(node.test, st, "Expression")
c(node.consequent, st, "Statement")
if (node.alternate) c(node.alternate, st, "Statement")
}
base.LabeledStatement = (node, st, c) => c(node.body, st, "Statement")
base.BreakStatement = base.ContinueStatement = ignore
base.WithStatement = (node, st, c) => {
c(node.object, st, "Expression")
c(node.body, st, "Statement")
}
base.SwitchStatement = (node, st, c) => {
c(node.discriminant, st, "Expression")
for (let cs of node.cases) {
if (cs.test) c(cs.test, st, "Expression")
for (let cons of cs.consequent)
c(cons, st, "Statement")
}
}
base.SwitchCase = (node, st, c) => {
if (node.test) c(node.test, st, "Expression")
for (let cons of node.consequent)
c(cons, st, "Statement")
}
base.ReturnStatement = base.YieldExpression = base.AwaitExpression = (node, st, c) => {
if (node.argument) c(node.argument, st, "Expression")
}
base.ThrowStatement = base.SpreadElement =
(node, st, c) => c(node.argument, st, "Expression")
base.TryStatement = (node, st, c) => {
c(node.block, st, "Statement")
if (node.handler) c(node.handler, st)
if (node.finalizer) c(node.finalizer, st, "Statement")
}
base.CatchClause = (node, st, c) => {
c(node.param, st, "Pattern")
c(node.body, st, "ScopeBody")
}
base.WhileStatement = base.DoWhileStatement = (node, st, c) => {
c(node.test, st, "Expression")
c(node.body, st, "Statement")
}
base.ForStatement = (node, st, c) => {
if (node.init) c(node.init, st, "ForInit")
if (node.test) c(node.test, st, "Expression")
if (node.update) c(node.update, st, "Expression")
c(node.body, st, "Statement")
}
base.ForInStatement = base.ForOfStatement = (node, st, c) => {
c(node.left, st, "ForInit")
c(node.right, st, "Expression")
c(node.body, st, "Statement")
}
base.ForInit = (node, st, c) => {
if (node.type == "VariableDeclaration") c(node, st)
else c(node, st, "Expression")
}
base.DebuggerStatement = ignore
base.FunctionDeclaration = (node, st, c) => c(node, st, "Function")
base.VariableDeclaration = (node, st, c) => {
for (let decl of node.declarations)
c(decl, st)
}
base.VariableDeclarator = (node, st, c) => {
c(node.id, st, "Pattern")
if (node.init) c(node.init, st, "Expression")
}
base.Function = (node, st, c) => {
if (node.id) c(node.id, st, "Pattern")
for (let param of node.params)
c(param, st, "Pattern")
c(node.body, st, node.expression ? "ScopeExpression" : "ScopeBody")
}
// FIXME drop these node types in next major version
// (They are awkward, and in ES6 every block can be a scope.)
base.ScopeBody = (node, st, c) => c(node, st, "Statement")
base.ScopeExpression = (node, st, c) => c(node, st, "Expression")
base.Pattern = (node, st, c) => {
if (node.type == "Identifier")
c(node, st, "VariablePattern")
else if (node.type == "MemberExpression")
c(node, st, "MemberPattern")
else
c(node, st)
}
base.VariablePattern = ignore
base.MemberPattern = skipThrough
base.RestElement = (node, st, c) => c(node.argument, st, "Pattern")
base.ArrayPattern = (node, st, c) => {
for (let elt of node.elements) {
if (elt) c(elt, st, "Pattern")
}
}
base.ObjectPattern = (node, st, c) => {
for (let prop of node.properties) {
if (prop.type === "Property") {
if (prop.computed) c(prop.key, st, "Expression")
c(prop.value, st, "Pattern")
} else if (prop.type === "RestElement") {
c(prop.argument, st, "Pattern")
}
}
}
base.Expression = skipThrough
base.ThisExpression = base.Super = base.MetaProperty = ignore
base.ArrayExpression = (node, st, c) => {
for (let elt of node.elements) {
if (elt) c(elt, st, "Expression")
}
}
base.ObjectExpression = (node, st, c) => {
for (let prop of node.properties)
c(prop, st)
}
base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration
base.SequenceExpression = base.TemplateLiteral = (node, st, c) => {
for (let expr of node.expressions)
c(expr, st, "Expression")
}
base.UnaryExpression = base.UpdateExpression = (node, st, c) => {
c(node.argument, st, "Expression")
}
base.BinaryExpression = base.LogicalExpression = (node, st, c) => {
c(node.left, st, "Expression")
c(node.right, st, "Expression")
}
base.AssignmentExpression = base.AssignmentPattern = (node, st, c) => {
c(node.left, st, "Pattern")
c(node.right, st, "Expression")
}
base.ConditionalExpression = (node, st, c) => {
c(node.test, st, "Expression")
c(node.consequent, st, "Expression")
c(node.alternate, st, "Expression")
}
base.NewExpression = base.CallExpression = (node, st, c) => {
c(node.callee, st, "Expression")
if (node.arguments)
for (let arg of node.arguments)
c(arg, st, "Expression")
}
base.MemberExpression = (node, st, c) => {
c(node.object, st, "Expression")
if (node.computed) c(node.property, st, "Expression")
}
base.ExportNamedDeclaration = base.ExportDefaultDeclaration = (node, st, c) => {
if (node.declaration)
c(node.declaration, st, node.type == "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression")
if (node.source) c(node.source, st, "Expression")
}
base.ExportAllDeclaration = (node, st, c) => {
c(node.source, st, "Expression")
}
base.ImportDeclaration = (node, st, c) => {
for (let spec of node.specifiers)
c(spec, st)
c(node.source, st, "Expression")
}
base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.Literal = ignore
base.TaggedTemplateExpression = (node, st, c) => {
c(node.tag, st, "Expression")
c(node.quasi, st, "Expression")
}
base.ClassDeclaration = base.ClassExpression = (node, st, c) => c(node, st, "Class")
base.Class = (node, st, c) => {
if (node.id) c(node.id, st, "Pattern")
if (node.superClass) c(node.superClass, st, "Expression")
c(node.body, st)
}
base.ClassBody = (node, st, c) => {
for (let elt of node.body)
c(elt, st)
}
base.MethodDefinition = base.Property = (node, st, c) => {
if (node.computed) c(node.key, st, "Expression")
c(node.value, st, "Expression")
}

View File

@@ -4,10 +4,10 @@
export const lineBreak = /\r\n?|\n|\u2028|\u2029/
export const lineBreakG = new RegExp(lineBreak.source, "g")
export function isNewLine(code) {
return code === 10 || code === 13 || code === 0x2028 || code === 0x2029
export function isNewLine(code, ecma2019String) {
return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029))
}
export const nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/
export const nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/
export const skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g

View File

@@ -572,6 +572,7 @@ describe("symlinking node_modules", () => {
assert.strictEqual(tuple1, tuple2);
});
Meteor.isClient &&
it("should support application-compiled `npm link`ed packages", () => {
assert.strictEqual(
require.resolve("acorn"),