summaryrefslogtreecommitdiff
path: root/data/extensions/jid1-KtlZuoiikVfFew@jetpack
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/jid1-KtlZuoiikVfFew@jetpack')
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/manifest.mf84
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.rsabin4326 -> 4326 bytes
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.sf6
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/bundle.js8629
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/common/Test.js55
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/contactFinder.js (renamed from data/extensions/jid1-KtlZuoiikVfFew@jetpack/contact_finder.js)203
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/dialog.css91
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/externalLicenseChecker.js31
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/overlay.css28
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/common.css12
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/display-panel.html2
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/main_panel.js12
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/panel-styles.css9
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/preferences_panel.html10
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/prefs.css4
-rw-r--r--data/extensions/jid1-KtlZuoiikVfFew@jetpack/manifest.json2
16 files changed, 7208 insertions, 1970 deletions
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/manifest.mf b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/manifest.mf
index 867154f..3e84b45 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/manifest.mf
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/manifest.mf
@@ -2,21 +2,15 @@ Manifest-Version: 1.0
Name: bundle.js
Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: 6en04qcAU18ecDlENLfTlw==
-SHA1-Digest: 9o/KrI9OZHVJ04Guze33SZYA6jc=
-SHA256-Digest: Yq0zZogzXpo7fURcjxPyeln8NGl3Ok69B14XKIqP1RI=
-
-Name: contact_finder.js
-Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: q/te8c0vlLG/eykRRTaAVg==
-SHA1-Digest: rXmHK1oZCxtvo3pPu/b69+I4sko=
-SHA256-Digest: rUweT65BRWMtP8xWrqlZWNXL3cv9QTl9hKQRJ5iHC88=
+MD5-Digest: chnl5FFMGAinEHLcQuUqqg==
+SHA1-Digest: MnAW5ePdtZFoxR44zTuhPsgS3sM=
+SHA256-Digest: rAnXKFhbofKxsMBkJc7AIqXPvOOAA7YqJJs+9Oa9UYc=
Name: manifest.json
Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: G9ICf62jdF9HQ4lY6CTH3g==
-SHA1-Digest: t/B/vPtRsG19/h9HxfquWvCTRcw=
-SHA256-Digest: MlytL27Z277zKvkch7BG2OGizYWNRV1wmTTQx2MLnmQ=
+MD5-Digest: DP7iWDR2WO63YX58ICbyyg==
+SHA1-Digest: 0GC61V7+4ekeT36GNT3r3k3Sxuw=
+SHA256-Digest: Ym+wro43TH9HqfxH1sPRDRAxiHqllCoGeSItnjTiOuk=
Name: common/Storage.js
Digest-Algorithms: MD5 SHA1 SHA256
@@ -24,11 +18,35 @@ MD5-Digest: XknN7QnoZ+4hUyB8Iq9p4Q==
SHA1-Digest: ULBbLu6E4/AxcM13yJgh0WL7mg0=
SHA256-Digest: eqlSKI2pauLf2OfK0oJbtM1dmBpTDDDcGDJwqteWg8o=
+Name: common/Test.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: /xrvG2mKv/WwH2xV6le5vw==
+SHA1-Digest: V6rYjMO15exXtS8Gsk6qzutJHzY=
+SHA256-Digest: BvUhNJgjyuD4MGFa3Ga2gEDunpwbn8PiDt1zeG9SJRs=
+
+Name: content/contactFinder.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: PWVDe7GG9dSGs3ml0tSUPw==
+SHA1-Digest: 6kejS+GJk1afxi0q0xhCf61QKIw=
+SHA256-Digest: 5sJk/9cmVNxCQAk9tFUuzXTZceDI7hXlRkUY2OqWL1Q=
+
+Name: content/dialog.css
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: W8uik0AALIYU8sh9/lyJjA==
+SHA1-Digest: OtHx7b2GxD8MYhJ2WJ6+FESRLt0=
+SHA256-Digest: PmP1jGEKgeLl698KLlhzFHKr1kKuXGjs2fekHWfri40=
+
Name: content/externalLicenseChecker.js
Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: kgiipkwEPP4VVS2UsjZpgw==
-SHA1-Digest: 7oBFXS9UowGs/1+cYzTgMzy8OPg=
-SHA256-Digest: cl8v1UKiuokgyvEBhpsT8bz1ow6jkrFJhYGDgvS+Cis=
+MD5-Digest: Sl2FdQKCTDjZjyUMSMBvhw==
+SHA1-Digest: hMvdvWdSf/w9EvoTCZfaTTeBDWs=
+SHA256-Digest: MrvR4yCtKDVzKOKf2LIef6uTbYctTX3J84QFReMuvgw=
+
+Name: content/overlay.css
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: hLA4XnU1U6SRi4eY1k56Vw==
+SHA1-Digest: HiornR2qULIjaGkBgK9+4mo6zhE=
+SHA256-Digest: QpbfWaEXXtxpCOA7o11c0plSmemhdrEp/AJF8uegrME=
Name: html/background-panel.png
Digest-Algorithms: MD5 SHA1 SHA256
@@ -38,9 +56,9 @@ SHA256-Digest: 8QXq/xEzAlvUjmlnoLZsSUNRzJVMlXfxvHXg+CjQCeo=
Name: html/common.css
Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: w9MbKnB8IOM18qpvD6VT5Q==
-SHA1-Digest: WV0HlFwt+OUxUDjSRh/cQ02b3GA=
-SHA256-Digest: 82940VEzo4bAK2BzdHa24RvUnbQtY2sTA3igZZUJcXg=
+MD5-Digest: /UyMvbNRLkMg16SUWBwfOQ==
+SHA1-Digest: o6/zL7koozqruepEs+gvg5oUbb8=
+SHA256-Digest: yxeB+bGnBghAhvZ0yzdf5Lz429egs72Z16L32bL16lo=
Name: html/librejs-title.png
Digest-Algorithms: MD5 SHA1 SHA256
@@ -56,21 +74,21 @@ SHA256-Digest: woimzHpj0kwEyX4pkh/OEWZg+nZMy//j3FFaxIUUSqE=
Name: html/display_panel/content/display-panel.html
Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: 9oTVelB+xHtOGKvQiQr9lQ==
-SHA1-Digest: NxAh/UW9LRRjSDdrPUCSqJezXt0=
-SHA256-Digest: d1QN45dTcRq7wWIh+B9AIFKRget6sd6i79+ir14459k=
+MD5-Digest: V1BZ0u/h4aPJkUW16tVEGQ==
+SHA1-Digest: 8ENBA17b5EPEhy0rhYsIrFldg1w=
+SHA256-Digest: krlx07T1g/t9XN9uPUJlAwA4Yf2JdbCCt55aSZW6+tY=
Name: html/display_panel/content/main_panel.js
Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: Z6/u/Xo7tD2Ge3wWMXg3PQ==
-SHA1-Digest: vMOHBFepDnzRFsflnoM6Md13Cno=
-SHA256-Digest: AQb3IJ3Wot6OWGeuW8vKioc/7d7SAkHiRoUp1Vvy9+U=
+MD5-Digest: mlLUTOuI0OiELp8rehU0bg==
+SHA1-Digest: saTukDvddiD+UY/Mavb8S2VYx6o=
+SHA256-Digest: oF74xayKVPIZY7n9+OKaSAdvwScEMtD1IOb9dix32D4=
Name: html/display_panel/content/panel-styles.css
Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: ceuW5hugF2ei2xuk9spiWA==
-SHA1-Digest: PZjIwk54Dmk/oMngCfZrHiIbWEc=
-SHA256-Digest: ptawtRBknBtsqY72T4kGvwHPycfRRsjyjcMR8Q3P+ok=
+MD5-Digest: 1CWzvMVt54XKDtxrNmcuwg==
+SHA1-Digest: nUIHXk8Z4nnsjD4IHYjdebSPh2Y=
+SHA256-Digest: puM8ec8cOeAVOb1P9pMV0fVDfyO8DpbjnkkKl+K0Aws=
Name: html/preferences_panel/pref.js
Digest-Algorithms: MD5 SHA1 SHA256
@@ -80,15 +98,15 @@ SHA256-Digest: 1+YDHE3wec6bgOwpvYisodDxLgqswy372azfiZIPfNo=
Name: html/preferences_panel/preferences_panel.html
Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: knFSyZ0Kx1rJnyV1GxFKZQ==
-SHA1-Digest: 8MRg2ICuSJnR1wNGnwDSFmlgMfU=
-SHA256-Digest: QsDHDI7d7F1yTy8S5UFDMun5ifc88fHpBHJsnJhmkLE=
+MD5-Digest: Ue6bF5KLFYQm7dA2mD5Frg==
+SHA1-Digest: N8YMrhm+Pu/V5Ms18ZejVV64ZgY=
+SHA256-Digest: goUr8B3e5DDVuvJjfprkGVhL93Blm5W7djf396hNdnM=
Name: html/preferences_panel/prefs.css
Digest-Algorithms: MD5 SHA1 SHA256
-MD5-Digest: exN7vR4k3Q23xWFcJVsvKQ==
-SHA1-Digest: 4M/iQCvCKCONmOCvZ/dGi+Ms7iE=
-SHA256-Digest: Olzdei+a43eQ2pfy6yrTB6lFgbq9lMb3x03gl0PJGcQ=
+MD5-Digest: Gddgx9kXNYTFXmjosSr61g==
+SHA1-Digest: pcsCRYBKnwUyTcRWuvjCTuQ/1ow=
+SHA256-Digest: tka3B4VXzE/NnqA5QUSqUWqMGtGsjOyYaqrbB/mISdk=
Name: icons/librejs.png
Digest-Algorithms: MD5 SHA1 SHA256
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.rsa b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.rsa
index 3f2a391..5d66bdb 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.rsa
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.rsa
Binary files differ
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.sf b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.sf
index 55b3cb5..ceea95e 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.sf
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/META-INF/mozilla.sf
@@ -1,5 +1,5 @@
Signature-Version: 1.0
-MD5-Digest-Manifest: EjvLEQft6v8DPhjc5w3zkw==
-SHA1-Digest-Manifest: XPN383aD9XbiHRWtmpQjw5nWIKI=
-SHA256-Digest-Manifest: lf4ZH7pQgtALdAaVR8PovqmBgs+76TenUb+VIBmFtYA=
+MD5-Digest-Manifest: q6f4uwAfQOjZgRD9l64Qtw==
+SHA1-Digest-Manifest: rhGjSqp5qD5blc1WvHufUzmldtM=
+SHA256-Digest-Manifest: saDYdrkSdvpyLK9J3sBtBxC0uDD/AscdzbOjuRnYmIo=
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/bundle.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/bundle.js
index f8d4e1e..b35ef98 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/bundle.js
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/bundle.js
@@ -26,12 +26,28 @@
"use strict";
-let licensesByURL = new Map();
+let licensesByLabel = new Map();
+let licensesByUrl = new Map();
{
let {licenses} = require("../license_definitions");
- for (let l of Object.values(licenses).filter(l => l.canonicalUrl)) {
- for (let url of l.canonicalUrl) {
- licensesByURL.set(url, l);
+ let mapByLabel = (label, license) => licensesByLabel.set(label.toUpperCase(), license);
+ for (let [id, l] of Object.entries(licenses)) {
+ let {identifier, canonicalUrl, licenseName} = l;
+ if (identifier) {
+ mapByLabel(identifier, l);
+ } else {
+ l.identifier = id;
+ }
+ if (id !== identifier) {
+ mapByLabel(id, l);
+ }
+ if (licenseName) {
+ mapByLabel(licenseName, l);
+ }
+ if (Array.isArray(canonicalUrl)) {
+ for (let url of canonicalUrl) {
+ licensesByUrl.set(url, l);
+ }
}
}
}
@@ -42,7 +58,7 @@ var ExternalLicenses = {
purgeCache(tabId) {
cachedHrefs.delete(tabId);
},
-
+
async check(script) {
let {url, tabId, frameId, documentUrl} = script;
let tabCache = cachedHrefs.get(tabId);
@@ -53,28 +69,34 @@ var ExternalLicenses = {
url,
cache,
}, {frameId});
-
- if (!(scriptInfo && scriptInfo.licenseURLs.length)) {
+
+ if (!(scriptInfo && scriptInfo.licenseLinks.length)) {
return null;
}
scriptInfo.licenses = new Set();
- scriptInfo.allFree = true;
scriptInfo.toString = function() {
let licenseIds = [...this.licenses].map(l => l.identifier).sort().join(", ");
- return this.allFree ? `Free license${licenseIds.length > 1 ? "s" : ""} (${licenseIds})` : `Mixed free (${licenseIds}) and unknown licenses`;
- }
-
- for (let u of scriptInfo.licenseURLs) {
- if (licensesByURL.has(u)) {
- scriptInfo.licenses.add(licensesByURL.get(u));
- } else {
- scriptInfo.allFree = false;
- break;
+ return licenseIds
+ ? `Free license${this.licenses.size > 1 ? "s" : ""} (${licenseIds})`
+ : "Unknown license(s)";
+ }
+ let match = (map, key) => {
+ if (map.has(key)) {
+ scriptInfo.licenses.add(map.get(key));
+ return true;
}
+ return false;
+ };
+
+ for (let {label, url} of scriptInfo.licenseLinks) {
+ match(licensesByLabel, label = label.trim().toUpperCase()) ||
+ match(licensesByUrl, url) ||
+ match(licensesByLabel, label.replace(/^GNU-|-(?:OR-LATER|ONLY)$/, ''));
}
+ scriptInfo.free = scriptInfo.licenses.size > 0;
return scriptInfo;
},
-
+
/**
* moves / creates external license references before any script in the page
* if needed, to have them ready when the first script load is triggered.
@@ -90,7 +112,7 @@ var ExternalLicenses = {
cachedHrefs.set(tabId, frameCache = new Map());
}
frameCache.set(frameId, new Map([[documentUrl, cache]]));
-
+
let link = document.querySelector(`link[rel="jslicense"], link[data-jslicense="1"], a[rel="jslicense"], a[data-jslicense="1"]`);
if (link) {
let href = link.getAttribute("href");
@@ -112,7 +134,7 @@ var ExternalLicenses = {
return move();
}
}
-
+
return false;
}
};
@@ -120,7 +142,7 @@ var ExternalLicenses = {
module.exports = { ExternalLicenses };
-},{"../license_definitions":9}],2:[function(require,module,exports){
+},{"../license_definitions":10}],2:[function(require,module,exports){
/**
* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
*
@@ -314,7 +336,7 @@ class ResponseProcessor {
static install(handler, types = ["main_frame", "sub_frame", "script"]) {
if (listeners.has(handler)) return false;
- let listener =
+ let listener =
async request => await new ResponseTextFilter(request).process(handler);
listeners.set(handler, listener);
webRequestEvent.addListener(
@@ -361,7 +383,7 @@ class ResponseTextFilter {
if (handler.post) handler = handler.post;
if (typeof handler !== "function") ResponseProcessor.ACCEPT;
}
-
+
let {requestId, responseHeaders} = request;
let filter = browser.webRequest.filterResponseData(requestId);
let buffer = [];
@@ -371,11 +393,29 @@ class ResponseTextFilter {
};
filter.onstop = async event => {
- let decoder = metaData.createDecoder();
+
let params = {stream: true};
- response.text = buffer.map(
- chunk => decoder.decode(chunk, params))
- .join('');
+ // concatenate chunks
+ let size = buffer.reduce((sum, chunk, n) => sum + chunk.byteLength, 0)
+ let allBytes = new Uint8Array(size);
+ let pos = 0;
+ for (let chunk of buffer) {
+ allBytes.set(new Uint8Array(chunk), pos);
+ pos += chunk.byteLength;
+ }
+ buffer = null; // allow garbage collection
+ if (allBytes.indexOf(0) !== -1) {
+ console.debug("Warning: zeroes in bytestream, probable cached encoding mismatch.", request);
+ if (request.type === "script") {
+ console.debug("It's a script, trying to refetch it.");
+ response.text = await (await fetch(request.url, {cache: "reload", credentials: "include"})).text();
+ } else {
+ console.debug("It's a %s, trying to decode it as UTF-16.", request.type);
+ response.text = new TextDecoder("utf-16be").decode(allBytes);
+ }
+ } else {
+ response.text = metaData.createDecoder().decode(allBytes, {stream: true});
+ }
let editedText = null;
try {
editedText = await handler(response);
@@ -389,10 +429,9 @@ class ResponseTextFilter {
filter.write(new TextEncoder().encode(editedText));
} else {
// ... otherwise pass all the raw bytes through
- for (let chunk of buffer) filter.write(chunk);
+ filter.write(allBytes);
}
-
- filter.disconnect();
+ filter.close();
}
return metaData.forceUTF8() ? {responseHeaders} : ResponseProcessor.ACCEPT;;
@@ -534,6 +573,63 @@ if (typeof module === "object") {
}
},{}],6:[function(require,module,exports){
+/**
+* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
+*
+* Copyright (C) 2018 Giorgio Maone <giorgio@maone.net>
+*
+* This file is part of GNU LibreJS.
+*
+* GNU LibreJS is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GNU LibreJS is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GNU LibreJS. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+var Test = (() => {
+ const RUNNER_URL = browser.extension.getURL("/test/SpecRunner.html");
+ return {
+ /*
+ returns RUNNER_URL if it's a test-enabled build or an about:debugging
+ temporary extension session, null otherwise
+ */
+ async getURL() {
+ let url = RUNNER_URL;
+ try {
+ await fetch(url);
+ } catch (e) {
+ url = null;
+ }
+ this.getURL = () => url;
+ return url;
+ },
+
+ async getTab(activate = false) {
+ let url = await this.getURL();
+ let tab = url ? (await browser.tabs.query({url}))[0] ||
+ (await browser.tabs.create({url}))
+ : null;
+ if (tab && activate) {
+ await browser.tabs.update(tab.id, {active: true});
+ }
+ return tab;
+ }
+ };
+})();
+if (typeof module === "object") {
+ module.exports = Test;
+}
+
+},{}],7:[function(require,module,exports){
module.exports=module.exports = {
fname_data : {
"WebGLShader": true,
@@ -871,7 +967,7 @@ module.exports=module.exports = {
"onwebkitanimationiteration": true,
"onwebkitanimationstart": true,
"onwebkittransitionend": true,
- "onerror": true,
+ "onerror": false,
"onafterprint": true,
"onbeforeprint": true,
"onbeforeunload": true,
@@ -1344,7 +1440,7 @@ module.exports=module.exports = {
"window": false,
"document": true,
"location": false,
- "top": true,
+ "top": false,
"netscape": true,
"Node": true,
"Document": true,
@@ -1367,12 +1463,12 @@ module.exports=module.exports = {
}
};
-},{}],7:[function(require,module,exports){
+},{}],8:[function(require,module,exports){
module.exports = {
whitelist: {"jquery":[{"filename":"core.js","version":"3.3.1","hash":"6026ca247eaee2c88fa54964d77d2e76efc97a974a5695e3744cb38defb3d691"},{"filename":"jquery.js","version":"3.3.1","hash":"d8aa24ecc6cecb1a60515bc093f1c9da38a0392612d9ab8ae0f7f36e6eee1fad"},{"filename":"jquery.min.js","version":"3.3.1","hash":"160a426ff2894252cd7cebbdd6d6b7da8fcd319c65b70468f10b6690c45d02ef"},{"filename":"jquery.slim.js","version":"3.3.1","hash":"7cd5c914895c6b4e4120ed98e73875c6b4a12b7304fbf9586748fe0a1c57d830"},{"filename":"jquery.slim.min.js","version":"3.3.1","hash":"dde76b9b2b90d30eb97fc81f06caa8c338c97b688cea7d2729c88f529f32fbb1"},{"filename":"core.js","version":"3.3.0","hash":"58db1cc9582b20320c552043b5880b40c8eaec3e6d4b46994222862a049330a1"},{"filename":"jquery.js","version":"3.3.0","hash":"4c5592b8326dea44be86e57ebd59725758ccdddc0675e356a9ece14f15c1fd7f"},{"filename":"jquery.min.js","version":"3.3.0","hash":"453432f153a63654fa6f63c846eaf7ee9e8910165413ba3cc0f80cbeed7c302e"},{"filename":"jquery.slim.js","version":"3.3.0","hash":"ec89a3d1f2cab57e4d144092d6e9a8429ecd0b594482be270536ac366ee004b6"},{"filename":"jquery.slim.min.js","version":"3.3.0","hash":"00c83723bc9aefa38b3c3f4cf8c93b92aac0dbd1d49ff16e1817d3ffd51ff65b"},{"filename":"core.js","version":"3.2.1","hash":"052b1b5ec0c4ae78aafc7a6e8542c5a2bf31d42a40dac3cfc102e512812b8bed"},{"filename":"jquery.js","version":"3.2.1","hash":"0d9027289ffa5d9f6c8b4e0782bb31bbff2cef5ee3708ccbcb7a22df9128bb21"},{"filename":"jquery.min.js","version":"3.2.1","hash":"87083882cc6015984eb0411a99d3981817f5dc5c90ba24f0940420c5548d82de"},{"filename":"jquery.slim.js","version":"3.2.1","hash":"b40f32d17aa2c27a7098e225dd218070597646fc478c0f2aa74fb5b821a64668"},{"filename":"jquery.slim.min.js","version":"3.2.1","hash":"9365920887b11b33a3dc4ba28a0f93951f200341263e3b9cefd384798e4be398"},{"filename":"core.js","version":"3.2.0","hash":"7c5c8f96ac182ed4d2c9ac74fda37941745f2793814fbd8b28624a9a720f9d39"},{"filename":"jquery.js","version":"3.2.0","hash":"c0f149348165558e3d07e0ae008ac3afddf65d26fa264dc9d4cdb6337136ca54"},{"filename":"jquery.min.js","version":"3.2.0","hash":"2405bdf4c255a4904671bcc4b97938033d39b3f5f20dd068985a8d94cde273e2"},{"filename":"jquery.slim.js","version":"3.2.0","hash":"f18ac10930e84233b80814f5595bcc1f6ffad74047d038d997114e08880aec03"},{"filename":"jquery.slim.min.js","version":"3.2.0","hash":"a8b02fd240408a170764b2377efdd621329e46c517dbb85deaea4105ad0c4a8c"},{"filename":"core.js","version":"3.1.1","hash":"4a4dec7ca8f2567b4327c82b873c8d7dd774f74b9009d2ff65431a8154693dea"},{"filename":"jquery.js","version":"3.1.1","hash":"d7a71d3dd740e95755227ba6446a3a21b8af6c4444f29ec2411dc7cd306e10b0"},{"filename":"jquery.min.js","version":"3.1.1","hash":"85556761a8800d14ced8fcd41a6b8b26bf012d44a318866c0d81a62092efd9bf"},{"filename":"jquery.slim.js","version":"3.1.1","hash":"e62fe6437d3433befd3763950eb975ea56e88705cd51dccbfd1d9a5545f25d60"},{"filename":"jquery.slim.min.js","version":"3.1.1","hash":"fd222b36abfc87a406283b8da0b180e22adeb7e9327ac0a41c6cd5514574b217"},{"filename":"core.js","version":"3.1.0","hash":"55994528e7efe901e92a76761a54ba0c3ae3f1f8d1c3a4da9a23a3e4a06d0eaa"},{"filename":"jquery.js","version":"3.1.0","hash":"b25a2092f0752b754e933008f10213c55dd5ce93a791e355b0abed9182cc8df9"},{"filename":"jquery.min.js","version":"3.1.0","hash":"702b9e051e82b32038ffdb33a4f7eb5f7b38f4cf6f514e4182d8898f4eb0b7fb"},{"filename":"jquery.slim.js","version":"3.1.0","hash":"2faa690232fa8e0b5199f8ae8a0784139030348da91ff5fd2016cfc9a9c9799c"},{"filename":"jquery.slim.min.js","version":"3.1.0","hash":"711a568e848ec3929cc8839a64da388ba7d9f6d28f85861bea2e53f51495246f"},{"filename":"core.js","version":"3.0.0-rc1","hash":"11853583eb5ce8ab1aacc380430145de705cdfff0e72c54d3dca17d01466999b"},{"filename":"jquery.js","version":"3.0.0-rc1","hash":"65ded5fa34aa91b976dae0af5888ce4c06fed34271f3665b2924505b704025c7"},{"filename":"jquery.min.js","version":"3.0.0-rc1","hash":"df68e90250b9a60fc184ef194d1769d3af8aa67396cc064281cb77e2ef6bf876"},{"filename":"jquery.slim.js","version":"3.0.0-rc1","hash":"c96eeff335114aa55df0328bbe5f9202ed7a3266b6e81fcd357cd17837fa9756"},{"filename":"jquery.slim.min.js","version":"3.0.0-rc1","hash":"e92bbd6e77604b75e910952f20f3c95ce29050c7b1137dc1edddad000c236b5d"},{"filename":"jquery.js","version":"3.0.0-beta1","hash":"78f27c3d7cb5d766466703adc7f7ad7706b7fb05514eec39be0aa253449bd0f8"},{"filename":"jquery.min.js","version":"3.0.0-beta1","hash":"b72a0aa436a8a8965041beda30577232677ef6588bb933b5bebed2de02c04dc8"},{"filename":"jquery.slim.js","version":"3.0.0-beta1","hash":"4db510700e5773fc7065f36363affd4885c9d9ef257fd7757744f91ac9da5671"},{"filename":"jquery.slim.min.js","version":"3.0.0-beta1","hash":"4c369c555423651822c2f7772d5e0b9a56a2372a92657bd2a696fe539b24be9e"},{"filename":"jquery.js","version":"3.0.0-alpha1","hash":"10b3ccff4cf14cdb5e7c31b2d323be750a13125cea8ded9ca5c1da4150a69238"},{"filename":"jquery.min.js","version":"3.0.0-alpha1","hash":"19e065eaadf26f58c0e1081a2e0e64450eec2983eebb08f998ecaacac8642a47"},{"filename":"core.js","version":"3.0.0","hash":"bad41b5e9f7c6b952b3a840b84ce2e97e3029bd2b2773c58a69a33e73217d1e4"},{"filename":"jquery.js","version":"3.0.0","hash":"8eb3cb67ef2f0f1b76167135cef6570a409c79b23f0bc0ede71c9a4018f1408a"},{"filename":"jquery.min.js","version":"3.0.0","hash":"266bcea0bb58b26aa5b16c5aee60d22ccc1ae9d67daeb21db6bad56119c3447d"},{"filename":"jquery.slim.js","version":"3.0.0","hash":"1a9ea1a741fe03b6b1835b44ac2b9c59e39cdfc8abb64556a546c16528fc2828"},{"filename":"jquery.slim.min.js","version":"3.0.0","hash":"45fe0169d7f20adb2f1e63bcf4151971b62f34dbd9bce4f4f002df133bc2b03d"},{"filename":"jquery.js","version":"2.2.4","hash":"893e90f6230962e42231635df650f20544ad22affc3ee396df768eaa6bc5a6a2"},{"filename":"jquery.min.js","version":"2.2.4","hash":"05b85d96f41fff14d8f608dad03ab71e2c1017c2da0914d7c59291bad7a54f8e"},{"filename":"jquery.js","version":"2.2.3","hash":"95a5d6b46c9da70a89f0903e5fdc769a2c266a22a19fcb5598e5448a044db4fe"},{"filename":"jquery.min.js","version":"2.2.3","hash":"6b6de0d4db7876d1183a3edb47ebd3bbbf93f153f5de1ba6645049348628109a"},{"filename":"jquery.slim.js","version":"2.2.3","hash":"4db510700e5773fc7065f36363affd4885c9d9ef257fd7757744f91ac9da5671"},{"filename":"jquery.slim.min.js","version":"2.2.3","hash":"4c369c555423651822c2f7772d5e0b9a56a2372a92657bd2a696fe539b24be9e"},{"filename":"jquery.js","version":"2.2.2","hash":"e3fcd40aa8aad24ab1859232a781b41a4f803ad089b18d53034d24e4296c6581"},{"filename":"jquery.min.js","version":"2.2.2","hash":"dfa729d82a3effadab1000181cb99108f232721e3b0af74cfae4c12704b35a32"},{"filename":"jquery.slim.js","version":"2.2.2","hash":"4db510700e5773fc7065f36363affd4885c9d9ef257fd7757744f91ac9da5671"},{"filename":"jquery.slim.min.js","version":"2.2.2","hash":"4c369c555423651822c2f7772d5e0b9a56a2372a92657bd2a696fe539b24be9e"},{"filename":"jquery.js","version":"2.2.1","hash":"78d714ccede3b2fd179492ef7851246c1f1b03bfc2ae83693559375e99a7c077"},{"filename":"jquery.min.js","version":"2.2.1","hash":"82f420005cd31fab6b4ab016a07d623e8f5773de90c526777de5ba91e9be3b4d"},{"filename":"jquery.slim.js","version":"2.2.1","hash":"4db510700e5773fc7065f36363affd4885c9d9ef257fd7757744f91ac9da5671"},{"filename":"jquery.slim.min.js","version":"2.2.1","hash":"4c369c555423651822c2f7772d5e0b9a56a2372a92657bd2a696fe539b24be9e"},{"filename":"jquery.js","version":"2.2.0","hash":"a18aa92dea997bd71eb540d5f931620591e9dee27e5f817978bb385bab924d21"},{"filename":"jquery.min.js","version":"2.2.0","hash":"8a102873a33f24f7eb22221e6b23c4f718e29f85168ecc769a35bfaed9b12cce"},{"filename":"jquery.js","version":"2.1.4","hash":"b2215cce5830e2350b9d420271d9bd82340f664c3f60f0ea850f7e9c0392704e"},{"filename":"jquery.min.js","version":"2.1.4","hash":"22642f202577f0ba2f22cbe56b6cf291a09374487567cd3563e0d2a29f75c0c5"},{"filename":"jquery.js","version":"2.1.3","hash":"828cbbcacb430f9c5b5d27fe9302f8795eb338f2421010f5141882125226f94f"},{"filename":"jquery.min.js","version":"2.1.3","hash":"2051d61446d4dbffb03727031022a08c84528ab44d203a7669c101e5fbdd5515"},{"filename":"jquery.js","version":"2.1.2","hash":"07cb07bdfba40ceff869b329eb48eeede41740ba6ce833dd3830bd0af49e4898"},{"filename":"jquery.min.js","version":"2.1.2","hash":"64c51d974a342e9df3ed548082a4ad7816d407b8c36b67356dde9e487b819cbe"},{"filename":"jquery.js","version":"2.1.1-rc2","hash":"dc0083a233768ed8554d770d9d4eed91c0e27de031b3d9cbdcecabc034265010"},{"filename":"jquery.min.js","version":"2.1.1-rc2","hash":"293c9966a4fea0fed0adc1aae242bb37e428e649337dcab65d9af5934a7cc775"},{"filename":"jquery.js","version":"2.1.1-rc1","hash":"5adbbda8312291291162ab054df8927291426dbfb550099945ece85b49707290"},{"filename":"jquery.min.js","version":"2.1.1-rc1","hash":"d246298c351558d4847d237bb2d052f22001ca24ea4a32c28de378c95af523c8"},{"filename":"jquery.js","version":"2.1.1-beta1","hash":"e96b9e8d7a12b381d2ed1efd785faef3c7bad0ea03edf42fb15c9fde533e761f"},{"filename":"jquery.min.js","version":"2.1.1-beta1","hash":"5aed44447956d7933861d56003dbd0f95504d79e19d094edacbe4a55e6cf8736"},{"filename":"jquery.js","version":"2.1.1","hash":"140ff438eaaede046f1ceba27579d16dc980595709391873fa9bf74d7dbe53ac"},{"filename":"jquery.min.js","version":"2.1.1","hash":"c0d4098bc8b34c6f87a3d7723988ae81214a53a0bb4a1d4d36a67640f98ed079"},{"filename":"jquery.js","version":"2.1.0-rc1","hash":"88d96de8ccf65e57a3f28134616e3abfe0af2b3712302beb0a73f77f6b873fd0"},{"filename":"jquery.min.js","version":"2.1.0-rc1","hash":"11f94218bacdd4dbdc5c1736ca7aa1f27bb9632bc0a1696175b408da8dcf16b3"},{"filename":"jquery.js","version":"2.1.0-beta3","hash":"8eb83f00967dd0e18877b71349f5a3641b1046a1667c54e602a5682ac0f07ab9"},{"filename":"jquery.min.js","version":"2.1.0-beta3","hash":"7ebd0c0a5a088da45a5ec48f4379dbe457129f2cbe434f2e045ef838136746a9"},{"filename":"jquery.js","version":"2.1.0-beta2","hash":"97efd5af482f4e74c37c04970421fdbd17388fd605d992a2aa0077d388b32b6d"},{"filename":"jquery.min.js","version":"2.1.0-beta2","hash":"22966516a31e64225df5e08e35f0fadb27d29a8fb2618ddca17ec171215fc323"},{"filename":"jquery.js","version":"2.1.0","hash":"0fa7752926a95e3ab6b5f67a21ef40628ce4447c81ddf4f6cacf663b6fb85af7"},{"filename":"jquery.min.js","version":"2.1.0","hash":"f284353a7cc4d97f6fe20a5155131bd43587a0f1c98a56eeaf52cff72910f47d"},{"filename":"jquery.js","version":"2.0.3","hash":"9427fe2df51f7d4c6bf35f96d19169714d0b432b99dc18f41760d0342c538122"},{"filename":"jquery.min.js","version":"2.0.3","hash":"a57b5242b9a9adc4c1ef846c365147b89c472b9cd770face331efcb965346b25"},{"filename":"jquery.js","version":"2.0.2","hash":"d2ed0720108a75db0d53248ba8e36332658064c4189714d16c0f117efb42016d"},{"filename":"jquery.min.js","version":"2.0.2","hash":"9d7d1c727e1cd32745764098a76e5d3d5fb7acd3b6527c5aacd85b7c6f8ce341"},{"filename":"jquery.js","version":"2.0.1","hash":"820fb338fe8c7478a1b820e2708b4fd306a68825de1194803e7a93fbc2177a16"},{"filename":"jquery.min.js","version":"2.0.1","hash":"4e1354fc542b617c58cbba3aeb5116a528cf08bb1299f5dc7f3bc77a3b902b68"},{"filename":"jquery.js","version":"2.0.0","hash":"896e379d334cf0b16c78d9962a1579147156d4a72355032fce0de5f673d4e287"},{"filename":"jquery.min.js","version":"2.0.0","hash":"d482871a5e948cb4884fa0972ea98a81abca057b6bd3f8c995a18c12487e761c"},{"filename":"jquery.js","version":"1.12.4","hash":"430f36f9b5f21aae8cc9dca6a81c4d3d84da5175eaedcf2fdc2c226302cb3575"},{"filename":"jquery.min.js","version":"1.12.4","hash":"668b046d12db350ccba6728890476b3efee53b2f42dbb84743e5e9f1ae0cc404"},{"filename":"jquery.js","version":"1.12.3","hash":"d5732912d03878a5cd3695dc275a6630fb3c255fa7c0b744ab08897824049327"},{"filename":"jquery.min.js","version":"1.12.3","hash":"69a3831c082fc105b56c53865cc797fa90b83d920fb2f9f6875b00ad83a18174"},{"filename":"jquery.slim.js","version":"1.12.3","hash":"4db510700e5773fc7065f36363affd4885c9d9ef257fd7757744f91ac9da5671"},{"filename":"jquery.slim.min.js","version":"1.12.3","hash":"4c369c555423651822c2f7772d5e0b9a56a2372a92657bd2a696fe539b24be9e"},{"filename":"jquery.js","version":"1.12.2","hash":"5540b2af46570795610626e8d8391356176ca639b1520c4319a2d0c7ba9bef16"},{"filename":"jquery.min.js","version":"1.12.2","hash":"95914789b5f3307a3718679e867d61b9d4c03f749cd2e2970570331d7d6c8ed9"},{"filename":"jquery.slim.js","version":"1.12.2","hash":"4db510700e5773fc7065f36363affd4885c9d9ef257fd7757744f91ac9da5671"},{"filename":"jquery.slim.min.js","version":"1.12.2","hash":"4c369c555423651822c2f7772d5e0b9a56a2372a92657bd2a696fe539b24be9e"},{"filename":"jquery.js","version":"1.12.1","hash":"56e843a66b2bf7188ac2f4c81df61608843ce144bd5aa66c2df4783fba85e8ef"},{"filename":"jquery.min.js","version":"1.12.1","hash":"2359d383bf2d4ab65ebf7923bdf74ce40e4093f6e58251b395a64034b3c39772"},{"filename":"jquery.slim.js","version":"1.12.1","hash":"4db510700e5773fc7065f36363affd4885c9d9ef257fd7757744f91ac9da5671"},{"filename":"jquery.slim.min.js","version":"1.12.1","hash":"4c369c555423651822c2f7772d5e0b9a56a2372a92657bd2a696fe539b24be9e"},{"filename":"jquery.js","version":"1.12.0","hash":"c85537acad72f0d7d409dfc1e2d2daa59032f71d29642a8b64b9852f70166fbb"},{"filename":"jquery.min.js","version":"1.12.0","hash":"5f1ab65fe2ad6b381a1ae036716475bf78c9b2e309528cf22170c1ddeefddcbf"},{"filename":"jquery.js","version":"1.11.3","hash":"2065aecca0fb9b0567358d352ed5f1ab72fce139bf449b4d09805f5d9c3725ed"},{"filename":"jquery.min.js","version":"1.11.3","hash":"aec3d419d50f05781a96f223e18289aeb52598b5db39be82a7b71dc67d6a7947"},{"filename":"jquery.js","version":"1.11.2","hash":"58c27035b7a2e589df397e5d7e05424b90b8c1aaaf73eff47d5ed6daecb70f25"},{"filename":"jquery.min.js","version":"1.11.2","hash":"d4ec583c7604001f87233d1fe0076cbd909f15a5f8c6b4c3f5dd81b462d79d32"},{"filename":"jquery.js","version":"1.11.1-rc2","hash":"648dbce0f3731ebce091c283b52f60b100d73807501eea1a99f7b23140bfcefa"},{"filename":"jquery.min.js","version":"1.11.1-rc2","hash":"06d766022172da3774651a3ccfeef893185f9ba46823bcbfcba744ab5e25a4bf"},{"filename":"jquery.js","version":"1.11.1-rc1","hash":"8241d4982de8a6fea3e0ebc47e99445337675a777054c09221f670adb3748995"},{"filename":"jquery.min.js","version":"1.11.1-rc1","hash":"a581c274adebdbc44022e45d9febf0b92c572481c58bfe562b3d74d5e8972c5a"},{"filename":"jquery.js","version":"1.11.1-beta1","hash":"0aab28e2fd1f61b6282132553325bd890fef40989b698311c5b00b7b38a1e19d"},{"filename":"jquery.min.js","version":"1.11.1-beta1","hash":"99ec4d1ab56cf49ee4c202cc41509ada5eeb334694815f75675792433828a527"},{"filename":"jquery.js","version":"1.11.1","hash":"3029834a820c79c154c377f52e2719fc3ff2a27600a07ae089ea7fde9087f6bc"},{"filename":"jquery.min.js","version":"1.11.1","hash":"540bc6dec1dd4b92ea4d3fb903f69eabf6d919afd48f4e312b163c28cff0f441"},{"filename":"jquery.js","version":"1.11.0-rc1","hash":"84792d2b1ab8a2d57dcc113abb910b4c31dda357a7acd3b46ed282dd03f15d25"},{"filename":"jquery.min.js","version":"1.11.0-rc1","hash":"5f58804382f5258bb6b187c1b5af1ec0b8ccbe2c904a5163580371352ca63424"},{"filename":"jquery.js","version":"1.11.0-beta3","hash":"847a61382a55d0c0e5244d0621f1e0674292dee6b850640c669fd1516ec9f4f5"},{"filename":"jquery.min.js","version":"1.11.0-beta3","hash":"51fc79c1828a885f3776e35d56a22895e3656d014b502b869bd05f891bd91602"},{"filename":"jquery.js","version":"1.11.0","hash":"ce0343e1d6f489768eeefe022c12181c6a0822e756239851310acf076d23d10c"},{"filename":"jquery.min.js","version":"1.11.0","hash":"b294e973896f8f874e90a8eb1a8908ac790980d034c4c4bdf0fc3d37b8abf682"},{"filename":"jquery.js","version":"1.10.2","hash":"8ade6740a1d3cfedf81e28d9250929341207b23a55f1be90ccc26cf6d98e052a"},{"filename":"jquery.min.js","version":"1.10.2","hash":"89a15e9c40bc6b14809f236ee8cd3ed1ea42393c1f6ca55c7855cd779b3f922e"},{"filename":"jquery.js","version":"1.10.1","hash":"ebaded49db62a60060caa2577f2a4ec1ff68726bc40861bc65d977abeb64fa7d"},{"filename":"jquery.min.js","version":"1.10.1","hash":"8bf150f6b29d6c9337de6c945a8f63c929b203442040688878bc2753fe13e007"},{"filename":"jquery.js","version":"1.10.0","hash":"8aa0f84b5331efcc3cb72c7d504c2bc6ebd861da003d72c33df99ce650d4531d"},{"filename":"jquery.min.js","version":"1.10.0","hash":"1e80de36726582824df3f9a7eb6ecdfe9827fc5a7c69f597b1502ebc13950ecd"},{"filename":"jquery.js","version":"1.9.1","hash":"7bd80d06c01c0340c1b9159b9b4a197db882ca18cbac8e9b9aa025e68f998d40"},{"filename":"jquery.min.js","version":"1.9.1","hash":"c12f6098e641aaca96c60215800f18f5671039aecf812217fab3c0d152f6adb4"},{"filename":"jquery.js","version":"1.9.0","hash":"4d7b01c2f6043bcee83a33d0f627dc6fbc27dc8aeb5bdd5d863e84304b512ef3"},{"filename":"jquery.min.js","version":"1.9.0","hash":"7fa0d5c3f538c76f878e012ac390597faecaabfe6fb9d459b919258e76c5df8e"},{"filename":"jquery.js","version":"1.8.3","hash":"756d7dfac4a35bb57543f677283d6c682e8d704e5350884b27325badd2b3c4a7"},{"filename":"jquery.min.js","version":"1.8.3","hash":"61c6caebd23921741fb5ffe6603f16634fca9840c2bf56ac8201e9264d6daccf"},{"filename":"jquery.js","version":"1.8.2","hash":"ba8f203a9ebbe5771f49bcbe0804079240c7225f4be6ab424769bfbfb35ebc35"},{"filename":"jquery.min.js","version":"1.8.2","hash":"f23d4b309b72743aa8afe1f8c98a25b3ee31246fa572c66d9d8cb1982cae4fbc"},{"filename":"jquery.js","version":"1.8.1","hash":"7614fc75c4fcf6f32f7307f37550440e12adefb9289226acb79020c66faeffea"},{"filename":"jquery.min.js","version":"1.8.1","hash":"a1305347219d673cc973172494248e557ce8eccaf65af995c07c9d7daed4475d"},{"filename":"jquery-1.8.0.js","version":"1.8.0","hash":"04ee795a1a5a908ee339e145ae6c6b394d1dc0d971fd0896e3cb776660adba2e"},{"filename":"jquery-1.8.0.min.js","version":"1.8.0","hash":"d73e2e1bff9c55b85284ff287cb20dc29ad9165ec09091a0597b61199f330805"},{"filename":"jquery.js","version":"1.8.0","hash":"04ee795a1a5a908ee339e145ae6c6b394d1dc0d971fd0896e3cb776660adba2e"},{"filename":"jquery.min.js","version":"1.8.0","hash":"d73e2e1bff9c55b85284ff287cb20dc29ad9165ec09091a0597b61199f330805"},{"filename":"jquery.min.js","version":"1.7.2","hash":"47b68dce8cb6805ad5b3ea4d27af92a241f4e29a5c12a274c852e4346a0500b4"},{"filename":"jquery.min.js","version":"1.7.1","hash":"88171413fc76dda23ab32baa17b11e4fff89141c633ece737852445f1ba6c1bd"},{"filename":"jquery.min.js","version":"1.7","hash":"ff4e4975ef403004f8fe8e59008db7ad47f54b10d84c72eb90e728d1ec9157ce"},{"filename":"jquery.js","version":"1.6.4","hash":"54964f8b580ad795a962fb27066715d3281ae1ad13a28bf8aedd5d8859ebae37"},{"filename":"jquery.min.js","version":"1.6.4","hash":"951d6bae39eb172f57a88bd686f7a921cf060fd21f59648f0d20b6a8f98fc5a5"},{"filename":"jquery.js","version":"1.6.3","hash":"9baa10e1c5630c3dcd9bb46bf00913cc94b3855d58c9459ae9848339c566e97b"},{"filename":"jquery.min.js","version":"1.6.3","hash":"d3f3779f5113da6da957c4d81481146a272c31aefe0d3e4b64414fd686fd9744"},{"filename":"jquery.js","version":"1.6.2","hash":"a57292619d14eb8cbd923bde9f28cf994ac66abc48f7c975b769328ff33bddc9"},{"filename":"jquery.min.js","version":"1.6.2","hash":"fefb084f14120d777c7857ba78603e8531a0778b2e639df7622513c70567afa0"},{"filename":"jquery.js","version":"1.6.1","hash":"0eef76a9583a6c7a1eb764d33fe376bfe1861df79fab82c2c3f5d16183e82016"},{"filename":"jquery.min.js","version":"1.6.1","hash":"c784376960f3163dc760bc019e72e5fed78203745a5510c69992a39d1d8fe776"},{"filename":"jquery.js","version":"1.5.1","hash":"e2ea0a6ca6b984a9405a759d24cf3c51eb3164e5c43e95c3e9a59b316be7b3b9"},{"filename":"jquery.min.js","version":"1.5.1","hash":"764b9e9f3ad386aaa5cdeae9368353994de61c0bede087c8f7e3579cb443de3b"},{"filename":"jquery.js","version":"1.4.4","hash":"b31cd094af7950b3a461dc78161fd2faf01faa9d0ed8c1c072790f83ab26d482"},{"filename":"jquery.min.js","version":"1.4.4","hash":"517364f2d45162fb5037437b5b6cb953d00d9b2b3b79ba87d9fe57ea6ee6070c"},{"filename":"jquery.js","version":"1.4.3","hash":"0e3303a3a0cec95ebc8c3cc3e19fc71c99487faa286b05d01a3eb8cca4d90bc7"},{"filename":"jquery.min.js","version":"1.4.3","hash":"f800b399e5c7a5254fc66bb407117fe38dbde0528780e68c9f7c87d299f8486a"},{"filename":"jquery.js","version":"1.4.2","hash":"95c023c80dfe0d30304c58244878995061f87801a66daa5d6bf4f2512be0e6f9"},{"filename":"jquery.min.js","version":"1.4.2","hash":"e23a2a4e2d7c2b41ebcdd8ffc0679df7140eb7f52e1eebabf827a88182643c59"},{"filename":"jquery.js","version":"1.4.1","hash":"9edc9f813781eca2aad6de78ef85cdbe92ee32bb0a56791be4da0fa7b472c1d8"},{"filename":"jquery.min.js","version":"1.4.1","hash":"2cec78f739fbddfed852cd7934d2530e7cc4c8f14b38673b03ba5fb880ad4cc7"},{"filename":"jquery.js","version":"1.4.0","hash":"882927b9aadb2504b5c6a823bd8c8c516f21dec6e441fe2c8fa228e35951bcc8"},{"filename":"jquery.min.js","version":"1.4.0","hash":"89abaf1e2471b00525b0694048e179c0f39a2674e3bcb34460ea6bc4801882be"},{"filename":"jquery.js","version":"1.3.2","hash":"74537639fa585509395c0d3b9a5601dd1e4ca036961c53dc5ab0e87386aa9be1"},{"filename":"jquery.min.js","version":"1.3.2","hash":"c8370a2d050359e9d505acc411e6f457a49b21360a21e6cbc9229bad3a767899"},{"filename":"jquery.js","version":"1.3.1","hash":"0ae058559b3e65d6cc5674fe3ff01581da5ae62387bb0dfa2923997a52093a06"},{"filename":"jquery.min.js","version":"1.3.1","hash":"17ec1f16efac893b9bd89bba5f13cb1e0bf938bdc9cece6cae3ed77f18fa6fd7"},{"filename":"jquery.js","version":"1.3.0","hash":"a7756f21ff6c558f983d5376072174af546e8d07f8bebe1e6f760b2f4b53012d"},{"filename":"jquery.min.js","version":"1.3.0","hash":"900191a443115d8b48a9d68d3062e8b3d7129727951b8617465b485baf253006"},{"filename":"jquery.js","version":"1.2.6","hash":"3cc5c121471323b25de45fcab48631d4a09c78e76af21c10d747352682605587"},{"filename":"jquery.min.js","version":"1.2.6","hash":"d548530775a6286f49ba66e0715876b4ec5985966b0291c21568fecfc4178e8d"},{"filename":"jquery.js","version":"1.2.3","hash":"d977fc32dd4bdb0479604abf078f1045b0e922666313f2f42cd71ce7835e0061"},{"filename":"jquery.min.js","version":"1.2.3","hash":"f1c4a0a7b5dead231fc9b42f06965a036ab7a2a788768847eb81e1528d6402ad"}]}
};
-},{}],8:[function(require,module,exports){
+},{}],9:[function(require,module,exports){
/**
* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
* *
@@ -1487,7 +1583,7 @@ var check = function(license_text){
module.exports.check = check;
-},{"./license_definitions.js":9,"./pattern_utils.js":16}],9:[function(require,module,exports){
+},{"./license_definitions.js":10,"./pattern_utils.js":17}],10:[function(require,module,exports){
/**
* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
* *
@@ -1799,7 +1895,7 @@ exports.licenses = {
}
};
-},{}],10:[function(require,module,exports){
+},{}],11:[function(require,module,exports){
module.exports=module.exports = {
licenses: {
'Apache-2.0':{
@@ -1894,7 +1990,7 @@ module.exports=module.exports = {
}
};
-},{}],11:[function(require,module,exports){
+},{}],12:[function(require,module,exports){
/**
* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
* *
@@ -1917,10 +2013,9 @@ module.exports=module.exports = {
* along with GNU LibreJS. If not, see <http://www.gnu.org/licenses/>.
*/
-var acorn_base = require("acorn");
-var acorn = require('acorn/dist/acorn_loose');
+var acorn = require('acorn');
+var acornLoose = require('acorn-loose');
var jssha = require('jssha');
-var walk = require("acorn/dist/walk");
var legacy_license_lib = require("./legacy_license_check.js");
var {ResponseProcessor} = require("./bg/ResponseProcessor");
var {Storage, ListStore} = require("./common/Storage");
@@ -1959,29 +2054,6 @@ function hash(source){
return shaObj.getHash("HEX");
}
-
-// the list of all available event attributes
-var intrinsic_events = [
- "onload",
- "onunload",
- "onclick",
- "ondblclick",
- "onmousedown",
- "onmouseup",
- "onmouseovr",
- "onmousemove",
- "onmouseout",
- "onfocus",
- "onblur",
- "onkeypress",
- "onkeydown",
- "onkeyup",
- "onsubmit",
- "onreset",
- "onselect",
- "onchange"
-];
-
/*
NONTRIVIAL THINGS:
- Fetch
@@ -2050,7 +2122,10 @@ function options_listener(changes, area){
var activeMessagePorts = {};
var activityReports = {};
-async function createReport(initializer = null) {
+async function createReport(initializer) {
+ if (!(initializer && (initializer.url || initializer.tabId))) {
+ throw new Error("createReport() needs an URL or a tabId at least");
+ }
let template = {
"accepted": [],
"blocked": [],
@@ -2058,14 +2133,10 @@ async function createReport(initializer = null) {
"whitelisted": [],
"unknown": [],
};
- if (initializer) {
- template = Object.assign(template, initializer);
- if (!template.url && initializer.tabId) {
- template.url = (await browser.tabs.get(initializer.tabId)).url;
- }
- }
-
- template.site = ListStore.siteItem(template.url);
+ template = Object.assign(template, initializer);
+ let [url] = (template.url || (await browser.tabs.get(initializer.tabId)).url).split("#");
+ template.url = url;
+ template.site = ListStore.siteItem(url);
template.siteStatus = listManager.getStatus(template.site);
return template;
}
@@ -2237,13 +2308,18 @@ function get_domain(url){
*
*/
var portFromCS;
-function connected(p) {
- if(p["name"] == "contact_finder"){
+async function connected(p) {
+ if(p.name === "contact_finder"){
+ // style the contact finder panel
+ await browser.tabs.insertCSS(p.sender.tab.id, {
+ file: "/content/dialog.css",
+ cssOrigin: "user",
+ matchAboutBlank: true,
+ allFrames: true
+ });
+
// Send a message back with the relevant settings
- function cb(items){
- p.postMessage(items);
- }
- browser.storage.local.get(cb);
+ p.postMessage(await browser.storage.local.get(["prefs_subject", "prefs_body"]));
return;
}
p.onMessage.addListener(async function(m) {
@@ -2270,7 +2346,7 @@ function connected(p) {
// invoke_contact_finder
if(m["invoke_contact_finder"] !== undefined){
contact_finder = true;
- inject_contact_finder();
+ await injectContactFinder();
}
// a debug feature (maybe give the user an option to do this?)
if(m["deletelocalstorage"] !== undefined){
@@ -2333,7 +2409,7 @@ function delete_removed_tab_info(tab_id, remove_info){
*/
async function onTabUpdated(tabId, changedInfo, tab) {
- let url = tab.url.replace(/#.*/, '');
+ let [url] = tab.url.split("#");
let report = activityReports[tabId];
if (!(report && report.url === url)) {
let cache = await browser.sessions.getTabValue(tabId, url);
@@ -2359,7 +2435,7 @@ function full_evaluate(script){
return [true,"Harmless null script"];
}
- var ast = acorn.parse_dammit(script).body[0];
+ var ast = acornLoose.parse(script).body[0];
var flag = false;
var amtloops = 0;
@@ -2367,7 +2443,7 @@ function full_evaluate(script){
var loopkeys = {"for":true,"if":true,"while":true,"switch":true};
var operators = {"||":true,"&&":true,"=":true,"==":true,"++":true,"--":true,"+=":true,"-=":true,"*":true};
try{
- var tokens = acorn_base.tokenizer(script);
+ var tokens = acorn.tokenizer(script);
}catch(e){
console.warn("Tokenizer could not be initiated (probably invalid code)");
return [false,"Tokenizer could not be initiated (probably invalid code)"];
@@ -2409,7 +2485,8 @@ function full_evaluate(script){
return script.charAt(end+i) == "[";
}
var error_count = 0;
- while(toke !== undefined && toke.type != acorn_base.tokTypes.eof){
+ var defines_functions = false;
+ while(toke !== undefined && toke.type != acorn.tokTypes.eof){
if(toke.type.keyword !== undefined){
//dbg_print("Keyword:");
//dbg_print(toke);
@@ -2417,10 +2494,8 @@ function full_evaluate(script){
// This type of loop detection ignores functional loop alternatives and ternary operators
if(toke.type.keyword == "function"){
- dbg_print("%c NONTRIVIAL: Function declaration.","color:red");
- if(DEBUG == false){
- return [false,"NONTRIVIAL: Function declaration."];
- }
+ dbg_print("%c NOTICE: Function declaration.","color:green");
+ defines_functions = true;
}
if(loopkeys[toke.type.keyword] !== undefined){
@@ -2451,13 +2526,6 @@ function full_evaluate(script){
}
}
}else if(status === undefined){// is the identifier user defined?
- // Are arguments being passed to a user defined variable?
- if(being_called(toke.end)){
- dbg_print("%c NONTRIVIAL: User defined variable '"+toke.value+"' called as function","color:red");
- if(DEBUG == false){
- return [false,"NONTRIVIAL: User defined variable '"+toke.value+"' called as function"];
- }
- }
// Is there bracket suffix notation?
if(is_bsn(toke.end)){
dbg_print("%c NONTRIVIAL: Bracket suffix notation on variable '"+toke.value+"'","color:red");
@@ -2479,7 +2547,10 @@ function full_evaluate(script){
}
dbg_print("%cAppears to be trivial.","color:green;");
- return [true,"Script appears to be trivial."];
+ if (defines_functions === true)
+ return [true,"Script appears to be trivial but defines functions."];
+ else
+ return [true,"Script appears to be trivial."];
}
@@ -2492,6 +2563,8 @@ function full_evaluate(script){
* This can only determine if a script is bad, not if it's good
*
* If it passes the intitial pass, it runs the full pass and returns the result
+
+* It returns an array of [flag (boolean, false if "bad"), reason (string, human readable report)]
*
*/
function evaluate(script,name){
@@ -2529,27 +2602,32 @@ function evaluate(script,name){
return [flag,reason];
}
- var final = full_evaluate(script);
-// final[1] = final[1] + "<br>";
- return final;
+ return full_evaluate(script);
}
-function license_valid(matches){
- if(matches.length != 4){
- return [false, "malformed or unrecognized license tag"];
+function validateLicense(matches) {
+ if (!(Array.isArray(matches) && matches.length >= 4)){
+ return [false, "Malformed or unrecognized license tag."];
}
- if(matches[1] != "@license"){
- return [false, "malformed or unrecognized license tag"];
+ let [all, tag, link, id] = matches;
+ let license = null;
+ if (licenses[id])
+ license = licenses[id];
+ for (let key in licenses){
+ if (licenses[key]["Magnet link"] === link)
+ license = licenses[key];
+ if (licenses[key]["URL"] === link)
+ license = licenses[key];
}
- if(licenses[matches[3]] === undefined){
- return [false, "malformed or unrecognized license tag"];
+ if(!license){
+ return [false, `Unrecognized license "${id}"`];
}
- if(licenses[matches[3]]["Magnet link"] != matches[2]){
- return [false, "malformed or unrecognized license tag"];
+ if (!(license["Magnet link"] === link || license["URL"] === link)){
+ return [false, `License magnet link does not match for "${id}".`];
}
- return [true,"Recognized license as '"+matches[3]+"'<br>"];
+ return [true, `Recognized license: "${id}".`];
}
/**
*
@@ -2562,91 +2640,92 @@ function license_valid(matches){
* reason text
* ]
*/
-function license_read(script_src, name, external = false){
-
- var reason_text = "";
-
- var edited_src = "";
- var unedited_src = script_src;
- var nontrivial_status;
- var parts_denied = false;
- var parts_accepted = false;
- var license = legacy_license_lib.check(script_src);
- if(license != false){
- return [true,script_src,"Licensed under: "+license];
+function license_read(scriptSrc, name, external = false){
+
+ let license = legacy_license_lib.check(scriptSrc);
+ if (license){
+ return [true, scriptSrc, `Licensed under: ${license}`];
}
- if (listManager.builtInHashes.has(hash(script_src))){
- return [true,script_src,"Common script known to be free software."];
+ if (listManager.builtInHashes.has(hash(scriptSrc))){
+ return [true, scriptSrc, "Common script known to be free software."];
}
- while(true){ // TODO: refactor me
- // TODO: support multiline comments
- var matches = /\/[\/\*]\s*?(@license)\s([\S]+)\s([\S]+$)/gm.exec(unedited_src);
- var empty = /[^\s]/gm.exec(unedited_src);
- if(empty == null){
- return [true,edited_src,reason_text];
+
+ let editedSrc = "";
+ let uneditedSrc = scriptSrc.trim();
+ let reason = uneditedSrc ? "" : "Empty source.";
+ let partsDenied = false;
+ let partsAccepted = false;
+
+ function checkTriviality(s) {
+ if (!s.trim()) {
+ return true; // empty, ignore it
}
- if(matches == null){
- if (external)
- return [false,edited_src,"External script with no known license."];
+ let [trivial, message] = external ?
+ [false, "External script with no known license"]
+ : evaluate(s, name);
+ if (trivial) {
+ partsAccepted = true;
+ editedSrc += s;
+ } else {
+ partsDenied = true;
+ if (s.startsWith("javascript:"))
+ editedSrc += `# LIBREJS BLOCKED: ${message}`;
else
- nontrivial_status = evaluate(unedited_src,name);
- if(nontrivial_status[0] == true){
- parts_accepted = true;
- edited_src += unedited_src;
- } else{
- parts_denied = true;
- edited_src += "\n/*\nLIBREJS BLOCKED:"+nontrivial_status[1]+"\n*/\n";
- }
- reason_text += "\n" + nontrivial_status[1];
+ editedSrc += `/*\nLIBREJS BLOCKED: ${message}\n*/`;
+ }
+ reason += `\n${message}`;
+ return trivial;
+ }
- if(parts_denied == true && parts_accepted == true){
- reason_text = "Script was determined partly non-trivial after editing. (check source for details)\n"+reason_text;
- }
- if(parts_denied == true && parts_accepted == false){
- return [false,edited_src,reason_text];
- }
- else return [true,edited_src,reason_text];
+ while (uneditedSrc) {
+ let openingMatch = /\/[\/\*]\s*?(@license)\s+(\S+)\s+(\S+)\s*$/mi.exec(uneditedSrc);
+ if (!openingMatch) { // no license found, check for triviality
+ checkTriviality(uneditedSrc);
+ break;
+ }
+ let openingIndex = openingMatch.index;
+ if (openingIndex) {
+ // let's check the triviality of the code before the license tag, if any
+ checkTriviality(uneditedSrc.substring(0, openingIndex));
}
- // sponge
- dbg_print("undedited_src:");
- dbg_print(unedited_src);
- dbg_print(matches);
- dbg_print("chopping at " + matches["index"] + ".");
- var before = unedited_src.substring(0,matches["index"]);
- // sponge
- dbg_print("before:");
- dbg_print(before);
- if (external)
- nontrivial_status = [true, "External script with no known license"]
- else
- nontrivial_status = evaluate(before,name);
- if(nontrivial_status[0] == true){
- parts_accepted = true;
- edited_src += before;
- } else{
- parts_denied = true;
- edited_src += "\n/*\nLIBREJS BLOCKED:"+nontrivial_status[1]+"\n*/\n";
+ // let's check the actual license
+ uneditedSrc = uneditedSrc.substring(openingIndex);
+
+ let closureMatch = /\/([*/])\s*@license-end\b[^*/\n]*/i.exec(uneditedSrc);
+ if (!closureMatch) {
+ let msg = "ERROR: @license with no @license-end";
+ return [false, `\n/*\n ${msg} \n*/\n`, msg];
}
- unedited_src = unedited_src.substr(matches["index"],unedited_src.length);
- // TODO: support multiline comments
- var matches_end = /\/\/\s*?(@license-end)/gm.exec(unedited_src);
- if(matches_end == null){
- dbg_print("ERROR: @license with no @license-end");
- return [false,"\n/*\n ERROR: @license with no @license-end \n*/\n","ERROR: @license with no @license-end"];
+
+ let closureEndIndex = closureMatch.index + closureMatch[0].length;
+ let commentEndOffset = uneditedSrc.substring(closureEndIndex).indexOf(closureMatch[1] === "*" ? "*/" : "\n");
+ if (commentEndOffset !== -1) {
+ closureEndIndex += commentEndOffset;
}
- var endtag_end_index = matches_end["index"]+matches_end[0].length;
- var license_res = license_valid(matches);
- if(license_res[0] == true){
- edited_src = edited_src + unedited_src.substr(0,endtag_end_index);
- reason_text += "\n" + license_res[1];
- } else{
- edited_src = edited_src + "\n/*\n"+license_res[1]+"\n*/\n";
- reason_text += "\n" + license_res[1];
+
+ let [licenseOK, message] = validateLicense(openingMatch);
+ if(licenseOK) {
+ editedSrc += uneditedSrc.substr(0, closureEndIndex);
+ partsAccepted = true;
+ } else {
+ editedSrc += `\n/*\n${message}\n*/\n`;
+ partsDenied = true;
}
+ reason += `\n${message}`;
+
// trim off everything we just evaluated
- unedited_src = unedited_src.substr(endtag_end_index,unedited_src.length);
+ uneditedSrc = uneditedSrc.substring(closureEndIndex).trim();
}
+
+ if(partsDenied) {
+ if (partsAccepted) {
+ reason = `Some parts of the script have been disabled (check the source for details).\n^--- ${reason}`;
+ }
+ return [false, editedSrc, reason];
+ }
+
+ return [true, scriptSrc, reason];
}
/* *********************************************************************************************** */
@@ -2672,7 +2751,10 @@ async function get_script(response, url, tabId = -1, whitelisted = false, index
: "Address whitelisted by user";
addReportEntry(tabId, url, {"whitelisted": [url, reason], url});
}
- return result(`/* LibreJS: script whitelisted by user preference. */\n${response}`);
+ if (response.startsWith("javascript:"))
+ return result(response);
+ else
+ return result(`/* LibreJS: script whitelisted by user preference. */\n${response}`);
}
let [verdict, editedSource, reason] = license_read(response, scriptName, index === -2);
@@ -2689,10 +2771,20 @@ async function get_script(response, url, tabId = -1, whitelisted = false, index
let scriptSource = verdict ? response : editedSource;
switch(category) {
case "blacklisted":
+ if (response.startsWith("javascript:"))
+ return result(`# LibreJS: script ${category} by user.`);
+ else
+ return result(`/* LibreJS: script ${category} by user. */`);
case "whitelisted":
- return result(`/* LibreJS: script ${category} by user. */\n${scriptSource}`);
+ if (response.startsWith("javascript:"))
+ return result(scriptSource);
+ else
+ return result(`/* LibreJS: script ${category} by user. */\n${scriptSource}`);
default:
- return result(`/* LibreJS: script ${category}. */\n${scriptSource}`);
+ if (response.startsWith("javascript:"))
+ return result(scriptSource);
+ else
+ return result(`/* LibreJS: script ${category}. */\n${scriptSource}`);
}
}
@@ -2755,6 +2847,7 @@ var ResponseHandler = {
let {request} = response;
let {url, type, tabId, frameId, documentUrl} = request;
+ let fullUrl = url;
url = ListStore.urlItem(url);
let site = ListStore.siteItem(url);
@@ -2784,11 +2877,11 @@ var ResponseHandler = {
"whitelisted": [url, whitelistedSite ? `User whitelisted ${site}` : "Whitelisted by user"]});
return ResponseProcessor.ACCEPT;
} else {
- let scriptInfo = await ExternalLicenses.check({url, tabId, frameId, documentUrl});
+ let scriptInfo = await ExternalLicenses.check({url: fullUrl, tabId, frameId, documentUrl});
if (scriptInfo) {
let verdict, ret;
let msg = scriptInfo.toString();
- if (scriptInfo.allFree) {
+ if (scriptInfo.free) {
verdict = "accepted";
ret = ResponseProcessor.ACCEPT;
} else {
@@ -2951,20 +3044,21 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
let modified = false;
// Deal with intrinsic events
+ let intrinsecindex = 0;
for (let element of html_doc.all) {
- let attributes = element.attributes;
- for (let event of intrinsic_events) {
- if (event in attributes) {
- let attr = attributes[event];
+ for (let attr of element.attributes){
+ if (attr.name.startsWith("on") || (attr.name === "href" && attr.value.startsWith("javascript:"))){
+ intrinsecindex++;
try {
- let edited = await get_script(attr.value, `Intrinsic event [${event}]`);
- if (edited) {
- let value = edited[0];
- if (value !== attr.value) {
- modified = true;
- attr.value = value;
+ let url = `${documentUrl}# Intrinsic event ${intrinsecindex} [${attr.name}]`;
+ let edited = await get_script(attr.value, url, tabId, whitelist.contains(url));
+ if (edited) {
+ let value = edited;
+ if (value !== attr.value) {
+ modified = true;
+ attr.value = value;
+ }
}
- }
} catch (e) {
console.error(e);
}
@@ -2975,6 +3069,7 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
let modifiedInline = false;
for(let i = 0, len = scripts.length; i < len; i++) {
let script = scripts[i];
+ let url = `${documentUrl}# script ${i}`;
if (!script.src && !(script.type && script.type !== "text/javascript")) {
let edited = await get_script(script.textContent, url, tabId, whitelisted, i);
if (edited) {
@@ -2986,11 +3081,11 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
}
}
}
- if (modified) {
- return modifiedInline
- ? await remove_noscripts(html_doc)
- : doc2HTML(html_doc);
- }
+ }
+ if (modified) {
+ return modifiedInline
+ ? await remove_noscripts(html_doc)
+ : doc2HTML(html_doc);
}
}
return null;
@@ -3018,11 +3113,35 @@ var listManager = new ListManager(whitelist, blacklist,
.map(script => script.hash)
);
+
+async function initDefaults() {
+ let defaults = {
+ pref_subject: "Issues with Javascript on your website",
+ pref_body: `Please consider using a free license for the Javascript on your website.
+
+[Message generated by LibreJS. See https://www.gnu.org/software/librejs/ for more information]
+`
+ };
+ let keys = Object.keys(defaults);
+ let prefs = await browser.storage.local.get(keys);
+ let changed = false;
+ for (let k of keys) {
+ if (!(k in prefs)) {
+ prefs[k] = defaults[k];
+ changed = true;
+ }
+ }
+ if (changed) {
+ await browser.storage.local.set(prefs);
+ }
+}
+
/**
* Initializes various add-on functions
* only meant to be called once when the script starts
*/
-async function init_addon(){
+async function init_addon() {
+ await initDefaults();
await whitelist.load();
browser.runtime.onConnect.addListener(connected);
browser.storage.onChanged.addListener(options_listener);
@@ -3046,22 +3165,1469 @@ async function init_addon(){
ResponseProcessor.install(ResponseHandler);
legacy_license_lib.init();
+
+
+ let Test = require("./common/Test");
+ if (Test.getURL()) {
+ // export testable functions to the global scope
+ this.LibreJS = {
+ editHtml,
+ handle_script,
+ ExternalLicenses,
+ };
+ // create or focus the autotest tab if it's a debugging session
+ if ((await browser.management.getSelf()).installType === "development") {
+ Test.getTab(true);
+ }
+ }
}
/**
* Loads the contact finder on the given tab ID.
*/
-function inject_contact_finder(tab_id){
- function executed(result) {
- dbg_print("[TABID:"+tab_id+"]"+"finished executing contact finder: " + result);
- }
- var executing = browser.tabs.executeScript(tab_id, {file: "/contact_finder.js"}, executed);
+async function injectContactFinder(tabId){
+ await Promise.all([
+ browser.tabs.insertCSS(tabId, {file: "/content/overlay.css", cssOrigin: "user"}),
+ browser.tabs.executeScript(tabId, {file: "/content/contactFinder.js"}),
+ ]);
}
init_addon();
-},{"./bg/ExternalLicenses":1,"./bg/ListManager":2,"./bg/ResponseProcessor":4,"./common/Storage":5,"./fname_data.json":6,"./hash_script/whitelist":7,"./legacy_license_check.js":8,"./licenses.json":10,"acorn":12,"acorn/dist/acorn_loose":13,"acorn/dist/walk":14,"jssha":15}],12:[function(require,module,exports){
+},{"./bg/ExternalLicenses":1,"./bg/ListManager":2,"./bg/ResponseProcessor":4,"./common/Storage":5,"./common/Test":6,"./fname_data.json":7,"./hash_script/whitelist":8,"./legacy_license_check.js":9,"./licenses.json":11,"acorn":15,"acorn-loose":13,"jssha":16}],13:[function(require,module,exports){
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('acorn')) :
+ typeof define === 'function' && define.amd ? define(['exports', 'acorn'], factory) :
+ (factory((global.acorn = global.acorn || {}, global.acorn.loose = {}),global.acorn));
+}(this, (function (exports,acorn) { 'use strict';
+
+function noop() {}
+
+var LooseParser = function LooseParser(input, options) {
+ if ( options === void 0 ) options = {};
+
+ this.toks = this.constructor.BaseParser.tokenizer(input, options);
+ this.options = this.toks.options;
+ this.input = this.toks.input;
+ this.tok = this.last = {type: acorn.tokTypes.eof, start: 0, end: 0};
+ this.tok.validateRegExpFlags = noop;
+ this.tok.validateRegExpPattern = noop;
+ if (this.options.locations) {
+ var here = this.toks.curPosition();
+ this.tok.loc = new acorn.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;
+ this.inFunction = false;
+};
+
+LooseParser.prototype.startNode = function startNode () {
+ return new acorn.Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null)
+};
+
+LooseParser.prototype.storeCurrentPos = function storeCurrentPos () {
+ return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start
+};
+
+LooseParser.prototype.startNodeAt = function startNodeAt (pos) {
+ if (this.options.locations) {
+ return new acorn.Node(this.toks, pos[0], pos[1])
+ } else {
+ return new acorn.Node(this.toks, pos)
+ }
+};
+
+LooseParser.prototype.finishNode = function 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
+};
+
+LooseParser.prototype.dummyNode = function dummyNode (type) {
+ var 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: acorn.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc};
+ return dummy
+};
+
+LooseParser.prototype.dummyIdent = function dummyIdent () {
+ var dummy = this.dummyNode("Identifier");
+ dummy.name = "✖";
+ return dummy
+};
+
+LooseParser.prototype.dummyString = function dummyString () {
+ var dummy = this.dummyNode("Literal");
+ dummy.value = dummy.raw = "✖";
+ return dummy
+};
+
+LooseParser.prototype.eat = function eat (type) {
+ if (this.tok.type === type) {
+ this.next();
+ return true
+ } else {
+ return false
+ }
+};
+
+LooseParser.prototype.isContextual = function isContextual (name) {
+ return this.tok.type === acorn.tokTypes.name && this.tok.value === name
+};
+
+LooseParser.prototype.eatContextual = function eatContextual (name) {
+ return this.tok.value === name && this.eat(acorn.tokTypes.name)
+};
+
+LooseParser.prototype.canInsertSemicolon = function canInsertSemicolon () {
+ return this.tok.type === acorn.tokTypes.eof || this.tok.type === acorn.tokTypes.braceR ||
+ acorn.lineBreak.test(this.input.slice(this.last.end, this.tok.start))
+};
+
+LooseParser.prototype.semicolon = function semicolon () {
+ return this.eat(acorn.tokTypes.semi)
+};
+
+LooseParser.prototype.expect = function expect (type) {
+ var this$1 = this;
+
+ if (this.eat(type)) { return true }
+ for (var i = 1; i <= 2; i++) {
+ if (this$1.lookAhead(i).type === type) {
+ for (var j = 0; j < i; j++) { this$1.next(); }
+ return true
+ }
+ }
+};
+
+LooseParser.prototype.pushCx = function pushCx () {
+ this.context.push(this.curIndent);
+};
+
+LooseParser.prototype.popCx = function popCx () {
+ this.curIndent = this.context.pop();
+};
+
+LooseParser.prototype.lineEnd = function lineEnd (pos) {
+ while (pos < this.input.length && !acorn.isNewLine(this.input.charCodeAt(pos))) { ++pos; }
+ return pos
+};
+
+LooseParser.prototype.indentationAfter = function indentationAfter (pos) {
+ var this$1 = this;
+
+ for (var count = 0;; ++pos) {
+ var ch = this$1.input.charCodeAt(pos);
+ if (ch === 32) { ++count; }
+ else if (ch === 9) { count += this$1.options.tabSize; }
+ else { return count }
+ }
+};
+
+LooseParser.prototype.closes = function closes (closeTok, indent, line, blockHeuristic) {
+ if (this.tok.type === closeTok || this.tok.type === acorn.tokTypes.eof) { return true }
+ return line !== this.curLineStart && this.curIndent < indent && this.tokenStartsLine() &&
+ (!blockHeuristic || this.nextLineStart >= this.input.length ||
+ this.indentationAfter(this.nextLineStart) < indent)
+};
+
+LooseParser.prototype.tokenStartsLine = function tokenStartsLine () {
+ var this$1 = this;
+
+ for (var p = this.tok.start - 1; p >= this.curLineStart; --p) {
+ var ch = this$1.input.charCodeAt(p);
+ if (ch !== 9 && ch !== 32) { return false }
+ }
+ return true
+};
+
+LooseParser.prototype.extend = function extend (name, f) {
+ this[name] = f(this[name]);
+};
+
+LooseParser.prototype.parse = function parse () {
+ this.next();
+ return this.parseTopLevel()
+};
+
+LooseParser.extend = function extend () {
+ var plugins = [], len = arguments.length;
+ while ( len-- ) plugins[ len ] = arguments[ len ];
+
+ var cls = this;
+ for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
+ return cls
+};
+
+LooseParser.parse = function parse (input, options) {
+ return new this(input, options).parse()
+};
+
+// Allows plugins to extend the base parser / tokenizer used
+LooseParser.BaseParser = acorn.Parser;
+
+var lp = LooseParser.prototype;
+
+function isSpace(ch) {
+ return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || acorn.isNewLine(ch)
+}
+
+lp.next = function() {
+ var this$1 = this;
+
+ 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$1.curLineStart = this$1.nextLineStart;
+ this$1.nextLineStart = this$1.lineEnd(this$1.curLineStart) + 1;
+ }
+ this.curIndent = this.indentationAfter(this.curLineStart);
+ }
+};
+
+lp.readToken = function() {
+ var this$1 = this;
+
+ for (;;) {
+ try {
+ this$1.toks.next();
+ if (this$1.toks.type === acorn.tokTypes.dot &&
+ this$1.input.substr(this$1.toks.end, 1) === "." &&
+ this$1.options.ecmaVersion >= 6) {
+ this$1.toks.end++;
+ this$1.toks.type = acorn.tokTypes.ellipsis;
+ }
+ return new acorn.Token(this$1.toks)
+ } catch (e) {
+ if (!(e instanceof SyntaxError)) { throw e }
+
+ // Try to skip some text, based on the error message, and then continue
+ var msg = e.message, pos = e.raisedAt, replace = true;
+ if (/unterminated/i.test(msg)) {
+ pos = this$1.lineEnd(e.pos + 1);
+ if (/string/.test(msg)) {
+ replace = {start: e.pos, end: pos, type: acorn.tokTypes.string, value: this$1.input.slice(e.pos + 1, pos)};
+ } else if (/regular expr/i.test(msg)) {
+ var re = this$1.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: acorn.tokTypes.regexp, value: re};
+ } else if (/template/.test(msg)) {
+ replace = {
+ start: e.pos,
+ end: pos,
+ type: acorn.tokTypes.template,
+ value: this$1.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) {
+ var ch = this$1.input.charCodeAt(pos++);
+ if (ch === 34 || ch === 39 || acorn.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$1.resetTo(pos);
+ if (replace === true) { replace = {start: pos, end: pos, type: acorn.tokTypes.name, value: "✖"}; }
+ if (replace) {
+ if (this$1.options.locations)
+ { replace.loc = new acorn.SourceLocation(
+ this$1.toks,
+ acorn.getLineInfo(this$1.input, replace.start),
+ acorn.getLineInfo(this$1.input, replace.end)); }
+ return replace
+ }
+ }
+ }
+};
+
+lp.resetTo = function(pos) {
+ var this$1 = this;
+
+ this.toks.pos = pos;
+ var 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 = acorn.lineBreakG.lastIndex = 0;
+ var match;
+ while ((match = acorn.lineBreakG.exec(this.input)) && match.index < pos) {
+ ++this$1.toks.curLine;
+ this$1.toks.lineStart = match.index + match[0].length;
+ }
+ }
+};
+
+lp.lookAhead = function(n) {
+ var this$1 = this;
+
+ while (n > this.ahead.length)
+ { this$1.ahead.push(this$1.readToken()); }
+ return this.ahead[n - 1]
+};
+
+function isDummy(node) { return node.name === "✖" }
+
+var lp$1 = LooseParser.prototype;
+
+lp$1.parseTopLevel = function() {
+ var this$1 = this;
+
+ var node = this.startNodeAt(this.options.locations ? [0, acorn.getLineInfo(this.input, 0)] : 0);
+ node.body = [];
+ while (this.tok.type !== acorn.tokTypes.eof) { node.body.push(this$1.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$1.parseStatement = function() {
+ var this$1 = this;
+
+ var starttype = this.tok.type, node = this.startNode(), kind;
+
+ if (this.toks.isLet()) {
+ starttype = acorn.tokTypes._var;
+ kind = "let";
+ }
+
+ switch (starttype) {
+ case acorn.tokTypes._break: case acorn.tokTypes._continue:
+ this.next();
+ var isBreak = starttype === acorn.tokTypes._break;
+ if (this.semicolon() || this.canInsertSemicolon()) {
+ node.label = null;
+ } else {
+ node.label = this.tok.type === acorn.tokTypes.name ? this.parseIdent() : null;
+ this.semicolon();
+ }
+ return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
+
+ case acorn.tokTypes._debugger:
+ this.next();
+ this.semicolon();
+ return this.finishNode(node, "DebuggerStatement")
+
+ case acorn.tokTypes._do:
+ this.next();
+ node.body = this.parseStatement();
+ node.test = this.eat(acorn.tokTypes._while) ? this.parseParenExpression() : this.dummyIdent();
+ this.semicolon();
+ return this.finishNode(node, "DoWhileStatement")
+
+ case acorn.tokTypes._for:
+ this.next(); // `for` keyword
+ var isAwait = this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await");
+
+ this.pushCx();
+ this.expect(acorn.tokTypes.parenL);
+ if (this.tok.type === acorn.tokTypes.semi) { return this.parseFor(node, null) }
+ var isLet = this.toks.isLet();
+ if (isLet || this.tok.type === acorn.tokTypes._var || this.tok.type === acorn.tokTypes._const) {
+ var init$1 = this.parseVar(this.startNode(), true, isLet ? "let" : this.tok.value);
+ if (init$1.declarations.length === 1 && (this.tok.type === acorn.tokTypes._in || this.isContextual("of"))) {
+ if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) {
+ node.await = isAwait;
+ }
+ return this.parseForIn(node, init$1)
+ }
+ return this.parseFor(node, init$1)
+ }
+ var init = this.parseExpression(true);
+ if (this.tok.type === acorn.tokTypes._in || this.isContextual("of")) {
+ if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) {
+ node.await = isAwait;
+ }
+ return this.parseForIn(node, this.toAssignable(init))
+ }
+ return this.parseFor(node, init)
+
+ case acorn.tokTypes._function:
+ this.next();
+ return this.parseFunction(node, true)
+
+ case acorn.tokTypes._if:
+ this.next();
+ node.test = this.parseParenExpression();
+ node.consequent = this.parseStatement();
+ node.alternate = this.eat(acorn.tokTypes._else) ? this.parseStatement() : null;
+ return this.finishNode(node, "IfStatement")
+
+ case acorn.tokTypes._return:
+ this.next();
+ if (this.eat(acorn.tokTypes.semi) || this.canInsertSemicolon()) { node.argument = null; }
+ else { node.argument = this.parseExpression(); this.semicolon(); }
+ return this.finishNode(node, "ReturnStatement")
+
+ case acorn.tokTypes._switch:
+ var blockIndent = this.curIndent, line = this.curLineStart;
+ this.next();
+ node.discriminant = this.parseParenExpression();
+ node.cases = [];
+ this.pushCx();
+ this.expect(acorn.tokTypes.braceL);
+
+ var cur;
+ while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) {
+ if (this$1.tok.type === acorn.tokTypes._case || this$1.tok.type === acorn.tokTypes._default) {
+ var isCase = this$1.tok.type === acorn.tokTypes._case;
+ if (cur) { this$1.finishNode(cur, "SwitchCase"); }
+ node.cases.push(cur = this$1.startNode());
+ cur.consequent = [];
+ this$1.next();
+ if (isCase) { cur.test = this$1.parseExpression(); }
+ else { cur.test = null; }
+ this$1.expect(acorn.tokTypes.colon);
+ } else {
+ if (!cur) {
+ node.cases.push(cur = this$1.startNode());
+ cur.consequent = [];
+ cur.test = null;
+ }
+ cur.consequent.push(this$1.parseStatement());
+ }
+ }
+ if (cur) { this.finishNode(cur, "SwitchCase"); }
+ this.popCx();
+ this.eat(acorn.tokTypes.braceR);
+ return this.finishNode(node, "SwitchStatement")
+
+ case acorn.tokTypes._throw:
+ this.next();
+ node.argument = this.parseExpression();
+ this.semicolon();
+ return this.finishNode(node, "ThrowStatement")
+
+ case acorn.tokTypes._try:
+ this.next();
+ node.block = this.parseBlock();
+ node.handler = null;
+ if (this.tok.type === acorn.tokTypes._catch) {
+ var clause = this.startNode();
+ this.next();
+ if (this.eat(acorn.tokTypes.parenL)) {
+ clause.param = this.toAssignable(this.parseExprAtom(), true);
+ this.expect(acorn.tokTypes.parenR);
+ } else {
+ clause.param = null;
+ }
+ clause.body = this.parseBlock();
+ node.handler = this.finishNode(clause, "CatchClause");
+ }
+ node.finalizer = this.eat(acorn.tokTypes._finally) ? this.parseBlock() : null;
+ if (!node.handler && !node.finalizer) { return node.block }
+ return this.finishNode(node, "TryStatement")
+
+ case acorn.tokTypes._var:
+ case acorn.tokTypes._const:
+ return this.parseVar(node, false, kind || this.tok.value)
+
+ case acorn.tokTypes._while:
+ this.next();
+ node.test = this.parseParenExpression();
+ node.body = this.parseStatement();
+ return this.finishNode(node, "WhileStatement")
+
+ case acorn.tokTypes._with:
+ this.next();
+ node.object = this.parseParenExpression();
+ node.body = this.parseStatement();
+ return this.finishNode(node, "WithStatement")
+
+ case acorn.tokTypes.braceL:
+ return this.parseBlock()
+
+ case acorn.tokTypes.semi:
+ this.next();
+ return this.finishNode(node, "EmptyStatement")
+
+ case acorn.tokTypes._class:
+ return this.parseClass(true)
+
+ case acorn.tokTypes._import:
+ return this.parseImport()
+
+ case acorn.tokTypes._export:
+ return this.parseExport()
+
+ default:
+ if (this.toks.isAsyncFunction()) {
+ this.next();
+ this.next();
+ return this.parseFunction(node, true, true)
+ }
+ var expr = this.parseExpression();
+ if (isDummy(expr)) {
+ this.next();
+ if (this.tok.type === acorn.tokTypes.eof) { return this.finishNode(node, "EmptyStatement") }
+ return this.parseStatement()
+ } else if (starttype === acorn.tokTypes.name && expr.type === "Identifier" && this.eat(acorn.tokTypes.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$1.parseBlock = function() {
+ var this$1 = this;
+
+ var node = this.startNode();
+ this.pushCx();
+ this.expect(acorn.tokTypes.braceL);
+ var blockIndent = this.curIndent, line = this.curLineStart;
+ node.body = [];
+ while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true))
+ { node.body.push(this$1.parseStatement()); }
+ this.popCx();
+ this.eat(acorn.tokTypes.braceR);
+ return this.finishNode(node, "BlockStatement")
+};
+
+lp$1.parseFor = function(node, init) {
+ node.init = init;
+ node.test = node.update = null;
+ if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.semi) { node.test = this.parseExpression(); }
+ if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.parenR) { node.update = this.parseExpression(); }
+ this.popCx();
+ this.expect(acorn.tokTypes.parenR);
+ node.body = this.parseStatement();
+ return this.finishNode(node, "ForStatement")
+};
+
+lp$1.parseForIn = function(node, init) {
+ var type = this.tok.type === acorn.tokTypes._in ? "ForInStatement" : "ForOfStatement";
+ this.next();
+ node.left = init;
+ node.right = this.parseExpression();
+ this.popCx();
+ this.expect(acorn.tokTypes.parenR);
+ node.body = this.parseStatement();
+ return this.finishNode(node, type)
+};
+
+lp$1.parseVar = function(node, noIn, kind) {
+ var this$1 = this;
+
+ node.kind = kind;
+ this.next();
+ node.declarations = [];
+ do {
+ var decl = this$1.startNode();
+ decl.id = this$1.options.ecmaVersion >= 6 ? this$1.toAssignable(this$1.parseExprAtom(), true) : this$1.parseIdent();
+ decl.init = this$1.eat(acorn.tokTypes.eq) ? this$1.parseMaybeAssign(noIn) : null;
+ node.declarations.push(this$1.finishNode(decl, "VariableDeclarator"));
+ } while (this.eat(acorn.tokTypes.comma))
+ if (!node.declarations.length) {
+ var decl$1 = this.startNode();
+ decl$1.id = this.dummyIdent();
+ node.declarations.push(this.finishNode(decl$1, "VariableDeclarator"));
+ }
+ if (!noIn) { this.semicolon(); }
+ return this.finishNode(node, "VariableDeclaration")
+};
+
+lp$1.parseClass = function(isStatement) {
+ var this$1 = this;
+
+ var node = this.startNode();
+ this.next();
+ if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); }
+ else if (isStatement === true) { node.id = this.dummyIdent(); }
+ else { node.id = null; }
+ node.superClass = this.eat(acorn.tokTypes._extends) ? this.parseExpression() : null;
+ node.body = this.startNode();
+ node.body.body = [];
+ this.pushCx();
+ var indent = this.curIndent + 1, line = this.curLineStart;
+ this.eat(acorn.tokTypes.braceL);
+ if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
+ while (!this.closes(acorn.tokTypes.braceR, indent, line)) {
+ if (this$1.semicolon()) { continue }
+ var method = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0);
+ if (this$1.options.ecmaVersion >= 6) {
+ method.static = false;
+ isGenerator = this$1.eat(acorn.tokTypes.star);
+ }
+ this$1.parsePropertyName(method);
+ if (isDummy(method.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(acorn.tokTypes.comma); continue }
+ if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" &&
+ (this$1.tok.type !== acorn.tokTypes.parenL && this$1.tok.type !== acorn.tokTypes.braceL)) {
+ method.static = true;
+ isGenerator = this$1.eat(acorn.tokTypes.star);
+ this$1.parsePropertyName(method);
+ } else {
+ method.static = false;
+ }
+ if (!method.computed &&
+ method.key.type === "Identifier" && method.key.name === "async" && this$1.tok.type !== acorn.tokTypes.parenL &&
+ !this$1.canInsertSemicolon()) {
+ isAsync = true;
+ isGenerator = this$1.options.ecmaVersion >= 9 && this$1.eat(acorn.tokTypes.star);
+ this$1.parsePropertyName(method);
+ } else {
+ isAsync = false;
+ }
+ if (this$1.options.ecmaVersion >= 5 && method.key.type === "Identifier" &&
+ !method.computed && (method.key.name === "get" || method.key.name === "set") &&
+ this$1.tok.type !== acorn.tokTypes.parenL && this$1.tok.type !== acorn.tokTypes.braceL) {
+ method.kind = method.key.name;
+ this$1.parsePropertyName(method);
+ method.value = this$1.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$1.parseMethod(isGenerator, isAsync);
+ }
+ node.body.body.push(this$1.finishNode(method, "MethodDefinition"));
+ }
+ this.popCx();
+ if (!this.eat(acorn.tokTypes.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$1.parseFunction = function(node, isStatement, isAsync) {
+ var oldInAsync = this.inAsync, oldInFunction = this.inFunction;
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 6) {
+ node.generator = this.eat(acorn.tokTypes.star);
+ }
+ if (this.options.ecmaVersion >= 8) {
+ node.async = !!isAsync;
+ }
+ if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); }
+ else if (isStatement === true) { node.id = this.dummyIdent(); }
+ this.inAsync = node.async;
+ this.inFunction = true;
+ node.params = this.parseFunctionParams();
+ node.body = this.parseBlock();
+ this.toks.adaptDirectivePrologue(node.body.body);
+ this.inAsync = oldInAsync;
+ this.inFunction = oldInFunction;
+ return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
+};
+
+lp$1.parseExport = function() {
+ var node = this.startNode();
+ this.next();
+ if (this.eat(acorn.tokTypes.star)) {
+ node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString();
+ return this.finishNode(node, "ExportAllDeclaration")
+ }
+ if (this.eat(acorn.tokTypes._default)) {
+ // export default (function foo() {}) // This is FunctionExpression.
+ var isAsync;
+ if (this.tok.type === acorn.tokTypes._function || (isAsync = this.toks.isAsyncFunction())) {
+ var fNode = this.startNode();
+ this.next();
+ if (isAsync) { this.next(); }
+ node.declaration = this.parseFunction(fNode, "nullableID", isAsync);
+ } else if (this.tok.type === acorn.tokTypes._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$1.parseImport = function() {
+ var node = this.startNode();
+ this.next();
+ if (this.tok.type === acorn.tokTypes.string) {
+ node.specifiers = [];
+ node.source = this.parseExprAtom();
+ } else {
+ var elt;
+ if (this.tok.type === acorn.tokTypes.name && this.tok.value !== "from") {
+ elt = this.startNode();
+ elt.local = this.parseIdent();
+ this.finishNode(elt, "ImportDefaultSpecifier");
+ this.eat(acorn.tokTypes.comma);
+ }
+ node.specifiers = this.parseImportSpecifiers();
+ node.source = this.eatContextual("from") && this.tok.type === acorn.tokTypes.string ? this.parseExprAtom() : this.dummyString();
+ if (elt) { node.specifiers.unshift(elt); }
+ }
+ this.semicolon();
+ return this.finishNode(node, "ImportDeclaration")
+};
+
+lp$1.parseImportSpecifiers = function() {
+ var this$1 = this;
+
+ var elts = [];
+ if (this.tok.type === acorn.tokTypes.star) {
+ var elt = this.startNode();
+ this.next();
+ elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent();
+ elts.push(this.finishNode(elt, "ImportNamespaceSpecifier"));
+ } else {
+ var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart;
+ this.pushCx();
+ this.eat(acorn.tokTypes.braceL);
+ if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; }
+ while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
+ var elt$1 = this$1.startNode();
+ if (this$1.eat(acorn.tokTypes.star)) {
+ elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : this$1.dummyIdent();
+ this$1.finishNode(elt$1, "ImportNamespaceSpecifier");
+ } else {
+ if (this$1.isContextual("from")) { break }
+ elt$1.imported = this$1.parseIdent();
+ if (isDummy(elt$1.imported)) { break }
+ elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : elt$1.imported;
+ this$1.finishNode(elt$1, "ImportSpecifier");
+ }
+ elts.push(elt$1);
+ this$1.eat(acorn.tokTypes.comma);
+ }
+ this.eat(acorn.tokTypes.braceR);
+ this.popCx();
+ }
+ return elts
+};
+
+lp$1.parseExportSpecifierList = function() {
+ var this$1 = this;
+
+ var elts = [];
+ var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart;
+ this.pushCx();
+ this.eat(acorn.tokTypes.braceL);
+ if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; }
+ while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
+ if (this$1.isContextual("from")) { break }
+ var elt = this$1.startNode();
+ elt.local = this$1.parseIdent();
+ if (isDummy(elt.local)) { break }
+ elt.exported = this$1.eatContextual("as") ? this$1.parseIdent() : elt.local;
+ this$1.finishNode(elt, "ExportSpecifier");
+ elts.push(elt);
+ this$1.eat(acorn.tokTypes.comma);
+ }
+ this.eat(acorn.tokTypes.braceR);
+ this.popCx();
+ return elts
+};
+
+var lp$2 = LooseParser.prototype;
+
+lp$2.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$2.parseExpression = function(noIn) {
+ var this$1 = this;
+
+ var start = this.storeCurrentPos();
+ var expr = this.parseMaybeAssign(noIn);
+ if (this.tok.type === acorn.tokTypes.comma) {
+ var node = this.startNodeAt(start);
+ node.expressions = [expr];
+ while (this.eat(acorn.tokTypes.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn)); }
+ return this.finishNode(node, "SequenceExpression")
+ }
+ return expr
+};
+
+lp$2.parseParenExpression = function() {
+ this.pushCx();
+ this.expect(acorn.tokTypes.parenL);
+ var val = this.parseExpression();
+ this.popCx();
+ this.expect(acorn.tokTypes.parenR);
+ return val
+};
+
+lp$2.parseMaybeAssign = function(noIn) {
+ if (this.toks.isContextual("yield")) {
+ var node = this.startNode();
+ this.next();
+ if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type !== acorn.tokTypes.star && !this.tok.type.startsExpr)) {
+ node.delegate = false;
+ node.argument = null;
+ } else {
+ node.delegate = this.eat(acorn.tokTypes.star);
+ node.argument = this.parseMaybeAssign();
+ }
+ return this.finishNode(node, "YieldExpression")
+ }
+
+ var start = this.storeCurrentPos();
+ var left = this.parseMaybeConditional(noIn);
+ if (this.tok.type.isAssign) {
+ var node$1 = this.startNodeAt(start);
+ node$1.operator = this.tok.value;
+ node$1.left = this.tok.type === acorn.tokTypes.eq ? this.toAssignable(left) : this.checkLVal(left);
+ this.next();
+ node$1.right = this.parseMaybeAssign(noIn);
+ return this.finishNode(node$1, "AssignmentExpression")
+ }
+ return left
+};
+
+lp$2.parseMaybeConditional = function(noIn) {
+ var start = this.storeCurrentPos();
+ var expr = this.parseExprOps(noIn);
+ if (this.eat(acorn.tokTypes.question)) {
+ var node = this.startNodeAt(start);
+ node.test = expr;
+ node.consequent = this.parseMaybeAssign();
+ node.alternate = this.expect(acorn.tokTypes.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent();
+ return this.finishNode(node, "ConditionalExpression")
+ }
+ return expr
+};
+
+lp$2.parseExprOps = function(noIn) {
+ var start = this.storeCurrentPos();
+ var indent = this.curIndent, line = this.curLineStart;
+ return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line)
+};
+
+lp$2.parseExprOp = function(left, start, minPrec, noIn, indent, line) {
+ if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { return left }
+ var prec = this.tok.type.binop;
+ if (prec != null && (!noIn || this.tok.type !== acorn.tokTypes._in)) {
+ if (prec > minPrec) {
+ var 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 {
+ var 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$2.parseMaybeUnary = function(sawUnary) {
+ var this$1 = this;
+
+ var start = this.storeCurrentPos(), expr;
+ if (this.options.ecmaVersion >= 8 && this.toks.isContextual("await") &&
+ (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))
+ ) {
+ expr = this.parseAwait();
+ sawUnary = true;
+ } else if (this.tok.type.prefix) {
+ var node = this.startNode(), update = this.tok.type === acorn.tokTypes.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 === acorn.tokTypes.ellipsis) {
+ var node$1 = this.startNode();
+ this.next();
+ node$1.argument = this.parseMaybeUnary(sawUnary);
+ expr = this.finishNode(node$1, "SpreadElement");
+ } else {
+ expr = this.parseExprSubscripts();
+ while (this.tok.type.postfix && !this.canInsertSemicolon()) {
+ var node$2 = this$1.startNodeAt(start);
+ node$2.operator = this$1.tok.value;
+ node$2.prefix = false;
+ node$2.argument = this$1.checkLVal(expr);
+ this$1.next();
+ expr = this$1.finishNode(node$2, "UpdateExpression");
+ }
+ }
+
+ if (!sawUnary && this.eat(acorn.tokTypes.starstar)) {
+ var node$3 = this.startNodeAt(start);
+ node$3.operator = "**";
+ node$3.left = expr;
+ node$3.right = this.parseMaybeUnary(false);
+ return this.finishNode(node$3, "BinaryExpression")
+ }
+
+ return expr
+};
+
+lp$2.parseExprSubscripts = function() {
+ var start = this.storeCurrentPos();
+ return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart)
+};
+
+lp$2.parseSubscripts = function(base, start, noCalls, startIndent, line) {
+ var this$1 = this;
+
+ for (;;) {
+ if (this$1.curLineStart !== line && this$1.curIndent <= startIndent && this$1.tokenStartsLine()) {
+ if (this$1.tok.type === acorn.tokTypes.dot && this$1.curIndent === startIndent)
+ { --startIndent; }
+ else
+ { return base }
+ }
+
+ var maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this$1.canInsertSemicolon();
+
+ if (this$1.eat(acorn.tokTypes.dot)) {
+ var node = this$1.startNodeAt(start);
+ node.object = base;
+ if (this$1.curLineStart !== line && this$1.curIndent <= startIndent && this$1.tokenStartsLine())
+ { node.property = this$1.dummyIdent(); }
+ else
+ { node.property = this$1.parsePropertyAccessor() || this$1.dummyIdent(); }
+ node.computed = false;
+ base = this$1.finishNode(node, "MemberExpression");
+ } else if (this$1.tok.type === acorn.tokTypes.bracketL) {
+ this$1.pushCx();
+ this$1.next();
+ var node$1 = this$1.startNodeAt(start);
+ node$1.object = base;
+ node$1.property = this$1.parseExpression();
+ node$1.computed = true;
+ this$1.popCx();
+ this$1.expect(acorn.tokTypes.bracketR);
+ base = this$1.finishNode(node$1, "MemberExpression");
+ } else if (!noCalls && this$1.tok.type === acorn.tokTypes.parenL) {
+ var exprList = this$1.parseExprList(acorn.tokTypes.parenR);
+ if (maybeAsyncArrow && this$1.eat(acorn.tokTypes.arrow))
+ { return this$1.parseArrowExpression(this$1.startNodeAt(start), exprList, true) }
+ var node$2 = this$1.startNodeAt(start);
+ node$2.callee = base;
+ node$2.arguments = exprList;
+ base = this$1.finishNode(node$2, "CallExpression");
+ } else if (this$1.tok.type === acorn.tokTypes.backQuote) {
+ var node$3 = this$1.startNodeAt(start);
+ node$3.tag = base;
+ node$3.quasi = this$1.parseTemplate();
+ base = this$1.finishNode(node$3, "TaggedTemplateExpression");
+ } else {
+ return base
+ }
+ }
+};
+
+lp$2.parseExprAtom = function() {
+ var node;
+ switch (this.tok.type) {
+ case acorn.tokTypes._this:
+ case acorn.tokTypes._super:
+ var type = this.tok.type === acorn.tokTypes._this ? "ThisExpression" : "Super";
+ node = this.startNode();
+ this.next();
+ return this.finishNode(node, type)
+
+ case acorn.tokTypes.name:
+ var start = this.storeCurrentPos();
+ var id = this.parseIdent();
+ var isAsync = false;
+ if (id.name === "async" && !this.canInsertSemicolon()) {
+ if (this.eat(acorn.tokTypes._function))
+ { return this.parseFunction(this.startNodeAt(start), false, true) }
+ if (this.tok.type === acorn.tokTypes.name) {
+ id = this.parseIdent();
+ isAsync = true;
+ }
+ }
+ return this.eat(acorn.tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id
+
+ case acorn.tokTypes.regexp:
+ node = this.startNode();
+ var 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 acorn.tokTypes.num: case acorn.tokTypes.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 acorn.tokTypes._null: case acorn.tokTypes._true: case acorn.tokTypes._false:
+ node = this.startNode();
+ node.value = this.tok.type === acorn.tokTypes._null ? null : this.tok.type === acorn.tokTypes._true;
+ node.raw = this.tok.type.keyword;
+ this.next();
+ return this.finishNode(node, "Literal")
+
+ case acorn.tokTypes.parenL:
+ var parenStart = this.storeCurrentPos();
+ this.next();
+ var inner = this.parseExpression();
+ this.expect(acorn.tokTypes.parenR);
+ if (this.eat(acorn.tokTypes.arrow)) {
+ // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy.
+ var 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) {
+ var par = this.startNodeAt(parenStart);
+ par.expression = inner;
+ inner = this.finishNode(par, "ParenthesizedExpression");
+ }
+ return inner
+
+ case acorn.tokTypes.bracketL:
+ node = this.startNode();
+ node.elements = this.parseExprList(acorn.tokTypes.bracketR, true);
+ return this.finishNode(node, "ArrayExpression")
+
+ case acorn.tokTypes.braceL:
+ return this.parseObj()
+
+ case acorn.tokTypes._class:
+ return this.parseClass(false)
+
+ case acorn.tokTypes._function:
+ node = this.startNode();
+ this.next();
+ return this.parseFunction(node, false)
+
+ case acorn.tokTypes._new:
+ return this.parseNew()
+
+ case acorn.tokTypes.backQuote:
+ return this.parseTemplate()
+
+ default:
+ return this.dummyIdent()
+ }
+};
+
+lp$2.parseNew = function() {
+ var node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart;
+ var meta = this.parseIdent(true);
+ if (this.options.ecmaVersion >= 6 && this.eat(acorn.tokTypes.dot)) {
+ node.meta = meta;
+ node.property = this.parseIdent(true);
+ return this.finishNode(node, "MetaProperty")
+ }
+ var start = this.storeCurrentPos();
+ node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line);
+ if (this.tok.type === acorn.tokTypes.parenL) {
+ node.arguments = this.parseExprList(acorn.tokTypes.parenR);
+ } else {
+ node.arguments = [];
+ }
+ return this.finishNode(node, "NewExpression")
+};
+
+lp$2.parseTemplateElement = function() {
+ var elem = this.startNode();
+
+ // The loose parser accepts invalid unicode escapes even in untagged templates.
+ if (this.tok.type === acorn.tokTypes.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 === acorn.tokTypes.backQuote;
+ return this.finishNode(elem, "TemplateElement")
+};
+
+lp$2.parseTemplate = function() {
+ var this$1 = this;
+
+ var node = this.startNode();
+ this.next();
+ node.expressions = [];
+ var curElt = this.parseTemplateElement();
+ node.quasis = [curElt];
+ while (!curElt.tail) {
+ this$1.next();
+ node.expressions.push(this$1.parseExpression());
+ if (this$1.expect(acorn.tokTypes.braceR)) {
+ curElt = this$1.parseTemplateElement();
+ } else {
+ curElt = this$1.startNode();
+ curElt.value = {cooked: "", raw: ""};
+ curElt.tail = true;
+ this$1.finishNode(curElt, "TemplateElement");
+ }
+ node.quasis.push(curElt);
+ }
+ this.expect(acorn.tokTypes.backQuote);
+ return this.finishNode(node, "TemplateLiteral")
+};
+
+lp$2.parseObj = function() {
+ var this$1 = this;
+
+ var node = this.startNode();
+ node.properties = [];
+ this.pushCx();
+ var indent = this.curIndent + 1, line = this.curLineStart;
+ this.eat(acorn.tokTypes.braceL);
+ if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
+ while (!this.closes(acorn.tokTypes.braceR, indent, line)) {
+ var prop = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0), start = (void 0);
+ if (this$1.options.ecmaVersion >= 9 && this$1.eat(acorn.tokTypes.ellipsis)) {
+ prop.argument = this$1.parseMaybeAssign();
+ node.properties.push(this$1.finishNode(prop, "SpreadElement"));
+ this$1.eat(acorn.tokTypes.comma);
+ continue
+ }
+ if (this$1.options.ecmaVersion >= 6) {
+ start = this$1.storeCurrentPos();
+ prop.method = false;
+ prop.shorthand = false;
+ isGenerator = this$1.eat(acorn.tokTypes.star);
+ }
+ this$1.parsePropertyName(prop);
+ if (this$1.toks.isAsyncProp(prop)) {
+ isAsync = true;
+ isGenerator = this$1.options.ecmaVersion >= 9 && this$1.eat(acorn.tokTypes.star);
+ this$1.parsePropertyName(prop);
+ } else {
+ isAsync = false;
+ }
+ if (isDummy(prop.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(acorn.tokTypes.comma); continue }
+ if (this$1.eat(acorn.tokTypes.colon)) {
+ prop.kind = "init";
+ prop.value = this$1.parseMaybeAssign();
+ } else if (this$1.options.ecmaVersion >= 6 && (this$1.tok.type === acorn.tokTypes.parenL || this$1.tok.type === acorn.tokTypes.braceL)) {
+ prop.kind = "init";
+ prop.method = true;
+ prop.value = this$1.parseMethod(isGenerator, isAsync);
+ } else if (this$1.options.ecmaVersion >= 5 && prop.key.type === "Identifier" &&
+ !prop.computed && (prop.key.name === "get" || prop.key.name === "set") &&
+ (this$1.tok.type !== acorn.tokTypes.comma && this$1.tok.type !== acorn.tokTypes.braceR && this$1.tok.type !== acorn.tokTypes.eq)) {
+ prop.kind = prop.key.name;
+ this$1.parsePropertyName(prop);
+ prop.value = this$1.parseMethod(false);
+ } else {
+ prop.kind = "init";
+ if (this$1.options.ecmaVersion >= 6) {
+ if (this$1.eat(acorn.tokTypes.eq)) {
+ var assign = this$1.startNodeAt(start);
+ assign.operator = "=";
+ assign.left = prop.key;
+ assign.right = this$1.parseMaybeAssign();
+ prop.value = this$1.finishNode(assign, "AssignmentExpression");
+ } else {
+ prop.value = prop.key;
+ }
+ } else {
+ prop.value = this$1.dummyIdent();
+ }
+ prop.shorthand = true;
+ }
+ node.properties.push(this$1.finishNode(prop, "Property"));
+ this$1.eat(acorn.tokTypes.comma);
+ }
+ this.popCx();
+ if (!this.eat(acorn.tokTypes.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$2.parsePropertyName = function(prop) {
+ if (this.options.ecmaVersion >= 6) {
+ if (this.eat(acorn.tokTypes.bracketL)) {
+ prop.computed = true;
+ prop.key = this.parseExpression();
+ this.expect(acorn.tokTypes.bracketR);
+ return
+ } else {
+ prop.computed = false;
+ }
+ }
+ var key = (this.tok.type === acorn.tokTypes.num || this.tok.type === acorn.tokTypes.string) ? this.parseExprAtom() : this.parseIdent();
+ prop.key = key || this.dummyIdent();
+};
+
+lp$2.parsePropertyAccessor = function() {
+ if (this.tok.type === acorn.tokTypes.name || this.tok.type.keyword) { return this.parseIdent() }
+};
+
+lp$2.parseIdent = function() {
+ var name = this.tok.type === acorn.tokTypes.name ? this.tok.value : this.tok.type.keyword;
+ if (!name) { return this.dummyIdent() }
+ var node = this.startNode();
+ this.next();
+ node.name = name;
+ return this.finishNode(node, "Identifier")
+};
+
+lp$2.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$2.toAssignable = function(node, binding) {
+ var this$1 = this;
+
+ 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 (var i = 0, list = node.properties; i < list.length; i += 1)
+ {
+ var prop = list[i];
+
+ this$1.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$2.toAssignableList = function(exprList, binding) {
+ var this$1 = this;
+
+ for (var i = 0, list = exprList; i < list.length; i += 1)
+ {
+ var expr = list[i];
+
+ this$1.toAssignable(expr, binding);
+ }
+ return exprList
+};
+
+lp$2.parseFunctionParams = function(params) {
+ params = this.parseExprList(acorn.tokTypes.parenR);
+ return this.toAssignableList(params, true)
+};
+
+lp$2.parseMethod = function(isGenerator, isAsync) {
+ var node = this.startNode(), oldInAsync = this.inAsync, oldInFunction = this.inFunction;
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 6)
+ { node.generator = !!isGenerator; }
+ if (this.options.ecmaVersion >= 8)
+ { node.async = !!isAsync; }
+ this.inAsync = node.async;
+ this.inFunction = true;
+ node.params = this.parseFunctionParams();
+ node.body = this.parseBlock();
+ this.toks.adaptDirectivePrologue(node.body.body);
+ this.inAsync = oldInAsync;
+ this.inFunction = oldInFunction;
+ return this.finishNode(node, "FunctionExpression")
+};
+
+lp$2.parseArrowExpression = function(node, params, isAsync) {
+ var oldInAsync = this.inAsync, oldInFunction = this.inFunction;
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 8)
+ { node.async = !!isAsync; }
+ this.inAsync = node.async;
+ this.inFunction = true;
+ node.params = this.toAssignableList(params, true);
+ node.expression = this.tok.type !== acorn.tokTypes.braceL;
+ if (node.expression) {
+ node.body = this.parseMaybeAssign();
+ } else {
+ node.body = this.parseBlock();
+ this.toks.adaptDirectivePrologue(node.body.body);
+ }
+ this.inAsync = oldInAsync;
+ this.inFunction = oldInFunction;
+ return this.finishNode(node, "ArrowFunctionExpression")
+};
+
+lp$2.parseExprList = function(close, allowEmpty) {
+ var this$1 = this;
+
+ this.pushCx();
+ var indent = this.curIndent, line = this.curLineStart, elts = [];
+ this.next(); // Opening bracket
+ while (!this.closes(close, indent + 1, line)) {
+ if (this$1.eat(acorn.tokTypes.comma)) {
+ elts.push(allowEmpty ? null : this$1.dummyIdent());
+ continue
+ }
+ var elt = this$1.parseMaybeAssign();
+ if (isDummy(elt)) {
+ if (this$1.closes(close, indent, line)) { break }
+ this$1.next();
+ } else {
+ elts.push(elt);
+ }
+ this$1.eat(acorn.tokTypes.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$2.parseAwait = function() {
+ var node = this.startNode();
+ this.next();
+ node.argument = this.parseMaybeUnary();
+ return this.finishNode(node, "AwaitExpression")
+};
+
+// Acorn: Loose parser
+//
+// This module provides an alternative parser that exposes that same
+// interface as the main module's `parse` function, 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 the loose parser. 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.
+
+acorn.defaultOptions.tabSize = 4;
+
+function parse(input, options) {
+ return LooseParser.parse(input, options)
+}
+
+exports.parse = parse;
+exports.LooseParser = LooseParser;
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
+
+
+},{"acorn":14}],14:[function(require,module,exports){
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -3377,11 +4943,12 @@ function getLineInfo(input, offset) {
// the parser process. These options are recognized:
var defaultOptions = {
- // `ecmaVersion` indicates the ECMAScript version to parse. Must
- // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support
- // for strict mode, the set of reserved words, and support for
- // new syntax features. The default is 7.
- ecmaVersion: 7,
+ // `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 9.
+ ecmaVersion: 9,
// `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.
@@ -3457,8 +5024,7 @@ var 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
@@ -3501,8 +5067,26 @@ function pushComment(options, array) {
}
}
-// Registered plugins
-var plugins = {};
+// Each scope gets a bitset that may contain these flags
+var SCOPE_TOP = 1;
+var SCOPE_FUNCTION = 2;
+var SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION;
+var SCOPE_ASYNC = 4;
+var SCOPE_GENERATOR = 8;
+var SCOPE_ARROW = 16;
+var SCOPE_SIMPLE_CATCH = 32;
+
+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
+var BIND_NONE = 0;
+var BIND_VAR = 1;
+var BIND_LEXICAL = 2;
+var BIND_FUNCTION = 3;
+var BIND_SIMPLE_CATCH = 4;
+var BIND_OUTSIDE = 5; // Special case for function names as bound inside the function
function keywordRegexp(words) {
return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
@@ -3529,9 +5113,6 @@ var Parser = function Parser(options, input, startPos) {
// 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.
@@ -3572,8 +5153,6 @@ var Parser = function Parser(options, input, startPos) {
// 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;
// Labels in scope.
@@ -3585,36 +5164,49 @@ var Parser = function Parser(options, input, startPos) {
// 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
-Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) };
-Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) };
+var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true } };
-Parser.prototype.extend = function extend (name, f) {
- this[name] = f(this[name]);
+Parser.prototype.parse = function parse () {
+ var node = this.options.program || this.startNode();
+ this.nextToken();
+ return this.parseTopLevel(node)
};
-Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) {
- var this$1 = this;
+prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 };
+prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 };
+prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 };
- for (var name in pluginConfigs) {
- var plugin = plugins[name];
- if (!plugin) { throw new Error("Plugin '" + name + "' not found") }
- plugin(this$1, pluginConfigs[name]);
- }
+Parser.extend = function extend () {
+ var plugins = [], len = arguments.length;
+ while ( len-- ) plugins[ len ] = arguments[ len ];
+
+ var cls = this;
+ for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
+ return cls
};
-Parser.prototype.parse = function parse () {
- var node = this.options.program || this.startNode();
- this.nextToken();
- return this.parseTopLevel(node)
+Parser.parse = function parse (input, options) {
+ return new this(options, input).parse()
+};
+
+Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) {
+ var parser = new this(options, input, pos);
+ parser.nextToken();
+ return parser.parseExpression()
};
+Parser.tokenizer = function tokenizer (input, options) {
+ return new this(options, input)
+};
+
+Object.defineProperties( Parser.prototype, prototypeAccessors );
+
var pp = Parser.prototype;
// ## Parser utilities
@@ -3767,7 +5359,7 @@ pp$1.parseTopLevel = function(node) {
var exports = {};
if (!node.body) { node.body = []; }
while (this.type !== types.eof) {
- var stmt = this$1.parseStatement(true, true, exports);
+ var stmt = this$1.parseStatement(null, true, exports);
node.body.push(stmt);
}
this.adaptDirectivePrologue(node.body);
@@ -3818,7 +5410,7 @@ pp$1.isAsyncFunction = function() {
// `if (foo) /blah/.exec(foo)`, where looking at the previous token
// does not help.
-pp$1.parseStatement = function(declaration, topLevel, exports) {
+pp$1.parseStatement = function(context, topLevel, exports) {
var starttype = this.type, node = this.startNode(), kind;
if (this.isLet()) {
@@ -3836,10 +5428,10 @@ pp$1.parseStatement = function(declaration, topLevel, exports) {
case types._do: return this.parseDoStatement(node)
case types._for: return this.parseForStatement(node)
case types._function:
- if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); }
- return this.parseFunctionStatement(node, false)
+ if ((context && (this.strict || context !== "if")) && this.options.ecmaVersion >= 6) { this.unexpected(); }
+ return this.parseFunctionStatement(node, false, !context)
case types._class:
- if (!declaration) { this.unexpected(); }
+ if (context) { this.unexpected(); }
return this.parseClass(node, true)
case types._if: return this.parseIfStatement(node)
case types._return: return this.parseReturnStatement(node)
@@ -3848,11 +5440,11 @@ pp$1.parseStatement = function(declaration, topLevel, exports) {
case types._try: return this.parseTryStatement(node)
case types._const: case types._var:
kind = kind || this.value;
- if (!declaration && kind !== "var") { this.unexpected(); }
+ if (context && kind !== "var") { this.unexpected(); }
return this.parseVarStatement(node, kind)
case types._while: return this.parseWhileStatement(node)
case types._with: return this.parseWithStatement(node)
- case types.braceL: return this.parseBlock()
+ case types.braceL: return this.parseBlock(true, node)
case types.semi: return this.parseEmptyStatement(node)
case types._export:
case types._import:
@@ -3871,14 +5463,14 @@ pp$1.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)
}
var maybeName = this.value, expr = this.parseExpression();
if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
- { return this.parseLabeledStatement(node, maybeName, expr) }
+ { return this.parseLabeledStatement(node, maybeName, expr, context) }
else { return this.parseExpressionStatement(node, expr) }
}
};
@@ -3918,7 +5510,7 @@ pp$1.parseDebuggerStatement = function(node) {
pp$1.parseDoStatement = function(node) {
this.next();
this.labels.push(loopLabel);
- node.body = this.parseStatement(false);
+ node.body = this.parseStatement("do");
this.labels.pop();
this.expect(types._while);
node.test = this.parseParenExpression();
@@ -3939,9 +5531,9 @@ pp$1.parseDoStatement = function(node) {
pp$1.parseForStatement = function(node) {
this.next();
- var awaitAt = (this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await")) ? this.lastTokStart : -1;
+ var 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(types.parenL);
if (this.type === types.semi) {
if (awaitAt > -1) { this.unexpected(awaitAt); }
@@ -3983,17 +5575,17 @@ pp$1.parseForStatement = function(node) {
return this.parseFor(node, init)
};
-pp$1.parseFunctionStatement = function(node, isAsync) {
+pp$1.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$1.parseIfStatement = function(node) {
this.next();
node.test = this.parseParenExpression();
// allow function declarations in branches, but only in non-strict mode
- node.consequent = this.parseStatement(!this.strict && this.type === types._function);
- node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.type === types._function) : null;
+ node.consequent = this.parseStatement("if");
+ node.alternate = this.eat(types._else) ? this.parseStatement("if") : null;
return this.finishNode(node, "IfStatement")
};
@@ -4019,7 +5611,7 @@ pp$1.parseSwitchStatement = function(node) {
node.cases = [];
this.expect(types.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
@@ -4043,10 +5635,10 @@ pp$1.parseSwitchStatement = function(node) {
this$1.expect(types.colon);
} else {
if (!cur) { this$1.unexpected(); }
- cur.consequent.push(this$1.parseStatement(true));
+ cur.consequent.push(this$1.parseStatement(null));
}
}
- this.exitLexicalScope();
+ this.exitScope();
if (cur) { this.finishNode(cur, "SwitchCase"); }
this.next(); // Closing brace
this.labels.pop();
@@ -4075,16 +5667,17 @@ pp$1.parseTryStatement = function(node) {
this.next();
if (this.eat(types.parenL)) {
clause.param = this.parseBindingAtom();
- this.enterLexicalScope();
- this.checkLVal(clause.param, "let");
+ var simple = clause.param.type === "Identifier";
+ this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
+ this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
this.expect(types.parenR);
} else {
if (this.options.ecmaVersion < 10) { this.unexpected(); }
clause.param = null;
- this.enterLexicalScope();
+ this.enterScope(0);
}
clause.body = this.parseBlock(false);
- this.exitLexicalScope();
+ this.exitScope();
node.handler = this.finishNode(clause, "CatchClause");
}
node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
@@ -4104,7 +5697,7 @@ pp$1.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")
};
@@ -4113,7 +5706,7 @@ pp$1.parseWithStatement = function(node) {
if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
this.next();
node.object = this.parseParenExpression();
- node.body = this.parseStatement(false);
+ node.body = this.parseStatement("with");
return this.finishNode(node, "WithStatement")
};
@@ -4122,7 +5715,7 @@ pp$1.parseEmptyStatement = function(node) {
return this.finishNode(node, "EmptyStatement")
};
-pp$1.parseLabeledStatement = function(node, maybeName, expr) {
+pp$1.parseLabeledStatement = function(node, maybeName, expr, context) {
var this$1 = this;
for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1)
@@ -4142,10 +5735,10 @@ pp$1.parseLabeledStatement = function(node, maybeName, expr) {
} else { break }
}
this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
- node.body = this.parseStatement(true);
+ node.body = this.parseStatement(context);
if (node.body.type === "ClassDeclaration" ||
node.body.type === "VariableDeclaration" && node.body.kind !== "var" ||
- node.body.type === "FunctionDeclaration" && (this.strict || node.body.generator))
+ node.body.type === "FunctionDeclaration" && (this.strict || node.body.generator || node.body.async))
{ this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); }
this.labels.pop();
node.label = expr;
@@ -4162,23 +5755,19 @@ pp$1.parseExpressionStatement = function(node, expr) {
// strict"` declarations when `allowStrict` is true (used for
// function bodies).
-pp$1.parseBlock = function(createNewLexicalScope) {
+pp$1.parseBlock = function(createNewLexicalScope, node) {
var this$1 = this;
if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
+ if ( node === void 0 ) node = this.startNode();
- var node = this.startNode();
node.body = [];
this.expect(types.braceL);
- if (createNewLexicalScope) {
- this.enterLexicalScope();
- }
+ if (createNewLexicalScope) { this.enterScope(0); }
while (!this.eat(types.braceR)) {
- var stmt = this$1.parseStatement(true);
+ var stmt = this$1.parseStatement(null);
node.body.push(stmt);
}
- if (createNewLexicalScope) {
- this.exitLexicalScope();
- }
+ if (createNewLexicalScope) { this.exitScope(); }
return this.finishNode(node, "BlockStatement")
};
@@ -4193,8 +5782,8 @@ pp$1.parseFor = function(node, init) {
this.expect(types.semi);
node.update = this.type === types.parenR ? null : this.parseExpression();
this.expect(types.parenR);
- this.exitLexicalScope();
- node.body = this.parseStatement(false);
+ this.exitScope();
+ node.body = this.parseStatement("for");
this.labels.pop();
return this.finishNode(node, "ForStatement")
};
@@ -4214,8 +5803,8 @@ pp$1.parseForIn = function(node, init) {
node.left = init;
node.right = type === "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign();
this.expect(types.parenR);
- this.exitLexicalScope();
- node.body = this.parseStatement(false);
+ this.exitScope();
+ node.body = this.parseStatement("for");
this.labels.pop();
return this.finishNode(node, type)
};
@@ -4247,47 +5836,43 @@ pp$1.parseVar = function(node, isFor, kind) {
pp$1.parseVarId = function(decl, kind) {
decl.id = this.parseBindingAtom(kind);
- this.checkLVal(decl.id, kind, false);
+ this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false);
};
+var FUNC_STATEMENT = 1;
+var FUNC_HANGING_STATEMENT = 2;
+var FUNC_NULLABLE_ID = 4;
+
// Parse a function declaration or literal (depending on the
// `isStatement` parameter).
-pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) {
+pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) {
this.initFunction(node);
if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync)
{ node.generator = this.eat(types.star); }
if (this.options.ecmaVersion >= 8)
{ node.async = !!isAsync; }
- if (isStatement) {
- node.id = isStatement === "nullableID" && this.type !== types.name ? null : this.parseIdent();
- if (node.id) {
- this.checkLVal(node.id, "var");
- }
+ if (statement & FUNC_STATEMENT) {
+ node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent();
+ if (node.id && !(statement & FUNC_HANGING_STATEMENT))
+ { this.checkLVal(node.id, this.inModule && !this.inFunction ? BIND_LEXICAL : BIND_FUNCTION); }
}
- var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
- oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;
- this.inGenerator = node.generator;
- this.inAsync = node.async;
+ var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos;
this.yieldPos = 0;
this.awaitPos = 0;
- this.inFunction = true;
- this.enterFunctionScope();
+ this.enterScope(functionFlags(node.async, node.generator));
- if (!isStatement)
+ if (!(statement & FUNC_STATEMENT))
{ node.id = this.type === types.name ? this.parseIdent() : null; }
this.parseFunctionParams(node);
this.parseFunctionBody(node, allowExpressionBody);
- this.inGenerator = oldInGen;
- this.inAsync = oldInAsync;
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
- this.inFunction = oldInFunc;
- return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
+ return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression")
};
pp$1.parseFunctionParams = function(node) {
@@ -4311,17 +5896,20 @@ pp$1.parseClass = function(node, isStatement) {
classBody.body = [];
this.expect(types.braceL);
while (!this.eat(types.braceR)) {
- var member = this$1.parseClassMember(classBody);
- if (member && member.type === "MethodDefinition" && member.kind === "constructor") {
- if (hadConstructor) { this$1.raise(member.start, "Duplicate constructor in the same class"); }
- hadConstructor = true;
+ var element = this$1.parseClassElement();
+ if (element) {
+ classBody.body.push(element);
+ if (element.type === "MethodDefinition" && element.kind === "constructor") {
+ if (hadConstructor) { this$1.raise(element.start, "Duplicate constructor in the same class"); }
+ hadConstructor = true;
+ }
}
}
node.body = this.finishNode(classBody, "ClassBody");
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
};
-pp$1.parseClassMember = function(classBody) {
+pp$1.parseClassElement = function() {
var this$1 = this;
if (this.eat(types.semi)) { return null }
@@ -4366,7 +5954,7 @@ pp$1.parseClassMember = function(classBody) {
} 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);
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)
@@ -4376,9 +5964,9 @@ pp$1.parseClassMember = function(classBody) {
return method
};
-pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) {
+pp$1.parseClassMethod = function(method, isGenerator, isAsync) {
method.value = this.parseMethod(isGenerator, isAsync);
- classBody.body.push(this.finishNode(method, "MethodDefinition"));
+ return this.finishNode(method, "MethodDefinition")
};
pp$1.parseClassId = function(node, isStatement) {
@@ -4410,7 +5998,7 @@ pp$1.parseExport = function(node, exports) {
var 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, true);
} else if (this.type === types._class) {
var cNode = this.startNode();
node.declaration = this.parseClass(cNode, "nullableID");
@@ -4422,7 +6010,7 @@ pp$1.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
@@ -4557,7 +6145,7 @@ pp$1.parseImportSpecifiers = function() {
// import defaultObj, { x, y as z } from '...'
var 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(types.comma)) { return nodes }
}
@@ -4566,7 +6154,7 @@ pp$1.parseImportSpecifiers = function() {
this.next();
this.expectContextual("as");
node$1.local = this.parseIdent();
- this.checkLVal(node$1.local, "let");
+ this.checkLVal(node$1.local, BIND_LEXICAL);
nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
return nodes
}
@@ -4585,7 +6173,7 @@ pp$1.parseImportSpecifiers = function() {
this$1.checkUnreserved(node$2.imported);
node$2.local = node$2.imported;
}
- this$1.checkLVal(node$2.local, "let");
+ this$1.checkLVal(node$2.local, BIND_LEXICAL);
nodes.push(this$1.finishNode(node$2, "ImportSpecifier"));
}
return nodes
@@ -4800,6 +6388,7 @@ pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
pp$2.checkLVal = function(expr, bindingType, checkClashes) {
var this$1 = this;
+ if ( bindingType === void 0 ) bindingType = BIND_NONE;
switch (expr.type) {
case "Identifier":
@@ -4810,19 +6399,7 @@ pp$2.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":
@@ -4971,7 +6548,12 @@ pp$3.parseExpression = function(noIn, refDestructuringErrors) {
// operators like `+=`.
pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
- if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() }
+ if (this.isContextual("yield")) {
+ if (this.inGenerator) { return this.parseYield() }
+ // The tokenizer will assume an expression is allowed after
+ // `yield`, but this isn't that kind of yield
+ else { this.exprAllowed = false; }
+ }
var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1;
if (refDestructuringErrors) {
@@ -5194,7 +6776,7 @@ pp$3.parseExprAtom = function(refDestructuringErrors) {
var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
var id = this.parseIdent(this.type !== types.name);
if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
- { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) }
+ { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) }
if (canBeArrow && !this.canInsertSemicolon()) {
if (this.eat(types.arrow))
{ return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
@@ -5245,7 +6827,7 @@ pp$3.parseExprAtom = function(refDestructuringErrors) {
case types._function:
node = this.startNode();
this.next();
- return this.parseFunction(node, false)
+ return this.parseFunction(node, 0)
case types._class:
return this.parseClass(this.startNode(), false)
@@ -5364,7 +6946,7 @@ pp$3.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")
}
@@ -5411,6 +6993,7 @@ pp$3.parseTemplate = function(ref) {
var curElt = this.parseTemplateElement({isTagged: isTagged});
node.quasis = [curElt];
while (!curElt.tail) {
+ if (this$1.type === types.eof) { this$1.raise(this$1.pos, "Unterminated template literal"); }
this$1.expect(types.dollarBraceL);
node.expressions.push(this$1.parseExpression());
this$1.expect(types.braceR);
@@ -5563,19 +7146,14 @@ pp$3.parsePropertyName = function(prop) {
pp$3.initFunction = function(node) {
node.id = null;
- if (this.options.ecmaVersion >= 6) {
- node.generator = false;
- node.expression = false;
- }
- if (this.options.ecmaVersion >= 8)
- { node.async = false; }
+ if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; }
+ if (this.options.ecmaVersion >= 8) { node.async = false; }
};
// Parse object or class method.
pp$3.parseMethod = function(isGenerator, isAsync) {
- var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync,
- oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;
+ var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos;
this.initFunction(node);
if (this.options.ecmaVersion >= 6)
@@ -5583,51 +7161,37 @@ pp$3.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.enterScope(functionFlags(isAsync, node.generator));
this.expect(types.parenL);
node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
this.checkYieldAwaitInDefaultParams();
this.parseFunctionBody(node, false);
- this.inGenerator = oldInGen;
- this.inAsync = oldInAsync;
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
- this.inFunction = oldInFunc;
return this.finishNode(node, "FunctionExpression")
};
// Parse arrow function expression with given parameters.
pp$3.parseArrowExpression = function(node, params, isAsync) {
- var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
- oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;
+ var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos;
- 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;
node.params = this.toAssignableList(params, true);
this.parseFunctionBody(node, true);
- this.inGenerator = oldInGen;
- this.inAsync = oldInAsync;
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
- this.inFunction = oldInFunc;
return this.finishNode(node, "ArrowFunctionExpression")
};
@@ -5665,12 +7229,10 @@ pp$3.parseFunctionBody = function(node, isArrowFunction) {
this.adaptDirectivePrologue(node.body.body);
this.labels = oldLabels;
}
- this.exitFunctionScope();
+ this.exitScope();
- 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");
- }
+ // 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); }
this.strict = oldStrict;
};
@@ -5695,7 +7257,7 @@ pp$3.checkParams = function(node, allowDuplicates) {
{
var param = list[i];
- this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash);
+ this$1.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash);
}
};
@@ -5739,7 +7301,7 @@ pp$3.checkUnreserved = function(ref) {
{ this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); }
if (this.inAsync && name === "await")
{ this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); }
- if (this.isKeyword(name))
+ if (this.keywords.test(name))
{ this.raise(start, ("Unexpected keyword '" + name + "'")); }
if (this.options.ecmaVersion < 6 &&
this.input.slice(start, end).indexOf("\\") !== -1) { return }
@@ -5832,79 +7394,69 @@ pp$4.curPosition = function() {
var pp$5 = Parser.prototype;
-// Object.assign polyfill
-var assign = Object.assign || function(target) {
- var sources = [], len = arguments.length - 1;
- while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
-
- for (var i = 0, list = sources; i < list.length; i += 1) {
- var source = list[i];
-
- for (var key in source) {
- if (has(source, key)) {
- target[key] = source[key];
- }
- }
- }
- return target
+var Scope = function Scope(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 = [];
};
// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
-pp$5.enterFunctionScope = function() {
- // var: a hash of var-declared names in the current lexical scope
- // lexical: a hash of lexically-declared names in the current lexical scope
- // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope)
- // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope)
- this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}});
+pp$5.enterScope = function(flags) {
+ this.scopeStack.push(new Scope(flags));
};
-pp$5.exitFunctionScope = function() {
+pp$5.exitScope = function() {
this.scopeStack.pop();
};
-pp$5.enterLexicalScope = function() {
- var parentScope = this.scopeStack[this.scopeStack.length - 1];
- var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}};
-
- this.scopeStack.push(childScope);
- assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical);
-};
-
-pp$5.exitLexicalScope = function() {
- var childScope = this.scopeStack.pop();
- var parentScope = this.scopeStack[this.scopeStack.length - 1];
+pp$5.declareName = function(name, bindingType, pos) {
+ var this$1 = this;
- assign(parentScope.childVar, childScope.var, childScope.childVar);
+ var redeclared = false;
+ if (bindingType === BIND_LEXICAL) {
+ var scope = this.currentScope();
+ redeclared = scope.lexical.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
+ scope.lexical.push(name);
+ } else if (bindingType === BIND_SIMPLE_CATCH) {
+ var scope$1 = this.currentScope();
+ scope$1.lexical.push(name);
+ } else if (bindingType === BIND_FUNCTION) {
+ var scope$2 = this.currentScope();
+ redeclared = scope$2.lexical.indexOf(name) > -1;
+ scope$2.var.push(name);
+ } else {
+ for (var i = this.scopeStack.length - 1; i >= 0; --i) {
+ var scope$3 = this$1.scopeStack[i];
+ if (scope$3.lexical.indexOf(name) > -1 && !(scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) { redeclared = true; }
+ scope$3.var.push(name);
+ if (scope$3.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$5.canDeclareVarName = function(name) {
- var currentScope = this.scopeStack[this.scopeStack.length - 1];
-
- return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name)
+pp$5.currentScope = function() {
+ return this.scopeStack[this.scopeStack.length - 1]
};
-/**
- * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const`
- * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in
- * any child lexical scopes in this function.
- */
-pp$5.canDeclareLexicalName = function(name) {
- var currentScope = this.scopeStack[this.scopeStack.length - 1];
+pp$5.currentVarScope = function() {
+ var this$1 = this;
- return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name)
+ for (var i = this.scopeStack.length - 1;; i--) {
+ var scope = this$1.scopeStack[i];
+ if (scope.flags & SCOPE_VAR) { return scope }
+ }
};
-pp$5.declareVarName = function(name) {
- this.scopeStack[this.scopeStack.length - 1].var[name] = true;
-};
+pp$5.inNonArrowFunction = function() {
+ var this$1 = this;
-pp$5.declareLexicalName = function(name) {
- this.scopeStack[this.scopeStack.length - 1].lexical[name] = true;
+ for (var i = this.scopeStack.length - 1; i >= 0; i--)
+ { if (this$1.scopeStack[i].flags & SCOPE_FUNCTION && !(this$1.scopeStack[i].flags & SCOPE_ARROW)) { return true } }
+ return false
};
var Node = function Node(parser, pos, loc) {
@@ -6090,7 +7642,7 @@ types.star.updateContext = function(prevType) {
types.name.updateContext = function(prevType) {
var allowed = false;
- if (this.options.ecmaVersion >= 6) {
+ if (this.options.ecmaVersion >= 6 && prevType !== types.dot) {
if (this.value === "of" && !this.exprAllowed ||
this.value === "yield" && this.inGeneratorContext())
{ allowed = true; }
@@ -8331,14 +9883,9 @@ pp$8.readWord = function() {
//
// [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
-var version = "5.7.1";
+var version = "6.0.1";
// The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and
@@ -8348,7 +9895,7 @@ var version = "5.7.1";
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
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
@@ -8356,35 +9903,21 @@ function parse(input, options) {
// that embed JavaScript expressions.
function parseExpressionAt(input, pos, options) {
- var 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.
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.
- // eslint-disable-line camelcase
-function addLooseExports(parse, Parser$$1, plugins$$1) {
- exports.parse_dammit = parse; // eslint-disable-line camelcase
- exports.LooseParser = Parser$$1;
- exports.pluginsLoose = plugins$$1;
+ return Parser.tokenizer(input, options)
}
exports.version = version;
exports.parse = parse;
exports.parseExpressionAt = parseExpressionAt;
exports.tokenizer = tokenizer;
-exports.addLooseExports = addLooseExports;
exports.Parser = Parser;
-exports.plugins = plugins;
exports.defaultOptions = defaultOptions;
exports.Position = Position;
exports.SourceLocation = SourceLocation;
@@ -8407,1258 +9940,2509 @@ Object.defineProperty(exports, '__esModule', { value: true });
})));
-},{}],13:[function(require,module,exports){
+
+},{}],15:[function(require,module,exports){
(function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('./acorn')) :
- typeof define === 'function' && define.amd ? define(['exports', './acorn'], factory) :
- (factory((global.acorn = global.acorn || {}, global.acorn.loose = {}),global.acorn));
-}(this, (function (exports,__acorn) { 'use strict';
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
+ (factory((global.acorn = {})));
+}(this, (function (exports) { 'use strict';
-function noop() {}
+// Reserved word lists for various dialects of the language
-// Registered plugins
-var pluginsLoose = {};
+var reservedWords = {
+ 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
+ 5: "class enum extends super const export import",
+ 6: "enum",
+ strict: "implements interface let package private protected public static yield",
+ strictBind: "eval arguments"
+};
-var LooseParser = function LooseParser(input, options) {
- if ( options === void 0 ) options = {};
+// And the keywords
- this.toks = __acorn.tokenizer(input, options);
- this.options = this.toks.options;
- this.input = this.toks.input;
- this.tok = this.last = {type: __acorn.tokTypes.eof, start: 0, end: 0};
- this.tok.validateRegExpFlags = noop;
- this.tok.validateRegExpPattern = noop;
- if (this.options.locations) {
- var here = this.toks.curPosition();
- this.tok.loc = new __acorn.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;
- this.inFunction = false;
- // Load plugins
- this.options.pluginsLoose = options.pluginsLoose || {};
- this.loadPlugins(this.options.pluginsLoose);
-};
+var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
-LooseParser.prototype.startNode = function startNode () {
- return new __acorn.Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null)
+var keywords = {
+ 5: ecma5AndLessKeywords,
+ 6: ecma5AndLessKeywords + " const class extends export import super"
};
-LooseParser.prototype.storeCurrentPos = function storeCurrentPos () {
- return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start
-};
+var keywordRelationalOperator = /^in(stanceof)?$/;
-LooseParser.prototype.startNodeAt = function startNodeAt (pos) {
- if (this.options.locations) {
- return new __acorn.Node(this.toks, pos[0], pos[1])
- } else {
- return new __acorn.Node(this.toks, pos)
- }
-};
+// ## Character categories
-LooseParser.prototype.finishNode = function 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
-};
+// Big ugly regular expressions that match characters in the
+// whitespace, identifier, and identifier-start categories. These
+// are only applied when a character is found to actually have a
+// code point above 128.
+// Generated by `bin/generate-identifier-regex.js`.
-LooseParser.prototype.dummyNode = function dummyNode (type) {
- var 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: __acorn.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc};
- return dummy
-};
+var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\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-\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-\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-\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-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7b9\ua7f7-\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-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
+var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\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\u0b56\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\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\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";
-LooseParser.prototype.dummyIdent = function dummyIdent () {
- var dummy = this.dummyNode("Identifier");
- dummy.name = "✖";
- return dummy
-};
+var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
+var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
-LooseParser.prototype.dummyString = function dummyString () {
- var dummy = this.dummyNode("Literal");
- dummy.value = dummy.raw = "✖";
- return dummy
-};
+nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
-LooseParser.prototype.eat = function eat (type) {
- if (this.tok.type === type) {
- this.next();
- return true
- } else {
- return false
+// These are a run-length and offset encoded representation of the
+// >0xffff code points that are a valid part of identifiers. The
+// offset starts at 0x10000, and each pair of numbers represents an
+// offset to the next range, and then a size of the range. They were
+// generated by bin/generate-identifier-regex.js
+
+// eslint-disable-next-line comma-spacing
+var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,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,477,28,11,0,9,21,190,52,76,44,33,24,27,35,30,0,12,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,26,230,43,117,63,32,0,257,0,11,39,8,0,22,0,12,39,3,3,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,270,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,68,12,0,67,12,65,1,31,6129,15,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];
+
+// eslint-disable-next-line comma-spacing
+var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,525,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,4,9,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,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,49,4,2,1,2,4,9,9,330,3,19306,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];
+
+// This has a complexity linear to the value of the code. The
+// assumption is that looking up astral identifier characters is
+// rare.
+function isInAstralSet(code, set) {
+ var pos = 0x10000;
+ for (var i = 0; i < set.length; i += 2) {
+ pos += set[i];
+ if (pos > code) { return false }
+ pos += set[i + 1];
+ if (pos >= code) { return true }
}
+}
+
+// Test whether a given character code starts an identifier.
+
+function isIdentifierStart(code, astral) {
+ if (code < 65) { return code === 36 }
+ if (code < 91) { return true }
+ if (code < 97) { return code === 95 }
+ if (code < 123) { return true }
+ if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
+ if (astral === false) { return false }
+ return isInAstralSet(code, astralIdentifierStartCodes)
+}
+
+// Test whether a given character is part of an identifier.
+
+function isIdentifierChar(code, astral) {
+ if (code < 48) { return code === 36 }
+ if (code < 58) { return true }
+ if (code < 65) { return false }
+ if (code < 91) { return true }
+ if (code < 97) { return code === 95 }
+ if (code < 123) { return true }
+ if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
+ if (astral === false) { return false }
+ return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
+}
+
+// ## Token types
+
+// The assignment of fine-grained, information-carrying type objects
+// allows the tokenizer to store the information it has about a
+// token in a way that is very cheap for the parser to look up.
+
+// All token type variables start with an underscore, to make them
+// easy to recognize.
+
+// The `beforeExpr` property is used to disambiguate between regular
+// expressions and divisions. It is set on all token types that can
+// be followed by an expression (thus, a slash after them would be a
+// regular expression).
+//
+// The `startsExpr` property is used to check if the token ends a
+// `yield` expression. It is set on all token types that either can
+// directly start an expression (like a quotation mark) or can
+// continue an expression (like the body of a string).
+//
+// `isLoop` marks a keyword as starting a loop, which is important
+// to know when parsing a label, in order to allow or disallow
+// continue jumps to that label.
+
+var TokenType = function TokenType(label, conf) {
+ if ( conf === void 0 ) conf = {};
+
+ this.label = label;
+ this.keyword = conf.keyword;
+ this.beforeExpr = !!conf.beforeExpr;
+ this.startsExpr = !!conf.startsExpr;
+ this.isLoop = !!conf.isLoop;
+ this.isAssign = !!conf.isAssign;
+ this.prefix = !!conf.prefix;
+ this.postfix = !!conf.postfix;
+ this.binop = conf.binop || null;
+ this.updateContext = null;
};
-LooseParser.prototype.isContextual = function isContextual (name) {
- return this.tok.type === __acorn.tokTypes.name && this.tok.value === name
+function binop(name, prec) {
+ return new TokenType(name, {beforeExpr: true, binop: prec})
+}
+var beforeExpr = {beforeExpr: true};
+var startsExpr = {startsExpr: true};
+
+// Map keyword names to token types.
+
+var keywords$1 = {};
+
+// Succinct definitions of keyword token types
+function kw(name, options) {
+ if ( options === void 0 ) options = {};
+
+ options.keyword = name;
+ return keywords$1[name] = new TokenType(name, options)
+}
+
+var types = {
+ num: new TokenType("num", startsExpr),
+ regexp: new TokenType("regexp", startsExpr),
+ string: new TokenType("string", startsExpr),
+ name: new TokenType("name", startsExpr),
+ eof: new TokenType("eof"),
+
+ // Punctuation token types.
+ bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
+ bracketR: new TokenType("]"),
+ braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
+ braceR: new TokenType("}"),
+ parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
+ parenR: new TokenType(")"),
+ comma: new TokenType(",", beforeExpr),
+ semi: new TokenType(";", beforeExpr),
+ colon: new TokenType(":", beforeExpr),
+ dot: new TokenType("."),
+ question: new TokenType("?", beforeExpr),
+ arrow: new TokenType("=>", beforeExpr),
+ template: new TokenType("template"),
+ invalidTemplate: new TokenType("invalidTemplate"),
+ ellipsis: new TokenType("...", beforeExpr),
+ backQuote: new TokenType("`", startsExpr),
+ dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
+
+ // Operators. These carry several kinds of properties to help the
+ // parser use them properly (the presence of these properties is
+ // what categorizes them as operators).
+ //
+ // `binop`, when present, specifies that this operator is a binary
+ // operator, and will refer to its precedence.
+ //
+ // `prefix` and `postfix` mark the operator as a prefix or postfix
+ // unary operator.
+ //
+ // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
+ // binary operators with a very low precedence, that should result
+ // in AssignmentExpression nodes.
+
+ eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
+ assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
+ incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
+ prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
+ logicalOR: binop("||", 1),
+ logicalAND: binop("&&", 2),
+ bitwiseOR: binop("|", 3),
+ bitwiseXOR: binop("^", 4),
+ bitwiseAND: binop("&", 5),
+ equality: binop("==/!=/===/!==", 6),
+ relational: binop("</>/<=/>=", 7),
+ bitShift: binop("<</>>/>>>", 8),
+ plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
+ modulo: binop("%", 10),
+ star: binop("*", 10),
+ slash: binop("/", 10),
+ starstar: new TokenType("**", {beforeExpr: true}),
+
+ // Keyword token types.
+ _break: kw("break"),
+ _case: kw("case", beforeExpr),
+ _catch: kw("catch"),
+ _continue: kw("continue"),
+ _debugger: kw("debugger"),
+ _default: kw("default", beforeExpr),
+ _do: kw("do", {isLoop: true, beforeExpr: true}),
+ _else: kw("else", beforeExpr),
+ _finally: kw("finally"),
+ _for: kw("for", {isLoop: true}),
+ _function: kw("function", startsExpr),
+ _if: kw("if"),
+ _return: kw("return", beforeExpr),
+ _switch: kw("switch"),
+ _throw: kw("throw", beforeExpr),
+ _try: kw("try"),
+ _var: kw("var"),
+ _const: kw("const"),
+ _while: kw("while", {isLoop: true}),
+ _with: kw("with"),
+ _new: kw("new", {beforeExpr: true, startsExpr: true}),
+ _this: kw("this", startsExpr),
+ _super: kw("super", startsExpr),
+ _class: kw("class", startsExpr),
+ _extends: kw("extends", beforeExpr),
+ _export: kw("export"),
+ _import: kw("import"),
+ _null: kw("null", startsExpr),
+ _true: kw("true", startsExpr),
+ _false: kw("false", startsExpr),
+ _in: kw("in", {beforeExpr: true, binop: 7}),
+ _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
+ _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
+ _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
+ _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
};
-LooseParser.prototype.eatContextual = function eatContextual (name) {
- return this.tok.value === name && this.eat(__acorn.tokTypes.name)
+// Matches a whole line break (where CRLF is considered a single
+// line break). Used to count lines.
+
+var lineBreak = /\r\n?|\n|\u2028|\u2029/;
+var lineBreakG = new RegExp(lineBreak.source, "g");
+
+function isNewLine(code, ecma2019String) {
+ return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029))
+}
+
+var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
+
+var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
+
+var ref = Object.prototype;
+var hasOwnProperty = ref.hasOwnProperty;
+var toString = ref.toString;
+
+// Checks if an object has a property.
+
+function has(obj, propName) {
+ return hasOwnProperty.call(obj, propName)
+}
+
+var isArray = Array.isArray || (function (obj) { return (
+ toString.call(obj) === "[object Array]"
+); });
+
+// These are used when `options.locations` is on, for the
+// `startLoc` and `endLoc` properties.
+
+var Position = function Position(line, col) {
+ this.line = line;
+ this.column = col;
};
-LooseParser.prototype.canInsertSemicolon = function canInsertSemicolon () {
- return this.tok.type === __acorn.tokTypes.eof || this.tok.type === __acorn.tokTypes.braceR ||
- __acorn.lineBreak.test(this.input.slice(this.last.end, this.tok.start))
+Position.prototype.offset = function offset (n) {
+ return new Position(this.line, this.column + n)
};
-LooseParser.prototype.semicolon = function semicolon () {
- return this.eat(__acorn.tokTypes.semi)
+var SourceLocation = function SourceLocation(p, start, end) {
+ this.start = start;
+ this.end = end;
+ if (p.sourceFile !== null) { this.source = p.sourceFile; }
};
-LooseParser.prototype.expect = function expect (type) {
- var this$1 = this;
+// The `getLineInfo` function is mostly useful when the
+// `locations` option is off (for performance reasons) and you
+// want to find the line/column position for a given character
+// offset. `input` should be the code string that the offset refers
+// into.
- if (this.eat(type)) { return true }
- for (var i = 1; i <= 2; i++) {
- if (this$1.lookAhead(i).type === type) {
- for (var j = 0; j < i; j++) { this$1.next(); }
- return true
+function getLineInfo(input, offset) {
+ for (var line = 1, cur = 0;;) {
+ lineBreakG.lastIndex = cur;
+ var match = lineBreakG.exec(input);
+ if (match && match.index < offset) {
+ ++line;
+ cur = match.index + match[0].length;
+ } else {
+ return new Position(line, offset - cur)
}
}
-};
+}
-LooseParser.prototype.pushCx = function pushCx () {
- this.context.push(this.curIndent);
-};
+// A second optional argument can be given to further configure
+// the parser process. These options are recognized:
-LooseParser.prototype.popCx = function popCx () {
- this.curIndent = this.context.pop();
+var defaultOptions = {
+ // `ecmaVersion` indicates the ECMAScript version to parse. Must
+ // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support
+ // for strict mode, the set of reserved words, and support for
+ // new syntax features. The default is 7.
+ ecmaVersion: 7,
+ // `sourceType` indicates the mode the code should be parsed in.
+ // Can be either `"script"` or `"module"`. This influences global
+ // strict mode and parsing of `import` and `export` declarations.
+ sourceType: "script",
+ // `onInsertedSemicolon` can be a callback that will be called
+ // when a semicolon is automatically inserted. It will be passed
+ // th position of the comma as an offset, and if `locations` is
+ // enabled, it is given the location as a `{line, column}` object
+ // as second argument.
+ onInsertedSemicolon: null,
+ // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
+ // trailing commas.
+ onTrailingComma: null,
+ // By default, reserved words are only enforced if ecmaVersion >= 5.
+ // Set `allowReserved` to a boolean value to explicitly turn this on
+ // an off. When this option has the value "never", reserved words
+ // and keywords can also not be used as property names.
+ allowReserved: null,
+ // When enabled, a return at the top level is not considered an
+ // error.
+ allowReturnOutsideFunction: false,
+ // When enabled, import/export statements are not constrained to
+ // appearing at the top of the program.
+ allowImportExportEverywhere: false,
+ // When enabled, 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,
+ // When `locations` is on, `loc` properties holding objects with
+ // `start` and `end` properties in `{line, column}` form (with
+ // line being 1-based and column 0-based) will be attached to the
+ // nodes.
+ locations: false,
+ // A function can be passed as `onToken` option, which will
+ // cause Acorn to call that function with object in the same
+ // format as tokens returned from `tokenizer().getToken()`. Note
+ // that you are not allowed to call the parser from the
+ // callback—that will corrupt its internal state.
+ onToken: null,
+ // A function can be passed as `onComment` option, which will
+ // cause Acorn to call that function with `(block, text, start,
+ // end)` parameters whenever a comment is skipped. `block` is a
+ // boolean indicating whether this is a block (`/* */`) comment,
+ // `text` is the content of the comment, and `start` and `end` are
+ // character offsets that denote the start and end of the comment.
+ // When the `locations` option is on, two more parameters are
+ // passed, the full `{line, column}` locations of the start and
+ // end of the comments. Note that you are not allowed to call the
+ // parser from the callback—that will corrupt its internal state.
+ onComment: null,
+ // Nodes have their start and end characters offsets recorded in
+ // `start` and `end` properties (directly on the node, rather than
+ // the `loc` object, which holds line/column data. To also add a
+ // [semi-standardized][range] `range` property holding a `[start,
+ // end]` array with the same numbers, set the `ranges` option to
+ // `true`.
+ //
+ // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
+ ranges: false,
+ // It is possible to parse multiple files into a single AST by
+ // passing the tree produced by parsing the first file as
+ // `program` option in subsequent parses. This will add the
+ // toplevel forms of the parsed file to the `Program` (top) node
+ // of an existing parse tree.
+ program: null,
+ // When `locations` is on, you can pass this to record the source
+ // file in every node's `loc` object.
+ sourceFile: null,
+ // This value, if given, is stored in every node, whether
+ // `locations` is on or off.
+ directSourceFile: null,
+ // When enabled, parenthesized expressions are represented by
+ // (non-standard) ParenthesizedExpression nodes
+ preserveParens: false,
+ plugins: {}
};
-LooseParser.prototype.lineEnd = function lineEnd (pos) {
- while (pos < this.input.length && !__acorn.isNewLine(this.input.charCodeAt(pos))) { ++pos; }
- return pos
-};
+// Interpret and default an options object
-LooseParser.prototype.indentationAfter = function indentationAfter (pos) {
- var this$1 = this;
+function getOptions(opts) {
+ var options = {};
- for (var count = 0;; ++pos) {
- var ch = this$1.input.charCodeAt(pos);
- if (ch === 32) { ++count; }
- else if (ch === 9) { count += this$1.options.tabSize; }
- else { return count }
+ for (var opt in defaultOptions)
+ { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }
+
+ if (options.ecmaVersion >= 2015)
+ { options.ecmaVersion -= 2009; }
+
+ if (options.allowReserved == null)
+ { options.allowReserved = options.ecmaVersion < 5; }
+
+ if (isArray(options.onToken)) {
+ var tokens = options.onToken;
+ options.onToken = function (token) { return tokens.push(token); };
}
-};
+ if (isArray(options.onComment))
+ { options.onComment = pushComment(options, options.onComment); }
-LooseParser.prototype.closes = function closes (closeTok, indent, line, blockHeuristic) {
- if (this.tok.type === closeTok || this.tok.type === __acorn.tokTypes.eof) { return true }
- return line !== this.curLineStart && this.curIndent < indent && this.tokenStartsLine() &&
- (!blockHeuristic || this.nextLineStart >= this.input.length ||
- this.indentationAfter(this.nextLineStart) < indent)
-};
+ return options
+}
-LooseParser.prototype.tokenStartsLine = function tokenStartsLine () {
- var this$1 = this;
+function pushComment(options, array) {
+ return function(block, text, start, end, startLoc, endLoc) {
+ var comment = {
+ type: block ? "Block" : "Line",
+ value: text,
+ start: start,
+ end: end
+ };
+ if (options.locations)
+ { comment.loc = new SourceLocation(this, startLoc, endLoc); }
+ if (options.ranges)
+ { comment.range = [start, end]; }
+ array.push(comment);
+ }
+}
- for (var p = this.tok.start - 1; p >= this.curLineStart; --p) {
- var ch = this$1.input.charCodeAt(p);
- if (ch !== 9 && ch !== 32) { return false }
+// Registered plugins
+var plugins = {};
+
+function keywordRegexp(words) {
+ return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
+}
+
+var Parser = function Parser(options, input, startPos) {
+ this.options = options = getOptions(options);
+ this.sourceFile = options.sourceFile;
+ this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]);
+ var reserved = "";
+ if (!options.allowReserved) {
+ for (var v = options.ecmaVersion;; v--)
+ { if (reserved = reservedWords[v]) { break } }
+ if (options.sourceType === "module") { reserved += " await"; }
}
- return true
+ this.reservedWords = keywordRegexp(reserved);
+ var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
+ this.reservedWordsStrict = keywordRegexp(reservedStrict);
+ this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind);
+ this.input = String(input);
+
+ // Used to signal to callers of `readWord1` whether the word
+ // contained any escape sequences. This is needed because words with
+ // escape sequences must not be interpreted as keywords.
+ this.containsEsc = false;
+
+ // Load plugins
+ this.loadPlugins(options.plugins);
+
+ // Set up token state
+
+ // The current position of the tokenizer in the input.
+ if (startPos) {
+ this.pos = startPos;
+ this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
+ this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
+ } else {
+ this.pos = this.lineStart = 0;
+ this.curLine = 1;
+ }
+
+ // Properties of the current token:
+ // Its type
+ this.type = types.eof;
+ // For tokens that include more information than their type, the value
+ this.value = null;
+ // Its start and end offset
+ this.start = this.end = this.pos;
+ // And, if locations are used, the {line, column} object
+ // corresponding to those offsets
+ this.startLoc = this.endLoc = this.curPosition();
+
+ // Position information for the previous token
+ this.lastTokEndLoc = this.lastTokStartLoc = null;
+ this.lastTokStart = this.lastTokEnd = this.pos;
+
+ // The context stack is used to superficially track syntactic
+ // context to predict whether a regular expression is allowed in a
+ // given position.
+ this.context = this.initialContext();
+ this.exprAllowed = true;
+
+ // Figure out if it's a module code.
+ this.inModule = options.sourceType === "module";
+ this.strict = this.inModule || this.strictDirective(this.pos);
+
+ // 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;
+ // Labels in scope.
+ this.labels = [];
+
+ // If enabled, skip leading hashbang line.
+ if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
+ { this.skipLineComment(2); }
+
+ // Scope tracking for duplicate variable names (see scope.js)
+ this.scopeStack = [];
+ this.enterFunctionScope();
+
+ // For RegExp validation
+ this.regexpState = null;
};
-LooseParser.prototype.extend = function extend (name, f) {
+// DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them
+Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) };
+Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) };
+
+Parser.prototype.extend = function extend (name, f) {
this[name] = f(this[name]);
};
-LooseParser.prototype.loadPlugins = function loadPlugins (pluginConfigs) {
+Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) {
var this$1 = this;
for (var name in pluginConfigs) {
- var plugin = pluginsLoose[name];
+ var plugin = plugins[name];
if (!plugin) { throw new Error("Plugin '" + name + "' not found") }
plugin(this$1, pluginConfigs[name]);
}
};
-LooseParser.prototype.parse = function parse () {
- this.next();
- return this.parseTopLevel()
+Parser.prototype.parse = function parse () {
+ var node = this.options.program || this.startNode();
+ this.nextToken();
+ return this.parseTopLevel(node)
};
-var lp = LooseParser.prototype;
+var pp = Parser.prototype;
-function isSpace(ch) {
- return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || __acorn.isNewLine(ch)
-}
+// ## Parser utilities
-lp.next = function() {
+var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/;
+pp.strictDirective = function(start) {
var this$1 = this;
- this.last = this.tok;
- if (this.ahead.length)
- { this.tok = this.ahead.shift(); }
- else
- { this.tok = this.readToken(); }
+ for (;;) {
+ skipWhiteSpace.lastIndex = start;
+ start += skipWhiteSpace.exec(this$1.input)[0].length;
+ var match = literal.exec(this$1.input.slice(start));
+ if (!match) { return false }
+ if ((match[1] || match[2]) === "use strict") { return true }
+ start += match[0].length;
+ }
+};
- if (this.tok.start >= this.nextLineStart) {
- while (this.tok.start >= this.nextLineStart) {
- this$1.curLineStart = this$1.nextLineStart;
- this$1.nextLineStart = this$1.lineEnd(this$1.curLineStart) + 1;
- }
- this.curIndent = this.indentationAfter(this.curLineStart);
+// Predicate that tests whether the next token is of the given
+// type, and if yes, consumes it as a side effect.
+
+pp.eat = function(type) {
+ if (this.type === type) {
+ this.next();
+ return true
+ } else {
+ return false
}
};
-lp.readToken = function() {
- var this$1 = this;
+// Tests whether parsed token is a contextual keyword.
- for (;;) {
- try {
- this$1.toks.next();
- if (this$1.toks.type === __acorn.tokTypes.dot &&
- this$1.input.substr(this$1.toks.end, 1) === "." &&
- this$1.options.ecmaVersion >= 6) {
- this$1.toks.end++;
- this$1.toks.type = __acorn.tokTypes.ellipsis;
- }
- return new __acorn.Token(this$1.toks)
- } catch (e) {
- if (!(e instanceof SyntaxError)) { throw e }
+pp.isContextual = function(name) {
+ return this.type === types.name && this.value === name && !this.containsEsc
+};
- // Try to skip some text, based on the error message, and then continue
- var msg = e.message, pos = e.raisedAt, replace = true;
- if (/unterminated/i.test(msg)) {
- pos = this$1.lineEnd(e.pos + 1);
- if (/string/.test(msg)) {
- replace = {start: e.pos, end: pos, type: __acorn.tokTypes.string, value: this$1.input.slice(e.pos + 1, pos)};
- } else if (/regular expr/i.test(msg)) {
- var re = this$1.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: __acorn.tokTypes.regexp, value: re};
- } else if (/template/.test(msg)) {
- replace = {
- start: e.pos,
- end: pos,
- type: __acorn.tokTypes.template,
- value: this$1.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) {
- var ch = this$1.input.charCodeAt(pos++);
- if (ch === 34 || ch === 39 || __acorn.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$1.resetTo(pos);
- if (replace === true) { replace = {start: pos, end: pos, type: __acorn.tokTypes.name, value: "✖"}; }
- if (replace) {
- if (this$1.options.locations)
- { replace.loc = new __acorn.SourceLocation(
- this$1.toks,
- __acorn.getLineInfo(this$1.input, replace.start),
- __acorn.getLineInfo(this$1.input, replace.end)); }
- return replace
- }
- }
+// Consumes contextual keyword if possible.
+
+pp.eatContextual = function(name) {
+ if (!this.isContextual(name)) { return false }
+ this.next();
+ return true
+};
+
+// Asserts that following token is given contextual keyword.
+
+pp.expectContextual = function(name) {
+ if (!this.eatContextual(name)) { this.unexpected(); }
+};
+
+// Test whether a semicolon can be inserted at the current position.
+
+pp.canInsertSemicolon = function() {
+ return this.type === types.eof ||
+ this.type === types.braceR ||
+ lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
+};
+
+pp.insertSemicolon = function() {
+ if (this.canInsertSemicolon()) {
+ if (this.options.onInsertedSemicolon)
+ { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
+ return true
}
};
-lp.resetTo = function(pos) {
- var this$1 = this;
+// Consume a semicolon, or, failing that, see if we are allowed to
+// pretend that there is a semicolon at this position.
- this.toks.pos = pos;
- var 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));
+pp.semicolon = function() {
+ if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); }
+};
- if (this.options.locations) {
- this.toks.curLine = 1;
- this.toks.lineStart = __acorn.lineBreakG.lastIndex = 0;
- var match;
- while ((match = __acorn.lineBreakG.exec(this.input)) && match.index < pos) {
- ++this$1.toks.curLine;
- this$1.toks.lineStart = match.index + match[0].length;
- }
+pp.afterTrailingComma = function(tokType, notNext) {
+ if (this.type === tokType) {
+ if (this.options.onTrailingComma)
+ { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
+ if (!notNext)
+ { this.next(); }
+ return true
}
};
-lp.lookAhead = function(n) {
- var this$1 = this;
+// Expect a token of a given type. If found, consume it, otherwise,
+// raise an unexpected token error.
- while (n > this.ahead.length)
- { this$1.ahead.push(this$1.readToken()); }
- return this.ahead[n - 1]
+pp.expect = function(type) {
+ this.eat(type) || this.unexpected();
};
-function isDummy(node) { return node.name === "✖" }
+// Raise an unexpected token error.
-var lp$1 = LooseParser.prototype;
+pp.unexpected = function(pos) {
+ this.raise(pos != null ? pos : this.start, "Unexpected token");
+};
-lp$1.parseTopLevel = function() {
+function DestructuringErrors() {
+ this.shorthandAssign =
+ this.trailingComma =
+ this.parenthesizedAssign =
+ this.parenthesizedBind =
+ this.doubleProto =
+ -1;
+}
+
+pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
+ if (!refDestructuringErrors) { return }
+ if (refDestructuringErrors.trailingComma > -1)
+ { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
+ var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
+ if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); }
+};
+
+pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
+ if (!refDestructuringErrors) { return false }
+ var shorthandAssign = refDestructuringErrors.shorthandAssign;
+ var doubleProto = refDestructuringErrors.doubleProto;
+ if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
+ if (shorthandAssign >= 0)
+ { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
+ if (doubleProto >= 0)
+ { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
+};
+
+pp.checkYieldAwaitInDefaultParams = function() {
+ if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
+ { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
+ if (this.awaitPos)
+ { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
+};
+
+pp.isSimpleAssignTarget = function(expr) {
+ if (expr.type === "ParenthesizedExpression")
+ { return this.isSimpleAssignTarget(expr.expression) }
+ return expr.type === "Identifier" || expr.type === "MemberExpression"
+};
+
+var pp$1 = Parser.prototype;
+
+// ### Statement parsing
+
+// Parse a program. Initializes the parser, reads any number of
+// statements, and wraps them in a Program node. Optionally takes a
+// `program` argument. If present, the statements will be appended
+// to its body instead of creating a new node.
+
+pp$1.parseTopLevel = function(node) {
var this$1 = this;
- var node = this.startNodeAt(this.options.locations ? [0, __acorn.getLineInfo(this.input, 0)] : 0);
- node.body = [];
- while (this.tok.type !== __acorn.tokTypes.eof) { node.body.push(this$1.parseStatement()); }
- this.toks.adaptDirectivePrologue(node.body);
- this.last = this.tok;
+ var exports = {};
+ if (!node.body) { node.body = []; }
+ while (this.type !== types.eof) {
+ var stmt = this$1.parseStatement(true, true, exports);
+ node.body.push(stmt);
+ }
+ this.adaptDirectivePrologue(node.body);
+ this.next();
if (this.options.ecmaVersion >= 6) {
node.sourceType = this.options.sourceType;
}
return this.finishNode(node, "Program")
};
-lp$1.parseStatement = function() {
- var this$1 = this;
+var loopLabel = {kind: "loop"};
+var switchLabel = {kind: "switch"};
- var starttype = this.tok.type, node = this.startNode(), kind;
+pp$1.isLet = function() {
+ if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
+ skipWhiteSpace.lastIndex = this.pos;
+ var skip = skipWhiteSpace.exec(this.input);
+ var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
+ if (nextCh === 91 || nextCh === 123) { return true } // '{' and '['
+ if (isIdentifierStart(nextCh, true)) {
+ var pos = next + 1;
+ while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; }
+ var ident = this.input.slice(next, pos);
+ if (!keywordRelationalOperator.test(ident)) { return true }
+ }
+ return false
+};
- if (this.toks.isLet()) {
- starttype = __acorn.tokTypes._var;
+// check 'async [no LineTerminator here] function'
+// - 'async /*foo*/ function' is OK.
+// - 'async /*\n*/ function' is invalid.
+pp$1.isAsyncFunction = function() {
+ if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
+ { return false }
+
+ skipWhiteSpace.lastIndex = this.pos;
+ var skip = skipWhiteSpace.exec(this.input);
+ var next = this.pos + skip[0].length;
+ return !lineBreak.test(this.input.slice(this.pos, next)) &&
+ this.input.slice(next, next + 8) === "function" &&
+ (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
+};
+
+// Parse a single statement.
+//
+// If expecting a statement and finding a slash operator, parse a
+// regular expression literal. This is to handle cases like
+// `if (foo) /blah/.exec(foo)`, where looking at the previous token
+// does not help.
+
+pp$1.parseStatement = function(declaration, topLevel, exports) {
+ var starttype = this.type, node = this.startNode(), kind;
+
+ if (this.isLet()) {
+ starttype = types._var;
kind = "let";
}
+ // Most types of statements are recognized by the keyword they
+ // start with. Many are trivial to parse, some require a bit of
+ // complexity.
+
switch (starttype) {
- case __acorn.tokTypes._break: case __acorn.tokTypes._continue:
- this.next();
- var isBreak = starttype === __acorn.tokTypes._break;
- if (this.semicolon() || this.canInsertSemicolon()) {
- node.label = null;
- } else {
- node.label = this.tok.type === __acorn.tokTypes.name ? this.parseIdent() : null;
- this.semicolon();
+ case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
+ case types._debugger: return this.parseDebuggerStatement(node)
+ case types._do: return this.parseDoStatement(node)
+ case types._for: return this.parseForStatement(node)
+ case types._function:
+ if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); }
+ return this.parseFunctionStatement(node, false)
+ case types._class:
+ if (!declaration) { this.unexpected(); }
+ return this.parseClass(node, true)
+ case types._if: return this.parseIfStatement(node)
+ case types._return: return this.parseReturnStatement(node)
+ case types._switch: return this.parseSwitchStatement(node)
+ case types._throw: return this.parseThrowStatement(node)
+ case types._try: return this.parseTryStatement(node)
+ case types._const: case types._var:
+ kind = kind || this.value;
+ if (!declaration && kind !== "var") { this.unexpected(); }
+ return this.parseVarStatement(node, kind)
+ case types._while: return this.parseWhileStatement(node)
+ case types._with: return this.parseWithStatement(node)
+ case types.braceL: return this.parseBlock()
+ case types.semi: return this.parseEmptyStatement(node)
+ case types._export:
+ case types._import:
+ if (!this.options.allowImportExportEverywhere) {
+ if (!topLevel)
+ { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
+ if (!this.inModule)
+ { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
}
- return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
+ return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports)
- case __acorn.tokTypes._debugger:
- this.next();
- this.semicolon();
- return this.finishNode(node, "DebuggerStatement")
+ // If the statement does not start with a statement keyword or a
+ // brace, it's an ExpressionStatement or LabeledStatement. We
+ // simply start parsing an expression, and afterwards, if the
+ // next token is a colon and the expression was a simple
+ // Identifier node, we switch to interpreting it as a label.
+ default:
+ if (this.isAsyncFunction()) {
+ if (!declaration) { this.unexpected(); }
+ this.next();
+ return this.parseFunctionStatement(node, true)
+ }
- case __acorn.tokTypes._do:
- this.next();
- node.body = this.parseStatement();
- node.test = this.eat(__acorn.tokTypes._while) ? this.parseParenExpression() : this.dummyIdent();
+ var maybeName = this.value, expr = this.parseExpression();
+ if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
+ { return this.parseLabeledStatement(node, maybeName, expr) }
+ else { return this.parseExpressionStatement(node, expr) }
+ }
+};
+
+pp$1.parseBreakContinueStatement = function(node, keyword) {
+ var this$1 = this;
+
+ var isBreak = keyword === "break";
+ this.next();
+ if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; }
+ else if (this.type !== types.name) { this.unexpected(); }
+ else {
+ node.label = this.parseIdent();
this.semicolon();
- return this.finishNode(node, "DoWhileStatement")
+ }
- case __acorn.tokTypes._for:
- this.next(); // `for` keyword
- var isAwait = this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await");
+ // Verify that there is an actual destination to break or
+ // continue to.
+ var i = 0;
+ for (; i < this.labels.length; ++i) {
+ var lab = this$1.labels[i];
+ if (node.label == null || lab.name === node.label.name) {
+ if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
+ if (node.label && isBreak) { break }
+ }
+ }
+ if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
+ return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
+};
- this.pushCx();
- this.expect(__acorn.tokTypes.parenL);
- if (this.tok.type === __acorn.tokTypes.semi) { return this.parseFor(node, null) }
- var isLet = this.toks.isLet();
- if (isLet || this.tok.type === __acorn.tokTypes._var || this.tok.type === __acorn.tokTypes._const) {
- var init$1 = this.parseVar(true, isLet ? "let" : this.tok.value);
- if (init$1.declarations.length === 1 && (this.tok.type === __acorn.tokTypes._in || this.isContextual("of"))) {
- if (this.options.ecmaVersion >= 9 && this.tok.type !== __acorn.tokTypes._in) {
- node.await = isAwait;
- }
- return this.parseForIn(node, init$1)
+pp$1.parseDebuggerStatement = function(node) {
+ this.next();
+ this.semicolon();
+ return this.finishNode(node, "DebuggerStatement")
+};
+
+pp$1.parseDoStatement = function(node) {
+ this.next();
+ this.labels.push(loopLabel);
+ node.body = this.parseStatement(false);
+ this.labels.pop();
+ this.expect(types._while);
+ node.test = this.parseParenExpression();
+ if (this.options.ecmaVersion >= 6)
+ { this.eat(types.semi); }
+ else
+ { this.semicolon(); }
+ return this.finishNode(node, "DoWhileStatement")
+};
+
+// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
+// loop is non-trivial. Basically, we have to parse the init `var`
+// statement or expression, disallowing the `in` operator (see
+// the second parameter to `parseExpression`), and then check
+// whether the next token is `in` or `of`. When there is no init
+// part (semicolon immediately after the opening parenthesis), it
+// is a regular `for` loop.
+
+pp$1.parseForStatement = function(node) {
+ this.next();
+ var awaitAt = (this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await")) ? this.lastTokStart : -1;
+ this.labels.push(loopLabel);
+ this.enterLexicalScope();
+ this.expect(types.parenL);
+ if (this.type === types.semi) {
+ if (awaitAt > -1) { this.unexpected(awaitAt); }
+ return this.parseFor(node, null)
+ }
+ var isLet = this.isLet();
+ if (this.type === types._var || this.type === types._const || isLet) {
+ var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
+ this.next();
+ this.parseVar(init$1, true, kind);
+ this.finishNode(init$1, "VariableDeclaration");
+ if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 &&
+ !(kind !== "var" && init$1.declarations[0].init)) {
+ if (this.options.ecmaVersion >= 9) {
+ if (this.type === types._in) {
+ if (awaitAt > -1) { this.unexpected(awaitAt); }
+ } else { node.await = awaitAt > -1; }
}
- return this.parseFor(node, init$1)
+ return this.parseForIn(node, init$1)
}
- var init = this.parseExpression(true);
- if (this.tok.type === __acorn.tokTypes._in || this.isContextual("of")) {
- if (this.options.ecmaVersion >= 9 && this.tok.type !== __acorn.tokTypes._in) {
- node.await = isAwait;
- }
- return this.parseForIn(node, this.toAssignable(init))
+ if (awaitAt > -1) { this.unexpected(awaitAt); }
+ return this.parseFor(node, init$1)
+ }
+ var refDestructuringErrors = new DestructuringErrors;
+ var init = this.parseExpression(true, refDestructuringErrors);
+ if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
+ if (this.options.ecmaVersion >= 9) {
+ if (this.type === types._in) {
+ if (awaitAt > -1) { this.unexpected(awaitAt); }
+ } else { node.await = awaitAt > -1; }
}
- return this.parseFor(node, init)
+ this.toAssignable(init, false, refDestructuringErrors);
+ this.checkLVal(init);
+ return this.parseForIn(node, init)
+ } else {
+ this.checkExpressionErrors(refDestructuringErrors, true);
+ }
+ if (awaitAt > -1) { this.unexpected(awaitAt); }
+ return this.parseFor(node, init)
+};
- case __acorn.tokTypes._function:
- this.next();
- return this.parseFunction(node, true)
+pp$1.parseFunctionStatement = function(node, isAsync) {
+ this.next();
+ return this.parseFunction(node, true, false, isAsync)
+};
- case __acorn.tokTypes._if:
- this.next();
- node.test = this.parseParenExpression();
- node.consequent = this.parseStatement();
- node.alternate = this.eat(__acorn.tokTypes._else) ? this.parseStatement() : null;
- return this.finishNode(node, "IfStatement")
+pp$1.parseIfStatement = function(node) {
+ this.next();
+ node.test = this.parseParenExpression();
+ // allow function declarations in branches, but only in non-strict mode
+ node.consequent = this.parseStatement(!this.strict && this.type === types._function);
+ node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.type === types._function) : null;
+ return this.finishNode(node, "IfStatement")
+};
- case __acorn.tokTypes._return:
- this.next();
- if (this.eat(__acorn.tokTypes.semi) || this.canInsertSemicolon()) { node.argument = null; }
- else { node.argument = this.parseExpression(); this.semicolon(); }
- return this.finishNode(node, "ReturnStatement")
+pp$1.parseReturnStatement = function(node) {
+ if (!this.inFunction && !this.options.allowReturnOutsideFunction)
+ { this.raise(this.start, "'return' outside of function"); }
+ this.next();
- case __acorn.tokTypes._switch:
- var blockIndent = this.curIndent, line = this.curLineStart;
- this.next();
- node.discriminant = this.parseParenExpression();
- node.cases = [];
- this.pushCx();
- this.expect(__acorn.tokTypes.braceL);
+ // In `return` (and `break`/`continue`), the keywords with
+ // optional arguments, we eagerly look for a semicolon or the
+ // possibility to insert one.
- var cur;
- while (!this.closes(__acorn.tokTypes.braceR, blockIndent, line, true)) {
- if (this$1.tok.type === __acorn.tokTypes._case || this$1.tok.type === __acorn.tokTypes._default) {
- var isCase = this$1.tok.type === __acorn.tokTypes._case;
- if (cur) { this$1.finishNode(cur, "SwitchCase"); }
- node.cases.push(cur = this$1.startNode());
- cur.consequent = [];
- this$1.next();
- if (isCase) { cur.test = this$1.parseExpression(); }
- else { cur.test = null; }
- this$1.expect(__acorn.tokTypes.colon);
- } else {
- if (!cur) {
- node.cases.push(cur = this$1.startNode());
- cur.consequent = [];
- cur.test = null;
- }
- cur.consequent.push(this$1.parseStatement());
- }
- }
- if (cur) { this.finishNode(cur, "SwitchCase"); }
- this.popCx();
- this.eat(__acorn.tokTypes.braceR);
- return this.finishNode(node, "SwitchStatement")
+ if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; }
+ else { node.argument = this.parseExpression(); this.semicolon(); }
+ return this.finishNode(node, "ReturnStatement")
+};
- case __acorn.tokTypes._throw:
- this.next();
- node.argument = this.parseExpression();
- this.semicolon();
- return this.finishNode(node, "ThrowStatement")
+pp$1.parseSwitchStatement = function(node) {
+ var this$1 = this;
- case __acorn.tokTypes._try:
- this.next();
- node.block = this.parseBlock();
- node.handler = null;
- if (this.tok.type === __acorn.tokTypes._catch) {
- var clause = this.startNode();
- this.next();
- if (this.eat(__acorn.tokTypes.parenL)) {
- clause.param = this.toAssignable(this.parseExprAtom(), true);
- this.expect(__acorn.tokTypes.parenR);
+ this.next();
+ node.discriminant = this.parseParenExpression();
+ node.cases = [];
+ this.expect(types.braceL);
+ this.labels.push(switchLabel);
+ this.enterLexicalScope();
+
+ // Statements under must be grouped (by label) in SwitchCase
+ // nodes. `cur` is used to keep the node that we are currently
+ // adding statements to.
+
+ var cur;
+ for (var sawDefault = false; this.type !== types.braceR;) {
+ if (this$1.type === types._case || this$1.type === types._default) {
+ var isCase = this$1.type === types._case;
+ if (cur) { this$1.finishNode(cur, "SwitchCase"); }
+ node.cases.push(cur = this$1.startNode());
+ cur.consequent = [];
+ this$1.next();
+ if (isCase) {
+ cur.test = this$1.parseExpression();
} else {
- clause.param = null;
+ if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); }
+ sawDefault = true;
+ cur.test = null;
}
- clause.body = this.parseBlock();
- node.handler = this.finishNode(clause, "CatchClause");
+ this$1.expect(types.colon);
+ } else {
+ if (!cur) { this$1.unexpected(); }
+ cur.consequent.push(this$1.parseStatement(true));
}
- node.finalizer = this.eat(__acorn.tokTypes._finally) ? this.parseBlock() : null;
- if (!node.handler && !node.finalizer) { return node.block }
- return this.finishNode(node, "TryStatement")
+ }
+ this.exitLexicalScope();
+ if (cur) { this.finishNode(cur, "SwitchCase"); }
+ this.next(); // Closing brace
+ this.labels.pop();
+ return this.finishNode(node, "SwitchStatement")
+};
- case __acorn.tokTypes._var:
- case __acorn.tokTypes._const:
- return this.parseVar(false, kind || this.tok.value)
+pp$1.parseThrowStatement = function(node) {
+ this.next();
+ if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
+ { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
+ node.argument = this.parseExpression();
+ this.semicolon();
+ return this.finishNode(node, "ThrowStatement")
+};
- case __acorn.tokTypes._while:
- this.next();
- node.test = this.parseParenExpression();
- node.body = this.parseStatement();
- return this.finishNode(node, "WhileStatement")
+// Reused empty array added for node fields that are always empty.
- case __acorn.tokTypes._with:
+var empty = [];
+
+pp$1.parseTryStatement = function(node) {
+ this.next();
+ node.block = this.parseBlock();
+ node.handler = null;
+ if (this.type === types._catch) {
+ var clause = this.startNode();
this.next();
- node.object = this.parseParenExpression();
- node.body = this.parseStatement();
- return this.finishNode(node, "WithStatement")
+ if (this.eat(types.parenL)) {
+ clause.param = this.parseBindingAtom();
+ this.enterLexicalScope();
+ this.checkLVal(clause.param, "let");
+ this.expect(types.parenR);
+ } else {
+ if (this.options.ecmaVersion < 10) { this.unexpected(); }
+ clause.param = null;
+ this.enterLexicalScope();
+ }
+ clause.body = this.parseBlock(false);
+ this.exitLexicalScope();
+ node.handler = this.finishNode(clause, "CatchClause");
+ }
+ node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
+ if (!node.handler && !node.finalizer)
+ { this.raise(node.start, "Missing catch or finally clause"); }
+ return this.finishNode(node, "TryStatement")
+};
- case __acorn.tokTypes.braceL:
- return this.parseBlock()
+pp$1.parseVarStatement = function(node, kind) {
+ this.next();
+ this.parseVar(node, false, kind);
+ this.semicolon();
+ return this.finishNode(node, "VariableDeclaration")
+};
- case __acorn.tokTypes.semi:
- this.next();
- return this.finishNode(node, "EmptyStatement")
+pp$1.parseWhileStatement = function(node) {
+ this.next();
+ node.test = this.parseParenExpression();
+ this.labels.push(loopLabel);
+ node.body = this.parseStatement(false);
+ this.labels.pop();
+ return this.finishNode(node, "WhileStatement")
+};
- case __acorn.tokTypes._class:
- return this.parseClass(true)
+pp$1.parseWithStatement = function(node) {
+ if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
+ this.next();
+ node.object = this.parseParenExpression();
+ node.body = this.parseStatement(false);
+ return this.finishNode(node, "WithStatement")
+};
- case __acorn.tokTypes._import:
- return this.parseImport()
+pp$1.parseEmptyStatement = function(node) {
+ this.next();
+ return this.finishNode(node, "EmptyStatement")
+};
- case __acorn.tokTypes._export:
- return this.parseExport()
+pp$1.parseLabeledStatement = function(node, maybeName, expr) {
+ var this$1 = this;
- default:
- if (this.toks.isAsyncFunction()) {
- this.next();
- this.next();
- return this.parseFunction(node, true, true)
- }
- var expr = this.parseExpression();
- if (isDummy(expr)) {
- this.next();
- if (this.tok.type === __acorn.tokTypes.eof) { return this.finishNode(node, "EmptyStatement") }
- return this.parseStatement()
- } else if (starttype === __acorn.tokTypes.name && expr.type === "Identifier" && this.eat(__acorn.tokTypes.colon)) {
- node.body = this.parseStatement();
- node.label = expr;
- return this.finishNode(node, "LabeledStatement")
- } else {
- node.expression = expr;
- this.semicolon();
- return this.finishNode(node, "ExpressionStatement")
- }
+ for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1)
+ {
+ var label = list[i$1];
+
+ if (label.name === maybeName)
+ { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared");
+ } }
+ var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null;
+ for (var i = this.labels.length - 1; i >= 0; i--) {
+ var label$1 = this$1.labels[i];
+ if (label$1.statementStart === node.start) {
+ // Update information about previous labels on this node
+ label$1.statementStart = this$1.start;
+ label$1.kind = kind;
+ } else { break }
}
+ this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
+ node.body = this.parseStatement(true);
+ if (node.body.type === "ClassDeclaration" ||
+ node.body.type === "VariableDeclaration" && node.body.kind !== "var" ||
+ node.body.type === "FunctionDeclaration" && (this.strict || node.body.generator))
+ { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); }
+ this.labels.pop();
+ node.label = expr;
+ return this.finishNode(node, "LabeledStatement")
};
-lp$1.parseBlock = function() {
+pp$1.parseExpressionStatement = function(node, expr) {
+ node.expression = expr;
+ this.semicolon();
+ return this.finishNode(node, "ExpressionStatement")
+};
+
+// Parse a semicolon-enclosed block of statements, handling `"use
+// strict"` declarations when `allowStrict` is true (used for
+// function bodies).
+
+pp$1.parseBlock = function(createNewLexicalScope) {
var this$1 = this;
+ if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
var node = this.startNode();
- this.pushCx();
- this.expect(__acorn.tokTypes.braceL);
- var blockIndent = this.curIndent, line = this.curLineStart;
node.body = [];
- while (!this.closes(__acorn.tokTypes.braceR, blockIndent, line, true))
- { node.body.push(this$1.parseStatement()); }
- this.popCx();
- this.eat(__acorn.tokTypes.braceR);
+ this.expect(types.braceL);
+ if (createNewLexicalScope) {
+ this.enterLexicalScope();
+ }
+ while (!this.eat(types.braceR)) {
+ var stmt = this$1.parseStatement(true);
+ node.body.push(stmt);
+ }
+ if (createNewLexicalScope) {
+ this.exitLexicalScope();
+ }
return this.finishNode(node, "BlockStatement")
};
-lp$1.parseFor = function(node, init) {
+// Parse a regular `for` loop. The disambiguation code in
+// `parseStatement` will already have parsed the init statement or
+// expression.
+
+pp$1.parseFor = function(node, init) {
node.init = init;
- node.test = node.update = null;
- if (this.eat(__acorn.tokTypes.semi) && this.tok.type !== __acorn.tokTypes.semi) { node.test = this.parseExpression(); }
- if (this.eat(__acorn.tokTypes.semi) && this.tok.type !== __acorn.tokTypes.parenR) { node.update = this.parseExpression(); }
- this.popCx();
- this.expect(__acorn.tokTypes.parenR);
- node.body = this.parseStatement();
+ this.expect(types.semi);
+ node.test = this.type === types.semi ? null : this.parseExpression();
+ this.expect(types.semi);
+ node.update = this.type === types.parenR ? null : this.parseExpression();
+ this.expect(types.parenR);
+ this.exitLexicalScope();
+ node.body = this.parseStatement(false);
+ this.labels.pop();
return this.finishNode(node, "ForStatement")
};
-lp$1.parseForIn = function(node, init) {
- var type = this.tok.type === __acorn.tokTypes._in ? "ForInStatement" : "ForOfStatement";
+// Parse a `for`/`in` and `for`/`of` loop, which are almost
+// same from parser's perspective.
+
+pp$1.parseForIn = function(node, init) {
+ var type = this.type === types._in ? "ForInStatement" : "ForOfStatement";
this.next();
+ if (type === "ForInStatement") {
+ if (init.type === "AssignmentPattern" ||
+ (init.type === "VariableDeclaration" && init.declarations[0].init != null &&
+ (this.strict || init.declarations[0].id.type !== "Identifier")))
+ { this.raise(init.start, "Invalid assignment in for-in loop head"); }
+ }
node.left = init;
- node.right = this.parseExpression();
- this.popCx();
- this.expect(__acorn.tokTypes.parenR);
- node.body = this.parseStatement();
+ node.right = type === "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign();
+ this.expect(types.parenR);
+ this.exitLexicalScope();
+ node.body = this.parseStatement(false);
+ this.labels.pop();
return this.finishNode(node, type)
};
-lp$1.parseVar = function(noIn, kind) {
+// Parse a list of variable declarations.
+
+pp$1.parseVar = function(node, isFor, kind) {
var this$1 = this;
- var node = this.startNode();
- node.kind = kind;
- this.next();
node.declarations = [];
- do {
+ node.kind = kind;
+ for (;;) {
var decl = this$1.startNode();
- decl.id = this$1.options.ecmaVersion >= 6 ? this$1.toAssignable(this$1.parseExprAtom(), true) : this$1.parseIdent();
- decl.init = this$1.eat(__acorn.tokTypes.eq) ? this$1.parseMaybeAssign(noIn) : null;
+ this$1.parseVarId(decl, kind);
+ if (this$1.eat(types.eq)) {
+ decl.init = this$1.parseMaybeAssign(isFor);
+ } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) {
+ this$1.unexpected();
+ } else if (decl.id.type !== "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) {
+ this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value");
+ } else {
+ decl.init = null;
+ }
node.declarations.push(this$1.finishNode(decl, "VariableDeclarator"));
- } while (this.eat(__acorn.tokTypes.comma))
- if (!node.declarations.length) {
- var decl$1 = this.startNode();
- decl$1.id = this.dummyIdent();
- node.declarations.push(this.finishNode(decl$1, "VariableDeclarator"));
+ if (!this$1.eat(types.comma)) { break }
}
- if (!noIn) { this.semicolon(); }
- return this.finishNode(node, "VariableDeclaration")
+ return node
};
-lp$1.parseClass = function(isStatement) {
+pp$1.parseVarId = function(decl, kind) {
+ decl.id = this.parseBindingAtom(kind);
+ this.checkLVal(decl.id, kind, false);
+};
+
+// Parse a function declaration or literal (depending on the
+// `isStatement` parameter).
+
+pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) {
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync)
+ { node.generator = this.eat(types.star); }
+ if (this.options.ecmaVersion >= 8)
+ { node.async = !!isAsync; }
+
+ if (isStatement) {
+ node.id = isStatement === "nullableID" && this.type !== types.name ? null : this.parseIdent();
+ if (node.id) {
+ this.checkLVal(node.id, "var");
+ }
+ }
+
+ var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
+ oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;
+ this.inGenerator = node.generator;
+ this.inAsync = node.async;
+ this.yieldPos = 0;
+ this.awaitPos = 0;
+ this.inFunction = true;
+ this.enterFunctionScope();
+
+ if (!isStatement)
+ { node.id = this.type === types.name ? this.parseIdent() : null; }
+
+ this.parseFunctionParams(node);
+ this.parseFunctionBody(node, allowExpressionBody);
+
+ this.inGenerator = oldInGen;
+ this.inAsync = oldInAsync;
+ this.yieldPos = oldYieldPos;
+ this.awaitPos = oldAwaitPos;
+ this.inFunction = oldInFunc;
+ return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
+};
+
+pp$1.parseFunctionParams = function(node) {
+ this.expect(types.parenL);
+ node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
+ this.checkYieldAwaitInDefaultParams();
+};
+
+// Parse a class declaration or literal (depending on the
+// `isStatement` parameter).
+
+pp$1.parseClass = function(node, isStatement) {
var this$1 = this;
- var node = this.startNode();
this.next();
- if (this.tok.type === __acorn.tokTypes.name) { node.id = this.parseIdent(); }
- else if (isStatement === true) { node.id = this.dummyIdent(); }
- else { node.id = null; }
- node.superClass = this.eat(__acorn.tokTypes._extends) ? this.parseExpression() : null;
- node.body = this.startNode();
- node.body.body = [];
- this.pushCx();
- var indent = this.curIndent + 1, line = this.curLineStart;
- this.eat(__acorn.tokTypes.braceL);
- if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
- while (!this.closes(__acorn.tokTypes.braceR, indent, line)) {
- if (this$1.semicolon()) { continue }
- var method = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0);
- if (this$1.options.ecmaVersion >= 6) {
- method.static = false;
- isGenerator = this$1.eat(__acorn.tokTypes.star);
- }
- this$1.parsePropertyName(method);
- if (isDummy(method.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(__acorn.tokTypes.comma); continue }
- if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" &&
- (this$1.tok.type !== __acorn.tokTypes.parenL && this$1.tok.type !== __acorn.tokTypes.braceL)) {
- method.static = true;
- isGenerator = this$1.eat(__acorn.tokTypes.star);
- this$1.parsePropertyName(method);
- } else {
- method.static = false;
- }
- if (!method.computed &&
- method.key.type === "Identifier" && method.key.name === "async" && this$1.tok.type !== __acorn.tokTypes.parenL &&
- !this$1.canInsertSemicolon()) {
- isAsync = true;
- isGenerator = this$1.options.ecmaVersion >= 9 && this$1.eat(__acorn.tokTypes.star);
- this$1.parsePropertyName(method);
- } else {
- isAsync = false;
- }
- if (this$1.options.ecmaVersion >= 5 && method.key.type === "Identifier" &&
- !method.computed && (method.key.name === "get" || method.key.name === "set") &&
- this$1.tok.type !== __acorn.tokTypes.parenL && this$1.tok.type !== __acorn.tokTypes.braceL) {
- method.kind = method.key.name;
- this$1.parsePropertyName(method);
- method.value = this$1.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$1.parseMethod(isGenerator, isAsync);
+
+ this.parseClassId(node, isStatement);
+ this.parseClassSuper(node);
+ var classBody = this.startNode();
+ var hadConstructor = false;
+ classBody.body = [];
+ this.expect(types.braceL);
+ while (!this.eat(types.braceR)) {
+ var member = this$1.parseClassMember(classBody);
+ if (member && member.type === "MethodDefinition" && member.kind === "constructor") {
+ if (hadConstructor) { this$1.raise(member.start, "Duplicate constructor in the same class"); }
+ hadConstructor = true;
}
- node.body.body.push(this$1.finishNode(method, "MethodDefinition"));
}
- this.popCx();
- if (!this.eat(__acorn.tokTypes.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");
+ node.body = this.finishNode(classBody, "ClassBody");
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
};
-lp$1.parseFunction = function(node, isStatement, isAsync) {
- var oldInAsync = this.inAsync, oldInFunction = this.inFunction;
- this.initFunction(node);
- if (this.options.ecmaVersion >= 6) {
- node.generator = this.eat(__acorn.tokTypes.star);
+pp$1.parseClassMember = function(classBody) {
+ var this$1 = this;
+
+ if (this.eat(types.semi)) { return null }
+
+ var method = this.startNode();
+ var tryContextual = function (k, noLineBreak) {
+ if ( noLineBreak === void 0 ) noLineBreak = false;
+
+ var start = this$1.start, startLoc = this$1.startLoc;
+ if (!this$1.eatContextual(k)) { return false }
+ if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
+ if (method.key) { this$1.unexpected(); }
+ method.computed = false;
+ method.key = this$1.startNodeAt(start, startLoc);
+ method.key.name = k;
+ this$1.finishNode(method.key, "Identifier");
+ return false
+ };
+
+ method.kind = "method";
+ method.static = tryContextual("static");
+ var isGenerator = this.eat(types.star);
+ var isAsync = false;
+ if (!isGenerator) {
+ if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) {
+ isAsync = true;
+ isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
+ } else if (tryContextual("get")) {
+ method.kind = "get";
+ } else if (tryContextual("set")) {
+ method.kind = "set";
+ }
}
- if (this.options.ecmaVersion >= 8) {
- node.async = !!isAsync;
+ if (!method.key) { this.parsePropertyName(method); }
+ var key = method.key;
+ if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" ||
+ key.type === "Literal" && key.value === "constructor")) {
+ if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); }
+ if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
+ if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
+ method.kind = "constructor";
+ } else if (method.static && key.type === "Identifier" && key.name === "prototype") {
+ this.raise(key.start, "Classes may not have a static property named prototype");
}
- if (this.tok.type === __acorn.tokTypes.name) { node.id = this.parseIdent(); }
- else if (isStatement === true) { node.id = this.dummyIdent(); }
- this.inAsync = node.async;
- this.inFunction = true;
- node.params = this.parseFunctionParams();
- node.body = this.parseBlock();
- this.toks.adaptDirectivePrologue(node.body.body);
- this.inAsync = oldInAsync;
- this.inFunction = oldInFunction;
- return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
+ this.parseClassMethod(classBody, method, isGenerator, isAsync);
+ if (method.kind === "get" && method.value.params.length !== 0)
+ { this.raiseRecoverable(method.value.start, "getter should have no params"); }
+ if (method.kind === "set" && method.value.params.length !== 1)
+ { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); }
+ if (method.kind === "set" && method.value.params[0].type === "RestElement")
+ { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); }
+ return method
};
-lp$1.parseExport = function() {
- var node = this.startNode();
+pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) {
+ method.value = this.parseMethod(isGenerator, isAsync);
+ classBody.body.push(this.finishNode(method, "MethodDefinition"));
+};
+
+pp$1.parseClassId = function(node, isStatement) {
+ node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null;
+};
+
+pp$1.parseClassSuper = function(node) {
+ node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null;
+};
+
+// Parses module export declaration.
+
+pp$1.parseExport = function(node, exports) {
+ var this$1 = this;
+
this.next();
- if (this.eat(__acorn.tokTypes.star)) {
- node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString();
+ // export * from '...'
+ if (this.eat(types.star)) {
+ this.expectContextual("from");
+ if (this.type !== types.string) { this.unexpected(); }
+ node.source = this.parseExprAtom();
+ this.semicolon();
return this.finishNode(node, "ExportAllDeclaration")
}
- if (this.eat(__acorn.tokTypes._default)) {
- // export default (function foo() {}) // This is FunctionExpression.
+ if (this.eat(types._default)) { // export default ...
+ this.checkExport(exports, "default", this.lastTokStart);
var isAsync;
- if (this.tok.type === __acorn.tokTypes._function || (isAsync = this.toks.isAsyncFunction())) {
+ if (this.type === types._function || (isAsync = this.isAsyncFunction())) {
var fNode = this.startNode();
this.next();
if (isAsync) { this.next(); }
- node.declaration = this.parseFunction(fNode, "nullableID", isAsync);
- } else if (this.tok.type === __acorn.tokTypes._class) {
- node.declaration = this.parseClass("nullableID");
+ node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync);
+ } else if (this.type === types._class) {
+ var cNode = this.startNode();
+ node.declaration = this.parseClass(cNode, "nullableID");
} else {
node.declaration = this.parseMaybeAssign();
this.semicolon();
}
return this.finishNode(node, "ExportDefaultDeclaration")
}
- if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) {
- node.declaration = this.parseStatement();
+ // export var|const|let|function|class ...
+ if (this.shouldParseExportStatement()) {
+ node.declaration = this.parseStatement(true);
+ if (node.declaration.type === "VariableDeclaration")
+ { this.checkVariableExport(exports, node.declaration.declarations); }
+ else
+ { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); }
node.specifiers = [];
node.source = null;
- } else {
+ } else { // export { x, y as z } [from '...']
node.declaration = null;
- node.specifiers = this.parseExportSpecifierList();
- node.source = this.eatContextual("from") ? this.parseExprAtom() : null;
+ node.specifiers = this.parseExportSpecifiers(exports);
+ if (this.eatContextual("from")) {
+ if (this.type !== types.string) { this.unexpected(); }
+ node.source = this.parseExprAtom();
+ } else {
+ // check for keywords used as local names
+ for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
+ var spec = list[i];
+
+ this$1.checkUnreserved(spec.local);
+ }
+
+ node.source = null;
+ }
this.semicolon();
}
return this.finishNode(node, "ExportNamedDeclaration")
};
-lp$1.parseImport = function() {
- var node = this.startNode();
+pp$1.checkExport = function(exports, name, pos) {
+ if (!exports) { return }
+ if (has(exports, name))
+ { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
+ exports[name] = true;
+};
+
+pp$1.checkPatternExport = function(exports, pat) {
+ var this$1 = this;
+
+ var type = pat.type;
+ if (type === "Identifier")
+ { this.checkExport(exports, pat.name, pat.start); }
+ else if (type === "ObjectPattern")
+ { for (var i = 0, list = pat.properties; i < list.length; i += 1)
+ {
+ var prop = list[i];
+
+ this$1.checkPatternExport(exports, prop);
+ } }
+ else if (type === "ArrayPattern")
+ { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
+ var elt = list$1[i$1];
+
+ if (elt) { this$1.checkPatternExport(exports, elt); }
+ } }
+ else if (type === "Property")
+ { this.checkPatternExport(exports, pat.value); }
+ else if (type === "AssignmentPattern")
+ { this.checkPatternExport(exports, pat.left); }
+ else if (type === "RestElement")
+ { this.checkPatternExport(exports, pat.argument); }
+ else if (type === "ParenthesizedExpression")
+ { this.checkPatternExport(exports, pat.expression); }
+};
+
+pp$1.checkVariableExport = function(exports, decls) {
+ var this$1 = this;
+
+ if (!exports) { return }
+ for (var i = 0, list = decls; i < list.length; i += 1)
+ {
+ var decl = list[i];
+
+ this$1.checkPatternExport(exports, decl.id);
+ }
+};
+
+pp$1.shouldParseExportStatement = function() {
+ return this.type.keyword === "var" ||
+ this.type.keyword === "const" ||
+ this.type.keyword === "class" ||
+ this.type.keyword === "function" ||
+ this.isLet() ||
+ this.isAsyncFunction()
+};
+
+// Parses a comma-separated list of module exports.
+
+pp$1.parseExportSpecifiers = function(exports) {
+ var this$1 = this;
+
+ var nodes = [], first = true;
+ // export { x, y as z } [from '...']
+ this.expect(types.braceL);
+ while (!this.eat(types.braceR)) {
+ if (!first) {
+ this$1.expect(types.comma);
+ if (this$1.afterTrailingComma(types.braceR)) { break }
+ } else { first = false; }
+
+ var node = this$1.startNode();
+ node.local = this$1.parseIdent(true);
+ node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local;
+ this$1.checkExport(exports, node.exported.name, node.exported.start);
+ nodes.push(this$1.finishNode(node, "ExportSpecifier"));
+ }
+ return nodes
+};
+
+// Parses import declaration.
+
+pp$1.parseImport = function(node) {
this.next();
- if (this.tok.type === __acorn.tokTypes.string) {
- node.specifiers = [];
+ // import '...'
+ if (this.type === types.string) {
+ node.specifiers = empty;
node.source = this.parseExprAtom();
} else {
- var elt;
- if (this.tok.type === __acorn.tokTypes.name && this.tok.value !== "from") {
- elt = this.startNode();
- elt.local = this.parseIdent();
- this.finishNode(elt, "ImportDefaultSpecifier");
- this.eat(__acorn.tokTypes.comma);
- }
- node.specifiers = this.parseImportSpecifierList();
- node.source = this.eatContextual("from") && this.tok.type === __acorn.tokTypes.string ? this.parseExprAtom() : this.dummyString();
- if (elt) { node.specifiers.unshift(elt); }
+ node.specifiers = this.parseImportSpecifiers();
+ this.expectContextual("from");
+ node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
}
this.semicolon();
return this.finishNode(node, "ImportDeclaration")
};
-lp$1.parseImportSpecifierList = function() {
+// Parses a comma-separated list of module imports.
+
+pp$1.parseImportSpecifiers = function() {
var this$1 = this;
- var elts = [];
- if (this.tok.type === __acorn.tokTypes.star) {
- var elt = this.startNode();
+ var nodes = [], first = true;
+ if (this.type === types.name) {
+ // import defaultObj, { x, y as z } from '...'
+ var node = this.startNode();
+ node.local = this.parseIdent();
+ this.checkLVal(node.local, "let");
+ nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
+ if (!this.eat(types.comma)) { return nodes }
+ }
+ if (this.type === types.star) {
+ var node$1 = this.startNode();
this.next();
- elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent();
- elts.push(this.finishNode(elt, "ImportNamespaceSpecifier"));
- } else {
- var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart;
- this.pushCx();
- this.eat(__acorn.tokTypes.braceL);
- if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; }
- while (!this.closes(__acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
- var elt$1 = this$1.startNode();
- if (this$1.eat(__acorn.tokTypes.star)) {
- elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : this$1.dummyIdent();
- this$1.finishNode(elt$1, "ImportNamespaceSpecifier");
- } else {
- if (this$1.isContextual("from")) { break }
- elt$1.imported = this$1.parseIdent();
- if (isDummy(elt$1.imported)) { break }
- elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : elt$1.imported;
- this$1.finishNode(elt$1, "ImportSpecifier");
+ this.expectContextual("as");
+ node$1.local = this.parseIdent();
+ this.checkLVal(node$1.local, "let");
+ nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
+ return nodes
+ }
+ this.expect(types.braceL);
+ while (!this.eat(types.braceR)) {
+ if (!first) {
+ this$1.expect(types.comma);
+ if (this$1.afterTrailingComma(types.braceR)) { break }
+ } else { first = false; }
+
+ var node$2 = this$1.startNode();
+ node$2.imported = this$1.parseIdent(true);
+ if (this$1.eatContextual("as")) {
+ node$2.local = this$1.parseIdent();
+ } else {
+ this$1.checkUnreserved(node$2.imported);
+ node$2.local = node$2.imported;
+ }
+ this$1.checkLVal(node$2.local, "let");
+ nodes.push(this$1.finishNode(node$2, "ImportSpecifier"));
+ }
+ return nodes
+};
+
+// Set `ExpressionStatement#directive` property for directive prologues.
+pp$1.adaptDirectivePrologue = function(statements) {
+ for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
+ statements[i].directive = statements[i].expression.raw.slice(1, -1);
+ }
+};
+pp$1.isDirectiveCandidate = function(statement) {
+ return (
+ statement.type === "ExpressionStatement" &&
+ statement.expression.type === "Literal" &&
+ typeof statement.expression.value === "string" &&
+ // Reject parenthesized strings.
+ (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
+ )
+};
+
+var pp$2 = Parser.prototype;
+
+// Convert existing expression atom to assignable pattern
+// if possible.
+
+pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) {
+ var this$1 = this;
+
+ if (this.options.ecmaVersion >= 6 && node) {
+ switch (node.type) {
+ case "Identifier":
+ if (this.inAsync && node.name === "await")
+ { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); }
+ break
+
+ case "ObjectPattern":
+ case "ArrayPattern":
+ case "RestElement":
+ break
+
+ case "ObjectExpression":
+ node.type = "ObjectPattern";
+ if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
+ for (var i = 0, list = node.properties; i < list.length; i += 1) {
+ var prop = list[i];
+
+ this$1.toAssignable(prop, isBinding);
+ // Early error:
+ // AssignmentRestProperty[Yield, Await] :
+ // `...` DestructuringAssignmentTarget[Yield, Await]
+ //
+ // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
+ if (
+ prop.type === "RestElement" &&
+ (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
+ ) {
+ this$1.raise(prop.argument.start, "Unexpected token");
+ }
}
- elts.push(elt$1);
- this$1.eat(__acorn.tokTypes.comma);
+ break
+
+ case "Property":
+ // AssignmentProperty has type === "Property"
+ if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
+ this.toAssignable(node.value, isBinding);
+ break
+
+ case "ArrayExpression":
+ node.type = "ArrayPattern";
+ if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
+ this.toAssignableList(node.elements, isBinding);
+ break
+
+ case "SpreadElement":
+ node.type = "RestElement";
+ this.toAssignable(node.argument, isBinding);
+ if (node.argument.type === "AssignmentPattern")
+ { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
+ break
+
+ case "AssignmentExpression":
+ if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
+ node.type = "AssignmentPattern";
+ delete node.operator;
+ this.toAssignable(node.left, isBinding);
+ // falls through to AssignmentPattern
+
+ case "AssignmentPattern":
+ break
+
+ case "ParenthesizedExpression":
+ this.toAssignable(node.expression, isBinding);
+ break
+
+ case "MemberExpression":
+ if (!isBinding) { break }
+
+ default:
+ this.raise(node.start, "Assigning to rvalue");
}
- this.eat(__acorn.tokTypes.braceR);
- this.popCx();
+ } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
+ return node
+};
+
+// Convert list of expression atoms to binding list.
+
+pp$2.toAssignableList = function(exprList, isBinding) {
+ var this$1 = this;
+
+ var end = exprList.length;
+ for (var i = 0; i < end; i++) {
+ var elt = exprList[i];
+ if (elt) { this$1.toAssignable(elt, isBinding); }
}
- return elts
+ if (end) {
+ var last = exprList[end - 1];
+ if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
+ { this.unexpected(last.argument.start); }
+ }
+ return exprList
};
-lp$1.parseExportSpecifierList = function() {
+// Parses spread element.
+
+pp$2.parseSpread = function(refDestructuringErrors) {
+ var node = this.startNode();
+ this.next();
+ node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
+ return this.finishNode(node, "SpreadElement")
+};
+
+pp$2.parseRestBinding = function() {
+ var node = this.startNode();
+ this.next();
+
+ // RestElement inside of a function parameter must be an identifier
+ if (this.options.ecmaVersion === 6 && this.type !== types.name)
+ { this.unexpected(); }
+
+ node.argument = this.parseBindingAtom();
+
+ return this.finishNode(node, "RestElement")
+};
+
+// Parses lvalue (assignable) atom.
+
+pp$2.parseBindingAtom = function() {
+ if (this.options.ecmaVersion >= 6) {
+ switch (this.type) {
+ case types.bracketL:
+ var node = this.startNode();
+ this.next();
+ node.elements = this.parseBindingList(types.bracketR, true, true);
+ return this.finishNode(node, "ArrayPattern")
+
+ case types.braceL:
+ return this.parseObj(true)
+ }
+ }
+ return this.parseIdent()
+};
+
+pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
var this$1 = this;
- var elts = [];
- var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart;
- this.pushCx();
- this.eat(__acorn.tokTypes.braceL);
- if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; }
- while (!this.closes(__acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
- if (this$1.isContextual("from")) { break }
- var elt = this$1.startNode();
- elt.local = this$1.parseIdent();
- if (isDummy(elt.local)) { break }
- elt.exported = this$1.eatContextual("as") ? this$1.parseIdent() : elt.local;
- this$1.finishNode(elt, "ExportSpecifier");
- elts.push(elt);
- this$1.eat(__acorn.tokTypes.comma);
+ var elts = [], first = true;
+ while (!this.eat(close)) {
+ if (first) { first = false; }
+ else { this$1.expect(types.comma); }
+ if (allowEmpty && this$1.type === types.comma) {
+ elts.push(null);
+ } else if (allowTrailingComma && this$1.afterTrailingComma(close)) {
+ break
+ } else if (this$1.type === types.ellipsis) {
+ var rest = this$1.parseRestBinding();
+ this$1.parseBindingListItem(rest);
+ elts.push(rest);
+ if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); }
+ this$1.expect(close);
+ break
+ } else {
+ var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc);
+ this$1.parseBindingListItem(elem);
+ elts.push(elem);
+ }
}
- this.eat(__acorn.tokTypes.braceR);
- this.popCx();
return elts
};
-var lp$2 = LooseParser.prototype;
+pp$2.parseBindingListItem = function(param) {
+ return param
+};
+
+// Parses assignment pattern around given atom if possible.
+
+pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
+ left = left || this.parseBindingAtom();
+ if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left }
+ var node = this.startNodeAt(startPos, startLoc);
+ node.left = left;
+ node.right = this.parseMaybeAssign();
+ return this.finishNode(node, "AssignmentPattern")
+};
+
+// Verify that a node is an lval — something that can be assigned
+// to.
+// bindingType can be either:
+// 'var' indicating that the lval creates a 'var' binding
+// 'let' indicating that the lval creates a lexical ('let' or 'const') binding
+// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references
+
+pp$2.checkLVal = function(expr, bindingType, checkClashes) {
+ var this$1 = this;
-lp$2.checkLVal = function(expr) {
- if (!expr) { return expr }
switch (expr.type) {
case "Identifier":
+ if (this.strict && this.reservedWordsStrictBind.test(expr.name))
+ { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
+ if (checkClashes) {
+ if (has(checkClashes, expr.name))
+ { this.raiseRecoverable(expr.start, "Argument name clash"); }
+ checkClashes[expr.name] = true;
+ }
+ if (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);
+ }
+ }
+ break
+
case "MemberExpression":
- return expr
+ if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); }
+ break
+
+ case "ObjectPattern":
+ for (var i = 0, list = expr.properties; i < list.length; i += 1)
+ {
+ var prop = list[i];
+
+ this$1.checkLVal(prop, bindingType, checkClashes);
+ }
+ break
+
+ case "Property":
+ // AssignmentProperty has type === "Property"
+ this.checkLVal(expr.value, bindingType, checkClashes);
+ break
+
+ case "ArrayPattern":
+ for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
+ var elem = list$1[i$1];
+
+ if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); }
+ }
+ break
+
+ case "AssignmentPattern":
+ this.checkLVal(expr.left, bindingType, checkClashes);
+ break
+
+ case "RestElement":
+ this.checkLVal(expr.argument, bindingType, checkClashes);
+ break
case "ParenthesizedExpression":
- expr.expression = this.checkLVal(expr.expression);
- return expr
+ this.checkLVal(expr.expression, bindingType, checkClashes);
+ break
default:
- return this.dummyIdent()
+ this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue");
}
};
-lp$2.parseExpression = function(noIn) {
+// A recursive descent parser operates by defining functions for all
+// syntactic elements, and recursively calling those, each function
+// advancing the input stream and returning an AST node. Precedence
+// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
+// instead of `(!x)[1]` is handled by the fact that the parser
+// function that parses unary prefix operators is called first, and
+// in turn calls the function that parses `[]` subscripts — that
+// way, it'll receive the node for `x[1]` already parsed, and wraps
+// *that* in the unary operator node.
+//
+// Acorn uses an [operator precedence parser][opp] to handle binary
+// operator precedence, because it is much more compact than using
+// the technique outlined above, which uses different, nesting
+// functions to specify precedence, for all of the ten binary
+// precedence levels that JavaScript defines.
+//
+// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
+
+var pp$3 = Parser.prototype;
+
+// Check if property name clashes with already added.
+// Object/class getters and setters are not allowed to clash —
+// either with each other or with an init property — and in
+// strict mode, init properties are also not allowed to be repeated.
+
+pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) {
+ if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
+ { return }
+ if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
+ { return }
+ var key = prop.key;
+ var name;
+ switch (key.type) {
+ case "Identifier": name = key.name; break
+ case "Literal": name = String(key.value); break
+ default: return
+ }
+ var kind = prop.kind;
+ if (this.options.ecmaVersion >= 6) {
+ if (name === "__proto__" && kind === "init") {
+ if (propHash.proto) {
+ if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; }
+ // Backwards-compat kludge. Can be removed in version 6.0
+ else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); }
+ }
+ propHash.proto = true;
+ }
+ return
+ }
+ name = "$" + name;
+ var other = propHash[name];
+ if (other) {
+ var redefinition;
+ if (kind === "init") {
+ redefinition = this.strict && other.init || other.get || other.set;
+ } else {
+ redefinition = other.init || other[kind];
+ }
+ if (redefinition)
+ { this.raiseRecoverable(key.start, "Redefinition of property"); }
+ } else {
+ other = propHash[name] = {
+ init: false,
+ get: false,
+ set: false
+ };
+ }
+ other[kind] = true;
+};
+
+// ### Expression parsing
+
+// These nest, from the most general expression type at the top to
+// 'atomic', nondivisible expression types at the bottom. Most of
+// the functions will simply let the function(s) below them parse,
+// and, *if* the syntactic construct they handle is present, wrap
+// the AST node that the inner parser gave them in another node.
+
+// Parse a full expression. The optional arguments are used to
+// forbid the `in` operator (in for loops initalization expressions)
+// and provide reference for storing '=' operator inside shorthand
+// property assignment in contexts where both object expression
+// and object pattern might appear (so it's possible to raise
+// delayed syntax error at correct position).
+
+pp$3.parseExpression = function(noIn, refDestructuringErrors) {
var this$1 = this;
- var start = this.storeCurrentPos();
- var expr = this.parseMaybeAssign(noIn);
- if (this.tok.type === __acorn.tokTypes.comma) {
- var node = this.startNodeAt(start);
+ var startPos = this.start, startLoc = this.startLoc;
+ var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
+ if (this.type === types.comma) {
+ var node = this.startNodeAt(startPos, startLoc);
node.expressions = [expr];
- while (this.eat(__acorn.tokTypes.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn)); }
+ while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); }
return this.finishNode(node, "SequenceExpression")
}
return expr
};
-lp$2.parseParenExpression = function() {
- this.pushCx();
- this.expect(__acorn.tokTypes.parenL);
- var val = this.parseExpression();
- this.popCx();
- this.expect(__acorn.tokTypes.parenR);
- return val
-};
+// Parse an assignment expression. This includes applications of
+// operators like `+=`.
-lp$2.parseMaybeAssign = function(noIn) {
- if (this.toks.isContextual("yield")) {
- var node = this.startNode();
- this.next();
- if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type !== __acorn.tokTypes.star && !this.tok.type.startsExpr)) {
- node.delegate = false;
- node.argument = null;
- } else {
- node.delegate = this.eat(__acorn.tokTypes.star);
- node.argument = this.parseMaybeAssign();
- }
- return this.finishNode(node, "YieldExpression")
+pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
+ if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() }
+
+ var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1;
+ if (refDestructuringErrors) {
+ oldParenAssign = refDestructuringErrors.parenthesizedAssign;
+ oldTrailingComma = refDestructuringErrors.trailingComma;
+ refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
+ } else {
+ refDestructuringErrors = new DestructuringErrors;
+ ownDestructuringErrors = true;
}
- var start = this.storeCurrentPos();
- var left = this.parseMaybeConditional(noIn);
- if (this.tok.type.isAssign) {
- var node$1 = this.startNodeAt(start);
- node$1.operator = this.tok.value;
- node$1.left = this.tok.type === __acorn.tokTypes.eq ? this.toAssignable(left) : this.checkLVal(left);
+ var startPos = this.start, startLoc = this.startLoc;
+ if (this.type === types.parenL || this.type === types.name)
+ { this.potentialArrowAt = this.start; }
+ var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
+ if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
+ if (this.type.isAssign) {
+ var node = this.startNodeAt(startPos, startLoc);
+ node.operator = this.value;
+ node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left;
+ if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); }
+ refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly
+ this.checkLVal(left);
this.next();
- node$1.right = this.parseMaybeAssign(noIn);
- return this.finishNode(node$1, "AssignmentExpression")
+ node.right = this.parseMaybeAssign(noIn);
+ return this.finishNode(node, "AssignmentExpression")
+ } else {
+ if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
}
+ if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
+ if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
return left
};
-lp$2.parseMaybeConditional = function(noIn) {
- var start = this.storeCurrentPos();
- var expr = this.parseExprOps(noIn);
- if (this.eat(__acorn.tokTypes.question)) {
- var node = this.startNodeAt(start);
+// Parse a ternary conditional (`?:`) operator.
+
+pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {
+ var startPos = this.start, startLoc = this.startLoc;
+ var expr = this.parseExprOps(noIn, refDestructuringErrors);
+ if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
+ if (this.eat(types.question)) {
+ var node = this.startNodeAt(startPos, startLoc);
node.test = expr;
node.consequent = this.parseMaybeAssign();
- node.alternate = this.expect(__acorn.tokTypes.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent();
+ this.expect(types.colon);
+ node.alternate = this.parseMaybeAssign(noIn);
return this.finishNode(node, "ConditionalExpression")
}
return expr
};
-lp$2.parseExprOps = function(noIn) {
- var start = this.storeCurrentPos();
- var indent = this.curIndent, line = this.curLineStart;
- return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line)
+// Start the precedence parser.
+
+pp$3.parseExprOps = function(noIn, refDestructuringErrors) {
+ var startPos = this.start, startLoc = this.startLoc;
+ var expr = this.parseMaybeUnary(refDestructuringErrors, false);
+ if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
+ return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
};
-lp$2.parseExprOp = function(left, start, minPrec, noIn, indent, line) {
- if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { return left }
- var prec = this.tok.type.binop;
- if (prec != null && (!noIn || this.tok.type !== __acorn.tokTypes._in)) {
+// Parse binary operators with the operator precedence parsing
+// algorithm. `left` is the left-hand side of the operator.
+// `minPrec` provides context that allows the function to stop and
+// defer further parser to one of its callers when it encounters an
+// operator that has a lower precedence than the set it is parsing.
+
+pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
+ var prec = this.type.binop;
+ if (prec != null && (!noIn || this.type !== types._in)) {
if (prec > minPrec) {
- var node = this.startNodeAt(start);
- node.left = left;
- node.operator = this.tok.value;
+ var logical = this.type === types.logicalOR || this.type === types.logicalAND;
+ var op = this.value;
this.next();
- if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) {
- node.right = this.dummyIdent();
- } else {
- var 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)
+ var startPos = this.start, startLoc = this.startLoc;
+ var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
+ var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical);
+ return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
}
}
return left
};
-lp$2.parseMaybeUnary = function(sawUnary) {
+pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {
+ var node = this.startNodeAt(startPos, startLoc);
+ node.left = left;
+ node.operator = op;
+ node.right = right;
+ return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
+};
+
+// Parse unary operators, both prefix and postfix.
+
+pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
var this$1 = this;
- var start = this.storeCurrentPos(), expr;
- if (this.options.ecmaVersion >= 8 && this.toks.isContextual("await") &&
- (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))
- ) {
+ var startPos = this.start, startLoc = this.startLoc, expr;
+ if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) {
expr = this.parseAwait();
sawUnary = true;
- } else if (this.tok.type.prefix) {
- var node = this.startNode(), update = this.tok.type === __acorn.tokTypes.incDec;
- if (!update) { sawUnary = true; }
- node.operator = this.tok.value;
+ } else if (this.type.prefix) {
+ var node = this.startNode(), update = this.type === types.incDec;
+ node.operator = this.value;
node.prefix = true;
this.next();
- node.argument = this.parseMaybeUnary(true);
- if (update) { node.argument = this.checkLVal(node.argument); }
+ node.argument = this.parseMaybeUnary(null, true);
+ this.checkExpressionErrors(refDestructuringErrors, true);
+ if (update) { this.checkLVal(node.argument); }
+ else if (this.strict && node.operator === "delete" &&
+ node.argument.type === "Identifier")
+ { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
+ else { sawUnary = true; }
expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
- } else if (this.tok.type === __acorn.tokTypes.ellipsis) {
- var node$1 = this.startNode();
- this.next();
- node$1.argument = this.parseMaybeUnary(sawUnary);
- expr = this.finishNode(node$1, "SpreadElement");
} else {
- expr = this.parseExprSubscripts();
- while (this.tok.type.postfix && !this.canInsertSemicolon()) {
- var node$2 = this$1.startNodeAt(start);
- node$2.operator = this$1.tok.value;
- node$2.prefix = false;
- node$2.argument = this$1.checkLVal(expr);
+ expr = this.parseExprSubscripts(refDestructuringErrors);
+ if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
+ while (this.type.postfix && !this.canInsertSemicolon()) {
+ var node$1 = this$1.startNodeAt(startPos, startLoc);
+ node$1.operator = this$1.value;
+ node$1.prefix = false;
+ node$1.argument = expr;
+ this$1.checkLVal(expr);
this$1.next();
- expr = this$1.finishNode(node$2, "UpdateExpression");
+ expr = this$1.finishNode(node$1, "UpdateExpression");
}
}
- if (!sawUnary && this.eat(__acorn.tokTypes.starstar)) {
- var node$3 = this.startNodeAt(start);
- node$3.operator = "**";
- node$3.left = expr;
- node$3.right = this.parseMaybeUnary(false);
- return this.finishNode(node$3, "BinaryExpression")
- }
-
- return expr
+ if (!sawUnary && this.eat(types.starstar))
+ { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) }
+ else
+ { return expr }
};
-lp$2.parseExprSubscripts = function() {
- var start = this.storeCurrentPos();
- return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart)
+// Parse call, dot, and `[]`-subscript expressions.
+
+pp$3.parseExprSubscripts = function(refDestructuringErrors) {
+ var startPos = this.start, startLoc = this.startLoc;
+ var expr = this.parseExprAtom(refDestructuringErrors);
+ var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")";
+ if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr }
+ var result = this.parseSubscripts(expr, startPos, startLoc);
+ if (refDestructuringErrors && result.type === "MemberExpression") {
+ if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
+ if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
+ }
+ return result
};
-lp$2.parseSubscripts = function(base, start, noCalls, startIndent, line) {
+pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {
var this$1 = this;
- for (;;) {
- if (this$1.curLineStart !== line && this$1.curIndent <= startIndent && this$1.tokenStartsLine()) {
- if (this$1.tok.type === __acorn.tokTypes.dot && this$1.curIndent === startIndent)
- { --startIndent; }
- else
- { return base }
- }
-
- var maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this$1.canInsertSemicolon();
-
- if (this$1.eat(__acorn.tokTypes.dot)) {
- var node = this$1.startNodeAt(start);
+ var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
+ this.lastTokEnd === base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async";
+ for (var computed = (void 0);;) {
+ if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) {
+ var node = this$1.startNodeAt(startPos, startLoc);
node.object = base;
- if (this$1.curLineStart !== line && this$1.curIndent <= startIndent && this$1.tokenStartsLine())
- { node.property = this$1.dummyIdent(); }
- else
- { node.property = this$1.parsePropertyAccessor() || this$1.dummyIdent(); }
- node.computed = false;
+ node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true);
+ node.computed = !!computed;
+ if (computed) { this$1.expect(types.bracketR); }
base = this$1.finishNode(node, "MemberExpression");
- } else if (this$1.tok.type === __acorn.tokTypes.bracketL) {
- this$1.pushCx();
- this$1.next();
- var node$1 = this$1.startNodeAt(start);
- node$1.object = base;
- node$1.property = this$1.parseExpression();
- node$1.computed = true;
- this$1.popCx();
- this$1.expect(__acorn.tokTypes.bracketR);
- base = this$1.finishNode(node$1, "MemberExpression");
- } else if (!noCalls && this$1.tok.type === __acorn.tokTypes.parenL) {
- var exprList = this$1.parseExprList(__acorn.tokTypes.parenR);
- if (maybeAsyncArrow && this$1.eat(__acorn.tokTypes.arrow))
- { return this$1.parseArrowExpression(this$1.startNodeAt(start), exprList, true) }
- var node$2 = this$1.startNodeAt(start);
- node$2.callee = base;
- node$2.arguments = exprList;
- base = this$1.finishNode(node$2, "CallExpression");
- } else if (this$1.tok.type === __acorn.tokTypes.backQuote) {
- var node$3 = this$1.startNodeAt(start);
- node$3.tag = base;
- node$3.quasi = this$1.parseTemplate();
- base = this$1.finishNode(node$3, "TaggedTemplateExpression");
+ } else if (!noCalls && this$1.eat(types.parenL)) {
+ var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos;
+ this$1.yieldPos = 0;
+ this$1.awaitPos = 0;
+ var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors);
+ if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) {
+ this$1.checkPatternErrors(refDestructuringErrors, false);
+ this$1.checkYieldAwaitInDefaultParams();
+ this$1.yieldPos = oldYieldPos;
+ this$1.awaitPos = oldAwaitPos;
+ return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true)
+ }
+ this$1.checkExpressionErrors(refDestructuringErrors, true);
+ this$1.yieldPos = oldYieldPos || this$1.yieldPos;
+ this$1.awaitPos = oldAwaitPos || this$1.awaitPos;
+ var node$1 = this$1.startNodeAt(startPos, startLoc);
+ node$1.callee = base;
+ node$1.arguments = exprList;
+ base = this$1.finishNode(node$1, "CallExpression");
+ } else if (this$1.type === types.backQuote) {
+ var node$2 = this$1.startNodeAt(startPos, startLoc);
+ node$2.tag = base;
+ node$2.quasi = this$1.parseTemplate({isTagged: true});
+ base = this$1.finishNode(node$2, "TaggedTemplateExpression");
} else {
return base
}
}
};
-lp$2.parseExprAtom = function() {
- var node;
- switch (this.tok.type) {
- case __acorn.tokTypes._this:
- case __acorn.tokTypes._super:
- var type = this.tok.type === __acorn.tokTypes._this ? "ThisExpression" : "Super";
+// Parse an atomic expression — either a single token that is an
+// expression, an expression started by a keyword like `function` or
+// `new`, or an expression wrapped in punctuation like `()`, `[]`,
+// or `{}`.
+
+pp$3.parseExprAtom = function(refDestructuringErrors) {
+ var node, canBeArrow = this.potentialArrowAt === this.start;
+ switch (this.type) {
+ case types._super:
+ if (!this.inFunction)
+ { this.raise(this.start, "'super' outside of function or class"); }
node = this.startNode();
this.next();
- return this.finishNode(node, type)
+ // The `super` keyword can appear at below:
+ // SuperProperty:
+ // super [ Expression ]
+ // super . IdentifierName
+ // SuperCall:
+ // super Arguments
+ if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
+ { this.unexpected(); }
+ return this.finishNode(node, "Super")
- case __acorn.tokTypes.name:
- var start = this.storeCurrentPos();
- var id = this.parseIdent();
- var isAsync = false;
- if (id.name === "async" && !this.canInsertSemicolon()) {
- if (this.eat(__acorn.tokTypes._function))
- { return this.parseFunction(this.startNodeAt(start), false, true) }
- if (this.tok.type === __acorn.tokTypes.name) {
+ case types._this:
+ node = this.startNode();
+ this.next();
+ return this.finishNode(node, "ThisExpression")
+
+ case types.name:
+ var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
+ var id = this.parseIdent(this.type !== types.name);
+ if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
+ { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) }
+ if (canBeArrow && !this.canInsertSemicolon()) {
+ if (this.eat(types.arrow))
+ { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
+ if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) {
id = this.parseIdent();
- isAsync = true;
+ if (this.canInsertSemicolon() || !this.eat(types.arrow))
+ { this.unexpected(); }
+ return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
}
}
- return this.eat(__acorn.tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id
+ return id
- case __acorn.tokTypes.regexp:
- node = this.startNode();
- var 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 types.regexp:
+ var value = this.value;
+ node = this.parseLiteral(value.value);
+ node.regex = {pattern: value.pattern, flags: value.flags};
+ return node
- case __acorn.tokTypes.num: case __acorn.tokTypes.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 types.num: case types.string:
+ return this.parseLiteral(this.value)
- case __acorn.tokTypes._null: case __acorn.tokTypes._true: case __acorn.tokTypes._false:
+ case types._null: case types._true: case types._false:
node = this.startNode();
- node.value = this.tok.type === __acorn.tokTypes._null ? null : this.tok.type === __acorn.tokTypes._true;
- node.raw = this.tok.type.keyword;
+ node.value = this.type === types._null ? null : this.type === types._true;
+ node.raw = this.type.keyword;
this.next();
return this.finishNode(node, "Literal")
- case __acorn.tokTypes.parenL:
- var parenStart = this.storeCurrentPos();
- this.next();
- var inner = this.parseExpression();
- this.expect(__acorn.tokTypes.parenR);
- if (this.eat(__acorn.tokTypes.arrow)) {
- // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy.
- var 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) {
- var par = this.startNodeAt(parenStart);
- par.expression = inner;
- inner = this.finishNode(par, "ParenthesizedExpression");
+ case types.parenL:
+ var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
+ if (refDestructuringErrors) {
+ if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
+ { refDestructuringErrors.parenthesizedAssign = start; }
+ if (refDestructuringErrors.parenthesizedBind < 0)
+ { refDestructuringErrors.parenthesizedBind = start; }
}
- return inner
+ return expr
- case __acorn.tokTypes.bracketL:
+ case types.bracketL:
node = this.startNode();
- node.elements = this.parseExprList(__acorn.tokTypes.bracketR, true);
+ this.next();
+ node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors);
return this.finishNode(node, "ArrayExpression")
- case __acorn.tokTypes.braceL:
- return this.parseObj()
-
- case __acorn.tokTypes._class:
- return this.parseClass(false)
+ case types.braceL:
+ return this.parseObj(false, refDestructuringErrors)
- case __acorn.tokTypes._function:
+ case types._function:
node = this.startNode();
this.next();
return this.parseFunction(node, false)
- case __acorn.tokTypes._new:
+ case types._class:
+ return this.parseClass(this.startNode(), false)
+
+ case types._new:
return this.parseNew()
- case __acorn.tokTypes.backQuote:
+ case types.backQuote:
return this.parseTemplate()
default:
- return this.dummyIdent()
+ this.unexpected();
}
};
-lp$2.parseNew = function() {
- var node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart;
+pp$3.parseLiteral = function(value) {
+ var node = this.startNode();
+ node.value = value;
+ node.raw = this.input.slice(this.start, this.end);
+ this.next();
+ return this.finishNode(node, "Literal")
+};
+
+pp$3.parseParenExpression = function() {
+ this.expect(types.parenL);
+ var val = this.parseExpression();
+ this.expect(types.parenR);
+ return val
+};
+
+pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {
+ var this$1 = this;
+
+ var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
+ if (this.options.ecmaVersion >= 6) {
+ this.next();
+
+ var innerStartPos = this.start, innerStartLoc = this.startLoc;
+ var exprList = [], first = true, lastIsComma = false;
+ var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
+ this.yieldPos = 0;
+ this.awaitPos = 0;
+ while (this.type !== types.parenR) {
+ first ? first = false : this$1.expect(types.comma);
+ if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) {
+ lastIsComma = true;
+ break
+ } else if (this$1.type === types.ellipsis) {
+ spreadStart = this$1.start;
+ exprList.push(this$1.parseParenItem(this$1.parseRestBinding()));
+ if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); }
+ break
+ } else {
+ exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem));
+ }
+ }
+ var innerEndPos = this.start, innerEndLoc = this.startLoc;
+ this.expect(types.parenR);
+
+ if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
+ this.checkPatternErrors(refDestructuringErrors, false);
+ this.checkYieldAwaitInDefaultParams();
+ this.yieldPos = oldYieldPos;
+ this.awaitPos = oldAwaitPos;
+ return this.parseParenArrowList(startPos, startLoc, exprList)
+ }
+
+ if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
+ if (spreadStart) { this.unexpected(spreadStart); }
+ this.checkExpressionErrors(refDestructuringErrors, true);
+ this.yieldPos = oldYieldPos || this.yieldPos;
+ this.awaitPos = oldAwaitPos || this.awaitPos;
+
+ if (exprList.length > 1) {
+ val = this.startNodeAt(innerStartPos, innerStartLoc);
+ val.expressions = exprList;
+ this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
+ } else {
+ val = exprList[0];
+ }
+ } else {
+ val = this.parseParenExpression();
+ }
+
+ if (this.options.preserveParens) {
+ var par = this.startNodeAt(startPos, startLoc);
+ par.expression = val;
+ return this.finishNode(par, "ParenthesizedExpression")
+ } else {
+ return val
+ }
+};
+
+pp$3.parseParenItem = function(item) {
+ return item
+};
+
+pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {
+ return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
+};
+
+// New's precedence is slightly tricky. It must allow its argument to
+// be a `[]` or dot subscript expression, but not a call — at least,
+// not without wrapping it in parentheses. Thus, it uses the noCalls
+// argument to parseSubscripts to prevent it from consuming the
+// argument list.
+
+var empty$1 = [];
+
+pp$3.parseNew = function() {
+ var node = this.startNode();
var meta = this.parseIdent(true);
- if (this.options.ecmaVersion >= 6 && this.eat(__acorn.tokTypes.dot)) {
+ if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) {
node.meta = meta;
+ var containsEsc = this.containsEsc;
node.property = this.parseIdent(true);
+ if (node.property.name !== "target" || containsEsc)
+ { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); }
+ if (!this.inFunction)
+ { this.raiseRecoverable(node.start, "new.target can only be used in functions"); }
return this.finishNode(node, "MetaProperty")
}
- var start = this.storeCurrentPos();
- node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line);
- if (this.tok.type === __acorn.tokTypes.parenL) {
- node.arguments = this.parseExprList(__acorn.tokTypes.parenR);
- } else {
- node.arguments = [];
- }
+ var startPos = this.start, startLoc = this.startLoc;
+ node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
+ if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); }
+ else { node.arguments = empty$1; }
return this.finishNode(node, "NewExpression")
};
-lp$2.parseTemplateElement = function() {
- var elem = this.startNode();
+// Parse template expression.
- // The loose parser accepts invalid unicode escapes even in untagged templates.
- if (this.tok.type === __acorn.tokTypes.invalidTemplate) {
+pp$3.parseTemplateElement = function(ref) {
+ var isTagged = ref.isTagged;
+
+ var elem = this.startNode();
+ if (this.type === types.invalidTemplate) {
+ if (!isTagged) {
+ this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
+ }
elem.value = {
- raw: this.tok.value,
+ raw: this.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
+ raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
+ cooked: this.value
};
}
this.next();
- elem.tail = this.tok.type === __acorn.tokTypes.backQuote;
+ elem.tail = this.type === types.backQuote;
return this.finishNode(elem, "TemplateElement")
};
-lp$2.parseTemplate = function() {
+pp$3.parseTemplate = function(ref) {
var this$1 = this;
+ if ( ref === void 0 ) ref = {};
+ var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;
var node = this.startNode();
this.next();
node.expressions = [];
- var curElt = this.parseTemplateElement();
+ var curElt = this.parseTemplateElement({isTagged: isTagged});
node.quasis = [curElt];
while (!curElt.tail) {
- this$1.next();
+ this$1.expect(types.dollarBraceL);
node.expressions.push(this$1.parseExpression());
- if (this$1.expect(__acorn.tokTypes.braceR)) {
- curElt = this$1.parseTemplateElement();
- } else {
- curElt = this$1.startNode();
- curElt.value = {cooked: "", raw: ""};
- curElt.tail = true;
- this$1.finishNode(curElt, "TemplateElement");
- }
- node.quasis.push(curElt);
+ this$1.expect(types.braceR);
+ node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged}));
}
- this.expect(__acorn.tokTypes.backQuote);
+ this.next();
return this.finishNode(node, "TemplateLiteral")
};
-lp$2.parseObj = function() {
+pp$3.isAsyncProp = function(prop) {
+ return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
+ (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) &&
+ !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
+};
+
+// Parse an object literal or binding pattern.
+
+pp$3.parseObj = function(isPattern, refDestructuringErrors) {
var this$1 = this;
- var node = this.startNode();
+ var node = this.startNode(), first = true, propHash = {};
node.properties = [];
- this.pushCx();
- var indent = this.curIndent + 1, line = this.curLineStart;
- this.eat(__acorn.tokTypes.braceL);
- if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
- while (!this.closes(__acorn.tokTypes.braceR, indent, line)) {
- var prop = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0), start = (void 0);
- if (this$1.options.ecmaVersion >= 9 && this$1.eat(__acorn.tokTypes.ellipsis)) {
- prop.argument = this$1.parseMaybeAssign();
- node.properties.push(this$1.finishNode(prop, "SpreadElement"));
- this$1.eat(__acorn.tokTypes.comma);
- continue
+ this.next();
+ while (!this.eat(types.braceR)) {
+ if (!first) {
+ this$1.expect(types.comma);
+ if (this$1.afterTrailingComma(types.braceR)) { break }
+ } else { first = false; }
+
+ var prop = this$1.parseProperty(isPattern, refDestructuringErrors);
+ if (!isPattern) { this$1.checkPropClash(prop, propHash, refDestructuringErrors); }
+ node.properties.push(prop);
+ }
+ return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
+};
+
+pp$3.parseProperty = function(isPattern, refDestructuringErrors) {
+ var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
+ if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) {
+ if (isPattern) {
+ prop.argument = this.parseIdent(false);
+ if (this.type === types.comma) {
+ this.raise(this.start, "Comma is not permitted after the rest element");
+ }
+ return this.finishNode(prop, "RestElement")
}
- if (this$1.options.ecmaVersion >= 6) {
- start = this$1.storeCurrentPos();
- prop.method = false;
- prop.shorthand = false;
- isGenerator = this$1.eat(__acorn.tokTypes.star);
+ // To disallow parenthesized identifier via `this.toAssignable()`.
+ if (this.type === types.parenL && refDestructuringErrors) {
+ if (refDestructuringErrors.parenthesizedAssign < 0) {
+ refDestructuringErrors.parenthesizedAssign = this.start;
+ }
+ if (refDestructuringErrors.parenthesizedBind < 0) {
+ refDestructuringErrors.parenthesizedBind = this.start;
+ }
}
- this$1.parsePropertyName(prop);
- if (this$1.toks.isAsyncProp(prop)) {
- isAsync = true;
- isGenerator = this$1.options.ecmaVersion >= 9 && this$1.eat(__acorn.tokTypes.star);
- this$1.parsePropertyName(prop);
- } else {
- isAsync = false;
+ // Parse argument.
+ prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
+ // To disallow trailing comma via `this.toAssignable()`.
+ if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
+ refDestructuringErrors.trailingComma = this.start;
}
- if (isDummy(prop.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(__acorn.tokTypes.comma); continue }
- if (this$1.eat(__acorn.tokTypes.colon)) {
- prop.kind = "init";
- prop.value = this$1.parseMaybeAssign();
- } else if (this$1.options.ecmaVersion >= 6 && (this$1.tok.type === __acorn.tokTypes.parenL || this$1.tok.type === __acorn.tokTypes.braceL)) {
- prop.kind = "init";
- prop.method = true;
- prop.value = this$1.parseMethod(isGenerator, isAsync);
- } else if (this$1.options.ecmaVersion >= 5 && prop.key.type === "Identifier" &&
- !prop.computed && (prop.key.name === "get" || prop.key.name === "set") &&
- (this$1.tok.type !== __acorn.tokTypes.comma && this$1.tok.type !== __acorn.tokTypes.braceR && this$1.tok.type !== __acorn.tokTypes.eq)) {
- prop.kind = prop.key.name;
- this$1.parsePropertyName(prop);
- prop.value = this$1.parseMethod(false);
- } else {
- prop.kind = "init";
- if (this$1.options.ecmaVersion >= 6) {
- if (this$1.eat(__acorn.tokTypes.eq)) {
- var assign = this$1.startNodeAt(start);
- assign.operator = "=";
- assign.left = prop.key;
- assign.right = this$1.parseMaybeAssign();
- prop.value = this$1.finishNode(assign, "AssignmentExpression");
- } else {
- prop.value = prop.key;
- }
- } else {
- prop.value = this$1.dummyIdent();
- }
- prop.shorthand = true;
+ // Finish
+ return this.finishNode(prop, "SpreadElement")
+ }
+ if (this.options.ecmaVersion >= 6) {
+ prop.method = false;
+ prop.shorthand = false;
+ if (isPattern || refDestructuringErrors) {
+ startPos = this.start;
+ startLoc = this.startLoc;
}
- node.properties.push(this$1.finishNode(prop, "Property"));
- this$1.eat(__acorn.tokTypes.comma);
+ if (!isPattern)
+ { isGenerator = this.eat(types.star); }
}
- this.popCx();
- if (!this.eat(__acorn.tokTypes.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; }
+ var containsEsc = this.containsEsc;
+ this.parsePropertyName(prop);
+ if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
+ isAsync = true;
+ isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
+ this.parsePropertyName(prop, refDestructuringErrors);
+ } else {
+ isAsync = false;
}
- return this.finishNode(node, "ObjectExpression")
+ this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
+ return this.finishNode(prop, "Property")
};
-lp$2.parsePropertyName = function(prop) {
+pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
+ if ((isGenerator || isAsync) && this.type === types.colon)
+ { this.unexpected(); }
+
+ if (this.eat(types.colon)) {
+ prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
+ prop.kind = "init";
+ } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) {
+ if (isPattern) { this.unexpected(); }
+ prop.kind = "init";
+ prop.method = true;
+ prop.value = this.parseMethod(isGenerator, isAsync);
+ } else if (!isPattern && !containsEsc &&
+ this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
+ (prop.key.name === "get" || prop.key.name === "set") &&
+ (this.type !== types.comma && this.type !== types.braceR)) {
+ if (isGenerator || isAsync) { this.unexpected(); }
+ prop.kind = prop.key.name;
+ this.parsePropertyName(prop);
+ prop.value = this.parseMethod(false);
+ var paramCount = prop.kind === "get" ? 0 : 1;
+ if (prop.value.params.length !== paramCount) {
+ var start = prop.value.start;
+ if (prop.kind === "get")
+ { this.raiseRecoverable(start, "getter should have no params"); }
+ else
+ { this.raiseRecoverable(start, "setter should have exactly one param"); }
+ } else {
+ if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
+ { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
+ }
+ } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
+ this.checkUnreserved(prop.key);
+ prop.kind = "init";
+ if (isPattern) {
+ prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
+ } else if (this.type === types.eq && refDestructuringErrors) {
+ if (refDestructuringErrors.shorthandAssign < 0)
+ { refDestructuringErrors.shorthandAssign = this.start; }
+ prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
+ } else {
+ prop.value = prop.key;
+ }
+ prop.shorthand = true;
+ } else { this.unexpected(); }
+};
+
+pp$3.parsePropertyName = function(prop) {
if (this.options.ecmaVersion >= 6) {
- if (this.eat(__acorn.tokTypes.bracketL)) {
+ if (this.eat(types.bracketL)) {
prop.computed = true;
- prop.key = this.parseExpression();
- this.expect(__acorn.tokTypes.bracketR);
- return
+ prop.key = this.parseMaybeAssign();
+ this.expect(types.bracketR);
+ return prop.key
} else {
prop.computed = false;
}
}
- var key = (this.tok.type === __acorn.tokTypes.num || this.tok.type === __acorn.tokTypes.string) ? this.parseExprAtom() : this.parseIdent();
- prop.key = key || this.dummyIdent();
-};
-
-lp$2.parsePropertyAccessor = function() {
- if (this.tok.type === __acorn.tokTypes.name || this.tok.type.keyword) { return this.parseIdent() }
+ return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true)
};
-lp$2.parseIdent = function() {
- var name = this.tok.type === __acorn.tokTypes.name ? this.tok.value : this.tok.type.keyword;
- if (!name) { return this.dummyIdent() }
- var node = this.startNode();
- this.next();
- node.name = name;
- return this.finishNode(node, "Identifier")
-};
+// Initialize empty function node.
-lp$2.initFunction = function(node) {
+pp$3.initFunction = function(node) {
node.id = null;
- node.params = [];
if (this.options.ecmaVersion >= 6) {
node.generator = false;
node.expression = false;
@@ -9667,628 +12451,2843 @@ lp$2.initFunction = function(node) {
{ node.async = false; }
};
-// Convert existing expression atom to assignable pattern
-// if possible.
-
-lp$2.toAssignable = function(node, binding) {
- var this$1 = this;
-
- 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 (var i = 0, list = node.properties; i < list.length; i += 1)
- {
- var prop = list[i];
-
- this$1.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$2.toAssignableList = function(exprList, binding) {
- var this$1 = this;
-
- for (var i = 0, list = exprList; i < list.length; i += 1)
- {
- var expr = list[i];
-
- this$1.toAssignable(expr, binding);
- }
- return exprList
-};
+// Parse object or class method.
-lp$2.parseFunctionParams = function(params) {
- params = this.parseExprList(__acorn.tokTypes.parenR);
- return this.toAssignableList(params, true)
-};
+pp$3.parseMethod = function(isGenerator, isAsync) {
+ var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync,
+ oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;
-lp$2.parseMethod = function(isGenerator, isAsync) {
- var node = this.startNode(), oldInAsync = this.inAsync, oldInFunction = this.inFunction;
this.initFunction(node);
if (this.options.ecmaVersion >= 6)
- { node.generator = !!isGenerator; }
+ { node.generator = isGenerator; }
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;
- node.params = this.parseFunctionParams();
- node.body = this.parseBlock();
- this.toks.adaptDirectivePrologue(node.body.body);
+ this.enterFunctionScope();
+
+ this.expect(types.parenL);
+ node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
+ this.checkYieldAwaitInDefaultParams();
+ this.parseFunctionBody(node, false);
+
+ this.inGenerator = oldInGen;
this.inAsync = oldInAsync;
- this.inFunction = oldInFunction;
+ this.yieldPos = oldYieldPos;
+ this.awaitPos = oldAwaitPos;
+ this.inFunction = oldInFunc;
return this.finishNode(node, "FunctionExpression")
};
-lp$2.parseArrowExpression = function(node, params, isAsync) {
- var oldInAsync = this.inAsync, oldInFunction = this.inFunction;
+// Parse arrow function expression with given parameters.
+
+pp$3.parseArrowExpression = function(node, params, isAsync) {
+ var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
+ oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;
+
+ this.enterFunctionScope();
this.initFunction(node);
if (this.options.ecmaVersion >= 8)
{ node.async = !!isAsync; }
+
+ this.inGenerator = false;
this.inAsync = node.async;
+ this.yieldPos = 0;
+ this.awaitPos = 0;
this.inFunction = true;
+
node.params = this.toAssignableList(params, true);
- node.expression = this.tok.type !== __acorn.tokTypes.braceL;
- if (node.expression) {
+ this.parseFunctionBody(node, true);
+
+ this.inGenerator = oldInGen;
+ this.inAsync = oldInAsync;
+ this.yieldPos = oldYieldPos;
+ this.awaitPos = oldAwaitPos;
+ this.inFunction = oldInFunc;
+ return this.finishNode(node, "ArrowFunctionExpression")
+};
+
+// Parse function body and check parameters.
+
+pp$3.parseFunctionBody = function(node, isArrowFunction) {
+ var isExpression = isArrowFunction && this.type !== types.braceL;
+ var oldStrict = this.strict, useStrict = false;
+
+ if (isExpression) {
node.body = this.parseMaybeAssign();
+ node.expression = true;
+ this.checkParams(node, false);
} else {
- node.body = this.parseBlock();
- this.toks.adaptDirectivePrologue(node.body.body);
+ var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
+ if (!oldStrict || nonSimple) {
+ useStrict = this.strictDirective(this.end);
+ // If this is a strict mode function, verify that argument names
+ // are not repeated, and it does not try to bind the words `eval`
+ // or `arguments`.
+ if (useStrict && nonSimple)
+ { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
+ }
+ // Start a new scope with regard to labels and the `inFunction`
+ // flag (restore them to their old value afterwards).
+ var oldLabels = this.labels;
+ this.labels = [];
+ if (useStrict) { this.strict = true; }
+
+ // Add the params to varDeclaredNames to ensure that an error is thrown
+ // if a let/const declaration in the function clashes with one of the params.
+ this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params));
+ node.body = this.parseBlock(false);
+ node.expression = false;
+ this.adaptDirectivePrologue(node.body.body);
+ this.labels = oldLabels;
}
- this.inAsync = oldInAsync;
- this.inFunction = oldInFunction;
- return this.finishNode(node, "ArrowFunctionExpression")
+ 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;
};
-lp$2.parseExprList = function(close, allowEmpty) {
+pp$3.isSimpleParamList = function(params) {
+ for (var i = 0, list = params; i < list.length; i += 1)
+ {
+ var param = list[i];
+
+ if (param.type !== "Identifier") { return false
+ } }
+ return true
+};
+
+// Checks function params for various disallowed patterns such as using "eval"
+// or "arguments" and duplicate parameters.
+
+pp$3.checkParams = function(node, allowDuplicates) {
var this$1 = this;
- this.pushCx();
- var indent = this.curIndent, line = this.curLineStart, elts = [];
- this.next(); // Opening bracket
- while (!this.closes(close, indent + 1, line)) {
- if (this$1.eat(__acorn.tokTypes.comma)) {
- elts.push(allowEmpty ? null : this$1.dummyIdent());
- continue
- }
- var elt = this$1.parseMaybeAssign();
- if (isDummy(elt)) {
- if (this$1.closes(close, indent, line)) { break }
- this$1.next();
+ var nameHash = {};
+ for (var i = 0, list = node.params; i < list.length; i += 1)
+ {
+ var param = list[i];
+
+ this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash);
+ }
+};
+
+// Parses a comma-separated list of expressions, and returns them as
+// an array. `close` is the token type that ends the list, and
+// `allowEmpty` can be turned on to allow subsequent commas with
+// nothing in between them to be parsed as `null` (which is needed
+// for array literals).
+
+pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
+ var this$1 = this;
+
+ var elts = [], first = true;
+ while (!this.eat(close)) {
+ if (!first) {
+ this$1.expect(types.comma);
+ if (allowTrailingComma && this$1.afterTrailingComma(close)) { break }
+ } else { first = false; }
+
+ var elt = (void 0);
+ if (allowEmpty && this$1.type === types.comma)
+ { elt = null; }
+ else if (this$1.type === types.ellipsis) {
+ elt = this$1.parseSpread(refDestructuringErrors);
+ if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0)
+ { refDestructuringErrors.trailingComma = this$1.start; }
} else {
- elts.push(elt);
+ elt = this$1.parseMaybeAssign(false, refDestructuringErrors);
}
- this$1.eat(__acorn.tokTypes.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; }
+ elts.push(elt);
}
return elts
};
-lp$2.parseAwait = function() {
+pp$3.checkUnreserved = function(ref) {
+ var start = ref.start;
+ var end = ref.end;
+ var name = ref.name;
+
+ if (this.inGenerator && name === "yield")
+ { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); }
+ if (this.inAsync && name === "await")
+ { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); }
+ if (this.isKeyword(name))
+ { this.raise(start, ("Unexpected keyword '" + name + "'")); }
+ if (this.options.ecmaVersion < 6 &&
+ this.input.slice(start, end).indexOf("\\") !== -1) { return }
+ var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
+ if (re.test(name)) {
+ if (!this.inAsync && name === "await")
+ { this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function"); }
+ this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
+ }
+};
+
+// Parse the next token as an identifier. If `liberal` is true (used
+// when parsing properties), it will also convert keywords into
+// identifiers.
+
+pp$3.parseIdent = function(liberal, isBinding) {
var node = this.startNode();
+ if (liberal && this.options.allowReserved === "never") { liberal = false; }
+ if (this.type === types.name) {
+ node.name = this.value;
+ } else if (this.type.keyword) {
+ node.name = this.type.keyword;
+
+ // To fix https://github.com/acornjs/acorn/issues/575
+ // `class` and `function` keywords push new context into this.context.
+ // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
+ // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
+ if ((node.name === "class" || node.name === "function") &&
+ (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
+ this.context.pop();
+ }
+ } else {
+ this.unexpected();
+ }
this.next();
- node.argument = this.parseMaybeUnary();
+ this.finishNode(node, "Identifier");
+ if (!liberal) { this.checkUnreserved(node); }
+ return node
+};
+
+// Parses yield expression inside generator.
+
+pp$3.parseYield = function() {
+ if (!this.yieldPos) { this.yieldPos = this.start; }
+
+ var node = this.startNode();
+ this.next();
+ if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) {
+ node.delegate = false;
+ node.argument = null;
+ } else {
+ node.delegate = this.eat(types.star);
+ node.argument = this.parseMaybeAssign();
+ }
+ return this.finishNode(node, "YieldExpression")
+};
+
+pp$3.parseAwait = function() {
+ if (!this.awaitPos) { this.awaitPos = this.start; }
+
+ var node = this.startNode();
+ this.next();
+ node.argument = this.parseMaybeUnary(null, true);
return this.finishNode(node, "AwaitExpression")
};
-// 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.
+var pp$4 = Parser.prototype;
-__acorn.defaultOptions.tabSize = 4;
+// This function is used to raise exceptions on parse errors. It
+// takes an offset integer (into the current `input`) to indicate
+// the location of the error, attaches the position to the end
+// of the error message, and then raises a `SyntaxError` with that
+// message.
-// eslint-disable-next-line camelcase
-function parse_dammit(input, options) {
- return new LooseParser(input, options).parse()
-}
+pp$4.raise = function(pos, message) {
+ var loc = getLineInfo(this.input, pos);
+ message += " (" + loc.line + ":" + loc.column + ")";
+ var err = new SyntaxError(message);
+ err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
+ throw err
+};
-__acorn.addLooseExports(parse_dammit, LooseParser, pluginsLoose);
+pp$4.raiseRecoverable = pp$4.raise;
-exports.parse_dammit = parse_dammit;
-exports.LooseParser = LooseParser;
-exports.pluginsLoose = pluginsLoose;
+pp$4.curPosition = function() {
+ if (this.options.locations) {
+ return new Position(this.curLine, this.pos - this.lineStart)
+ }
+};
-Object.defineProperty(exports, '__esModule', { value: true });
+var pp$5 = Parser.prototype;
-})));
+// Object.assign polyfill
+var assign = Object.assign || function(target) {
+ var sources = [], len = arguments.length - 1;
+ while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
-},{"./acorn":12}],14:[function(require,module,exports){
-(function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (factory((global.acorn = global.acorn || {}, global.acorn.walk = {})));
-}(this, (function (exports) { 'use strict';
+ for (var i = 0, list = sources; i < list.length; i += 1) {
+ var source = list[i];
-// AST walker module for Mozilla Parser API compatible trees
+ for (var key in source) {
+ if (has(source, key)) {
+ target[key] = source[key];
+ }
+ }
+ }
+ return target
+};
-// 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.
-
-function simple(node, visitors, baseVisitor, state, override) {
- if (!baseVisitor) { baseVisitor = base
- ; }(function c(node, st, override) {
- var type = override || node.type, found = visitors[type];
- baseVisitor[type](node, st, c);
- if (found) { found(node, st); }
- })(node, state, override);
-}
+// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
-// 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).
-function ancestor(node, visitors, baseVisitor, state) {
- var ancestors = [];
- if (!baseVisitor) { baseVisitor = base
- ; }(function c(node, st, override) {
- var type = override || node.type, found = visitors[type];
- var 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);
-}
+pp$5.enterFunctionScope = function() {
+ // var: a hash of var-declared names in the current lexical scope
+ // lexical: a hash of lexically-declared names in the current lexical scope
+ // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope)
+ // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope)
+ this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}});
+};
+
+pp$5.exitFunctionScope = function() {
+ this.scopeStack.pop();
+};
+
+pp$5.enterLexicalScope = function() {
+ var parentScope = this.scopeStack[this.scopeStack.length - 1];
+ var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}};
+
+ this.scopeStack.push(childScope);
+ assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical);
+};
+
+pp$5.exitLexicalScope = function() {
+ var childScope = this.scopeStack.pop();
+ var parentScope = this.scopeStack[this.scopeStack.length - 1];
+
+ assign(parentScope.childVar, childScope.var, childScope.childVar);
+};
+
+/**
+ * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const`
+ * in the current lexical scope or any of the parent lexical scopes in this function.
+ */
+pp$5.canDeclareVarName = function(name) {
+ var currentScope = this.scopeStack[this.scopeStack.length - 1];
+
+ return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name)
+};
-// 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).
-function recursive(node, state, funcs, baseVisitor, override) {
- var visitor = funcs ? make(funcs, baseVisitor || undefined) : baseVisitor;(function c(node, st, override) {
- visitor[override || node.type](node, st, c);
- })(node, state, override);
+/**
+ * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const`
+ * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in
+ * any child lexical scopes in this function.
+ */
+pp$5.canDeclareLexicalName = function(name) {
+ var currentScope = this.scopeStack[this.scopeStack.length - 1];
+
+ return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name)
+};
+
+pp$5.declareVarName = function(name) {
+ this.scopeStack[this.scopeStack.length - 1].var[name] = true;
+};
+
+pp$5.declareLexicalName = function(name) {
+ this.scopeStack[this.scopeStack.length - 1].lexical[name] = true;
+};
+
+var Node = function Node(parser, pos, loc) {
+ this.type = "";
+ this.start = pos;
+ this.end = 0;
+ if (parser.options.locations)
+ { this.loc = new SourceLocation(parser, loc); }
+ if (parser.options.directSourceFile)
+ { this.sourceFile = parser.options.directSourceFile; }
+ if (parser.options.ranges)
+ { this.range = [pos, 0]; }
+};
+
+// Start an AST node, attaching a start offset.
+
+var pp$6 = Parser.prototype;
+
+pp$6.startNode = function() {
+ return new Node(this, this.start, this.startLoc)
+};
+
+pp$6.startNodeAt = function(pos, loc) {
+ return new Node(this, pos, loc)
+};
+
+// Finish an AST node, adding `type` and `end` properties.
+
+function finishNodeAt(node, type, pos, loc) {
+ node.type = type;
+ node.end = pos;
+ if (this.options.locations)
+ { node.loc.end = loc; }
+ if (this.options.ranges)
+ { node.range[1] = pos; }
+ return node
}
-function makeTest(test) {
- if (typeof test === "string")
- { return function (type) { return type === test; } }
- else if (!test)
- { return function () { return true; } }
+pp$6.finishNode = function(node, type) {
+ return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
+};
+
+// Finish node at given position
+
+pp$6.finishNodeAt = function(node, type, pos, loc) {
+ return finishNodeAt.call(this, node, type, pos, loc)
+};
+
+// The algorithm used to determine whether a regexp can appear at a
+// given point in the program is loosely based on sweet.js' approach.
+// See https://github.com/mozilla/sweet.js/wiki/design
+
+var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
+ this.token = token;
+ this.isExpr = !!isExpr;
+ this.preserveSpace = !!preserveSpace;
+ this.override = override;
+ this.generator = !!generator;
+};
+
+var types$1 = {
+ b_stat: new TokContext("{", false),
+ b_expr: new TokContext("{", true),
+ b_tmpl: new TokContext("${", false),
+ p_stat: new TokContext("(", false),
+ p_expr: new TokContext("(", true),
+ q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
+ f_stat: new TokContext("function", false),
+ f_expr: new TokContext("function", true),
+ f_expr_gen: new TokContext("function", true, false, null, true),
+ f_gen: new TokContext("function", false, false, null, true)
+};
+
+var pp$7 = Parser.prototype;
+
+pp$7.initialContext = function() {
+ return [types$1.b_stat]
+};
+
+pp$7.braceIsBlock = function(prevType) {
+ var parent = this.curContext();
+ if (parent === types$1.f_expr || parent === types$1.f_stat)
+ { return true }
+ if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr))
+ { return !parent.isExpr }
+
+ // The check for `tt.name && exprAllowed` detects whether we are
+ // after a `yield` or `of` construct. See the `updateContext` for
+ // `tt.name`.
+ if (prevType === types._return || prevType === types.name && this.exprAllowed)
+ { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
+ if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow)
+ { return true }
+ if (prevType === types.braceL)
+ { return parent === types$1.b_stat }
+ if (prevType === types._var || prevType === types.name)
+ { return false }
+ return !this.exprAllowed
+};
+
+pp$7.inGeneratorContext = function() {
+ var this$1 = this;
+
+ for (var i = this.context.length - 1; i >= 1; i--) {
+ var context = this$1.context[i];
+ if (context.token === "function")
+ { return context.generator }
+ }
+ return false
+};
+
+pp$7.updateContext = function(prevType) {
+ var update, type = this.type;
+ if (type.keyword && prevType === types.dot)
+ { this.exprAllowed = false; }
+ else if (update = type.updateContext)
+ { update.call(this, prevType); }
+ else
+ { this.exprAllowed = type.beforeExpr; }
+};
+
+// Token-specific context update code
+
+types.parenR.updateContext = types.braceR.updateContext = function() {
+ if (this.context.length === 1) {
+ this.exprAllowed = true;
+ return
+ }
+ var out = this.context.pop();
+ if (out === types$1.b_stat && this.curContext().token === "function") {
+ out = this.context.pop();
+ }
+ this.exprAllowed = !out.isExpr;
+};
+
+types.braceL.updateContext = function(prevType) {
+ this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr);
+ this.exprAllowed = true;
+};
+
+types.dollarBraceL.updateContext = function() {
+ this.context.push(types$1.b_tmpl);
+ this.exprAllowed = true;
+};
+
+types.parenL.updateContext = function(prevType) {
+ var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while;
+ this.context.push(statementParens ? types$1.p_stat : types$1.p_expr);
+ this.exprAllowed = true;
+};
+
+types.incDec.updateContext = function() {
+ // tokExprAllowed stays unchanged
+};
+
+types._function.updateContext = types._class.updateContext = function(prevType) {
+ if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else &&
+ !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat))
+ { this.context.push(types$1.f_expr); }
else
- { return test }
+ { this.context.push(types$1.f_stat); }
+ this.exprAllowed = false;
+};
+
+types.backQuote.updateContext = function() {
+ if (this.curContext() === types$1.q_tmpl)
+ { this.context.pop(); }
+ else
+ { this.context.push(types$1.q_tmpl); }
+ this.exprAllowed = false;
+};
+
+types.star.updateContext = function(prevType) {
+ if (prevType === types._function) {
+ var index = this.context.length - 1;
+ if (this.context[index] === types$1.f_expr)
+ { this.context[index] = types$1.f_expr_gen; }
+ else
+ { this.context[index] = types$1.f_gen; }
+ }
+ this.exprAllowed = true;
+};
+
+types.name.updateContext = function(prevType) {
+ var allowed = false;
+ if (this.options.ecmaVersion >= 6) {
+ if (this.value === "of" && !this.exprAllowed ||
+ this.value === "yield" && this.inGeneratorContext())
+ { allowed = true; }
+ }
+ this.exprAllowed = allowed;
+};
+
+var 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"
+ ]
+};
+Array.prototype.push.apply(data.$LONE, data.General_Category);
+data.gc = data.General_Category;
+data.sc = data.Script_Extensions = data.scx = data.Script;
+
+var pp$9 = Parser.prototype;
+
+var RegExpValidationState = function RegExpValidationState(parser) {
+ this.parser = parser;
+ this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "");
+ this.source = "";
+ this.flags = "";
+ this.start = 0;
+ this.switchU = false;
+ this.switchN = false;
+ this.pos = 0;
+ this.lastIntValue = 0;
+ this.lastStringValue = "";
+ this.lastAssertionIsQuantifiable = false;
+ this.numCapturingParens = 0;
+ this.maxBackReference = 0;
+ this.groupNames = [];
+ this.backReferenceNames = [];
+};
+
+RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
+ var unicode = flags.indexOf("u") !== -1;
+ this.start = start | 0;
+ this.source = pattern + "";
+ this.flags = flags;
+ this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
+ this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
+};
+
+RegExpValidationState.prototype.raise = function raise (message) {
+ this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
+};
+
+// If u flag is given, this returns the code point at the index (it combines a surrogate pair).
+// Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
+RegExpValidationState.prototype.at = function at (i) {
+ var s = this.source;
+ var l = s.length;
+ if (i >= l) {
+ return -1
+ }
+ var c = s.charCodeAt(i);
+ if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
+ return c
+ }
+ return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00
+};
+
+RegExpValidationState.prototype.nextIndex = function nextIndex (i) {
+ var s = this.source;
+ var l = s.length;
+ if (i >= l) {
+ return l
+ }
+ var c = s.charCodeAt(i);
+ if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
+ return i + 1
+ }
+ return i + 2
+};
+
+RegExpValidationState.prototype.current = function current () {
+ return this.at(this.pos)
+};
+
+RegExpValidationState.prototype.lookahead = function lookahead () {
+ return this.at(this.nextIndex(this.pos))
+};
+
+RegExpValidationState.prototype.advance = function advance () {
+ this.pos = this.nextIndex(this.pos);
+};
+
+RegExpValidationState.prototype.eat = function eat (ch) {
+ if (this.current() === ch) {
+ this.advance();
+ return true
+ }
+ return false
+};
+
+function codePointToString$1(ch) {
+ if (ch <= 0xFFFF) { return String.fromCharCode(ch) }
+ ch -= 0x10000;
+ return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00)
}
-var Found = function Found(node, state) { this.node = node; this.state = state; };
+/**
+ * Validate the flags part of a given RegExpLiteral.
+ *
+ * @param {RegExpValidationState} state The state to validate RegExp.
+ * @returns {void}
+ */
+pp$9.validateRegExpFlags = function(state) {
+ var this$1 = this;
+
+ var validFlags = state.validFlags;
+ var flags = state.flags;
+
+ for (var i = 0; i < flags.length; i++) {
+ var flag = flags.charAt(i);
+ if (validFlags.indexOf(flag) === -1) {
+ this$1.raise(state.start, "Invalid regular expression flag");
+ }
+ if (flags.indexOf(flag, i + 1) > -1) {
+ this$1.raise(state.start, "Duplicate regular expression flag");
+ }
+ }
+};
+
+/**
+ * Validate the pattern part of a given RegExpLiteral.
+ *
+ * @param {RegExpValidationState} state The state to validate RegExp.
+ * @returns {void}
+ */
+pp$9.validateRegExpPattern = function(state) {
+ this.regexp_pattern(state);
+
+ // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
+ // parsing contains a |GroupName|, reparse with the goal symbol
+ // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
+ // exception if _P_ did not conform to the grammar, if any elements of _P_
+ // were not matched by the parse, or if any Early Error conditions exist.
+ if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) {
+ state.switchN = true;
+ this.regexp_pattern(state);
+ }
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
+pp$9.regexp_pattern = function(state) {
+ state.pos = 0;
+ state.lastIntValue = 0;
+ state.lastStringValue = "";
+ state.lastAssertionIsQuantifiable = false;
+ state.numCapturingParens = 0;
+ state.maxBackReference = 0;
+ state.groupNames.length = 0;
+ state.backReferenceNames.length = 0;
-// A full walk triggers the callback on each node
-function full(node, callback, baseVisitor, state, override) {
- if (!baseVisitor) { baseVisitor = base
- ; }(function c(node, st, override) {
- var type = override || node.type;
- baseVisitor[type](node, st, c);
- if (!override) { callback(node, st, type); }
- })(node, state, override);
+ this.regexp_disjunction(state);
+
+ if (state.pos !== state.source.length) {
+ // Make the same messages as V8.
+ if (state.eat(0x29 /* ) */)) {
+ state.raise("Unmatched ')'");
+ }
+ if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) {
+ state.raise("Lone quantifier brackets");
+ }
+ }
+ if (state.maxBackReference > state.numCapturingParens) {
+ state.raise("Invalid escape");
+ }
+ for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
+ var name = list[i];
+
+ if (state.groupNames.indexOf(name) === -1) {
+ state.raise("Invalid named capture referenced");
+ }
+ }
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
+pp$9.regexp_disjunction = function(state) {
+ var this$1 = this;
+
+ this.regexp_alternative(state);
+ while (state.eat(0x7C /* | */)) {
+ this$1.regexp_alternative(state);
+ }
+
+ // Make the same message as V8.
+ if (this.regexp_eatQuantifier(state, true)) {
+ state.raise("Nothing to repeat");
+ }
+ if (state.eat(0x7B /* { */)) {
+ state.raise("Lone quantifier brackets");
+ }
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
+pp$9.regexp_alternative = function(state) {
+ while (state.pos < state.source.length && this.regexp_eatTerm(state))
+ { }
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
+pp$9.regexp_eatTerm = function(state) {
+ if (this.regexp_eatAssertion(state)) {
+ // Handle `QuantifiableAssertion Quantifier` alternative.
+ // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
+ // is a QuantifiableAssertion.
+ if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
+ // Make the same message as V8.
+ if (state.switchU) {
+ state.raise("Invalid quantifier");
+ }
+ }
+ return true
+ }
+
+ if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
+ this.regexp_eatQuantifier(state);
+ return true
+ }
+
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
+pp$9.regexp_eatAssertion = function(state) {
+ var start = state.pos;
+ state.lastAssertionIsQuantifiable = false;
+
+ // ^, $
+ if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
+ return true
+ }
+
+ // \b \B
+ if (state.eat(0x5C /* \ */)) {
+ if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
+ return true
+ }
+ state.pos = start;
+ }
+
+ // Lookahead / Lookbehind
+ if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
+ var lookbehind = false;
+ if (this.options.ecmaVersion >= 9) {
+ lookbehind = state.eat(0x3C /* < */);
+ }
+ if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
+ this.regexp_disjunction(state);
+ if (!state.eat(0x29 /* ) */)) {
+ state.raise("Unterminated group");
+ }
+ state.lastAssertionIsQuantifiable = !lookbehind;
+ return true
+ }
+ }
+
+ state.pos = start;
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
+pp$9.regexp_eatQuantifier = function(state, noError) {
+ if ( noError === void 0 ) noError = false;
+
+ if (this.regexp_eatQuantifierPrefix(state, noError)) {
+ state.eat(0x3F /* ? */);
+ return true
+ }
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
+pp$9.regexp_eatQuantifierPrefix = function(state, noError) {
+ return (
+ state.eat(0x2A /* * */) ||
+ state.eat(0x2B /* + */) ||
+ state.eat(0x3F /* ? */) ||
+ this.regexp_eatBracedQuantifier(state, noError)
+ )
+};
+pp$9.regexp_eatBracedQuantifier = function(state, noError) {
+ var start = state.pos;
+ if (state.eat(0x7B /* { */)) {
+ var min = 0, max = -1;
+ if (this.regexp_eatDecimalDigits(state)) {
+ min = state.lastIntValue;
+ if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
+ max = state.lastIntValue;
+ }
+ if (state.eat(0x7D /* } */)) {
+ // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
+ if (max !== -1 && max < min && !noError) {
+ state.raise("numbers out of order in {} quantifier");
+ }
+ return true
+ }
+ }
+ if (state.switchU && !noError) {
+ state.raise("Incomplete quantifier");
+ }
+ state.pos = start;
+ }
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
+pp$9.regexp_eatAtom = function(state) {
+ return (
+ this.regexp_eatPatternCharacters(state) ||
+ state.eat(0x2E /* . */) ||
+ this.regexp_eatReverseSolidusAtomEscape(state) ||
+ this.regexp_eatCharacterClass(state) ||
+ this.regexp_eatUncapturingGroup(state) ||
+ this.regexp_eatCapturingGroup(state)
+ )
+};
+pp$9.regexp_eatReverseSolidusAtomEscape = function(state) {
+ var start = state.pos;
+ if (state.eat(0x5C /* \ */)) {
+ if (this.regexp_eatAtomEscape(state)) {
+ return true
+ }
+ state.pos = start;
+ }
+ return false
+};
+pp$9.regexp_eatUncapturingGroup = function(state) {
+ var start = state.pos;
+ if (state.eat(0x28 /* ( */)) {
+ if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) {
+ this.regexp_disjunction(state);
+ if (state.eat(0x29 /* ) */)) {
+ return true
+ }
+ state.raise("Unterminated group");
+ }
+ state.pos = start;
+ }
+ return false
+};
+pp$9.regexp_eatCapturingGroup = function(state) {
+ if (state.eat(0x28 /* ( */)) {
+ if (this.options.ecmaVersion >= 9) {
+ this.regexp_groupSpecifier(state);
+ } else if (state.current() === 0x3F /* ? */) {
+ state.raise("Invalid group");
+ }
+ this.regexp_disjunction(state);
+ if (state.eat(0x29 /* ) */)) {
+ state.numCapturingParens += 1;
+ return true
+ }
+ state.raise("Unterminated group");
+ }
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
+pp$9.regexp_eatExtendedAtom = function(state) {
+ return (
+ state.eat(0x2E /* . */) ||
+ this.regexp_eatReverseSolidusAtomEscape(state) ||
+ this.regexp_eatCharacterClass(state) ||
+ this.regexp_eatUncapturingGroup(state) ||
+ this.regexp_eatCapturingGroup(state) ||
+ this.regexp_eatInvalidBracedQuantifier(state) ||
+ this.regexp_eatExtendedPatternCharacter(state)
+ )
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
+pp$9.regexp_eatInvalidBracedQuantifier = function(state) {
+ if (this.regexp_eatBracedQuantifier(state, true)) {
+ state.raise("Nothing to repeat");
+ }
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
+pp$9.regexp_eatSyntaxCharacter = function(state) {
+ var ch = state.current();
+ if (isSyntaxCharacter(ch)) {
+ state.lastIntValue = ch;
+ state.advance();
+ return true
+ }
+ return false
+};
+function isSyntaxCharacter(ch) {
+ return (
+ ch === 0x24 /* $ */ ||
+ ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
+ ch === 0x2E /* . */ ||
+ ch === 0x3F /* ? */ ||
+ ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
+ ch >= 0x7B /* { */ && ch <= 0x7D /* } */
+ )
}
-// An fullAncestor walk is like an ancestor walk, but triggers
-// the callback on each node
-function fullAncestor(node, callback, baseVisitor, state) {
- if (!baseVisitor) { baseVisitor = base; }
- var ancestors = [];(function c(node, st, override) {
- var type = override || node.type;
- var 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);
+// https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
+// But eat eager.
+pp$9.regexp_eatPatternCharacters = function(state) {
+ var start = state.pos;
+ var ch = 0;
+ while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
+ state.advance();
+ }
+ return state.pos !== start
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
+pp$9.regexp_eatExtendedPatternCharacter = function(state) {
+ var ch = state.current();
+ if (
+ ch !== -1 &&
+ ch !== 0x24 /* $ */ &&
+ !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
+ ch !== 0x2E /* . */ &&
+ ch !== 0x3F /* ? */ &&
+ ch !== 0x5B /* [ */ &&
+ ch !== 0x5E /* ^ */ &&
+ ch !== 0x7C /* | */
+ ) {
+ state.advance();
+ return true
+ }
+ return false
+};
+
+// GroupSpecifier[U] ::
+// [empty]
+// `?` GroupName[?U]
+pp$9.regexp_groupSpecifier = function(state) {
+ if (state.eat(0x3F /* ? */)) {
+ if (this.regexp_eatGroupName(state)) {
+ if (state.groupNames.indexOf(state.lastStringValue) !== -1) {
+ state.raise("Duplicate capture group name");
+ }
+ state.groupNames.push(state.lastStringValue);
+ return
+ }
+ state.raise("Invalid group");
+ }
+};
+
+// GroupName[U] ::
+// `<` RegExpIdentifierName[?U] `>`
+// Note: this updates `state.lastStringValue` property with the eaten name.
+pp$9.regexp_eatGroupName = function(state) {
+ state.lastStringValue = "";
+ if (state.eat(0x3C /* < */)) {
+ if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
+ return true
+ }
+ state.raise("Invalid capture group name");
+ }
+ return false
+};
+
+// RegExpIdentifierName[U] ::
+// RegExpIdentifierStart[?U]
+// RegExpIdentifierName[?U] RegExpIdentifierPart[?U]
+// Note: this updates `state.lastStringValue` property with the eaten name.
+pp$9.regexp_eatRegExpIdentifierName = function(state) {
+ state.lastStringValue = "";
+ if (this.regexp_eatRegExpIdentifierStart(state)) {
+ state.lastStringValue += codePointToString$1(state.lastIntValue);
+ while (this.regexp_eatRegExpIdentifierPart(state)) {
+ state.lastStringValue += codePointToString$1(state.lastIntValue);
+ }
+ return true
+ }
+ return false
+};
+
+// RegExpIdentifierStart[U] ::
+// UnicodeIDStart
+// `$`
+// `_`
+// `\` RegExpUnicodeEscapeSequence[?U]
+pp$9.regexp_eatRegExpIdentifierStart = function(state) {
+ var start = state.pos;
+ var ch = state.current();
+ state.advance();
+
+ if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
+ ch = state.lastIntValue;
+ }
+ if (isRegExpIdentifierStart(ch)) {
+ state.lastIntValue = ch;
+ return true
+ }
+
+ state.pos = start;
+ return false
+};
+function isRegExpIdentifierStart(ch) {
+ return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
}
-// 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.
-function findNodeAt(node, start, end, test, baseVisitor, state) {
- if (!baseVisitor) { baseVisitor = base; }
- test = makeTest(test);
- try {
- (function c(node, st, override) {
- var 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
+// RegExpIdentifierPart[U] ::
+// UnicodeIDContinue
+// `$`
+// `_`
+// `\` RegExpUnicodeEscapeSequence[?U]
+// <ZWNJ>
+// <ZWJ>
+pp$9.regexp_eatRegExpIdentifierPart = function(state) {
+ var start = state.pos;
+ var ch = state.current();
+ state.advance();
+
+ if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
+ ch = state.lastIntValue;
}
+ if (isRegExpIdentifierPart(ch)) {
+ state.lastIntValue = ch;
+ return true
+ }
+
+ state.pos = start;
+ return false
+};
+function isRegExpIdentifierPart(ch) {
+ return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
}
-// Find the innermost node of a given type that contains the given
-// position. Interface similar to findNodeAt.
-function findNodeAround(node, pos, test, baseVisitor, state) {
- test = makeTest(test);
- if (!baseVisitor) { baseVisitor = base; }
- try {
- (function c(node, st, override) {
- var 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
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
+pp$9.regexp_eatAtomEscape = function(state) {
+ if (
+ this.regexp_eatBackReference(state) ||
+ this.regexp_eatCharacterClassEscape(state) ||
+ this.regexp_eatCharacterEscape(state) ||
+ (state.switchN && this.regexp_eatKGroupName(state))
+ ) {
+ return true
+ }
+ if (state.switchU) {
+ // Make the same message as V8.
+ if (state.current() === 0x63 /* c */) {
+ state.raise("Invalid unicode escape");
+ }
+ state.raise("Invalid escape");
+ }
+ return false
+};
+pp$9.regexp_eatBackReference = function(state) {
+ var start = state.pos;
+ if (this.regexp_eatDecimalEscape(state)) {
+ var n = state.lastIntValue;
+ if (state.switchU) {
+ // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
+ if (n > state.maxBackReference) {
+ state.maxBackReference = n;
+ }
+ return true
+ }
+ if (n <= state.numCapturingParens) {
+ return true
+ }
+ state.pos = start;
+ }
+ return false
+};
+pp$9.regexp_eatKGroupName = function(state) {
+ if (state.eat(0x6B /* k */)) {
+ if (this.regexp_eatGroupName(state)) {
+ state.backReferenceNames.push(state.lastStringValue);
+ return true
+ }
+ state.raise("Invalid named reference");
+ }
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
+pp$9.regexp_eatCharacterEscape = function(state) {
+ return (
+ this.regexp_eatControlEscape(state) ||
+ this.regexp_eatCControlLetter(state) ||
+ this.regexp_eatZero(state) ||
+ this.regexp_eatHexEscapeSequence(state) ||
+ this.regexp_eatRegExpUnicodeEscapeSequence(state) ||
+ (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
+ this.regexp_eatIdentityEscape(state)
+ )
+};
+pp$9.regexp_eatCControlLetter = function(state) {
+ var start = state.pos;
+ if (state.eat(0x63 /* c */)) {
+ if (this.regexp_eatControlLetter(state)) {
+ return true
+ }
+ state.pos = start;
+ }
+ return false
+};
+pp$9.regexp_eatZero = function(state) {
+ if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
+ state.lastIntValue = 0;
+ state.advance();
+ return true
+ }
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
+pp$9.regexp_eatControlEscape = function(state) {
+ var ch = state.current();
+ if (ch === 0x74 /* t */) {
+ state.lastIntValue = 0x09; /* \t */
+ state.advance();
+ return true
+ }
+ if (ch === 0x6E /* n */) {
+ state.lastIntValue = 0x0A; /* \n */
+ state.advance();
+ return true
+ }
+ if (ch === 0x76 /* v */) {
+ state.lastIntValue = 0x0B; /* \v */
+ state.advance();
+ return true
+ }
+ if (ch === 0x66 /* f */) {
+ state.lastIntValue = 0x0C; /* \f */
+ state.advance();
+ return true
}
+ if (ch === 0x72 /* r */) {
+ state.lastIntValue = 0x0D; /* \r */
+ state.advance();
+ return true
+ }
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
+pp$9.regexp_eatControlLetter = function(state) {
+ var ch = state.current();
+ if (isControlLetter(ch)) {
+ state.lastIntValue = ch % 0x20;
+ state.advance();
+ return true
+ }
+ return false
+};
+function isControlLetter(ch) {
+ return (
+ (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
+ (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
+ )
}
-// Find the outermost matching node after a given position.
-function findNodeAfter(node, pos, test, baseVisitor, state) {
- test = makeTest(test);
- if (!baseVisitor) { baseVisitor = base; }
- try {
- (function c(node, st, override) {
- if (node.end < pos) { return }
- var 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
+// https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
+pp$9.regexp_eatRegExpUnicodeEscapeSequence = function(state) {
+ var start = state.pos;
+
+ if (state.eat(0x75 /* u */)) {
+ if (this.regexp_eatFixedHexDigits(state, 4)) {
+ var lead = state.lastIntValue;
+ if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) {
+ var leadSurrogateEnd = state.pos;
+ if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
+ var trail = state.lastIntValue;
+ if (trail >= 0xDC00 && trail <= 0xDFFF) {
+ state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
+ return true
+ }
+ }
+ state.pos = leadSurrogateEnd;
+ state.lastIntValue = lead;
+ }
+ return true
+ }
+ if (
+ state.switchU &&
+ state.eat(0x7B /* { */) &&
+ this.regexp_eatHexDigits(state) &&
+ state.eat(0x7D /* } */) &&
+ isValidUnicode(state.lastIntValue)
+ ) {
+ return true
+ }
+ if (state.switchU) {
+ state.raise("Invalid unicode escape");
+ }
+ state.pos = start;
}
+
+ return false
+};
+function isValidUnicode(ch) {
+ return ch >= 0 && ch <= 0x10FFFF
}
-// Find the outermost matching node before a given position.
-function findNodeBefore(node, pos, test, baseVisitor, state) {
- test = makeTest(test);
- if (!baseVisitor) { baseVisitor = base; }
- var max;(function c(node, st, override) {
- if (node.start > pos) { return }
- var 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
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
+pp$9.regexp_eatIdentityEscape = function(state) {
+ if (state.switchU) {
+ if (this.regexp_eatSyntaxCharacter(state)) {
+ return true
+ }
+ if (state.eat(0x2F /* / */)) {
+ state.lastIntValue = 0x2F; /* / */
+ return true
+ }
+ return false
+ }
+
+ var ch = state.current();
+ if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
+ state.lastIntValue = ch;
+ state.advance();
+ return true
+ }
+
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
+pp$9.regexp_eatDecimalEscape = function(state) {
+ state.lastIntValue = 0;
+ var ch = state.current();
+ if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
+ do {
+ state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
+ state.advance();
+ } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
+ return true
+ }
+ return false
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
+pp$9.regexp_eatCharacterClassEscape = function(state) {
+ var ch = state.current();
+
+ if (isCharacterClassEscape(ch)) {
+ state.lastIntValue = -1;
+ state.advance();
+ return true
+ }
+
+ if (
+ state.switchU &&
+ this.options.ecmaVersion >= 9 &&
+ (ch === 0x50 /* P */ || ch === 0x70 /* p */)
+ ) {
+ state.lastIntValue = -1;
+ state.advance();
+ if (
+ state.eat(0x7B /* { */) &&
+ this.regexp_eatUnicodePropertyValueExpression(state) &&
+ state.eat(0x7D /* } */)
+ ) {
+ return true
+ }
+ state.raise("Invalid property name");
+ }
+
+ return false
+};
+function isCharacterClassEscape(ch) {
+ return (
+ ch === 0x64 /* d */ ||
+ ch === 0x44 /* D */ ||
+ ch === 0x73 /* s */ ||
+ ch === 0x53 /* S */ ||
+ ch === 0x77 /* w */ ||
+ ch === 0x57 /* W */
+ )
}
-// Fallback to an Object.create polyfill for older environments.
-var create = Object.create || function(proto) {
- function Ctor() {}
- Ctor.prototype = proto;
- return new Ctor
+// UnicodePropertyValueExpression ::
+// UnicodePropertyName `=` UnicodePropertyValue
+// LoneUnicodePropertyNameOrValue
+pp$9.regexp_eatUnicodePropertyValueExpression = function(state) {
+ var start = state.pos;
+
+ // UnicodePropertyName `=` UnicodePropertyValue
+ if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
+ var name = state.lastStringValue;
+ if (this.regexp_eatUnicodePropertyValue(state)) {
+ var value = state.lastStringValue;
+ this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
+ return true
+ }
+ }
+ state.pos = start;
+
+ // LoneUnicodePropertyNameOrValue
+ if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
+ var nameOrValue = state.lastStringValue;
+ this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue);
+ return true
+ }
+ return false
+};
+pp$9.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
+ if (!data.hasOwnProperty(name) || data[name].indexOf(value) === -1) {
+ state.raise("Invalid property name");
+ }
+};
+pp$9.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
+ if (data.$LONE.indexOf(nameOrValue) === -1) {
+ state.raise("Invalid property name");
+ }
};
-// Used to create a custom walker. Will fill in all missing node
-// type properties with the defaults.
-function make(funcs, baseVisitor) {
- var visitor = create(baseVisitor || base);
- for (var type in funcs) { visitor[type] = funcs[type]; }
- return visitor
+// UnicodePropertyName ::
+// UnicodePropertyNameCharacters
+pp$9.regexp_eatUnicodePropertyName = function(state) {
+ var ch = 0;
+ state.lastStringValue = "";
+ while (isUnicodePropertyNameCharacter(ch = state.current())) {
+ state.lastStringValue += codePointToString$1(ch);
+ state.advance();
+ }
+ return state.lastStringValue !== ""
+};
+function isUnicodePropertyNameCharacter(ch) {
+ return isControlLetter(ch) || ch === 0x5F /* _ */
}
-function skipThrough(node, st, c) { c(node, st); }
-function ignore(_node, _st, _c) {}
+// UnicodePropertyValue ::
+// UnicodePropertyValueCharacters
+pp$9.regexp_eatUnicodePropertyValue = function(state) {
+ var ch = 0;
+ state.lastStringValue = "";
+ while (isUnicodePropertyValueCharacter(ch = state.current())) {
+ state.lastStringValue += codePointToString$1(ch);
+ state.advance();
+ }
+ return state.lastStringValue !== ""
+};
+function isUnicodePropertyValueCharacter(ch) {
+ return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
+}
+
+// LoneUnicodePropertyNameOrValue ::
+// UnicodePropertyValueCharacters
+pp$9.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
+ return this.regexp_eatUnicodePropertyValue(state)
+};
-// Node walkers.
+// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
+pp$9.regexp_eatCharacterClass = function(state) {
+ if (state.eat(0x5B /* [ */)) {
+ state.eat(0x5E /* ^ */);
+ this.regexp_classRanges(state);
+ if (state.eat(0x5D /* [ */)) {
+ return true
+ }
+ // Unreachable since it threw "unterminated regular expression" error before.
+ state.raise("Unterminated character class");
+ }
+ return false
+};
-var base = {};
+// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
+// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
+// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
+pp$9.regexp_classRanges = function(state) {
+ var this$1 = this;
-base.Program = base.BlockStatement = function (node, st, c) {
- for (var i = 0, list = node.body; i < list.length; i += 1)
- {
- var stmt = list[i];
+ while (this.regexp_eatClassAtom(state)) {
+ var left = state.lastIntValue;
+ if (state.eat(0x2D /* - */) && this$1.regexp_eatClassAtom(state)) {
+ var right = state.lastIntValue;
+ if (state.switchU && (left === -1 || right === -1)) {
+ state.raise("Invalid character class");
+ }
+ if (left !== -1 && right !== -1 && left > right) {
+ state.raise("Range out of order in character class");
+ }
+ }
+ }
+};
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
+// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
+pp$9.regexp_eatClassAtom = function(state) {
+ var start = state.pos;
+
+ if (state.eat(0x5C /* \ */)) {
+ if (this.regexp_eatClassEscape(state)) {
+ return true
+ }
+ if (state.switchU) {
+ // Make the same message as V8.
+ var ch$1 = state.current();
+ if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
+ state.raise("Invalid class escape");
+ }
+ state.raise("Invalid escape");
+ }
+ state.pos = start;
+ }
- c(stmt, st, "Statement");
+ var ch = state.current();
+ if (ch !== 0x5D /* [ */) {
+ state.lastIntValue = ch;
+ state.advance();
+ return true
}
+
+ return false
};
-base.Statement = skipThrough;
-base.EmptyStatement = ignore;
-base.ExpressionStatement = base.ParenthesizedExpression =
- function (node, st, c) { return c(node.expression, st, "Expression"); };
-base.IfStatement = function (node, st, c) {
- c(node.test, st, "Expression");
- c(node.consequent, st, "Statement");
- if (node.alternate) { c(node.alternate, st, "Statement"); }
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
+pp$9.regexp_eatClassEscape = function(state) {
+ var start = state.pos;
+
+ if (state.eat(0x62 /* b */)) {
+ state.lastIntValue = 0x08; /* <BS> */
+ return true
+ }
+
+ if (state.switchU && state.eat(0x2D /* - */)) {
+ state.lastIntValue = 0x2D; /* - */
+ return true
+ }
+
+ if (!state.switchU && state.eat(0x63 /* c */)) {
+ if (this.regexp_eatClassControlLetter(state)) {
+ return true
+ }
+ state.pos = start;
+ }
+
+ return (
+ this.regexp_eatCharacterClassEscape(state) ||
+ this.regexp_eatCharacterEscape(state)
+ )
};
-base.LabeledStatement = function (node, st, c) { return c(node.body, st, "Statement"); };
-base.BreakStatement = base.ContinueStatement = ignore;
-base.WithStatement = function (node, st, c) {
- c(node.object, st, "Expression");
- c(node.body, st, "Statement");
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
+pp$9.regexp_eatClassControlLetter = function(state) {
+ var ch = state.current();
+ if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
+ state.lastIntValue = ch % 0x20;
+ state.advance();
+ return true
+ }
+ return false
};
-base.SwitchStatement = function (node, st, c) {
- c(node.discriminant, st, "Expression");
- for (var i = 0, list = node.cases; i < list.length; i += 1) {
- var cs = list[i];
- if (cs.test) { c(cs.test, st, "Expression"); }
- for (var i$1 = 0, list$1 = cs.consequent; i$1 < list$1.length; i$1 += 1)
- {
- var cons = list$1[i$1];
+// https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
+pp$9.regexp_eatHexEscapeSequence = function(state) {
+ var start = state.pos;
+ if (state.eat(0x78 /* x */)) {
+ if (this.regexp_eatFixedHexDigits(state, 2)) {
+ return true
+ }
+ if (state.switchU) {
+ state.raise("Invalid escape");
+ }
+ state.pos = start;
+ }
+ return false
+};
- c(cons, st, "Statement");
+// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
+pp$9.regexp_eatDecimalDigits = function(state) {
+ var start = state.pos;
+ var ch = 0;
+ state.lastIntValue = 0;
+ while (isDecimalDigit(ch = state.current())) {
+ state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
+ state.advance();
+ }
+ return state.pos !== start
+};
+function isDecimalDigit(ch) {
+ return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
+}
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
+pp$9.regexp_eatHexDigits = function(state) {
+ var start = state.pos;
+ var ch = 0;
+ state.lastIntValue = 0;
+ while (isHexDigit(ch = state.current())) {
+ state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
+ state.advance();
+ }
+ return state.pos !== start
+};
+function isHexDigit(ch) {
+ return (
+ (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
+ (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
+ (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
+ )
+}
+function hexToInt(ch) {
+ if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
+ return 10 + (ch - 0x41 /* A */)
+ }
+ if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
+ return 10 + (ch - 0x61 /* a */)
+ }
+ return ch - 0x30 /* 0 */
+}
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
+// Allows only 0-377(octal) i.e. 0-255(decimal).
+pp$9.regexp_eatLegacyOctalEscapeSequence = function(state) {
+ if (this.regexp_eatOctalDigit(state)) {
+ var n1 = state.lastIntValue;
+ if (this.regexp_eatOctalDigit(state)) {
+ var n2 = state.lastIntValue;
+ if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
+ state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
+ } else {
+ state.lastIntValue = n1 * 8 + n2;
+ }
+ } else {
+ state.lastIntValue = n1;
}
+ return true
}
+ return false
};
-base.SwitchCase = function (node, st, c) {
- if (node.test) { c(node.test, st, "Expression"); }
- for (var i = 0, list = node.consequent; i < list.length; i += 1)
- {
- var cons = list[i];
- c(cons, st, "Statement");
+// https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
+pp$9.regexp_eatOctalDigit = function(state) {
+ var ch = state.current();
+ if (isOctalDigit(ch)) {
+ state.lastIntValue = ch - 0x30; /* 0 */
+ state.advance();
+ return true
}
+ state.lastIntValue = 0;
+ return false
};
-base.ReturnStatement = base.YieldExpression = base.AwaitExpression = function (node, st, c) {
- if (node.argument) { c(node.argument, st, "Expression"); }
+function isOctalDigit(ch) {
+ return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
+}
+
+// https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
+// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
+// And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
+pp$9.regexp_eatFixedHexDigits = function(state, length) {
+ var start = state.pos;
+ state.lastIntValue = 0;
+ for (var i = 0; i < length; ++i) {
+ var ch = state.current();
+ if (!isHexDigit(ch)) {
+ state.pos = start;
+ return false
+ }
+ state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
+ state.advance();
+ }
+ return true
};
-base.ThrowStatement = base.SpreadElement =
- function (node, st, c) { return c(node.argument, st, "Expression"); };
-base.TryStatement = function (node, st, c) {
- c(node.block, st, "Statement");
- if (node.handler) { c(node.handler, st); }
- if (node.finalizer) { c(node.finalizer, st, "Statement"); }
+
+// Object type used to represent tokens. Note that normally, tokens
+// simply exist as properties on the parser object. This is only
+// used for the onToken callback and the external tokenizer.
+
+var Token = function Token(p) {
+ this.type = p.type;
+ this.value = p.value;
+ this.start = p.start;
+ this.end = p.end;
+ if (p.options.locations)
+ { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
+ if (p.options.ranges)
+ { this.range = [p.start, p.end]; }
};
-base.CatchClause = function (node, st, c) {
- if (node.param) { c(node.param, st, "Pattern"); }
- c(node.body, st, "ScopeBody");
+
+// ## Tokenizer
+
+var pp$8 = Parser.prototype;
+
+// Move to the next token
+
+pp$8.next = function() {
+ if (this.options.onToken)
+ { this.options.onToken(new Token(this)); }
+
+ this.lastTokEnd = this.end;
+ this.lastTokStart = this.start;
+ this.lastTokEndLoc = this.endLoc;
+ this.lastTokStartLoc = this.startLoc;
+ this.nextToken();
};
-base.WhileStatement = base.DoWhileStatement = function (node, st, c) {
- c(node.test, st, "Expression");
- c(node.body, st, "Statement");
+
+pp$8.getToken = function() {
+ this.next();
+ return new Token(this)
};
-base.ForStatement = function (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");
+
+// If we're in an ES6 environment, make parsers iterable
+if (typeof Symbol !== "undefined")
+ { pp$8[Symbol.iterator] = function() {
+ var this$1 = this;
+
+ return {
+ next: function () {
+ var token = this$1.getToken();
+ return {
+ done: token.type === types.eof,
+ value: token
+ }
+ }
+ }
+ }; }
+
+// Toggle strict mode. Re-reads the next number or string to please
+// pedantic tests (`"use strict"; 010;` should fail).
+
+pp$8.curContext = function() {
+ return this.context[this.context.length - 1]
};
-base.ForInStatement = base.ForOfStatement = function (node, st, c) {
- c(node.left, st, "ForInit");
- c(node.right, st, "Expression");
- c(node.body, st, "Statement");
+
+// Read a single token, updating the parser object's token-related
+// properties.
+
+pp$8.nextToken = function() {
+ var curContext = this.curContext();
+ if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }
+
+ this.start = this.pos;
+ if (this.options.locations) { this.startLoc = this.curPosition(); }
+ if (this.pos >= this.input.length) { return this.finishToken(types.eof) }
+
+ if (curContext.override) { return curContext.override(this) }
+ else { this.readToken(this.fullCharCodeAtPos()); }
};
-base.ForInit = function (node, st, c) {
- if (node.type === "VariableDeclaration") { c(node, st); }
- else { c(node, st, "Expression"); }
+
+pp$8.readToken = function(code) {
+ // Identifier or keyword. '\uXXXX' sequences are allowed in
+ // identifiers, so '\' also dispatches to that.
+ if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
+ { return this.readWord() }
+
+ return this.getTokenFromCode(code)
};
-base.DebuggerStatement = ignore;
-base.FunctionDeclaration = function (node, st, c) { return c(node, st, "Function"); };
-base.VariableDeclaration = function (node, st, c) {
- for (var i = 0, list = node.declarations; i < list.length; i += 1)
- {
- var decl = list[i];
+pp$8.fullCharCodeAtPos = function() {
+ var code = this.input.charCodeAt(this.pos);
+ if (code <= 0xd7ff || code >= 0xe000) { return code }
+ var next = this.input.charCodeAt(this.pos + 1);
+ return (code << 10) + next - 0x35fdc00
+};
- c(decl, st);
+pp$8.skipBlockComment = function() {
+ var this$1 = this;
+
+ var startLoc = this.options.onComment && this.curPosition();
+ var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
+ if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
+ this.pos = end + 2;
+ if (this.options.locations) {
+ lineBreakG.lastIndex = start;
+ var match;
+ while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
+ ++this$1.curLine;
+ this$1.lineStart = match.index + match[0].length;
+ }
}
+ if (this.options.onComment)
+ { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
+ startLoc, this.curPosition()); }
};
-base.VariableDeclarator = function (node, st, c) {
- c(node.id, st, "Pattern");
- if (node.init) { c(node.init, st, "Expression"); }
+
+pp$8.skipLineComment = function(startSkip) {
+ var this$1 = this;
+
+ var start = this.pos;
+ var startLoc = this.options.onComment && this.curPosition();
+ var ch = this.input.charCodeAt(this.pos += startSkip);
+ while (this.pos < this.input.length && !isNewLine(ch)) {
+ ch = this$1.input.charCodeAt(++this$1.pos);
+ }
+ if (this.options.onComment)
+ { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
+ startLoc, this.curPosition()); }
};
-base.Function = function (node, st, c) {
- if (node.id) { c(node.id, st, "Pattern"); }
- for (var i = 0, list = node.params; i < list.length; i += 1)
- {
- var param = list[i];
+// Called at the start of the parse and after every token. Skips
+// whitespace and comments, and.
- c(param, st, "Pattern");
+pp$8.skipSpace = function() {
+ var this$1 = this;
+
+ loop: while (this.pos < this.input.length) {
+ var ch = this$1.input.charCodeAt(this$1.pos);
+ switch (ch) {
+ case 32: case 160: // ' '
+ ++this$1.pos;
+ break
+ case 13:
+ if (this$1.input.charCodeAt(this$1.pos + 1) === 10) {
+ ++this$1.pos;
+ }
+ case 10: case 8232: case 8233:
+ ++this$1.pos;
+ if (this$1.options.locations) {
+ ++this$1.curLine;
+ this$1.lineStart = this$1.pos;
+ }
+ break
+ case 47: // '/'
+ switch (this$1.input.charCodeAt(this$1.pos + 1)) {
+ case 42: // '*'
+ this$1.skipBlockComment();
+ break
+ case 47:
+ this$1.skipLineComment(2);
+ break
+ default:
+ break loop
+ }
+ break
+ default:
+ if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
+ ++this$1.pos;
+ } else {
+ break loop
+ }
+ }
}
- 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 = function (node, st, c) { return c(node, st, "Statement"); };
-base.ScopeExpression = function (node, st, c) { return c(node, st, "Expression"); };
-base.Pattern = function (node, st, c) {
- if (node.type === "Identifier")
- { c(node, st, "VariablePattern"); }
- else if (node.type === "MemberExpression")
- { c(node, st, "MemberPattern"); }
- else
- { c(node, st); }
+// Called at the end of every token. Sets `end`, `val`, and
+// maintains `context` and `exprAllowed`, and skips the space after
+// the token, so that the next one's `start` will point at the
+// right position.
+
+pp$8.finishToken = function(type, val) {
+ this.end = this.pos;
+ if (this.options.locations) { this.endLoc = this.curPosition(); }
+ var prevType = this.type;
+ this.type = type;
+ this.value = val;
+
+ this.updateContext(prevType);
};
-base.VariablePattern = ignore;
-base.MemberPattern = skipThrough;
-base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); };
-base.ArrayPattern = function (node, st, c) {
- for (var i = 0, list = node.elements; i < list.length; i += 1) {
- var elt = list[i];
- if (elt) { c(elt, st, "Pattern"); }
+// ### Token reading
+
+// This is the function that is called to fetch the next token. It
+// is somewhat obscure, because it works in character codes rather
+// than characters, and because operator parsing has been inlined
+// into it.
+//
+// All in the name of speed.
+//
+pp$8.readToken_dot = function() {
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next >= 48 && next <= 57) { return this.readNumber(true) }
+ var next2 = this.input.charCodeAt(this.pos + 2);
+ if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
+ this.pos += 3;
+ return this.finishToken(types.ellipsis)
+ } else {
+ ++this.pos;
+ return this.finishToken(types.dot)
}
};
-base.ObjectPattern = function (node, st, c) {
- for (var i = 0, list = node.properties; i < list.length; i += 1) {
- var prop = list[i];
- 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");
+pp$8.readToken_slash = function() { // '/'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
+ if (next === 61) { return this.finishOp(types.assign, 2) }
+ return this.finishOp(types.slash, 1)
+};
+
+pp$8.readToken_mult_modulo_exp = function(code) { // '%*'
+ var next = this.input.charCodeAt(this.pos + 1);
+ var size = 1;
+ var tokentype = code === 42 ? types.star : types.modulo;
+
+ // exponentiation operator ** and **=
+ if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
+ ++size;
+ tokentype = types.starstar;
+ next = this.input.charCodeAt(this.pos + 2);
+ }
+
+ if (next === 61) { return this.finishOp(types.assign, size + 1) }
+ return this.finishOp(tokentype, size)
+};
+
+pp$8.readToken_pipe_amp = function(code) { // '|&'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) }
+ if (next === 61) { return this.finishOp(types.assign, 2) }
+ return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1)
+};
+
+pp$8.readToken_caret = function() { // '^'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next === 61) { return this.finishOp(types.assign, 2) }
+ return this.finishOp(types.bitwiseXOR, 1)
+};
+
+pp$8.readToken_plus_min = function(code) { // '+-'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next === code) {
+ if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 &&
+ (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
+ // A `-->` line comment
+ this.skipLineComment(3);
+ this.skipSpace();
+ return this.nextToken()
}
+ return this.finishOp(types.incDec, 2)
}
+ if (next === 61) { return this.finishOp(types.assign, 2) }
+ return this.finishOp(types.plusMin, 1)
};
-base.Expression = skipThrough;
-base.ThisExpression = base.Super = base.MetaProperty = ignore;
-base.ArrayExpression = function (node, st, c) {
- for (var i = 0, list = node.elements; i < list.length; i += 1) {
- var elt = list[i];
+pp$8.readToken_lt_gt = function(code) { // '<>'
+ var next = this.input.charCodeAt(this.pos + 1);
+ var size = 1;
+ if (next === code) {
+ size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
+ if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
+ return this.finishOp(types.bitShift, size)
+ }
+ if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
+ this.input.charCodeAt(this.pos + 3) === 45) {
+ // `<!--`, an XML-style comment that should be interpreted as a line comment
+ this.skipLineComment(4);
+ this.skipSpace();
+ return this.nextToken()
+ }
+ if (next === 61) { size = 2; }
+ return this.finishOp(types.relational, size)
+};
- if (elt) { c(elt, st, "Expression"); }
+pp$8.readToken_eq_excl = function(code) { // '=!'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
+ if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
+ this.pos += 2;
+ return this.finishToken(types.arrow)
}
+ return this.finishOp(code === 61 ? types.eq : types.prefix, 1)
};
-base.ObjectExpression = function (node, st, c) {
- for (var i = 0, list = node.properties; i < list.length; i += 1)
- {
- var prop = list[i];
- c(prop, st);
+pp$8.getTokenFromCode = function(code) {
+ switch (code) {
+ // The interpretation of a dot depends on whether it is followed
+ // by a digit or another two dots.
+ case 46: // '.'
+ return this.readToken_dot()
+
+ // Punctuation tokens.
+ case 40: ++this.pos; return this.finishToken(types.parenL)
+ case 41: ++this.pos; return this.finishToken(types.parenR)
+ case 59: ++this.pos; return this.finishToken(types.semi)
+ case 44: ++this.pos; return this.finishToken(types.comma)
+ case 91: ++this.pos; return this.finishToken(types.bracketL)
+ case 93: ++this.pos; return this.finishToken(types.bracketR)
+ case 123: ++this.pos; return this.finishToken(types.braceL)
+ case 125: ++this.pos; return this.finishToken(types.braceR)
+ case 58: ++this.pos; return this.finishToken(types.colon)
+ case 63: ++this.pos; return this.finishToken(types.question)
+
+ case 96: // '`'
+ if (this.options.ecmaVersion < 6) { break }
+ ++this.pos;
+ return this.finishToken(types.backQuote)
+
+ case 48: // '0'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
+ if (this.options.ecmaVersion >= 6) {
+ if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
+ if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
+ }
+
+ // Anything else beginning with a digit is an integer, octal
+ // number, or float.
+ case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
+ return this.readNumber(false)
+
+ // Quotes produce strings.
+ case 34: case 39: // '"', "'"
+ return this.readString(code)
+
+ // Operators are parsed inline in tiny state machines. '=' (61) is
+ // often referred to. `finishOp` simply skips the amount of
+ // characters it is given as second argument, and returns a token
+ // of the type given by its first argument.
+
+ case 47: // '/'
+ return this.readToken_slash()
+
+ case 37: case 42: // '%*'
+ return this.readToken_mult_modulo_exp(code)
+
+ case 124: case 38: // '|&'
+ return this.readToken_pipe_amp(code)
+
+ case 94: // '^'
+ return this.readToken_caret()
+
+ case 43: case 45: // '+-'
+ return this.readToken_plus_min(code)
+
+ case 60: case 62: // '<>'
+ return this.readToken_lt_gt(code)
+
+ case 61: case 33: // '=!'
+ return this.readToken_eq_excl(code)
+
+ case 126: // '~'
+ return this.finishOp(types.prefix, 1)
}
+
+ this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
};
-base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration;
-base.SequenceExpression = base.TemplateLiteral = function (node, st, c) {
- for (var i = 0, list = node.expressions; i < list.length; i += 1)
- {
- var expr = list[i];
- c(expr, st, "Expression");
+pp$8.finishOp = function(type, size) {
+ var str = this.input.slice(this.pos, this.pos + size);
+ this.pos += size;
+ return this.finishToken(type, str)
+};
+
+pp$8.readRegexp = function() {
+ var this$1 = this;
+
+ var escaped, inClass, start = this.pos;
+ for (;;) {
+ if (this$1.pos >= this$1.input.length) { this$1.raise(start, "Unterminated regular expression"); }
+ var ch = this$1.input.charAt(this$1.pos);
+ if (lineBreak.test(ch)) { this$1.raise(start, "Unterminated regular expression"); }
+ if (!escaped) {
+ if (ch === "[") { inClass = true; }
+ else if (ch === "]" && inClass) { inClass = false; }
+ else if (ch === "/" && !inClass) { break }
+ escaped = ch === "\\";
+ } else { escaped = false; }
+ ++this$1.pos;
+ }
+ var pattern = this.input.slice(start, this.pos);
+ ++this.pos;
+ var flagsStart = this.pos;
+ var flags = this.readWord1();
+ if (this.containsEsc) { this.unexpected(flagsStart); }
+
+ // Validate pattern
+ var state = this.regexpState || (this.regexpState = new RegExpValidationState(this));
+ state.reset(start, pattern, flags);
+ this.validateRegExpFlags(state);
+ this.validateRegExpPattern(state);
+
+ // Create Literal#value property value.
+ var value = null;
+ try {
+ value = new RegExp(pattern, flags);
+ } catch (e) {
+ // ESTree requires null if it failed to instantiate RegExp object.
+ // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
}
+
+ return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value})
};
-base.UnaryExpression = base.UpdateExpression = function (node, st, c) {
- c(node.argument, st, "Expression");
+
+// Read an integer in the given radix. Return null if zero digits
+// were read, the integer value otherwise. When `len` is given, this
+// will return `null` unless the integer has exactly `len` digits.
+
+pp$8.readInt = function(radix, len) {
+ var this$1 = this;
+
+ var start = this.pos, total = 0;
+ for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
+ var code = this$1.input.charCodeAt(this$1.pos), val = (void 0);
+ if (code >= 97) { val = code - 97 + 10; } // a
+ else if (code >= 65) { val = code - 65 + 10; } // A
+ else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
+ else { val = Infinity; }
+ if (val >= radix) { break }
+ ++this$1.pos;
+ total = total * radix + val;
+ }
+ if (this.pos === start || len != null && this.pos - start !== len) { return null }
+
+ return total
};
-base.BinaryExpression = base.LogicalExpression = function (node, st, c) {
- c(node.left, st, "Expression");
- c(node.right, st, "Expression");
+
+pp$8.readRadixNumber = function(radix) {
+ this.pos += 2; // 0x
+ var 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"); }
+ return this.finishToken(types.num, val)
};
-base.AssignmentExpression = base.AssignmentPattern = function (node, st, c) {
- c(node.left, st, "Pattern");
- c(node.right, st, "Expression");
+
+// Read an integer, octal integer, or floating-point number.
+
+pp$8.readNumber = function(startsWithDot) {
+ var start = this.pos;
+ if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); }
+ var 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; }
+ var next = this.input.charCodeAt(this.pos);
+ if (next === 46 && !octal) { // '.'
+ ++this.pos;
+ this.readInt(10);
+ next = this.input.charCodeAt(this.pos);
+ }
+ if ((next === 69 || next === 101) && !octal) { // 'eE'
+ next = this.input.charCodeAt(++this.pos);
+ if (next === 43 || next === 45) { ++this.pos; } // '+-'
+ if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
+ }
+ if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
+
+ var str = this.input.slice(start, this.pos);
+ var val = octal ? parseInt(str, 8) : parseFloat(str);
+ return this.finishToken(types.num, val)
};
-base.ConditionalExpression = function (node, st, c) {
- c(node.test, st, "Expression");
- c(node.consequent, st, "Expression");
- c(node.alternate, st, "Expression");
+
+// Read a string value, interpreting backslash-escapes.
+
+pp$8.readCodePoint = function() {
+ var ch = this.input.charCodeAt(this.pos), code;
+
+ if (ch === 123) { // '{'
+ if (this.options.ecmaVersion < 6) { this.unexpected(); }
+ var codePos = ++this.pos;
+ code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
+ ++this.pos;
+ if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
+ } else {
+ code = this.readHexChar(4);
+ }
+ return code
};
-base.NewExpression = base.CallExpression = function (node, st, c) {
- c(node.callee, st, "Expression");
- if (node.arguments)
- { for (var i = 0, list = node.arguments; i < list.length; i += 1)
- {
- var arg = list[i];
- c(arg, st, "Expression");
- } }
+function codePointToString(code) {
+ // UTF-16 Decoding
+ if (code <= 0xFFFF) { return String.fromCharCode(code) }
+ code -= 0x10000;
+ return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
+}
+
+pp$8.readString = function(quote) {
+ var this$1 = this;
+
+ var out = "", chunkStart = ++this.pos;
+ for (;;) {
+ if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated string constant"); }
+ var ch = this$1.input.charCodeAt(this$1.pos);
+ if (ch === quote) { break }
+ if (ch === 92) { // '\'
+ out += this$1.input.slice(chunkStart, this$1.pos);
+ out += this$1.readEscapedChar(false);
+ chunkStart = this$1.pos;
+ } else {
+ if (isNewLine(ch, this$1.options.ecmaVersion >= 10)) { this$1.raise(this$1.start, "Unterminated string constant"); }
+ ++this$1.pos;
+ }
+ }
+ out += this.input.slice(chunkStart, this.pos++);
+ return this.finishToken(types.string, out)
};
-base.MemberExpression = function (node, st, c) {
- c(node.object, st, "Expression");
- if (node.computed) { c(node.property, st, "Expression"); }
+
+// Reads template string tokens.
+
+var INVALID_TEMPLATE_ESCAPE_ERROR = {};
+
+pp$8.tryReadTemplateToken = function() {
+ this.inTemplateElement = true;
+ try {
+ this.readTmplToken();
+ } catch (err) {
+ if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
+ this.readInvalidTemplateToken();
+ } else {
+ throw err
+ }
+ }
+
+ this.inTemplateElement = false;
};
-base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (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"); }
+
+pp$8.invalidStringToken = function(position, message) {
+ if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
+ throw INVALID_TEMPLATE_ESCAPE_ERROR
+ } else {
+ this.raise(position, message);
+ }
};
-base.ExportAllDeclaration = function (node, st, c) {
- c(node.source, st, "Expression");
+
+pp$8.readTmplToken = function() {
+ var this$1 = this;
+
+ var out = "", chunkStart = this.pos;
+ for (;;) {
+ if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated template"); }
+ var ch = this$1.input.charCodeAt(this$1.pos);
+ if (ch === 96 || ch === 36 && this$1.input.charCodeAt(this$1.pos + 1) === 123) { // '`', '${'
+ if (this$1.pos === this$1.start && (this$1.type === types.template || this$1.type === types.invalidTemplate)) {
+ if (ch === 36) {
+ this$1.pos += 2;
+ return this$1.finishToken(types.dollarBraceL)
+ } else {
+ ++this$1.pos;
+ return this$1.finishToken(types.backQuote)
+ }
+ }
+ out += this$1.input.slice(chunkStart, this$1.pos);
+ return this$1.finishToken(types.template, out)
+ }
+ if (ch === 92) { // '\'
+ out += this$1.input.slice(chunkStart, this$1.pos);
+ out += this$1.readEscapedChar(true);
+ chunkStart = this$1.pos;
+ } else if (isNewLine(ch)) {
+ out += this$1.input.slice(chunkStart, this$1.pos);
+ ++this$1.pos;
+ switch (ch) {
+ case 13:
+ if (this$1.input.charCodeAt(this$1.pos) === 10) { ++this$1.pos; }
+ case 10:
+ out += "\n";
+ break
+ default:
+ out += String.fromCharCode(ch);
+ break
+ }
+ if (this$1.options.locations) {
+ ++this$1.curLine;
+ this$1.lineStart = this$1.pos;
+ }
+ chunkStart = this$1.pos;
+ } else {
+ ++this$1.pos;
+ }
+ }
};
-base.ImportDeclaration = function (node, st, c) {
- for (var i = 0, list = node.specifiers; i < list.length; i += 1)
- {
- var spec = list[i];
- c(spec, st);
+// Reads a template token to search for the end, without validating any escape sequences
+pp$8.readInvalidTemplateToken = function() {
+ var this$1 = this;
+
+ for (; this.pos < this.input.length; this.pos++) {
+ switch (this$1.input[this$1.pos]) {
+ case "\\":
+ ++this$1.pos;
+ break
+
+ case "$":
+ if (this$1.input[this$1.pos + 1] !== "{") {
+ break
+ }
+ // falls through
+
+ case "`":
+ return this$1.finishToken(types.invalidTemplate, this$1.input.slice(this$1.start, this$1.pos))
+
+ // no default
+ }
}
- c(node.source, st, "Expression");
+ this.raise(this.start, "Unterminated template");
};
-base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.Literal = ignore;
-base.TaggedTemplateExpression = function (node, st, c) {
- c(node.tag, st, "Expression");
- c(node.quasi, st, "Expression");
+// Used to read escaped characters
+
+pp$8.readEscapedChar = function(inTemplate) {
+ var ch = this.input.charCodeAt(++this.pos);
+ ++this.pos;
+ switch (ch) {
+ case 110: return "\n" // 'n' -> '\n'
+ case 114: return "\r" // 'r' -> '\r'
+ case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
+ case 117: return codePointToString(this.readCodePoint()) // 'u'
+ case 116: return "\t" // 't' -> '\t'
+ case 98: return "\b" // 'b' -> '\b'
+ case 118: return "\u000b" // 'v' -> '\u000b'
+ case 102: return "\f" // 'f' -> '\f'
+ case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
+ case 10: // ' \n'
+ if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
+ return ""
+ default:
+ if (ch >= 48 && ch <= 55) {
+ var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
+ var octal = parseInt(octalStr, 8);
+ if (octal > 255) {
+ octalStr = octalStr.slice(0, -1);
+ octal = parseInt(octalStr, 8);
+ }
+ this.pos += octalStr.length - 1;
+ ch = this.input.charCodeAt(this.pos);
+ if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
+ this.invalidStringToken(
+ this.pos - 1 - octalStr.length,
+ inTemplate
+ ? "Octal literal in template string"
+ : "Octal literal in strict mode"
+ );
+ }
+ return String.fromCharCode(octal)
+ }
+ return String.fromCharCode(ch)
+ }
};
-base.ClassDeclaration = base.ClassExpression = function (node, st, c) { return c(node, st, "Class"); };
-base.Class = function (node, st, c) {
- if (node.id) { c(node.id, st, "Pattern"); }
- if (node.superClass) { c(node.superClass, st, "Expression"); }
- c(node.body, st);
+
+// Used to read character escape sequences ('\x', '\u', '\U').
+
+pp$8.readHexChar = function(len) {
+ var codePos = this.pos;
+ var n = this.readInt(16, len);
+ if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
+ return n
};
-base.ClassBody = function (node, st, c) {
- for (var i = 0, list = node.body; i < list.length; i += 1)
- {
- var elt = list[i];
- c(elt, st);
+// Read an identifier, and return it as a string. Sets `this.containsEsc`
+// to whether the word contained a '\u' escape.
+//
+// Incrementally adds only escaped chars, adding other chunks as-is
+// as a micro-optimization.
+
+pp$8.readWord1 = function() {
+ var this$1 = this;
+
+ this.containsEsc = false;
+ var word = "", first = true, chunkStart = this.pos;
+ var astral = this.options.ecmaVersion >= 6;
+ while (this.pos < this.input.length) {
+ var ch = this$1.fullCharCodeAtPos();
+ if (isIdentifierChar(ch, astral)) {
+ this$1.pos += ch <= 0xffff ? 1 : 2;
+ } else if (ch === 92) { // "\"
+ this$1.containsEsc = true;
+ word += this$1.input.slice(chunkStart, this$1.pos);
+ var escStart = this$1.pos;
+ if (this$1.input.charCodeAt(++this$1.pos) !== 117) // "u"
+ { this$1.invalidStringToken(this$1.pos, "Expecting Unicode escape sequence \\uXXXX"); }
+ ++this$1.pos;
+ var esc = this$1.readCodePoint();
+ if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
+ { this$1.invalidStringToken(escStart, "Invalid Unicode escape"); }
+ word += codePointToString(esc);
+ chunkStart = this$1.pos;
+ } else {
+ break
+ }
+ first = false;
}
+ return word + this.input.slice(chunkStart, this.pos)
};
-base.MethodDefinition = base.Property = function (node, st, c) {
- if (node.computed) { c(node.key, st, "Expression"); }
- c(node.value, st, "Expression");
+
+// Read an identifier or keyword token. Will check for reserved
+// words when necessary.
+
+pp$8.readWord = function() {
+ var word = this.readWord1();
+ var type = types.name;
+ if (this.keywords.test(word)) {
+ if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword " + word); }
+ type = keywords$1[word];
+ }
+ return this.finishToken(type, word)
};
-exports.simple = simple;
-exports.ancestor = ancestor;
-exports.recursive = recursive;
-exports.full = full;
-exports.fullAncestor = fullAncestor;
-exports.findNodeAt = findNodeAt;
-exports.findNodeAround = findNodeAround;
-exports.findNodeAfter = findNodeAfter;
-exports.findNodeBefore = findNodeBefore;
-exports.make = make;
-exports.base = base;
+// Acorn is a tiny, fast JavaScript parser written in JavaScript.
+//
+// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
+// various contributors and released under an MIT license.
+//
+// Git repositories for Acorn are available at
+//
+// http://marijnhaverbeke.nl/git/acorn
+// https://github.com/acornjs/acorn.git
+//
+// Please use the [github bug tracker][ghbt] to report issues.
+//
+// [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
+
+var version = "5.7.1";
+
+// The main exported interface (under `self.acorn` when in the
+// browser) is a `parse` function that takes a code string and
+// returns an abstract syntax tree as specified by [Mozilla parser
+// API][api].
+//
+// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
+
+function parse(input, options) {
+ return new Parser(options, input).parse()
+}
+
+// This function tries to parse a single expression at a given
+// offset in a string. Useful for parsing mixed-language formats
+// that embed JavaScript expressions.
+
+function parseExpressionAt(input, pos, options) {
+ var p = new Parser(options, input, pos);
+ p.nextToken();
+ return p.parseExpression()
+}
+
+// Acorn is organized as a tokenizer and a recursive-descent parser.
+// The `tokenizer` export provides an interface to the tokenizer.
+
+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.
+ // eslint-disable-line camelcase
+function addLooseExports(parse, Parser$$1, plugins$$1) {
+ exports.parse_dammit = parse; // eslint-disable-line camelcase
+ exports.LooseParser = Parser$$1;
+ exports.pluginsLoose = plugins$$1;
+}
+
+exports.version = version;
+exports.parse = parse;
+exports.parseExpressionAt = parseExpressionAt;
+exports.tokenizer = tokenizer;
+exports.addLooseExports = addLooseExports;
+exports.Parser = Parser;
+exports.plugins = plugins;
+exports.defaultOptions = defaultOptions;
+exports.Position = Position;
+exports.SourceLocation = SourceLocation;
+exports.getLineInfo = getLineInfo;
+exports.Node = Node;
+exports.TokenType = TokenType;
+exports.tokTypes = types;
+exports.keywordTypes = keywords$1;
+exports.TokContext = TokContext;
+exports.tokContexts = types$1;
+exports.isIdentifierChar = isIdentifierChar;
+exports.isIdentifierStart = isIdentifierStart;
+exports.Token = Token;
+exports.isNewLine = isNewLine;
+exports.lineBreak = lineBreak;
+exports.lineBreakG = lineBreakG;
+exports.nonASCIIwhitespace = nonASCIIwhitespace;
Object.defineProperty(exports, '__esModule', { value: true });
})));
-},{}],15:[function(require,module,exports){
+},{}],16:[function(require,module,exports){
/*
A JavaScript implementation of the SHA family of hashes, as
defined in FIPS PUB 180-4 and FIPS PUB 202, as well as the corresponding
@@ -10335,7 +15334,7 @@ new b(d[40],1290863460),new b(d[41],3158454273),new b(d[42],3505952657),new b(d[
1246189591)];X=[new b(0,1),new b(0,32898),new b(2147483648,32906),new b(2147483648,2147516416),new b(0,32907),new b(0,2147483649),new b(2147483648,2147516545),new b(2147483648,32777),new b(0,138),new b(0,136),new b(0,2147516425),new b(0,2147483658),new b(0,2147516555),new b(2147483648,139),new b(2147483648,32905),new b(2147483648,32771),new b(2147483648,32770),new b(2147483648,128),new b(0,32778),new b(2147483648,2147483658),new b(2147483648,2147516545),new b(2147483648,32896),new b(0,2147483649),
new b(2147483648,2147516424)];W=[[0,36,3,41,18],[1,44,10,45,2],[62,6,43,15,61],[28,55,25,21,56],[27,20,39,8,14]];"function"===typeof define&&define.amd?define(function(){return C}):"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(module.exports=C),exports=C):Y.jsSHA=C})(this);
-},{}],16:[function(require,module,exports){
+},{}],17:[function(require,module,exports){
/**
* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
* *
@@ -10379,4 +15378,4 @@ exports.patternUtils = {
}
};
-},{}]},{},[11]);
+},{}]},{},[12]);
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/common/Test.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/common/Test.js
new file mode 100644
index 0000000..e272d1e
--- /dev/null
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/common/Test.js
@@ -0,0 +1,55 @@
+/**
+* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
+*
+* Copyright (C) 2018 Giorgio Maone <giorgio@maone.net>
+*
+* This file is part of GNU LibreJS.
+*
+* GNU LibreJS is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GNU LibreJS is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GNU LibreJS. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+var Test = (() => {
+ const RUNNER_URL = browser.extension.getURL("/test/SpecRunner.html");
+ return {
+ /*
+ returns RUNNER_URL if it's a test-enabled build or an about:debugging
+ temporary extension session, null otherwise
+ */
+ async getURL() {
+ let url = RUNNER_URL;
+ try {
+ await fetch(url);
+ } catch (e) {
+ url = null;
+ }
+ this.getURL = () => url;
+ return url;
+ },
+
+ async getTab(activate = false) {
+ let url = await this.getURL();
+ let tab = url ? (await browser.tabs.query({url}))[0] ||
+ (await browser.tabs.create({url}))
+ : null;
+ if (tab && activate) {
+ await browser.tabs.update(tab.id, {active: true});
+ }
+ return tab;
+ }
+ };
+})();
+if (typeof module === "object") {
+ module.exports = Test;
+}
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/contact_finder.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/contactFinder.js
index 48f9c27..22bf2fc 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/contact_finder.js
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/contactFinder.js
@@ -2,6 +2,7 @@
* GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
* *
* Copyright (C) 2017 Nathan Nichols, Loic J. Duros, Nik Nyby
+* Copyright (C) 2018 Giorgio Maone
*
* This file is part of GNU LibreJS.
*
@@ -23,8 +24,12 @@
// - open the manifest.json
// - add a comma after the closing bracket of the key "background"
// - Copy and paste this after it:
-/*
- "content_scripts": [{"matches": ["<all_urls>"],"js": ["contact_finder.js"]}]
+/*
+ "content_scripts": [{
+ "matches": ["<all_urls>"],
+ "js": ["/content/contactFinder.js"],
+ "css": ["/content/contactFinder.css"]
+ }]
*/
// Now, the contact finder will load on every page and you can test it where ever you want.
@@ -34,7 +39,13 @@
//Copyright (C) 2011, 2012, 2014 Loic J. Duros
//Copyright (C) 2014, 2015 Nik Nyby
-console.log("contact_finder.js");
+function debug(format, ...args) {
+ console.debug(`LibreJS - ${format}`, ...args);
+}
+
+var myPort;
+
+debug("Injecting contact finder in %s", document.URL);
// email address regexp
var reEmail = /^mailto\:(admin|feedback|webmaster|info|contact|support|comments|team|help)\@[a-z0-9.\-]+\.[a-z]{2,4}$/i;
@@ -121,33 +132,14 @@ var email_regex = new RegExp(/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*
var prefs;
/**
-*
-* Creates a transparent floating button from a name string and a callback
-*
-*
-*/
-function new_debug_button(name_text,callback){
- if(document.getElementById("abc123_main_div") !== null){
- document.getElementById("abc123_main_div").remove();
- }
- console.log("adding button");
- if(document.getElementById("abc123_main_div") === null){
- var to_insert = '<div style="opacity: 0.5; font-size: small; z-index: 2147483647; position: fixed; right: 1%; top: 4%;" id="abc123_main_div"></div>';
- document.body.insertAdjacentHTML('afterbegin', to_insert);
- }
- var button_html = '<input id="abc123_button_complain" value="' + name_text +'" type="button"></input><br>';
- document.getElementById("abc123_main_div").insertAdjacentHTML('afterbegin', button_html); document.getElementById("abc123_button_complain").addEventListener("click",callback);
-
-}
-/**
* returns input with all elements not of type string removed
*/
function remove_not_str(a){
- var new_a = [];
+ var new_a = [];
for(var i in a){
if(typeof(a[i]) == "string"){
new_a.push(a[i])
- }
+ }
}
return new_a;
}
@@ -157,7 +149,7 @@ function remove_not_str(a){
* Will return either the first regex match from the selected certainty level or all regexes that
* match on that certainty level.
*
-* certainty_lvl can be "certain" > "probable" > "uncertain"
+* certainty_lvl can be "certain" > "probable" > "uncertain"
*/
function attempt(certainty_lvl, first=true){
// There needs to be some kind of max so that people can't troll by for example leaving a comment with a bunch of emails
@@ -165,8 +157,8 @@ function attempt(certainty_lvl, first=true){
var fail_flag = true;
var flag;
var matches = [];
- var result = [];
- var str_under_test = "";
+ var result = [];
+ var str_under_test = "";
for(var i in document.links){
if( typeof(document.links[i].innerText) != "string" || typeof(document.links[i].href) != "string"){
continue;
@@ -176,10 +168,10 @@ function attempt(certainty_lvl, first=true){
for(var j in contactStr){
for(var k in contactStr[j][certainty_lvl]){
if(flag){
- result = [];
+ result = [];
result = str_under_test.match(new RegExp(contactStr[j][certainty_lvl][k],"g"));
result = remove_not_str(result);
- if(result !== undefined && typeof(result[0]) == "string" ){
+ if(result !== undefined && typeof(result[0]) == "string" ){
if(first){
return {"fail":false,"result":document.links[i]};
} else{
@@ -197,7 +189,7 @@ function attempt(certainty_lvl, first=true){
}
/**
-* "LibreJS detects contact pages, email addresses that are likely to be owned by the
+* "LibreJS detects contact pages, email addresses that are likely to be owned by the
* maintainer of the site, Twitter and identi.ca links, and phone numbers."
*/
function find_contacts(){
@@ -207,19 +199,19 @@ function find_contacts(){
var identi = [];
var contact_pages = [];
var res = attempt("certain");
- var flag = true;
+ var flag = true;
var type = "";
if(res["fail"] == false){
type = "certain";
res = res["result"];
- flag = false;
+ flag = false;
}
if(flag){
res = attempt("probable");
if(res["fail"] == false){
type = "probable";
res = res["result"];
- flag = false;
+ flag = false;
}
}
if(flag){
@@ -227,7 +219,7 @@ function find_contacts(){
if(res["fail"] == false){
type = "uncertain";
res = res["result"];
- flag = false;
+ flag = false;
}
}
if(flag){
@@ -235,63 +227,102 @@ function find_contacts(){
}
return [type,res];
}
-// need to have this so the handler doesn't take too long
-function handler(){
- var res = find_contacts();
- if(document.getElementById("librejs_contactfinder") != null){
- document.getElementById("librejs_contactfinder").remove();
- }
- var to_insert;
- if("fail" in res){
- to_insert = '<div style="font-size: small; z-index: 2147483647; background-color: #eeeeee;'+
- 'position: fixed; display:inline-block; border: 3px solid #990000; width: 50%;"'+
- ' id="librejs_contactfinder">'+
- "Contact finder failed.";
- } else{
- if(typeof(res[1]) == "string"){
- to_insert = '<div style="font-size: small; z-index: 2147483647; background-color: #eeeeee;'+
- 'position: fixed; display:inline-block; border: 3px solid #990000; width: 50%;"'+
- ' id="librejs_contactfinder"><b>Result:</b><br>'+
- res[0] + ": " + '<a href="' + res[1] + '>'+res[1]+'</a>';
- }
- if(typeof(res[1]) == "object"){
- to_insert = '<div style="font-size: small; z-index: 2147483647; background-color: #eeeeee;'+
- 'position: fixed; display:inline-block; border: 3px solid #990000; width: 50%;"'+
- ' id="librejs_contactfinder"><b>Result:</b><br>'+
- res[0]+": "+res[1].outerHTML;
- }
- }
- var email = document.documentElement.innerText.match(email_regex);
- if(email != null){
- var max_i = 0;
- if(email.length >= 10){
- max_i = 10;
- } else{
- max_i = email.length;
- }
- for(var i = 0; i < max_i; i++){
- var mailto = "mailto:"+email[i]+"?subject="+encodeURI(prefs["pref_subject"])+"&body="+encodeURI(prefs["pref_body"]);
- to_insert += '<br>' + 'Possible email: <a href="' + mailto + '">'+email[i]+'</a>';
- }
- }
+function createWidget(id, tag, parent = document.body) {
+ let widget = document.getElementById(id);
+ if (widget) widget.remove();
+ widget = parent.appendChild(document.createElement(tag));
+ widget.id = id;
+ return widget;
+}
- to_insert += '</div>';
+/**
+*
+* Creates the contact finder / complain UI as a semi-transparent overlay
+*
+*/
- setTimeout(function(){document.getElementById("librejs_contactfinder").remove()}, 7500);
- document.body.insertAdjacentHTML("afterbegin",to_insert);
- return 0;
+function main() {
+ let overlay = createWidget("_LibreJS_overlay", "div");
+ let frame = createWidget("_LibreJS_frame", "iframe");
-}
+ let close = () => {
+ frame.remove();
+ overlay.remove();
+ };
-function main(){
- new_debug_button("Complain to website",handler);
-}
+ let closeListener = e => {
+ let t = e.currentTarget;
+ if (t.href) { // link navigation
+ if (t.href !== document.URL) {
+ if (t.href.includes("#")) {
+ window.addEventListener("hashchange", close);
+ }
+ return;
+ }
+ }
+ close();
+ };
+ let makeCloser = clickable => clickable.addEventListener("click", closeListener);
+
+ makeCloser(overlay);
+
+ let initFrame = () => {
+ debug("initFrame");
+ let res = find_contacts();
+ let contentDoc = frame.contentWindow.document;
+ let {body} = contentDoc;
+ body.id = "_LibreJS_dialog";
+ body.innerHTML = `<h1>LibreJS Complaint</h1><button class='close'>x</button>`;
+ contentDoc.documentElement.appendChild(contentDoc.createElement("base")).target = "_top";
+ let content = body.appendChild(contentDoc.createElement("div"));
+ content.id = "content";
+ let addHTML = s => content.insertAdjacentHTML("beforeend", s);
+ if ("fail" in res) {
+ content.classList.toggle("_LibreJS_fail", true)
+ addHTML("<div>Could not guess any contact page for this site.</div>");
+ } else {
+ addHTML("<h3>Contact info guessed for this site</h3>");
+ if(typeof(res[1]) === "string") {
+ let a = contentDoc.createElement("a");
+ a.href = a.textContent = res[1];
+ content.appendChild(a);
+ } else if (typeof(res[1]) === "object"){
+ addHTML(`${res[0]}: ${res[1].outerHTML}`);
+ }
+ }
-var myPort = browser.runtime.connect({name:"contact_finder"});
+ let emails = document.documentElement.textContent.match(email_regex);
+ if (emails && (emails = Array.filter(emails, e => !!e)).length) {
+ addHTML("<h5>Possible email addresses:</h5>");
+ let list = contentDoc.createElement("ul");
+ for (let i = 0, max = Math.min(emails.length, 10); i < max; i++) {
+ let recipient = emails[i];
+ let a = contentDoc.createElement("a");
+ a.href = `mailto:${recipient}?subject${
+ encodeURIComponent(prefs["pref_subject"])
+ }&body=${
+ encodeURIComponent(prefs["pref_body"])
+ }`;
+ a.textContent = recipient;
+ list.appendChild(contentDoc.createElement("li")).appendChild(a);
+ }
+ content.appendChild(list);
+ }
+ Array.forEach(contentDoc.querySelectorAll(".close, a"), makeCloser);
+ debug("frame initialized");
+ }
+
+
+
+ frame.addEventListener("load", e => {
+ debug("frame loaded");
+ myPort = browser.runtime.connect({name: "contact_finder"}).onMessage.addListener(m => {
+ prefs = m;
+ initFrame();
+ });
+ });
+}
-myPort.onMessage.addListener(function(m) {
- prefs = m;
- main();
-});
+main();
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/dialog.css b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/dialog.css
new file mode 100644
index 0000000..38b6634
--- /dev/null
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/dialog.css
@@ -0,0 +1,91 @@
+#_LibreJS_dialog {
+ font-family: sans-serif;
+ font-size: 1.2em;
+ color: #000;
+ background-color: #eee;
+ margin: 0;
+ padding: 0;
+ text-align: center;
+}
+#_LibreJS_dialog .close {
+ -moz-appearance: none;
+ border: 0;
+ position: fixed;
+ top: .2em;
+ right: .2em;
+ font-size: 1em;
+ font-weight: bold;
+ text-transform: uppercase;
+ color: white;
+ background: black;
+ border-radius: 1em;
+ cursor: pointer;
+ display: block;
+ width: 1.5em;
+ height: 1.5em;
+ text-align: center;
+ vertical-align: middle;
+ padding: 0;
+}
+#_LibreJS_dialog .close:hover {
+ background: #800;
+}
+
+ #_LibreJS_dialog h1, #_LibreJS_dialog h2, #_LibreJS_dialog h3 {
+ font-family: sans-serif;
+ color: #000;
+ font-weight: bold;
+ text-align: center;
+ border: none;
+ padding: .2em;
+ margin: .2em;
+ display: block;
+}
+
+#_LibreJS_dialog a {
+ text-decoration: none;
+ color: #048;
+ border: none;
+}
+
+#_LibreJS_dialog a:hover {
+ text-decoration: none;
+ color: #06c;
+ border-bottom: 1px solid #048;
+}
+
+#_LibreJS_dialog h1 {
+ font-size: 1.5em;
+ background: #666;
+ color: white;
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ margin: 0;
+ padding: .2em;
+}
+
+#_LibreJS_dialog h3 {
+ font-size: 1.2em !important
+}
+
+#_LibreJS_dialog h4 {
+ font-size: 1em;
+}
+
+#_LibreJS_dialog #content {
+ position: fixed;
+ overflow: auto;
+ top: 2.5em;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 100%;
+}
+
+#_LibreJS_dialog #content ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;"
+}
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/externalLicenseChecker.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/externalLicenseChecker.js
index be09ef1..516057e 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/externalLicenseChecker.js
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/externalLicenseChecker.js
@@ -21,7 +21,7 @@
"use strict";
{
let licensedScripts = null;
-
+
let fetchWebLabels = async args => {
// see https://www.gnu.org/software/librejs/free-your-javascript.html#step3
let {map, cache} = args;
@@ -40,26 +40,31 @@
} else {
doc.head.appendChild(doc.createElement("base")).href = baseURL;
}
- let firstURL = parent => parent.querySelector("a").href;
- let allURLs = parent => Array.map(parent.querySelectorAll("a"), a => a.href);
- for (let row of doc.querySelectorAll("table#jslicense-labels1 tr")) {
- let cols = row.querySelectorAll("td");
- let scriptURL = firstURL(cols[0]);
- let licenseURLs = allURLs(cols[1]);
- let sourceURLs = cols[2] ? allURLs(cols[2]) : [];
- map.set(scriptURL, {scriptURL, licenseURLs, sourceURLs});
+ let link = a => ({ url: a.href, label: a.textContent });
+ let firstLink = parent => link(parent.querySelector("a"));
+ let allLinks = parent => Array.map(parent.querySelectorAll("a"), link);
+ for (let row of doc.querySelectorAll("table#jslicense-labels1 > tbody > tr")) {
+ try {
+ let cols = row.querySelectorAll("td");
+ let script = firstLink(cols[0]);
+ let licenseLinks = allLinks(cols[1]);
+ let sources = cols[2] ? allLinks(cols[2]) : [];
+ map.set(script.url, {script, licenseLinks, sources});
+ } catch (e) {
+ console.error("LibreJS: error parsing Web Labels at %s, row %s", baseURL, row.innerHTML, e);
+ }
}
} catch (e) {
console.error("Error fetching Web Labels at %o", link, e);
}
return map;
}
-
+
let fetchLicenseInfo = async cache => {
let map = new Map();
let args = {map, cache};
// in the fetchXxx methods we add to a map whatever license(s)
- // URLs and source code references we can find in various formats
+ // URLs and source code references we can find in various formats
// (WebLabels is currently the only implementation), keyed by script URLs.
await Promise.all([
fetchWebLabels(args),
@@ -69,12 +74,12 @@
]);
return map;
}
-
+
let handlers = {
async checkLicensedScript(m) {
let {url, cache} = m;
if (!licensedScripts) licensedScripts = await fetchLicenseInfo(cache);
- return licensedScripts.get(url);
+ return licensedScripts.get(url) || licensedScripts.get(url.replace(/\?.*/, ''));
}
}
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/overlay.css b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/overlay.css
new file mode 100644
index 0000000..fa0a294
--- /dev/null
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/content/overlay.css
@@ -0,0 +1,28 @@
+#_LibreJS_overlay {
+ z-index: 2147483647 !important;
+ background-color: #000;
+ opacity: 0.7 !important;
+ display: block !important;
+ position: fixed !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ top: 0 !important;
+ bottom: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+}
+
+#_LibreJS_frame {
+ width: 60% !important;
+ height: 80% !important;
+ top: 10% !important;
+ bottom: 10% !important;
+ left: 20% !important;
+ right: 20% !important;
+ overflow: auto !important;
+ position: fixed !important;
+ display:inline-block !important;
+ border: 2px solid #444 !important;
+ z-index: 2147483647 !important;
+ background: #eee;
+}
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/common.css b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/common.css
index cf2c5d1..14931fa 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/common.css
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/common.css
@@ -3,6 +3,7 @@ html {
margin:0px;
color:#000 !important;
background:url('background-panel.png') !important;
+ font-family: sans-serif;
}
body {
padding:0;
@@ -26,4 +27,15 @@ h1.libre {
font-weight:bold;
background:url('librejs-title.png') no-repeat top left;
text-indent:-1000px;
+ position: relative;
+}
+h1.libre span {
+ font-family: sans-serif;
+ position: absolute;
+ bottom: 32px;
+ padding: 0 16px;
+ left: 230px;
+ display: block;
+ text-indent: 0;
+ vertical-align: bottom;
}
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/display-panel.html b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/display-panel.html
index df153b3..80f4cb9 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/display-panel.html
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/display-panel.html
@@ -53,6 +53,7 @@
<button id="complain">Complain to site owner</button>
<button id="report-tab">Show this report in a new tab</button>
<button id="open-options">Settings...</button>
+ <button id="autotest">Automated self test...</button>
</div>
</div>
<div id="info">
@@ -100,5 +101,6 @@
</div>
</div>
</body>
+<script src="/common/Test.js"></script>
<script src="main_panel.js"></script>
</html>
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/main_panel.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/main_panel.js
index c55b167..2509545 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/main_panel.js
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/main_panel.js
@@ -38,6 +38,18 @@ myPort.postMessage({"update": true, tabId: parseInt(currentReport && currentRepo
// Display the actual extension version Number
document.querySelector("#version").textContent = browser.runtime.getManifest().version;
+// Enable autotest button if this is a test-enabled build / session
+(async () => {
+ if (await Test.getURL()) {
+ let button = document.querySelector("#autotest");
+ button.style.display = "block";
+ button.onclick = async () => {
+ await Test.getTab(true);
+ close();
+ }
+ }
+})();
+
var liTemplate = document.querySelector("#li-template");
liTemplate.remove();
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/panel-styles.css b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/panel-styles.css
index cbf5cf5..940a8ff 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/panel-styles.css
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/display_panel/content/panel-styles.css
@@ -141,7 +141,8 @@ span.blocked {
display: none;
}
-.tab #must-reload, .tab #buttons, .empty #buttons {
+.tab #must-reload, .tab #buttons,
+.empty #complain, .empty #report-tab, #autotest {
display: none;
}
@@ -149,9 +150,3 @@ span.blocked {
width: 100%;
text-align: center;
}
-
-
-
-#complain {
- display: none; /* TODO: Complaint to owner UI */
-}
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/preferences_panel.html b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/preferences_panel.html
index effb724..70d3b86 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/preferences_panel.html
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/preferences_panel.html
@@ -71,15 +71,9 @@
<fieldset id="section-complaint"><legend>Complaint email defaults</legend>
<label for="pref_subject">Subject</label>
- <input id="pref_subject" type="text"
- value="Issues with Javascript on your website"
- />
+ <input id="pref_subject" type="text"/>
<label for="pref_body">Body</label>
- <textarea id="pref_body" rows="5"
->Please consider using a free license for the Javascript on your website.
-
-[Message generated by LibreJS. See https://www.gnu.org/software/librejs/ for more information]
-</textarea>
+ <textarea id="pref_body" rows="5"></textarea>
</fieldset>
</div>
</body>
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/prefs.css b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/prefs.css
index b52d6c5..3ac498e 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/prefs.css
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/html/preferences_panel/prefs.css
@@ -85,7 +85,3 @@ input[type="text"] {
background: #ffe;
color: #800;
}
-
-#section-complaint {
- display: none; /* TODO: Complaint to owner UI */
-}
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/manifest.json b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/manifest.json
index 03778d7..4f932ad 100644
--- a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/manifest.json
+++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/manifest.json
@@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "GNU LibreJS [webExtensions]",
"short_name": "LibreJS [experimental]",
- "version": "7.17",
+ "version": "7.18.1",
"author": "various",
"description": "Only allows free and/or trivial Javascript to run.",
"applications": {