diff --git a/.travis.yml b/.travis.yml index 7aadac0a75..0a82a67559 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "8.11.1" + - "12.16.1" cache: directories: - ".meteor" diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index f292452bee..77b5b74467 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -102,7 +102,7 @@ Pull requests that contain `dev_bundle` changes will be noted by repo collaborat The Meteor core is best documented within the code itself, however, many components also have a `README.md` in their respective directories. -Some compartmentalized portions of Meteor are broken into packages ([see a list of packages](packages/)) and they almost all have a `README.md` within their directory. For example, [`ddp`](packages/ddp/README.md), [`ecmascript`](packages/ecmascript/README.md) and [`tinytest`](packages/tinytest/README.md). +Some compartmentalized portions of Meteor are broken into packages ([see a list of packages](packages/)) and almost all of them have a `README.md` within their directory. For example, [`ddp`](packages/ddp/README.md), [`ecmascript`](packages/ecmascript/README.md) and [`tinytest`](packages/tinytest/README.md). For the rest, try looking nearby for a `README.md`. For example, [`isobuild`](tools/isobuild/README.md) or [`cordova`](tools/cordova/README.md). @@ -110,10 +110,10 @@ For the rest, try looking nearby for a `README.md`. For example, [`isobuild`](t ### Test against the local meteor copy -When running any of tests, be sure run them against the checked-out copy of Meteor instead of +When running any tests, be sure to run them against the checked-out copy of Meteor instead of the globally-installed version. This means ensuring that the command is `path-to-meteor-checkout/meteor` and not just `meteor`. -This is important so that tests are run against the version in development and not the stable (installed) Meteor release. +This is important so that tests are run against your local development version and not the stable (installed) Meteor release. ### Running tests on Meteor core @@ -142,7 +142,7 @@ While TinyTest and the `test-packages` command can be used to test internal Mete #### Listing available tests -To see a list of the tests which are included in the self-test system, list them with the `--list` option: +To see a list of tests included in the self-test system, use the `--list` option: ./meteor self-test --list diff --git a/History.md b/History.md index 53a8a8f4d2..c5e87ccdf4 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,51 @@ -## v1.10, 2020-03-12 + +## v1.10.2, 2020-04-21 + +### Breaking changes + +* The `babel-compiler` package, used by both `ecmascript` and + `typescript`, no longer supports stripping [Flow](https://flow.org/) + type annotations by default, which may be a breaking change if your + application (or Meteor package) relied on Flow syntax. + +### Migration steps + +* If you still need Babel's Flow plugins, you can install them with npm + and then enable them with a custom `.babelrc` file in your application's + (or package's) root directory: + ```json + { + "plugins": [ + "@babel/plugin-syntax-flow", + "@babel/plugin-transform-flow-strip-types" + ] + } + ``` + +### Changes + +* Adds support to override MongoDB options via Meteor settings. Code PR +[#10976](https://github.com/meteor/meteor/pull/10976), Docs PR +[#662](https://github.com/meteor/docs/pull/662) + +* The `meteor-babel` npm package has been updated to version 7.9.0. + +* The `typescript` npm package has been updated to version 3.8.3. + +* To pass Node command line flags to the server node instance, + now it is recommended to use `SERVER_NODE_OPTIONS` instead of `NODE_OPTIONS`. + Since Meteor 0.5.3, Meteor allowed to pass node command line flags via the `NODE_OPTIONS` + environment variable. + However, since Node version 8 / Meteor 1.6 this has become a default node + envar with the same behavior. The side effect is that this now also affects + Meteor tool. The command line parameters could already be set separately + via the `TOOL_NODE_FLAGS` envar. This is now also possible (again) for the server. + +* The version of MongoDB used by Meteor in development has been updated from + 4.2.1 to 4.2.5. + [PR #11020](https://github.com/meteor/meteor/pull/11020) + +## v1.10.1, 2020-03-12 ### Breaking changes @@ -250,6 +297,8 @@ N/A See [this comment](https://github.com/meteor/meteor/pull/10522#issuecomment-535535056) by [@SimonSimCity](https://github.com/SimonSimCity). +* `Plugin.fs` methods are now always sync and no longer accept a callback. + ### Migration Steps * Be sure to update the `@babel/runtime` npm package to its latest version diff --git a/LICENSE b/LICENSE index b21d2ed158..33a9060768 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2011 - 2019 Meteor Software Ltd. +Copyright (c) 2011 - present Meteor Software Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ad4c428778..7fa8cfb1be 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Try a getting started tutorial: * [React](https://www.meteor.com/tutorials/react/creating-an-app) * [Blaze](https://www.meteor.com/tutorials/blaze/creating-an-app) * [Angular](https://www.meteor.com/tutorials/angular/creating-an-app) + * [Vue](https://www.meteor.com/tutorials/vue/creating-an-app) Next, read the [guide](https://guide.meteor.com) and the [documentation](https://docs.meteor.com/). diff --git a/Roadmap.md b/Roadmap.md index a5a1f9268d..265ad6e0bb 100644 --- a/Roadmap.md +++ b/Roadmap.md @@ -84,30 +84,16 @@ Explore ideas to implement HMR in Meteor. Migrate packages that do not depend on Meteor exclusive features to NPM and we also continue to encourage new packages to be published as NPM packages when possible. ## Cordova -### Update Cordova to 9 -- Leaders: [Filipe Névola](https://github.com/filipenevola) / [Renan Castro](https://github.com/renanccastro) -- Status: In Progress (1.10-beta.4) -- PRs: https://github.com/meteor/meteor/pull/10861 / https://github.com/meteor/meteor/pull/10810 - -Update Cordoba lib and its dependencies to latest (version 9) - ### Cordova documentation -- Leaders: +- Leaders: [Filipe Névola](https://github.com/filipenevola) - Status: - - PRs: - Provide a skeleton with mobile native configurations already in place such as `mobile-config.js`, sample assets, Fastlane scripts, etc. Also improve docs and guide ([Forums post](https://forums.meteor.com/t/lets-create-the-ultimate-cordova-hot-code-push-faq-doc/50500)). ## DB -### Update MongoDB driver -- Leaders: [Christian Klaussner](https://github.com/klaussner) -- Status: In Progress (1.10-beta.4) -- PRs: https://github.com/meteor/meteor/pull/10861 / https://github.com/meteor/meteor/pull/10723 - -Update to Mongodb driver from 3.2.7 to 3.3.5, this version is compatible with MongoDB 4.2. - ### Minimongo secondary index support -- Leaders: +- Leaders: [Brian Mulhall](https://github.com/BrianMulhall) - Status: - - PRs: - @@ -150,12 +136,15 @@ React tutorial should reflect latest best practices for using Meteor and React t Provide a skeleton with PWA configurations already in place such as `manifest`, service worker, Open Graph meta tags, etc. Also improve docs and guide. ### SSR documentation -- Leaders: [Kevin Newman](https://github.com/CaptainN) +- Leaders: [Kevin Newman](https://github.com/CaptainN) / [Eric Burel](https://github.com/eric-burel) - Status: - - PRs: - Provide a skeleton with SSR configurations already in place. +Relevant issues: +- https://github.com/meteor/meteor-feature-requests/issues/174 + ### Tests documentation - Leaders: [Simon Schick](https://github.com/SimonSimCity) / [Florian Bienefelt](https://github.com/Floriferous) - Status: - @@ -206,6 +195,19 @@ Relevant discussions: - https://github.com/storybookjs/storybook/issues/5975 ## Recently completed +### Update MongoDB driver +- Leaders: [Christian Klaussner](https://github.com/klaussner) +- Status: shipped in Meteor 1.10.1 +- PRs: https://github.com/meteor/meteor/pull/10861 / https://github.com/meteor/meteor/pull/10723 + +Update to Mongodb driver from 3.2.7 to 3.5.4, this version is compatible with MongoDB 4.2. + +### Update Cordova to 9 +- Leaders: [Filipe Névola](https://github.com/filipenevola) / [Renan Castro](https://github.com/renanccastro) +- Status: shipped in Meteor 1.10.1 +- PRs: https://github.com/meteor/meteor/pull/10861 / https://github.com/meteor/meteor/pull/10810 / https://github.com/meteor/meteor/pull/10861 + +Update Cordoba lib and its dependencies to latest (version 9) ### Update to Node.js 12 - Leaders: [Ben Newman](https://github.com/benjamn) diff --git a/meteor b/meteor index 818b86551b..15264e56ef 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=12.16.1.6 +BUNDLE_VERSION=12.16.1.8 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/packages/appcache/appcache-server.js b/packages/appcache/appcache-server.js index 52613b83ae..55822427d4 100755 --- a/packages/appcache/appcache-server.js +++ b/packages/appcache/appcache-server.js @@ -1,5 +1,4 @@ import { Meteor } from 'meteor/meteor' -import { isModern } from "meteor/modern-browsers"; import { WebApp } from "meteor/webapp"; import crypto from 'crypto'; import fs from 'fs'; @@ -88,12 +87,12 @@ WebApp.connectHandlers.use((req, res, next) => { } const cacheInfo = { - modern: isModern(request.browser), + // Provided by WebApp.categorizeRequest. + modern: request.modern, }; - cacheInfo.arch = cacheInfo.modern - ? "web.browser" - : "web.browser.legacy"; + // Also provided by WebApp.categorizeRequest. + cacheInfo.arch = request.arch; // The true hash of the client manifest for this arch, regardless of // AUTOUPDATE_VERSION or Autoupdate.autoupdateVersion. diff --git a/packages/appcache/package.js b/packages/appcache/package.js index 5716bbc802..f2bbc8679c 100644 --- a/packages/appcache/package.js +++ b/packages/appcache/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Enable the application cache in the browser", - version: "1.2.5", + version: "1.2.7", }); Package.onUse(api => { diff --git a/packages/autoupdate/README.md b/packages/autoupdate/README.md index f76824b62a..b44d30f594 100644 --- a/packages/autoupdate/README.md +++ b/packages/autoupdate/README.md @@ -3,7 +3,7 @@ *** This package is the heart of Meteor's Hot Code Push functionality. It has a -client component and a server component component. The client component uses a +client component and a server component. The client component uses a DDP API provided by the server to subscribe to the version ID of the most recent build of the app's client. When it sees that a new version is available, it uses the [reload](https://atmospherejs.com/meteor/reload) package (if included in the diff --git a/packages/autoupdate/autoupdate_client.js b/packages/autoupdate/autoupdate_client.js index 46b6a504bb..1f95672541 100644 --- a/packages/autoupdate/autoupdate_client.js +++ b/packages/autoupdate/autoupdate_client.js @@ -15,7 +15,7 @@ // version available on the server. // // `Autoupdate.newClientAvailable` is a reactive data source which -// becomes `true` if there is a new version of the client is available on +// becomes `true` if a new version of the client is available on // the server. // // This package doesn't implement a soft code reload process itself, diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index 61af92703f..9705d36cb7 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -7,21 +7,21 @@ "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==" }, "@babel/core": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", - "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", "dependencies": { "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.2.tgz", + "integrity": "sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ==" } } }, "@babel/generator": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", - "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==" + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.4.tgz", + "integrity": "sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==" }, "@babel/helper-annotate-as-pure": { "version": "7.8.3", @@ -34,24 +34,24 @@ "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==" }, "@babel/helper-builder-react-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz", - "integrity": "sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz", + "integrity": "sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw==" }, - "@babel/helper-call-delegate": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz", - "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==" + "@babel/helper-builder-react-jsx-experimental": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.0.tgz", + "integrity": "sha512-3xJEiyuYU4Q/Ar9BsHisgdxZsRlsShMe90URZ0e6przL26CCs8NJbDoxH94kKT17PcxlMhsCAwZd90evCo26VQ==" }, "@babel/helper-create-class-features-plugin": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", - "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==" + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.6.tgz", + "integrity": "sha512-klTBDdsr+VFFqaDHm5rR69OpEQtO2Qv8ECxHS1mNhJJvaHArR6a1xTf5K/eZW7eZpJbhCx3NW1Yt/sKsLXLblg==" }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", - "integrity": "sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==" + "version": "7.8.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz", + "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==" }, "@babel/helper-define-map": { "version": "7.8.3", @@ -73,11 +73,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==" }, - "@babel/helper-hoist-variables": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", - "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==" - }, "@babel/helper-member-expression-to-functions": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", @@ -89,9 +84,9 @@ "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==" }, "@babel/helper-module-transforms": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz", - "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", + "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==" }, "@babel/helper-optimise-call-expression": { "version": "7.8.3", @@ -114,9 +109,9 @@ "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==" }, "@babel/helper-replace-supers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", - "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==" + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", + "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==" }, "@babel/helper-simple-access": { "version": "7.8.3", @@ -128,25 +123,30 @@ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==" }, + "@babel/helper-validator-identifier": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", + "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==" + }, "@babel/helper-wrap-function": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==" }, "@babel/helpers": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", - "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==" + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", + "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==" }, "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", + "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==" }, "@babel/parser": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", - "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==" + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", + "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==" }, "@babel/plugin-proposal-async-generator-functions": { "version": "7.8.3", @@ -164,9 +164,9 @@ "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==" }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.0.tgz", + "integrity": "sha512-UgqBv6bjq4fDb8uku9f+wcm1J7YxJ5nT7WO/jBr0cl0PLKb7t1O6RNR1kZbjgx2LQtsDI9hwoQVmn0yhXeQyow==" }, "@babel/plugin-proposal-optional-catch-binding": { "version": "7.8.3", @@ -174,9 +174,9 @@ "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==" }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz", - "integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz", + "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==" }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -193,11 +193,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==" }, - "@babel/plugin-syntax-flow": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz", - "integrity": "sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg==" - }, "@babel/plugin-syntax-jsx": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", @@ -244,9 +239,9 @@ "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==" }, "@babel/plugin-transform-classes": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz", - "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==" + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.2.tgz", + "integrity": "sha512-TC2p3bPzsfvSsqBZo0kJnuelnoK9O3welkUpqSqBQuBF6R5MN2rysopri8kNvtlGIb2jmUO7i15IooAZJjZuMQ==" }, "@babel/plugin-transform-computed-properties": { "version": "7.8.3", @@ -254,24 +249,19 @@ "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==" }, "@babel/plugin-transform-destructuring": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz", - "integrity": "sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==" + "version": "7.8.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.8.tgz", + "integrity": "sha512-eRJu4Vs2rmttFCdhPUM3bV0Yo/xPSdPw6ML9KHs/bjB4bLA5HXlbvYXPOD5yASodGod+krjYx21xm1QmL8dCJQ==" }, "@babel/plugin-transform-exponentiation-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==" }, - "@babel/plugin-transform-flow-strip-types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz", - "integrity": "sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA==" - }, "@babel/plugin-transform-for-of": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz", - "integrity": "sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz", + "integrity": "sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ==" }, "@babel/plugin-transform-literals": { "version": "7.8.3", @@ -279,9 +269,9 @@ "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==" }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", - "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz", + "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==" }, "@babel/plugin-transform-object-super": { "version": "7.8.3", @@ -289,9 +279,9 @@ "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==" }, "@babel/plugin-transform-parameters": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz", - "integrity": "sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==" + "version": "7.9.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.3.tgz", + "integrity": "sha512-fzrQFQhp7mIhOzmOtPiKffvCYQSK10NR8t6BBz2yPbeUHb9OLW8RZGtgDRBn8z2hGcwvKDL3vC7ojPTLNxmqEg==" }, "@babel/plugin-transform-property-literals": { "version": "7.8.3", @@ -304,29 +294,34 @@ "integrity": "sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A==" }, "@babel/plugin-transform-react-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz", - "integrity": "sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g==" + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz", + "integrity": "sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw==" + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.9.0.tgz", + "integrity": "sha512-tK8hWKrQncVvrhvtOiPpKrQjfNX3DtkNLSX4ObuGcpS9p0QrGetKmlySIGR07y48Zft8WVgPakqd/bk46JrMSw==" }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz", - "integrity": "sha512-01OT7s5oa0XTLf2I8XGsL8+KqV9lx3EZV+jxn/L2LQ97CGKila2YMroTkCEIE0HV/FF7CMSRsIAybopdN9NTdg==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.9.0.tgz", + "integrity": "sha512-K2ObbWPKT7KUTAoyjCsFilOkEgMvFG+y0FqOl6Lezd0/13kMkkjHskVsZvblRPj1PHA44PrToaZANrryppzTvQ==" }, "@babel/plugin-transform-react-jsx-source": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz", - "integrity": "sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.9.0.tgz", + "integrity": "sha512-K6m3LlSnTSfRkM6FcRk8saNEeaeyG5k7AVkBU2bZK3+1zdkSED3qNdsWrUgQBeTVD2Tp3VMmerxVO2yM5iITmw==" }, "@babel/plugin-transform-regenerator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz", - "integrity": "sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==" + "version": "7.8.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz", + "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==" }, "@babel/plugin-transform-runtime": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz", - "integrity": "sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz", + "integrity": "sha512-pUu9VSf3kI1OqbWINQ7MaugnitRss1z533436waNXp+0N3ur3zfut37sXiQMxkuCF4VUjwZucen/quskCh7NHw==" }, "@babel/plugin-transform-shorthand-properties": { "version": "7.8.3", @@ -359,34 +354,34 @@ "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==" }, "@babel/preset-react": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.8.3.tgz", - "integrity": "sha512-9hx0CwZg92jGb7iHYQVgi0tOEHP/kM60CtWJQnmbATSPIQQ2xYzfoCI3EdqAhFBeeJwYMdWQuDUHMsuDbH9hyQ==" + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.9.4.tgz", + "integrity": "sha512-AxylVB3FXeOTQXNXyiuAQJSvss62FEotbX2Pzx3K/7c+MKJMdSg6Ose6QYllkdCFA8EInCJVw7M/o5QbLuA4ZQ==" }, "@babel/runtime": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", - "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==" + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==" }, "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==" + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", + "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==" }, "@babel/traverse": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", - "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.0.tgz", + "integrity": "sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==" }, "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", + "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==" }, "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" }, "acorn-dynamic-import": { "version": "4.0.0", @@ -549,9 +544,9 @@ "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=" }, "babel-preset-meteor": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-7.8.1.tgz", - "integrity": "sha512-R0Z3iq11dvucBlhkobsLxyC+Q4kP61umabQSRYcbp/dkvxUcZWZg5Lhn8DbhAOzTuUt9sCtgsDlhwqJ+fOSDHg==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-7.9.0.tgz", + "integrity": "sha512-SB2hGHZ2wKFiqaovO5DlgoYEUjNGP9FytZlLXppDKKP+TGpoGSQUyNhQ/ACSPFbTEBhKSuyV1LCEmHS+yK7FyQ==" }, "babel-preset-minify": { "version": "0.5.1", @@ -644,14 +639,14 @@ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "magic-string": { - "version": "0.25.6", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.6.tgz", - "integrity": "sha512-3a5LOMSGoCTH5rbqobC2HuDNRtE2glHZ8J7pK+QZYppyWA36yuNpsX994rIY2nCuyP7CZYy7lQq/X2jygiZ89g==" + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==" }, "meteor-babel": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-7.8.2.tgz", - "integrity": "sha512-a7rUu156O7fCLZVtVh8bIkKnLYlLGNEo+q4jsupXgiMEh2RbuLsn8CCj8DyDoubi3AyIduGk7T0VRVZxr4XVQA==" + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-7.9.0.tgz", + "integrity": "sha512-cJI8Mu8XG0aFh7b6I/PpgfiJV46WKp75o0hgknw9oCQ8X/HhZ8BtQIRVT7WGCirH3ATfmEqRmW00UimAQJOnhw==" }, "meteor-babel-helpers": { "version": "0.0.3", @@ -659,9 +654,9 @@ "integrity": "sha1-8uXZ+HlvvS6JAQI9dpnlsgLqn7A=" }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "ms": { "version": "2.1.2", @@ -694,24 +689,24 @@ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" }, "regenerate-unicode-properties": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==" }, "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" }, "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==" + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz", + "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==" }, "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==" + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", + "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==" }, "regjsgen": { "version": "0.5.1", @@ -719,9 +714,9 @@ "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==" }, "regjsparser": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.3.tgz", - "integrity": "sha512-8uZvYbnfAtEm9Ab8NTb3hdLwL4g/LQzEYP7Xs27T96abJCCE2d6r3cPZPQEsLKy0vRSGVNG+/zVGtLr86HQduA==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", "dependencies": { "jsesc": { "version": "0.5.0", @@ -771,9 +766,9 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, "typescript": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz", - "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==" + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==" }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", @@ -786,14 +781,14 @@ "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==" }, "unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==" }, "unicode-property-aliases-ecmascript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" } } } diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index 34af7a8881..4534a9cb37 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,11 +6,11 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '7.5.2' + version: '7.5.3' }); Npm.depends({ - 'meteor-babel': '7.8.2', + 'meteor-babel': '7.9.0', 'json5': '2.1.1' }); diff --git a/packages/caching-compiler/caching-compiler.js b/packages/caching-compiler/caching-compiler.js index 670841773d..d0c3fe36a8 100644 --- a/packages/caching-compiler/caching-compiler.js +++ b/packages/caching-compiler/caching-compiler.js @@ -171,27 +171,16 @@ CachingCompilerBase = class CachingCompilerBase { return hash.digest('hex'); } - // We want to write the file atomically. But we also don't want to block - // processing on the file write. - _writeFileAsync(filename, contents) { + // Write the file atomically. + _writeFile(filename, contents) { const tempFilename = filename + '.tmp.' + Random.id(); - if (this._cacheDebugEnabled) { - // Write cache file synchronously when cache debugging enabled. - try { - fs.writeFileSync(tempFilename, contents); - fs.renameSync(tempFilename, filename); - } catch (e) { - // ignore errors, it's just a cache - } - } else { - fs.writeFile(tempFilename, contents, writeError => { - if (writeError) return; - try { - fs.renameSync(tempFilename, filename); - } catch (renameError) { - // ignore errors, it's just a cache - } - }); + + try { + fs.writeFileSync(tempFilename, contents); + fs.renameSync(tempFilename, filename); + } catch (e) { + // ignore errors, it's just a cache + this._cacheDebug(e); } } @@ -384,7 +373,7 @@ CachingCompiler = class CachingCompiler extends CachingCompilerBase { return; const cacheFilename = this._cacheFilename(cacheKey); const cacheContents = this.stringifyCompileResult(compileResult); - this._writeFileAsync(cacheFilename, cacheContents); + this._writeFile(cacheFilename, cacheContents); } // Returns null if the file does not exist or can't be parsed; otherwise diff --git a/packages/caching-compiler/multi-file-caching-compiler.js b/packages/caching-compiler/multi-file-caching-compiler.js index dcd75ac2e7..a180de2bba 100644 --- a/packages/caching-compiler/multi-file-caching-compiler.js +++ b/packages/caching-compiler/multi-file-caching-compiler.js @@ -253,6 +253,6 @@ extends CachingCompilerBase { const cacheContents = JSON.stringify(cacheEntry.cacheKeys) + '\n' + this.stringifyCompileResult(cacheEntry.compileResult); - this._writeFileAsync(cacheFilename, cacheContents); + this._writeFile(cacheFilename, cacheContents); } } diff --git a/packages/caching-compiler/package.js b/packages/caching-compiler/package.js index 3628d83a65..081db3c2fe 100644 --- a/packages/caching-compiler/package.js +++ b/packages/caching-compiler/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'caching-compiler', - version: '1.2.1', + version: '1.2.2', summary: 'An easy way to make compiler plugins cache', documentation: 'README.md' }); diff --git a/packages/jsparse/.gitignore b/packages/deprecated/jsparse/.gitignore similarity index 100% rename from packages/jsparse/.gitignore rename to packages/deprecated/jsparse/.gitignore diff --git a/packages/jsparse/README.md b/packages/deprecated/jsparse/README.md similarity index 51% rename from packages/jsparse/README.md rename to packages/deprecated/jsparse/README.md index ba75c9e81e..2ccdb1cb84 100644 --- a/packages/jsparse/README.md +++ b/packages/deprecated/jsparse/README.md @@ -2,4 +2,6 @@ [Source code of released version](https://github.com/meteor/meteor/tree/master/packages/jsparse) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/jsparse) *** -This is an internal Meteor package. \ No newline at end of file +This internal Meteor package is now unnecessary and has been deprecated. To +continue to use a working version of this package, please pin your package +version to 1.0.10 (e.g. meteor add jsparse@=1.0.10) \ No newline at end of file diff --git a/packages/deprecated/jsparse/deprecation_notice.js b/packages/deprecated/jsparse/deprecation_notice.js new file mode 100644 index 0000000000..33e82a90d8 --- /dev/null +++ b/packages/deprecated/jsparse/deprecation_notice.js @@ -0,0 +1,6 @@ +console.warn( + 'The "jsparse" package is now unnecessary and has been deprecated.\n' + + '\n' + + 'To continue to use a working version of this package, please pin your\n' + + 'package version to 1.0.10 (e.g. meteor add jsparse@=1.0.10).\n' +); diff --git a/packages/deprecated/jsparse/package.js b/packages/deprecated/jsparse/package.js new file mode 100644 index 0000000000..7e01fea896 --- /dev/null +++ b/packages/deprecated/jsparse/package.js @@ -0,0 +1,8 @@ +Package.describe({ + summary: "(Deprecated) Full-featured JavaScript parser", + version: "2.0.0" +}); + +Package.onUse(function (api) { + api.addFiles('deprecation_notice.js', 'server'); +}); diff --git a/packages/deprecated/markdown/package.js b/packages/deprecated/markdown/package.js index 4c5dc2638b..7f9e510a4f 100644 --- a/packages/deprecated/markdown/package.js +++ b/packages/deprecated/markdown/package.js @@ -2,7 +2,7 @@ Package.describe({ summary: "Markdown-to-HTML processor", - version: "1.0.12" + version: "1.0.13" }); Package.onUse(function (api) { diff --git a/packages/deprecated/markdown/showdown.js b/packages/deprecated/markdown/showdown.js index 50c0660442..2c0d0f0782 100644 --- a/packages/deprecated/markdown/showdown.js +++ b/packages/deprecated/markdown/showdown.js @@ -118,7 +118,7 @@ var g_output_modifiers = []; // Automatic Extension Loading (node only): // -if (typeof module !== 'undefind' && typeof exports !== 'undefined' && typeof require !== 'undefind') { +if (typeof module !== 'undefined' && typeof exports !== 'undefined' && typeof require !== 'undefind') { var fs = require('fs'); if (fs) { diff --git a/packages/meyerweb-reset/.gitignore b/packages/deprecated/meyerweb-reset/.gitignore similarity index 100% rename from packages/meyerweb-reset/.gitignore rename to packages/deprecated/meyerweb-reset/.gitignore diff --git a/packages/meyerweb-reset/README.md b/packages/deprecated/meyerweb-reset/README.md similarity index 53% rename from packages/meyerweb-reset/README.md rename to packages/deprecated/meyerweb-reset/README.md index a9bb580e4e..74c06454b4 100644 --- a/packages/meyerweb-reset/README.md +++ b/packages/deprecated/meyerweb-reset/README.md @@ -2,4 +2,6 @@ [Source code of released version](https://github.com/meteor/meteor/tree/master/packages/meyerweb-reset) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/meyerweb-reset) *** -This is an internal Meteor package. \ No newline at end of file +This internal Meteor package is now unnecessary and has been deprecated. To +continue to use a working version of this package, please pin your package +version to 1.0.7 (e.g. meteor add meyerweb-reset@=1.0.7) \ No newline at end of file diff --git a/packages/deprecated/meyerweb-reset/deprecation_notice.js b/packages/deprecated/meyerweb-reset/deprecation_notice.js new file mode 100644 index 0000000000..739d4d2c48 --- /dev/null +++ b/packages/deprecated/meyerweb-reset/deprecation_notice.js @@ -0,0 +1,6 @@ +console.warn( + 'The "meyerweb-reset" package is now unnecessary and has been deprecated.\n', + '\n', + 'To continue to use a working version of this package, please pin your\n', + 'package version to 1.0.7 (e.g. meteor add meyerweb-reset@=1.0.7).\n' +); diff --git a/packages/meyerweb-reset/package.js b/packages/deprecated/meyerweb-reset/package.js similarity index 62% rename from packages/meyerweb-reset/package.js rename to packages/deprecated/meyerweb-reset/package.js index 36e04ad154..dec2e88d92 100644 --- a/packages/meyerweb-reset/package.js +++ b/packages/deprecated/meyerweb-reset/package.js @@ -2,10 +2,10 @@ // files. I've marked it internal because I'm not sure if we want to // encourage this pattern. Maybe another solution would be better. Package.describe({ - summary: "reset.css v2.0 from http://meyerweb.com/eric/tools/css/reset/", - version: "1.0.7" + summary: "(Deprecated) reset.css v2.0 from http://meyerweb.com/eric/tools/css/reset/", + version: "2.0.0" }); Package.onUse(function (api) { - api.addFiles("reset.css", "client"); + api.addFiles('deprecation_notice.js', 'server'); }); diff --git a/packages/dynamic-import/package.js b/packages/dynamic-import/package.js index 0c87536f80..6fb1edbdf3 100644 --- a/packages/dynamic-import/package.js +++ b/packages/dynamic-import/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "dynamic-import", - version: "0.5.1", + version: "0.5.2", summary: "Runtime support for Meteor 1.5 dynamic import(...) syntax", documentation: "README.md" }); diff --git a/packages/dynamic-import/server.js b/packages/dynamic-import/server.js index a580def62b..8854b205f5 100644 --- a/packages/dynamic-import/server.js +++ b/packages/dynamic-import/server.js @@ -8,7 +8,6 @@ const { } = require("path"); const { fetchURL } = require("./common.js"); const { Meteor } = require("meteor/meteor"); -const { isModern } = require("meteor/modern-browsers"); const hasOwn = Object.prototype.hasOwnProperty; require("./security.js"); @@ -112,27 +111,19 @@ function middleware(request, response) { } function getPlatform(request) { - const { identifyBrowser } = Package.webapp.WebAppInternals; - const browser = identifyBrowser(request.headers["user-agent"]); - let platform = isModern(browser) - ? "web.browser" - : "web.browser.legacy"; - // If the __dynamicImport request includes a secret key, and it matches // dynamicImportInfo[platform].key, use platform instead of the default // platform, web.browser. const secretKey = request.query.key; - if (typeof secretKey === "string") { - Object.keys(dynamicImportInfo).some(p => { + for (const p of Object.keys(dynamicImportInfo)) { if (secretKey === dynamicImportInfo[p].key) { - platform = p; - return true; + return p; } - }); + } } - return platform; + return Package.webapp.WebApp.categorizeRequest(request).arch; } function readTree(tree, platform) { diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index 6926bff940..16cac4465e 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.14.2', + version: '0.14.3', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); diff --git a/packages/ecmascript/transpilation-tests.js b/packages/ecmascript/transpilation-tests.js index f961e7c335..e7fff88d48 100644 --- a/packages/ecmascript/transpilation-tests.js +++ b/packages/ecmascript/transpilation-tests.js @@ -120,9 +120,3 @@ class Foo { test.isTrue(/helpers\/(builtin\/)?createClass/.test(output)); }); - -Tinytest.add("ecmascript - transpilation - flow", (test) => { - const output = transform( - 'var foo = function (one: any, two: number, three?): string {};'); - test.isTrue(contains(output, '(one, two, three)')); -}); diff --git a/packages/jsparse/lexer.js b/packages/jsparse/lexer.js deleted file mode 100644 index 6a4fdb75b7..0000000000 --- a/packages/jsparse/lexer.js +++ /dev/null @@ -1,420 +0,0 @@ -var regexEscape = function (str) { - return str.replace(/[\][^$\\.*+?(){}|]/g, '\\$&'); -}; - -// Adapted from source code of http://xregexp.com/plugins/#unicode -var unicodeCategories = { - Ll: "0061-007A00B500DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F05210523052505270561-05871D00-1D2B1D6B-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7B2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2CF32D00-2D252D272D2DA641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA661A663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CA78EA791A793A7A1A7A3A7A5A7A7A7A9A7FAFB00-FB06FB13-FB17FF41-FF5A", - Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D6A1D781D9B-1DBF2071207F2090-209C2C7C2C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A7F8A7F9A9CFAA70AADDAAF3AAF4FF70FF9EFF9F", - Lo: "00AA00BA01BB01C0-01C3029405D0-05EA05F0-05F20620-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150840-085808A008A2-08AC0904-0939093D09500958-09610972-09770979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10CF10CF20D05-0D0C0D0E-0D100D12-0D3A0D3D0D4E0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC-0EDF0F000F40-0F470F49-0F6C0F88-0F8C1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA10FD-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1BBA-1BE51C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF11CF51CF62135-21382D30-2D672D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31BA31F0-31FF3400-4DB54E00-9FCCA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCAAE0-AAEAAAF2AB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2EABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", - Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC", - Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E05200522052405260531-055610A0-10C510C710CD1E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CED2CF2A640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA660A662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BA78DA790A792A7A0A7A2A7A4A7A6A7A8A7AAFF21-FF3A", - Mc: "0903093B093E-09400949-094C094E094F0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1BAC1BAD1BE71BEA-1BEC1BEE1BF21BF31C24-1C2B1C341C351CE11CF21CF3302E302FA823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BAAEBAAEEAAEFAAF5ABE3ABE4ABE6ABE7ABE9ABEAABEC", - Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065F067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0859-085B08E4-08FE0900-0902093A093C0941-0948094D0951-095709620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F8D-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135D-135F1712-17141732-1734175217531772177317B417B517B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91BAB1BE61BE81BE91BED1BEF-1BF11C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1CF41DC0-1DE61DFC-1DFF20D0-20DC20E120E5-20F02CEF-2CF12D7F2DE0-2DFF302A-302D3099309AA66FA674-A67DA69FA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1AAECAAEDAAF6ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26", - Nd: "0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19D91A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", - Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF", - Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F" -}; - -var unicodeClass = function (abbrev) { - return '[' + - unicodeCategories[abbrev].replace(/[0-9A-F]{4}/ig, "\\u$&") + ']'; -}; - -// See ECMA-262 spec, 3rd edition, section 7 - -// Section 7.2 -// Match one or more characters of whitespace, excluding line terminators. -// Do this by matching reluctantly, stopping at a non-dot (line terminator -// or end of string) or a non-whitespace. -// We are taking advantage of the fact that we are parsing JS from JS in -// regexes like this by "passing through" the spec's definition of whitespace, -// which is the same in regexes and the lexical grammar. -var rWhiteSpace = /[^\S\u000A\u000D\u2028\u2029]+/g; -// Section 7.3 -// Match one line terminator. Same as (?!.)[\s\S] but more explicit. -var rLineTerminator = /[\u000A\u000D\u2028\u2029]/g; -// Section 7.4 -// Match one multi-line comment. -// [\s\S] is shorthand for any character, including newlines. -// The *? reluctant qualifier makes this easy. -var rMultiLineComment = /\/\*[\s\S]*?\*\//g; -// Match one single-line comment, not including the line terminator. -var rSingleLineComment = /\/\/.*/g; -// Section 7.6 -// Match one or more characters that can start an identifier. -// This is IdentifierStart+. -var rIdentifierPrefix = new RegExp( - "([a-zA-Z$_]+|\\\\u[0-9a-fA-F]{4}|" + - [unicodeClass('Lu'), unicodeClass('Ll'), unicodeClass('Lt'), - unicodeClass('Lm'), unicodeClass('Lo'), unicodeClass('Nl')].join('|') + - ")+", 'g'); -// Match one or more characters that can continue an identifier. -// This is (IdentifierPart and not IdentifierStart)+. -// To match a full identifier, match rIdentifierPrefix, then -// match rIdentifierMiddle followed by rIdentifierPrefix until they both fail. -var rIdentifierMiddle = new RegExp( - "([0-9]|" + [unicodeClass('Mn'), unicodeClass('Mc'), unicodeClass('Nd'), - unicodeClass('Pc')].join('|') + ")+", 'g'); -// Section 7.7 -// Match one punctuator (except for division punctuators). -var rPunctuator = new RegExp( - regexEscape("{ } ( ) [ ] . ; , < > <= >= == != === !== + - * % ++ -- << >> "+ - ">>> & | ^ ! ~ && || ? : = += -= *= %= <<= >>= >>>= &= |= ^=") - // sort from longest to shortest so that we don't match '==' for '===' and - // '*' for '*=', etc. - .split(' ').sort(function (a,b) { return b.length - a.length; }) - .join('|'), 'g'); -var rDivPunctuator = /\/=?/g; -// Section 7.8.3 -var rHexLiteral = /0[xX][0-9a-fA-F]+(?!\w)/g; -var rOctLiteral = /0[0-7]+(?!\w)/g; // deprecated -var rDecLiteral = - /(((0|[1-9][0-9]*)(\.[0-9]*)?)|\.[0-9]+)([Ee][+-]?[0-9]+)?(?!\w)/g; -// Section 7.8.4 -var rStringQuote = /["']/g; -// Match one or more characters besides quotes, backslashes, or line ends -var rStringMiddle = /(?=.)[^"'\\]+?((?!.)|(?=["'\\]))/g; -// Match one escape sequence, including the backslash. -var rEscapeSequence = - /\\(['"\\bfnrtv]|0(?![0-9])|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|(?=.)[^ux0-9])/g; -// Match one ES5 line continuation -var rLineContinuation = - /\\(\r\n|[\u000A\u000D\u2028\u2029])/g; -// Section 7.8.5 -// Match one regex literal, including slashes, not including flags. -// Support unescaped '/' in character classes, per 5th ed. -// For example: `/[/]/` will match the string `"/"`. -// -// Explanation of regex: -// - Match `/` not followed by `/` or `*` -// - Match one or more of any of these: -// - Backslash followed by one non-newline -// - One non-newline, not `[` or `\` or `/` -// - A character class, beginning with `[` and ending with `]`. -// In the middle is zero or more of any of these: -// - Backslash followed by one non-newline -// - One non-newline, not `]` or `\` -// - Match closing `/` -var rRegexLiteral = - /\/(?![*\/])(\\.|(?=.)[^\[\/\\]|\[(\\.|(?=.)[^\]\\])*\])+\//g; -var rRegexFlags = /[a-zA-Z]*/g; - -var rDecider = - /((?=.)\s)|(\/[\/\*]?)|([\][{}();,<>=!+*%&|^~?:-]|\.(?![0-9]))|([\d.])|(["'])|(.)|([\S\s])/g; - -var keywordLookup = { - ' break': 'KEYWORD', - ' case': 'KEYWORD', - ' catch': 'KEYWORD', - ' continue': 'KEYWORD', - ' debugger': 'KEYWORD', - ' default': 'KEYWORD', - ' delete': 'KEYWORD', - ' do': 'KEYWORD', - ' else': 'KEYWORD', - ' finally': 'KEYWORD', - ' for': 'KEYWORD', - ' function': 'KEYWORD', - ' if': 'KEYWORD', - ' in': 'KEYWORD', - ' instanceof': 'KEYWORD', - ' new': 'KEYWORD', - ' return': 'KEYWORD', - ' switch': 'KEYWORD', - ' this': 'KEYWORD', - ' throw': 'KEYWORD', - ' try': 'KEYWORD', - ' typeof': 'KEYWORD', - ' var': 'KEYWORD', - ' void': 'KEYWORD', - ' while': 'KEYWORD', - ' with': 'KEYWORD', - - ' false': 'BOOLEAN', - ' true': 'BOOLEAN', - - ' null': 'NULL' -}; - -var makeSet = function (array) { - var s = {}; - for (var i = 0, N = array.length; i < N; i++) - s[array[i]] = true; - return s; -}; - -var nonTokenTypes = makeSet('WHITESPACE COMMENT NEWLINE EOF ERROR'.split(' ')); - -var punctuationBeforeDivision = makeSet('] ) } ++ --'.split(' ')); -var keywordsBeforeDivision = makeSet('this'.split(' ')); - -var guessIsDivisionPermittedAfterToken = function (tok) { - // Figure out if a '/' character should be interpreted as division - // rather than the start of a regular expression when it follows the - // token, which must be a token lexeme per isToken(). - // The beginning of section 7 of the spec briefly - // explains what's going on; basically the lexical grammar can't - // distinguish, for example, `e/f/g` (division) from `e=/f/g` - // (assignment of a regular expression), among many other variations. - // - // THIS IS ONLY A HEURISTIC, though it will rarely fail. - // Here are the two cases I know of where help from the parser is needed: - // - if (foo) - // /ba/.test("banana") && console.log("matches"); - // (Close paren of a control structure before a statement starting with - // a regex literal. Starting a statement with a regex literal is - // unusual, of course, because it's hard to have a side effect.) - // - ++ /foo/.abc - // (Prefix `++` or `--` before an expression starting with a regex - // literal. This will run but I can't see any use for it.) - switch (tok.type()) { - case "PUNCTUATION": - // few punctuators can end an expression, but e.g. `)` - return !! punctuationBeforeDivision[tok.text()]; - case "KEYWORD": - // few keywords can end an expression, but e.g. `this` - return !! keywordsBeforeDivision[tok.text()]; - case "IDENTIFIER": - return true; - default: // literal - return true; - } -}; - -////////// PUBLIC API - -var Lexeme = function (pos, type, text) { - this._pos = pos; - this._type = type; - this._text = text; -}; - -Lexeme.prototype.startPos = function () { - return this._pos; -}; - -Lexeme.prototype.endPos = function () { - return this._pos + this._text.length; -}; - -Lexeme.prototype.type = function () { - return this._type; -}; - -Lexeme.prototype.text = function () { - return this._text; -}; - -Lexeme.prototype.isToken = function () { - return ! nonTokenTypes[this._type]; -}; - -Lexeme.prototype.isError = function () { - return this._type === "ERROR"; -}; - -Lexeme.prototype.isEOF = function () { - return this._type === "EOF"; -}; - -Lexeme.prototype.prev = function () { - return this._prev; -}; - -Lexeme.prototype.next = function () { - return this._next; -}; - -Lexeme.prototype.toString = function () { - return this.isError() ? "ERROR" : - this.isEOF() ? "EOF" : "`" + this.text() + "`"; -}; - -// Create a Lexer for the given string of JavaScript code. -// -// A lexer keeps a pointer `pos` into the string that is -// advanced when you ask for the next lexeme with `next()`. -// -// XXXXX UPDATE DOCS -// Properties: -// code: Original JavaScript code string. -// pos: Current index into the string. You can assign to it -// to continue lexing from a different position. After -// calling next(), it is the ending index of the most -// recent lexeme. -// lastPos: The starting index of the most recent lexeme. -// Equal to `pos - text.length`. -// text: Text of the last lexeme as a string. -// type: Type of the last lexeme, as returned by `next()`. -// divisionPermitted: Whether a '/' character should be interpreted -// as division rather than the start of a regular expression. -// This flag is set automatically during lexing based on the -// previous token (i.e. the most recent token lexeme), but -// it is technically only a heuristic. -// Thie flag can be read and set manually to affect the -// parsing of the next token. - -JSLexer = function (code) { - this.code = code; - this.pos = 0; - this.divisionPermitted = false; - this.lastLexeme = null; -}; - -JSLexer.Lexeme = Lexeme; - -// XXXX UPDATE DOCS -// Return the type of the next of lexeme starting at `pos`, and advance -// `pos` to the end of the lexeme. The text of the lexeme is available -// in `text`. The text is always the substring of `code` between the -// old and new values of `pos`. An "EOF" lexeme terminates -// the stream. "ERROR" lexemes indicate a bad input string. Out of all -// lexemes, only "EOF" has empty text, and it always has empty text. -// All others contain at least one character from the source code. -// -// Lexeme types: -// Literals: BOOLEAN, NULL, REGEX, NUMBER, STRING -// Whitespace-like: WHITESPACE, COMMENT, NEWLINE, EOF -// Other Tokens: IDENTIFIER, KEYWORD, PUNCTUATION -// ... and ERROR - -JSLexer.prototype.next = function () { - var self = this; - var code = self.code; - var origPos = self.pos; - var divisionPermitted = self.divisionPermitted; - - if (origPos > code.length) - throw new Error("out of range"); - - // Running regexes inside this function will move this local - // `pos` forward. - // When we commit to emitting a lexeme, we'll set self.pos - // based on it. - var pos = origPos; - - // Emit a lexeme. Always called as `return lexeme(type)`. - var lexeme = function (type) { - // If `pos` hasn't moved, we consider this an error. - // This means that grammar cases that only run one regex - // or an alternation ('||') of regexes don't need to - // check for failure. - // This also guarantees that only EOF lexemes are empty. - if (pos === origPos && type !== 'EOF') { - type = 'ERROR'; - pos = origPos + 1; - } - self.pos = pos; - var lex = new JSLexer.Lexeme(origPos, type, code.substring(origPos, pos)); - if (self.lastLexeme) { - self.lastLexeme._next = lex; - lex._prev = self.lastLexeme; - } - self.lastLexeme = lex; - if (lex.isToken()) - self.divisionPermitted = guessIsDivisionPermittedAfterToken(lex); - return lex; - }; - - if (pos === code.length) - return lexeme('EOF'); - - // Result of the regex match in the most recent call to `run`. - var match = null; - - // Run a regex starting from `pos`, recording the end of the matched - // string in `pos` and the match data in `match`. The regex must have - // the 'g' (global) flag. If it doesn't match at `pos`, set `match` - // to null. The caller should expect the regex to match at `pos`, as - // failure is too expensive to run in a tight loop. - var run = function (regex) { - // Cause regex matching to start at `pos`. - regex.lastIndex = pos; - match = regex.exec(code); - // Simulate "sticky" matching by throwing out the match if it - // didn't match exactly at `pos`. If it didn't, we may have - // just searched the entire string. - if (match && (match.index !== pos)) - match = null; - // Record the end position of the match back into `pos`. - // Avoid an IE7 bug where lastIndex is incremented when - // the match has 0 length. - if (match && match[0].length !== 0) - pos = regex.lastIndex; - return match; - }; - - // Decide which case of the grammar we are in based on one or two - // characters, then roll back `pos`. - run(rDecider); - pos = origPos; - - // Grammar cases - if (match[1]) { // \s - run(rWhiteSpace); - return lexeme('WHITESPACE'); - } - if (match[2]) { // one of //, /*, / - if (match[2] === '//') { - run(rSingleLineComment); - return lexeme('COMMENT'); - } - if (match[2] === '/*') { - run(rMultiLineComment); - return lexeme(match ? 'COMMENT' : 'ERROR'); - } - if (match[2] === '/') { - if (divisionPermitted) { - run(rDivPunctuator); - return lexeme('PUNCTUATION'); - } else { - run(rRegexLiteral); - if (! match) - return lexeme('ERROR'); - run(rRegexFlags); - return lexeme('REGEX'); - } - } - } - if (match[3]) { // any other punctuation char - run(rPunctuator); - return lexeme(match ? 'PUNCTUATION' : 'ERROR'); - } - if (match[4]) { // 0-9 - run(rDecLiteral) || run(rHexLiteral) || run(rOctLiteral); - return lexeme(match ? 'NUMBER' : 'ERROR'); - } - if (match[5]) { // " or ' - run(rStringQuote); - var quote = match[0]; - do { - run(rStringMiddle) || run(rEscapeSequence) || - run(rLineContinuation) || run(rStringQuote); - } while (match && match[0] !== quote); - if (! (match && match[0] === quote)) - return lexeme('ERROR'); - return lexeme('STRING'); - } - if (match[7]) { // non-dot (line terminator) - run(rLineTerminator); - return lexeme('NEWLINE'); - } - // dot (any non-line-terminator) - run(rIdentifierPrefix); - // Use non-short-circuiting bitwise OR, '|', to always try - // both regexes in sequence, returning false only if neither - // matched. - while ((!! run(rIdentifierMiddle)) | - (!! run(rIdentifierPrefix))) { /*continue*/ } - var word = code.substring(origPos, pos); - return lexeme(keywordLookup[' '+word] || 'IDENTIFIER'); -}; - -JSLexer.prettyOffset = function (code, pos) { - var codeUpToPos = code.substring(0, pos); - var startOfLine = codeUpToPos.lastIndexOf('\n') + 1; - var indexInLine = pos - startOfLine; // 0-based - var lineNum = codeUpToPos.replace(/[^\n]+/g, '').length + 1; // 1-based - return "line " + lineNum + ", offset " + indexInLine; -}; diff --git a/packages/jsparse/package.js b/packages/jsparse/package.js deleted file mode 100644 index 5e3f58d85e..0000000000 --- a/packages/jsparse/package.js +++ /dev/null @@ -1,21 +0,0 @@ -Package.describe({ - summary: "Full-featured JavaScript parser", - version: "1.0.10" -}); - -Package.onUse(function (api) { - api.export(['JSLexer', 'JSParser', 'ParseNode']); - api.addFiles(['lexer.js', 'parserlib.js', 'stringify.js', 'parser.js'], - ['client', 'server']); -}); - -Package.onTest(function (api) { - api.use(['tinytest', 'underscore']); - api.use('jsparse', 'client'); - - api.addFiles('parser_tests.js', - // Test just on client for faster running; should run - // identically on server. - 'client'); - //['client', 'server']); -}); diff --git a/packages/jsparse/parser.js b/packages/jsparse/parser.js deleted file mode 100644 index 7fd4f0ed93..0000000000 --- a/packages/jsparse/parser.js +++ /dev/null @@ -1,838 +0,0 @@ -///// JAVASCRIPT PARSER - -// What we don't support from ECMA-262 5.1: -// - object literal trailing comma -// - object literal get/set - -var expecting = Parser.expecting; - -var assertion = Parsers.assertion; -var node = Parsers.node; -var or = Parsers.or; -var and = Parsers.and; -var not = Parsers.not; -var list = Parsers.list; -var seq = Parsers.seq; -var opt = Parsers.opt; -var constant = Parsers.constant; -var mapResult = Parsers.mapResult; - - -var makeSet = function (array) { - var s = {}; - for (var i = 0, N = array.length; i < N; i++) - s[array[i]] = true; - return s; -}; - - -JSParser = function (code, options) { - this.lexer = new JSLexer(code); - this.oldToken = null; - this.newToken = null; - this.pos = 0; - this.isLineTerminatorHere = false; - this.includeComments = false; - // the last COMMENT lexeme between oldToken and newToken - // that we've consumed, if any. - this.lastCommentConsumed = null; - - options = options || {}; - // pass {tokens:'strings'} to get strings for - // tokens instead of token objects - if (options.tokens === 'strings') { - this.tokenFunc = function (tok) { - return tok.text(); - }; - } else { - this.tokenFunc = function (tok) { - return tok; - }; - } - - // pass {includeComments: true} to include comments in the AST. For - // a comment to be included, it must occur where a series of - // statements could occur, and it must be preceded by only comments - // and whitespace on the same line. - if (options.includeComments) { - this.includeComments = true; - } -}; - -JSParser.prototype.consumeNewToken = function () { - var self = this; - var lexer = self.lexer; - self.oldToken = self.newToken; - self.isLineTerminatorHere = false; - var lex; - do { - lex = lexer.next(); - if (lex.isError()) - throw new Error("Bad token at " + - JSLexer.prettyOffset(lexer.code, lex.startPos()) + - ", text `" + lex.text() + "`"); - else if (lex.type() === "NEWLINE") - self.isLineTerminatorHere = true; - else if (lex.type() === "COMMENT" && ! /^.*$/.test(lex.text())) - // multiline comments containing line terminators count - // as line terminators. - self.isLineTerminatorHere = true; - } while (! lex.isEOF() && ! lex.isToken()); - self.newToken = lex; - self.pos = lex.startPos(); - self.lastCommentConsumed = null; -}; - -JSParser.prototype.getParseError = function (expecting, found) { - var msg = (expecting ? "Expected " + expecting : "Unexpected token"); - if (this.oldToken) - msg += " after " + this.oldToken; - var pos = this.pos; - msg += " at " + JSLexer.prettyOffset(this.lexer.code, pos); - msg += ", found " + (found || this.newToken); - return new Error(msg); -}; - -JSParser.prototype.getSyntaxTree = function () { - var self = this; - - self.consumeNewToken(); - - var NIL = new ParseNode('nil', []); - - var booleanFlaggedParser = function (parserConstructFunc) { - return { - 'false': parserConstructFunc(false), - 'true': parserConstructFunc(true) - }; - }; - - // Takes a space-separated list of either punctuation or keyword tokens - var lookAheadToken = function (tokens) { - var type = (/\w/.test(tokens) ? 'KEYWORD' : 'PUNCTUATION'); - var textSet = makeSet(tokens.split(' ')); - return expecting( - tokens.split(' ').join(', '), - assertion(function (t) { - return (t.newToken.type() === type && textSet[t.newToken.text()]); - })); - }; - - var lookAheadTokenType = function (type) { - return expecting(type, assertion(function (t) { - return t.newToken.type() === type; - })); - }; - - // Takes a space-separated list of either punctuation or keyword tokens - var token = function (tokens) { - var type = (/\w/.test(tokens) ? 'KEYWORD' : 'PUNCTUATION'); - var textSet = makeSet(tokens.split(' ')); - return new Parser( - tokens.split(' ').join(', '), - function (t) { - if (t.newToken.type() === type && textSet[t.newToken.text()]) { - t.consumeNewToken(); - return self.tokenFunc(t.oldToken); - } - return null; - }); - }; - - var tokenType = function (type) { - return new Parser(type, function (t) { - if (t.newToken.type() === type) { - t.consumeNewToken(); - return self.tokenFunc(t.oldToken); - } - return null; - }); - }; - - var noLineTerminatorHere = expecting( - 'noLineTerminator', assertion(function (t) { - return ! t.isLineTerminatorHere; - })); - - var nonLHSExpressionNames = makeSet( - 'unary binary postfix ternary assignment comma'.split(' ')); - var isExpressionLHS = function (exprNode) { - return ! nonLHSExpressionNames[exprNode.name]; - }; - - // Like token, but marks tokens that need to defy the lexer's - // heuristic about whether the next '/' is a division or - // starts a regex. - var preSlashToken = function (text, divisionNotRegex) { - var inner = token(text); - return new Parser( - inner.expecting, - function (t) { - // temporarily set divisionPermitted, - // restoring it if we don't match. - var oldValue = t.lexer.divisionPermitted; - var result; - try { - t.lexer.divisionPermitted = divisionNotRegex; - result = inner.parse(t); - return result; - } finally { - if (! result) - t.lexer.divisionPermitted = oldValue; - } - }); - }; - - // Mark some productions "lazy" to allow grammar circularity, i.e. accessing - // later parsers from earlier ones. - // These lazy versions will be replaced with real ones, which they will - // access when run. - var expressionMaybeNoIn = { - 'false': Parsers.lazy( - 'expression', - function () { return expressionMaybeNoIn[false]; }), - 'true': Parsers.lazy( - 'expression', - function () { return expressionMaybeNoIn[true]; }) - }; - var expression = expressionMaybeNoIn[false]; - - var assignmentExpressionMaybeNoIn = { - 'false': Parsers.lazy( - 'expression', - function () { return assignmentExpressionMaybeNoIn[false]; }), - 'true': Parsers.lazy( - 'expression', - function () { return assignmentExpressionMaybeNoIn[true]; }) - }; - var assignmentExpression = assignmentExpressionMaybeNoIn[false]; - - var functionBody = Parsers.lazy( - 'statement', function () { return functionBody; }); - var statement = Parsers.lazy( - 'statement', function () { return statement; }); - //// - - var arrayLiteral = - node('array', - seq(token('['), - opt(list(token(','))), - or( - lookAheadToken(']'), - list( - expecting( - 'expression', - or(assignmentExpression, - // count a peeked-at ']' as an expression - // to support elisions at end, e.g. - // `[1,2,3,,,,,,]`. - lookAheadToken(']'))), - // list seperator is one or more commas - // to support elision - list(token(',')))), - token(']'))); - - // "IdentifierName" in ES5 allows reserved words, like in a property access - // or a key of an object literal. - // Put IDENTIFIER last so it shows up in the error message. - var identifierName = or(tokenType('NULL'), tokenType('BOOLEAN'), - tokenType('KEYWORD'), tokenType('IDENTIFIER')); - - var propertyName = expecting('propertyName', or( - node('idPropName', identifierName), - node('numPropName', tokenType('NUMBER')), - node('strPropName', tokenType('STRING')))); - var nameColonValue = expecting( - 'propertyName', - node('prop', seq(propertyName, token(':'), assignmentExpression))); - - // Allow trailing comma in object literal, per ES5. Trailing comma - // must follow a `name:value`, that is, `{,}` is invalid. - // - // We can't just use a normal comma list(), because it will seize - // on the comma as a sign that the list continues. Instead, - // we specify a list of either ',' or nameColonValue, using positive - // and negative lookAheads to constrain the sequence. The grammar - // is ordered so that error messages will always say - // "Expected propertyName" or "Expected ," as appropriate, not - // "Expected ," when the look-ahead is negative or "Expected }". - var objectLiteral = - node('object', - seq(token('{'), - or(lookAheadToken('}'), - and(not(lookAheadToken(',')), - list(or(seq(token(','), - expecting('propertyName', - not(lookAheadToken(',')))), - seq(nameColonValue, - or(lookAheadToken('}'), - lookAheadToken(','))))))), - expecting('propertyName', token('}')))); - - var functionMaybeNameRequired = booleanFlaggedParser( - function (nameRequired) { - return seq(token('function'), - (nameRequired ? tokenType('IDENTIFIER') : - or(tokenType('IDENTIFIER'), - and(lookAheadToken('('), constant(NIL)))), - token('('), - or(lookAheadToken(')'), - list(tokenType('IDENTIFIER'), token(','))), - token(')'), - token('{'), - functionBody, - token('}')); - }); - var functionExpression = node('functionExpr', - functionMaybeNameRequired[false]); - - var primaryOrFunctionExpression = - expecting('expression', - or(node('this', token('this')), - node('identifier', tokenType('IDENTIFIER')), - node('number', tokenType('NUMBER')), - node('boolean', tokenType('BOOLEAN')), - node('null', tokenType('NULL')), - node('regex', tokenType('REGEX')), - node('string', tokenType('STRING')), - node('parens', - seq(token('('), expression, token(')'))), - arrayLiteral, - objectLiteral, - functionExpression)); - - - var dotEnding = seq(token('.'), identifierName); - var bracketEnding = seq(token('['), expression, token(']')); - var callArgs = seq(token('('), - or(lookAheadToken(')'), - list(assignmentExpression, - token(','))), - token(')')); - - var newKeyword = token('new'); - - // This is a completely equivalent refactor of the spec's production - // for a LeftHandSideExpression. - // - // An lhsExpression is basically an expression that can serve as - // the left-hand-side of an assignment, though function calls and - // "new" invocation are included because they have the same - // precedence. Actually, the spec technically allows a function - // call to "return" a valid l-value, as in `foo(bar) = baz`, - // though no built-in or user-specifiable call has this property - // (it would have to be defined by a browser or other "host"). - var lhsExpression = new Parser( - 'expression', - function (t) { - // Accumulate all initial "new" keywords, not yet knowing - // if they have a corresponding argument list later. - var news = []; - var n; - while ((n = newKeyword.parse(t))) - news.push(n); - - // Read the primaryOrFunctionExpression that will be the "core" - // of this lhsExpression. It is preceded by zero or more `new` - // keywords, and followed by any sequence of (...), [...], - // and .foo add-ons. - // if we have 'new' keywords, we are committed and must - // match an expression or error. - var result = primaryOrFunctionExpression.parseRequiredIf(t, news.length); - if (! result) - return null; - - // Our plan of attack is to apply each dot, bracket, or call - // as we come across it. Whether a call is a `new` call depends - // on whether there are `new` keywords we haven't used. If so, - // we pop one off the stack. - var done = false; - while (! done) { - var r; - if ((r = dotEnding.parse(t))) { - result = new ParseNode('dot', [result].concat(r)); - } else if ((r = bracketEnding.parse(t))) { - result = new ParseNode('bracket', [result].concat(r)); - } else if ((r = callArgs.parse(t))) { - if (news.length) - result = new ParseNode('newcall', [news.pop(), result].concat(r)); - else - result = new ParseNode('call', [result].concat(r)); - } else { - done = true; - } - } - - // There may be more `new` keywords than calls, which is how - // paren-less constructions (`new Date`) are parsed. We've - // already handled `new foo().bar()`, now handle `new new foo().bar`. - while (news.length) - result = new ParseNode('new', [news.pop(), result]); - - return result; - }); - - var postfixToken = token('++ --'); - var postfixLookahead = lookAheadToken('++ --'); - var postfixExpression = expecting( - 'expression', - mapResult(seq(lhsExpression, - opt(and(noLineTerminatorHere, - postfixLookahead, - postfixToken))), - function (v) { - if (v.length === 1) - return v[0]; - return new ParseNode('postfix', v); - })); - - var unaryExpression = Parsers.unary( - 'unary', postfixExpression, - or(token('delete void typeof'), - preSlashToken('++ -- + - ~ !', false))); - - // The "noIn" business is all to facilitate parsing - // of for-in constructs, though the cases that make - // this required are quite obscure. - // The `for(var x in y)` form is allowed to take - // an initializer for `x` (which is only useful for - // its side effects, or if `y` has no properties). - // So an example might be: - // `for(var x = a().b in c);` - // In this example, `var x = a().b` is parsed without - // the `in`, which would otherwise be part of the - // varDecl, using varDeclNoIn. - - // Our binaryExpression is the spec's LogicalORExpression, - // which includes all the higher-precendence operators. - var binaryExpressionMaybeNoIn = booleanFlaggedParser( - function (noIn) { - // high to low precedence - var binaryOps = [token('* / %'), - token('+ -'), - token('<< >> >>>'), - or(token('< > <= >='), - noIn ? token('instanceof') : - token('instanceof in')), - token('== != === !=='), - token('&'), - token('^'), - token('|'), - token('&&'), - token('||')]; - return expecting( - 'expression', - Parsers.binaryLeft('binary', unaryExpression, binaryOps)); - }); - var binaryExpression = binaryExpressionMaybeNoIn[false]; - - var conditionalExpressionMaybeNoIn = booleanFlaggedParser( - function (noIn) { - return expecting( - 'expression', - mapResult( - seq(binaryExpressionMaybeNoIn[noIn], - opt(seq( - token('?'), - assignmentExpression, token(':'), - assignmentExpressionMaybeNoIn[noIn]))), - function (v) { - if (v.length === 1) - return v[0]; - return new ParseNode('ternary', v); - })); - }); - var conditionalExpression = conditionalExpressionMaybeNoIn[false]; - - var assignOp = token('= *= /= %= += -= <<= >>= >>>= &= ^= |='); - - assignmentExpressionMaybeNoIn = booleanFlaggedParser( - function (noIn) { - return new Parser( - 'expression', - function (t) { - var r = conditionalExpressionMaybeNoIn[noIn].parse(t); - if (! r) - return null; - - // Assignment is right-associative. - // Plan of attack: make a list of all the parts - // [expression, op, expression, op, ... expression] - // and then fold them up at the end. - var parts = [r]; - var op; - while (isExpressionLHS(r) &&(op = assignOp.parse(t))) - parts.push(op, - conditionalExpressionMaybeNoIn[noIn].parseRequired(t)); - - var result = parts.pop(); - while (parts.length) { - op = parts.pop(); - var lhs = parts.pop(); - result = new ParseNode('assignment', [lhs, op, result]); - } - return result; - }); - }); - assignmentExpression = assignmentExpressionMaybeNoIn[false]; - - expressionMaybeNoIn = booleanFlaggedParser( - function (noIn) { - return expecting( - 'expression', - mapResult( - list(assignmentExpressionMaybeNoIn[noIn], token(',')), - function (v) { - if (v.length === 1) - return v[0]; - return new ParseNode('comma', v); - })); - }); - expression = expressionMaybeNoIn[false]; - - // STATEMENTS - - var comment = node('comment', new Parser(null, function (t) { - if (! t.includeComments) - return null; - - // Match a COMMENT lexeme between oldToken and newToken. - // - // This is an unusual Parser because it doesn't match and consume - // newToken, but instead uses the next()/prev() API on lexemes. - // It assumes it can walk the linked list backwards from newToken - // (though not necessarily forwards). - // - // We start at the last comment we've visited for this - // oldToken/newToken pair, if any, or else oldToken, or else the - // beginning of the token stream. We ignore comments that are - // preceded by any non-comment source code on the same line. - var lexeme = (t.lastCommentConsumed || t.oldToken || null); - if (! lexeme) { - // no oldToken, must be on first token. walk backwards - // to start with first lexeme (which may be a comment - // or whitespace) - lexeme = t.newToken; - while (lexeme.prev()) - lexeme = lexeme.prev(); - } else { - // start with lexeme after last token or comment consumed - lexeme = lexeme.next(); - } - var seenNewline = ((! t.oldToken) || t.lastCommentConsumed || false); - while (lexeme !== t.newToken) { - var type = lexeme.type(); - if (type === "NEWLINE") { - seenNewline = true; - } else if (type === "COMMENT") { - t.lastCommentConsumed = lexeme; - if (seenNewline) - return lexeme; - } - lexeme = lexeme.next(); - } - return null; - })); - - var statements = list(or(comment, statement)); - - // implements JavaScript's semicolon "insertion" rules - var maybeSemicolon = expecting( - 'semicolon', - or(token(';'), - and( - or( - lookAheadToken('}'), - lookAheadTokenType('EOF'), - assertion(function (t) { - return t.isLineTerminatorHere; - })), - constant(new ParseNode(';', []))))); - - var expressionStatement = node( - 'expressionStmnt', - and( - not(or(lookAheadToken('{'), lookAheadToken('function'))), - seq(expression, - expecting('semicolon', - or(maybeSemicolon, - // allow presence of colon to terminate - // statement legally, for the benefit of - // expressionOrLabelStatement. Basically assume - // an implicit semicolon. This - // is safe because a colon can never legally - // follow a semicolon anyway. - and(lookAheadToken(':'), - constant(new ParseNode(';', [])))))))); - - // it's hard to parse statement labels, as in - // `foo: x = 1`, because we can't tell from the - // first token whether we are looking at an expression - // statement or a label statement. To work around this, - // expressionOrLabelStatement parses the expression and - // then rewrites the result if it is an identifier - // followed by a colon. - var labelColonAndStatement = seq(token(':'), statement); - var noColon = expecting( - 'semicolon', not(lookAheadToken(':'))); - var expressionOrLabelStatement = new Parser( - null, - function (t) { - var exprStmnt = expressionStatement.parse(t); - if (! exprStmnt) - return null; - - var expr = exprStmnt.children[0]; - var maybeSemi = exprStmnt.children[1]; - if (expr.name !== 'identifier' || - ! (maybeSemi instanceof ParseNode)) { - // We either have a non-identifier expression or a present - // semicolon. This is not a label. - // - // Fail now if we are looking at a colon, causing an - // error message on input like `1+1:` of the same kind - // you'd get without statement label parsing. - noColon.parseRequired(t); - return exprStmnt; - } - - var rest = labelColonAndStatement.parse(t); - if (! rest) - return exprStmnt; - - return new ParseNode('labelStmnt', - [expr.children[0]].concat(rest)); - }); - - var emptyStatement = node('emptyStmnt', token(';')); // required semicolon - - var blockStatement = expecting('block', node('blockStmnt', seq( - token('{'), or(lookAheadToken('}'), statements), - token('}')))); - - var varDeclMaybeNoIn = booleanFlaggedParser(function (noIn) { - return node( - 'varDecl', - seq(tokenType('IDENTIFIER'), - opt(seq(token('='), - assignmentExpressionMaybeNoIn[noIn])))); - }); - var varDecl = varDeclMaybeNoIn[false]; - - var variableStatement = node( - 'varStmnt', - seq(token('var'), list(varDecl, token(',')), - maybeSemicolon)); - - // A paren that may be followed by a statement - // beginning with a regex literal. - var closeParenBeforeStatement = preSlashToken(')', false); - - var ifStatement = node( - 'ifStmnt', - seq(token('if'), token('('), expression, - closeParenBeforeStatement, statement, - opt(seq(token('else'), statement)))); - - var secondThirdClauses = expecting( - 'semicolon', - and(lookAheadToken(';'), - seq( - expecting('semicolon', token(';')), - or(and(lookAheadToken(';'), - constant(NIL)), - expression), - expecting('semicolon', token(';')), - or(and(lookAheadToken(')'), - constant(NIL)), - expression)))); - var inExpr = seq(token('in'), expression); - var inExprExpectingSemi = expecting('semicolon', - seq(token('in'), expression)); - var forSpec = mapResult(node( - 'forSpec', - or(seq(token('var'), - varDeclMaybeNoIn[true], - expecting( - 'commaOrIn', - or(inExpr, - seq( - or( - lookAheadToken(';'), - seq(token(','), - list(varDeclMaybeNoIn[true], token(',')))), - secondThirdClauses)))), - // get the case where the first clause is empty out of the way. - // the lookAhead's return value is the empty placeholder for the - // missing expression. - seq(and(lookAheadToken(';'), - constant(NIL)), secondThirdClauses), - // custom parser the non-var case because we have to - // read the first expression before we know if there's - // an "in". - new Parser( - null, - function (t) { - var firstExpr = expressionMaybeNoIn[true].parse(t); - if (! firstExpr) - return null; - var rest = secondThirdClauses.parse(t); - if (! rest) { - // we need a left-hand-side expression for a - // `for (x in y)` loop. - if (! isExpressionLHS(firstExpr)) - throw t.getParseError("semicolon"); - // if we don't see 'in' at this point, it's probably - // a missing semicolon - rest = inExprExpectingSemi.parseRequired(t); - } - - return [firstExpr].concat(rest); - }))), - function (clauses) { - // There are four kinds of for-loop, and we call the - // part between the parens one of forSpec, forVarSpec, - // forInSpec, and forVarInSpec. Having parsed it - // already, we rewrite the node name based on how - // many items came out. forIn and forVarIn always - // have 3 and 4 items respectively. for has 5 - // (the optional expressions are present as nils). - // forVar has 6 or more, because `for(var x;;);` - // produces [`var` `x` `;` nil `;` nil]. - var numChildren = clauses.children.length; - if (numChildren === 3) - return new ParseNode('forInSpec', clauses.children); - else if (numChildren === 4) - return new ParseNode('forVarInSpec', clauses.children); - else if (numChildren >= 6) - return new ParseNode('forVarSpec', clauses.children); - return clauses; - }); - - var iterationStatement = or( - node('doStmnt', seq(token('do'), statement, token('while'), - token('('), expression, token(')'), - maybeSemicolon)), - node('whileStmnt', seq(token('while'), token('('), expression, - closeParenBeforeStatement, statement)), - // semicolons must be real, not maybeSemicolons - node('forStmnt', seq( - token('for'), token('('), forSpec, closeParenBeforeStatement, - statement))); - - var returnStatement = node( - 'returnStmnt', - seq(token('return'), or( - and(noLineTerminatorHere, expression), constant(NIL)), - maybeSemicolon)); - var continueStatement = node( - 'continueStmnt', - seq(token('continue'), or( - and(noLineTerminatorHere, tokenType('IDENTIFIER')), constant(NIL)), - maybeSemicolon)); - var breakStatement = node( - 'breakStmnt', - seq(token('break'), or( - and(noLineTerminatorHere, tokenType('IDENTIFIER')), constant(NIL)), - maybeSemicolon)); - var throwStatement = node( - 'throwStmnt', - seq(token('throw'), - and(or(noLineTerminatorHere, - // If there is a line break here and more tokens after, - // we want to error appropriately. `throw \n e` should - // complain about the "end of line", not the `e`. - and(not(lookAheadTokenType("EOF")), - new Parser(null, - function (t) { - throw t.getParseError('expression', 'end of line'); - }))), - expression), - maybeSemicolon)); - - var withStatement = node( - 'withStmnt', - seq(token('with'), token('('), expression, closeParenBeforeStatement, - statement)); - - var switchCase = node( - 'case', - seq(token('case'), expression, token(':'), - or(lookAheadToken('}'), - lookAheadToken('case default'), - statements))); - var switchDefault = node( - 'default', - seq(token('default'), token(':'), - or(lookAheadToken('}'), - lookAheadToken('case'), - statements))); - - var switchStatement = node( - 'switchStmnt', - seq(token('switch'), token('('), expression, token(')'), - token('{'), - or(lookAheadToken('}'), - lookAheadToken('default'), - list(switchCase)), - opt(seq(switchDefault, - opt(list(switchCase)))), - token('}'))); - - var catchFinally = expecting( - 'catch', - and(lookAheadToken('catch finally'), - seq( - or(node( - 'catch', - seq(token('catch'), token('('), tokenType('IDENTIFIER'), - token(')'), blockStatement)), - constant(NIL)), - or(node( - 'finally', - seq(token('finally'), blockStatement)), - constant(NIL))))); - var tryStatement = node( - 'tryStmnt', - seq(token('try'), blockStatement, catchFinally)); - var debuggerStatement = node( - 'debuggerStmnt', seq(token('debugger'), maybeSemicolon)); - - statement = expecting('statement', - or(expressionOrLabelStatement, - emptyStatement, - blockStatement, - variableStatement, - ifStatement, - iterationStatement, - returnStatement, - continueStatement, - breakStatement, - withStatement, - switchStatement, - throwStatement, - tryStatement, - debuggerStatement)); - - // PROGRAM - - var functionDecl = node( - 'functionDecl', functionMaybeNameRequired[true]); - - // Look for statement before functionDecl, to catch comments in - // includeComments mode. A statement can't start with 'function' - // anyway, so the order doesn't matter otherwise. - var sourceElement = or(statement, functionDecl); - var sourceElements = list(or(comment, sourceElement)); - - functionBody = expecting( - 'functionBody', or(lookAheadToken('}'), sourceElements)); - - var program = node( - 'program', - seq(opt(sourceElements), - // If not at EOF, complain "expecting statement" - expecting('statement', lookAheadTokenType("EOF")))); - - return program.parse(this); -}; diff --git a/packages/jsparse/parser_tests.js b/packages/jsparse/parser_tests.js deleted file mode 100644 index 5dc77f5925..0000000000 --- a/packages/jsparse/parser_tests.js +++ /dev/null @@ -1,733 +0,0 @@ -var parserTestOptions = { includeComments: true }; - -var allNodeNames = [ - ";", - "array", - "assignment", - "binary", - "blockStmnt", - "boolean", - "bracket", - "breakStmnt", - "call", - "case", - "catch", - "comma", - "comment", - "continueStmnt", - "debuggerStmnt", - "default", - "doStmnt", - "dot", - "emptyStmnt", - "expressionStmnt", - "finally", - "forInSpec", - "forSpec", - "forStmnt", - "forVarInSpec", - "forVarSpec", - "functionDecl", - "functionExpr", - "idPropName", - "identifier", - "ifStmnt", - "labelStmnt", - "new", - "newcall", - "nil", - "null", - "numPropName", - "number", - "object", - "parens", - "postfix", - "program", - "prop", - "regex", - "returnStmnt", - "strPropName", - "string", - "switchStmnt", - "ternary", - "this", - "throwStmnt", - "tryStmnt", - "unary", - "varDecl", - "varStmnt", - "whileStmnt", - "withStmnt" -]; - -var allNodeNamesSet = {}; -_.each(allNodeNames, function (n) { allNodeNamesSet[n] = true; }); - - -var makeTester = function (test) { - return { - // Parse code and make sure it matches expectedTreeString. - goodParse: function (code, expectedTreeString, regexTokenHints) { - var expectedTree = ParseNode.unstringify(expectedTreeString); - - // first use lexer to collect all tokens - var lexer = new JSLexer(code); - var allTokensInOrder = []; - while (! lexer.next().isEOF()) { - var lex = lexer.lastLexeme; - if (lex.isError()) - test.fail("Lexer error at " + lex.startPos()); - if (lex.isToken()) - allTokensInOrder.push(lex); - if (regexTokenHints && regexTokenHints[allTokensInOrder.length]) - lexer.divisionPermitted = false; - } - - var parser = new JSParser(code, parserTestOptions); - var actualTree = parser.getSyntaxTree(); - - var nextTokenIndex = 0; - var check = function (tree) { - if (tree instanceof ParseNode) { - // This is a NODE (non-terminal). - var nodeName = tree.name; - if (! (nodeName && typeof nodeName === "string" && - allNodeNamesSet[nodeName] === true)) - test.fail("Not a node name: " + nodeName); - _.each(tree.children, check); - } else if (typeof tree === 'object' && - typeof tree.text === 'function') { - // This is a TOKEN (terminal). - // Make sure we are visiting every token once, in order. - // Make an exception for any comment lexemes present, - // because we couldn't know whether to include them in - // allTokensInOrder. - if (tree.type() !== "COMMENT") { - if (nextTokenIndex >= allTokensInOrder.length) - test.fail("Too many tokens: " + (nextTokenIndex + 1)); - var referenceToken = allTokensInOrder[nextTokenIndex++]; - if (tree.text() !== referenceToken.text()) - test.fail(tree.text() + " !== " + referenceToken.text()); - if (tree.startPos() !== referenceToken.startPos()) - test.fail(tree.startPos() + " !== " + referenceToken.startPos()); - if (code.substring(tree.startPos(), tree.endPos()) !== tree.text()) - test.fail("Didn't see " + tree.text() + " at " + tree.startPos() + - " in " + code); - } - } else { - test.fail("Unknown tree part: " + tree); - } - }; - - check(actualTree); - if (nextTokenIndex !== allTokensInOrder.length) - test.fail("Too few tokens: " + nextTokenIndex); - - test.equal(parser.pos, code.length); - - test.equal(ParseNode.stringify(actualTree), - ParseNode.stringify(expectedTree), code); - }, - // Takes code with part of it surrounding with backticks. - // Removes the two backtick characters, tries to parse the code, - // and then asserts that there was a tokenization-level error, - // with the part that was between the backticks called out as - // the bad token. - // - // For example, the test "123`@`" will try to parse "123@" and - // assert that a tokenization error occurred at '@'. - badToken: function (code) { - var constructMessage = function (pos, text) { - var nicePos = JSLexer.prettyOffset(code, pos); - return "Bad token at " + nicePos + ", text `" + text + "`"; - }; - var pos = code.indexOf('`'); - var text = code.match(/`(.*?)`/)[1]; - code = code.replace(/`/g, ''); - - var parsed = false; - var error = null; - try { - var tree = new JSParser(code, parserTestOptions).getSyntaxTree(); - parsed = true; - } catch (e) { - error = e; - } - test.isFalse(parsed); - test.isTrue(error); - test.equal(error.message, constructMessage(pos, text)); - }, - // Takes code with a backtick-quoted string embedded in it. - // Removes the backticks and their contents, tries to parse the code, - // and then asserts that there was a parse error at the location - // where the backtick-quoted string was embedded. The embedded - // string must match whatever the error message says was "expected". - // - // For example, the test "{`statement`" will try to parse the code - // "{" and then assert that an error occured at the end of the string - // saying "Expected statement". The test "1 `semicolon`2" will try - // to parse "1 2" and assert that the error "Expected semicolon" - // appeared after the space and before the 2. - // - // A second backtick-quoted string is used as the "found" token - // in the error message. - badParse: function (code) { - var constructMessage = function (whatExpected, pos, found, after) { - return "Expected " + whatExpected + (after ? " after " + after : "") + - " at " + JSLexer.prettyOffset(code, pos) + ", found " + found; - }; - var pos = code.indexOf('`'); - - var backticked = code.match(/`.*?`/g); - var whatExpected = backticked[0] && backticked[0].slice(1,-1); - var found = backticked[1] && backticked[1].slice(1, -1); - code = code.replace(/`.*?`/g, ''); - - var parsed = false; - var error = null; - var parser = new JSParser(code, parserTestOptions); - try { - var tree = parser.getSyntaxTree(); - parsed = true; - } catch (e) { - error = e; - } - test.isFalse(parsed); - test.isTrue(error); - if (! parsed && error) { - var after = parser.oldToken; - found = (found || parser.newToken); - test.equal(error.message, - constructMessage(whatExpected, pos, found, after), - code); - } - } - }; -}; - - -Tinytest.add("jsparse - basics", function (test) { - var tester = makeTester(test); - tester.goodParse('1', "program(expressionStmnt(number(1) ;()))"); - tester.goodParse('1 + 1', "program(expressionStmnt(binary(number(1) + number(1)) ;()))"); - tester.goodParse('1*2+3*4', "program(expressionStmnt(binary(binary(number(1) * number(2)) + " + - "binary(number(3) * number(4))) ;()))"); - tester.goodParse('1 + 1;', "program(expressionStmnt(binary(number(1) + number(1)) ;))"); - tester.goodParse('1 + 1;;', "program(expressionStmnt(binary(number(1) + number(1)) ;) emptyStmnt(;))"); - tester.goodParse('', "program()"); - tester.goodParse('\n', "program()"); - tester.goodParse(';;;\n\n;\n', "program(emptyStmnt(;) emptyStmnt(;) emptyStmnt(;) emptyStmnt(;))"); - tester.goodParse('foo', "program(expressionStmnt(identifier(foo) ;()))"); - tester.goodParse('foo();', "program(expressionStmnt(call(identifier(foo) `(` `)`) ;))"); - tester.goodParse('var x = 3', "program(varStmnt(var varDecl(x = number(3)) ;()))"); - tester.goodParse('++x;', "program(expressionStmnt(unary(++ identifier(x)) ;))"); - tester.goodParse('x++;', "program(expressionStmnt(postfix(identifier(x) ++) ;))"); - tester.goodParse( - 'throw new Error', - "program(throwStmnt(throw new(new identifier(Error)) ;()))"); - tester.goodParse( - 'var x = function () { return 123; };', - 'program(varStmnt(var varDecl(x = functionExpr(function nil() `(` `)` ' + - '{ returnStmnt(return number(123) ;) })) ;))'); - - tester.badParse("var x = `expression`"); - tester.badParse("1 `semicolon`1"); - tester.badParse("1+1`semicolon`:"); -}); - -Tinytest.add("jsparse - tokenization errors", function (test) { - var tester = makeTester(test); - tester.badToken("123`@`"); - tester.badToken("thisIsATestOf = `'unterminated `\n strings'"); - // make sure newlines aren't quietly included in regex literals - tester.badToken("var x = `/`a\nb/;"); - tester.badToken("var x = `/`a\\\nb/;"); - tester.badToken("var x = `/`a[\n]b/;"); -}); - -Tinytest.add("jsparse - syntax forms", function (test) { - var tester = makeTester(test); - var trials = [ - // STATEMENTS - ['1', - 'program(expressionStmnt(number(1) ;()))'], - ['1;;;;2', - 'program(expressionStmnt(number(1) ;) emptyStmnt(;) emptyStmnt(;) emptyStmnt(;) ' + - 'expressionStmnt(number(2) ;()))'], - ['{}', - 'program(blockStmnt({ }))'], - ['{null}', - 'program(blockStmnt({ expressionStmnt(null(null) ;()) }))'], - ['{\nfoo()\nbar();\n}', - 'program(blockStmnt({ expressionStmnt(call(identifier(foo) `(` `)`) ;()) ' + - 'expressionStmnt(call(identifier(bar) `(` `)`) ;) }))'], - ['{{{}}}', - 'program(blockStmnt({ blockStmnt({ blockStmnt({ }) }) }))'], - ['var x = y, z,\n a = b = c;', - 'program(varStmnt(var varDecl(x = identifier(y)) , varDecl(z) , varDecl(a = ' + - 'assignment(identifier(b) = identifier(c))) ;))'], - ['if (x === y);', - 'program(ifStmnt(if `(` binary(identifier(x) === identifier(y)) `)` emptyStmnt(;)))'], - ['if (z) return', - 'program(ifStmnt(if `(` identifier(z) `)` returnStmnt(return nil() ;())))'], - ['if (a) b; else c', - 'program(ifStmnt(if `(` identifier(a) `)` expressionStmnt(identifier(b) ;) else ' + - 'expressionStmnt(identifier(c) ;())))'], - ['if (n === 1) { foo(); } else if (n === 2) { bar(); } else { baz(); }', - 'program(ifStmnt(if `(` binary(identifier(n) === number(1)) `)` blockStmnt(' + - '{ expressionStmnt(call(identifier(foo) `(` `)`) ;) }) else ifStmnt(' + - 'if `(` binary(identifier(n) === number(2)) `)` blockStmnt(' + - '{ expressionStmnt(call(identifier(bar) `(` `)`) ;) }) else blockStmnt(' + - '{ expressionStmnt(call(identifier(baz) `(` `)`) ;) }))))'], - ['while (false);', - 'program(whileStmnt(while `(` boolean(false) `)` emptyStmnt(;)))'], - ['while (/foo/.test(bar.baz)) {\n bar = bar.baz;\n}', - 'program(whileStmnt(while `(` call(dot(regex(/foo/) . test) `(` ' + - 'dot(identifier(bar) . baz) `)`) `)` blockStmnt({ expressionStmnt(' + - 'assignment(identifier(bar) = dot(identifier(bar) . baz)) ;) })))'], - ['while (false) while (false);', - 'program(whileStmnt(while `(` boolean(false) `)` ' + - 'whileStmnt(while `(` boolean (false) `)` emptyStmnt(;))))'], - ['do a; while (b);', - 'program(doStmnt(do expressionStmnt(identifier(a) ;) while `(` identifier(b) `)` ;))'], - ['do { x-- } while (x);', - 'program(doStmnt(do blockStmnt({ expressionStmnt(postfix(identifier(x) --) ;()) }) ' + - 'while `(` identifier(x) `)` ;))'], - ['do a\n while (b)\n x++', - 'program(doStmnt(do expressionStmnt(identifier(a) ;()) while `(` identifier(b) `)` ;()) ' + - 'expressionStmnt(postfix(identifier(x) ++) ;()))'], - ["for(;;);", - "program(forStmnt(for `(` forSpec(nil() ; nil() ; nil()) `)` emptyStmnt(;)))"], - ["for(x in y);", - "program(forStmnt(for `(` forInSpec(identifier(x) in identifier(y)) `)` emptyStmnt(;)))"], - ["for(var x in y);", - "program(forStmnt(for `(` forVarInSpec(var varDecl(x) in identifier(y)) `)` emptyStmnt(;)))"], - ["for(var x;;);", - "program(forStmnt(for `(` forVarSpec(var varDecl(x) ; nil() ; nil()) `)` emptyStmnt(;)))"], - ["for(var i=0;i>h>>>ik<=l>=m instanceof n in o==p!=q===r!==s&t^u|v&&w||x", - "program(expressionStmnt(binary(binary(binary(binary(binary(binary(binary(" + - "binary(binary(binary(binary(binary(binary(binary(binary(binary(binary(binary(" + - "binary(binary(binary(binary(binary(identifier(a) * identifier(b)) / " + - "identifier(c)) % identifier(d)) + identifier(e)) - identifier(f)) << identifier(g)) " + - ">> identifier(h)) >>> identifier(i)) < identifier(j)) > identifier(k)) <= " + - "identifier(l)) >= identifier(m)) instanceof identifier(n)) in identifier(o)) == " + - "identifier(p)) != identifier(q)) === identifier(r)) !== identifier(s)) & " + - "identifier(t)) ^ identifier(u)) | identifier(v)) && identifier(w)) || " + - "identifier(x)) ;()))"], - ["a||b&&c|d^e&f!==g===h!=i==j in k instanceof l>=m<=n>>q>>r<= identifier(m)) <= identifier(n)) < " + - "identifier(o)) < binary(binary(binary(identifier(p) >>> identifier(q)) >> " + - "identifier(r)) << binary(binary(identifier(s) - identifier(t)) + " + - "binary(binary(binary(identifier(u) % identifier(v)) / identifier(w)) * " + - "identifier(x))))))))))) ;()))"], - ["a?b:c", - "program(expressionStmnt(ternary(identifier(a) ? identifier(b) : " + - "identifier(c)) ;()))"], - ["1==2?3=4:5=6", - "program(expressionStmnt(ternary(binary(number(1) == number(2)) ? " + - "assignment(number(3) = number(4)) : assignment(number(5) = number(6))) ;()))"], - ["a=b,c=d", - "program(expressionStmnt(comma(assignment(identifier(a) = identifier(b)) , " + - "assignment(identifier(c) = identifier(d))) ;()))"], - ["a=b=c=d", - "program(expressionStmnt(assignment(identifier(a) = assignment(identifier(b) " + - "= assignment(identifier(c) = identifier(d)))) ;()))"], - ["x[0]=x[1]=true", - "program(expressionStmnt(assignment(bracket(identifier(x) [ number(0) ]) = " + - "assignment(bracket(identifier(x) [ number(1) ]) = boolean(true))) ;()))"], - ["a*=b/=c%=d+=e-=f<<=g>>=h>>>=i&=j^=k|=l", - "program(expressionStmnt(assignment(identifier(a) *= assignment(identifier(b) " + - "/= assignment(identifier(c) %= assignment(identifier(d) += " + - "assignment(identifier(e) -= assignment(identifier(f) <<= " + - "assignment(identifier(g) >>= assignment(identifier(h) >>>= " + - "assignment(identifier(i) &= assignment(identifier(j) ^= " + - "assignment(identifier(k) |= identifier(l)))))))))))) ;()))"], - ["1;\n\n\n\n/* foo */\n// bar\n", // trailing whitespace and comments - "program(expressionStmnt(number(1) ;) comment(`/* foo */`) comment(`// bar`))"], - // includeComments option; comments in AST - ["//foo", - "program(comment(//foo))"], - ["//foo\n", - "program(comment(//foo))"], - ["/*foo*/", - "program(comment(/*foo*/))"], - ["/*foo*/\n", - "program(comment(/*foo*/))"], - [";\n//foo", - "program(emptyStmnt(;) comment(//foo))"], - [";\n/*foo*/", - "program(emptyStmnt(;) comment(/*foo*/))"], - [";\n//foo\n;", - "program(emptyStmnt(;) comment(//foo) emptyStmnt(;))"], - [";\n/*foo*/\n;", - "program(emptyStmnt(;) comment(/*foo*/) emptyStmnt(;))"], - [";\n//foo\n//bar\n;", - "program(emptyStmnt(;) comment(//foo) comment(//bar) emptyStmnt(;))"], - [";\n/*foo*/ /*bar*/\n;", - "program(emptyStmnt(;) comment(/*foo*/) comment(/*bar*/) emptyStmnt(;))"], - [";//foo\n//bar\n;", - "program(emptyStmnt(;) comment(//bar) emptyStmnt(;))"], - [";/*foo*/\n/*bar*/\n;", - "program(emptyStmnt(;) comment(/*bar*/) emptyStmnt(;))"], - [";/*foo*//*bar*///baz\n;", - "program(emptyStmnt(;) emptyStmnt(;))"], - [";/*foo*//*bar*///baz", - "program(emptyStmnt(;))"], - ["/*foo*//*bar*///baz", - "program(comment(/*foo*/) comment(/*bar*/) comment(//baz))"], - ["//foo\n//bar\nfunction aaa() {}\nfunction bbb() {}", - "program(comment(//foo) comment(//bar) functionDecl(function aaa `(` `)` { }) " + - "functionDecl(function bbb `(` `)` { }))"], - // comments don't interfere with parse - ["if (true)\n//comment\nfoo();", - "program(ifStmnt(if `(` boolean(true) `)` " + - "expressionStmnt(call(identifier(foo) `(` `)`) ;)))"], - // bare keywords allowed in property access and object literal - ["foo.return();", - "program(expressionStmnt(call(dot(identifier(foo) . return) `(` `)`) ;))"], - ["foo.true();", - "program(expressionStmnt(call(dot(identifier(foo) . true) `(` `)`) ;))"], - ["foo.null();", - "program(expressionStmnt(call(dot(identifier(foo) . null) `(` `)`) ;))"], - ["({true:3})", - "program(expressionStmnt(parens(`(` object({ prop(idPropName(true) : number(3)) }) `)`) ;()))"], - ["({null:3})", - "program(expressionStmnt(parens(`(` object({ prop(idPropName(null) : number(3)) }) `)`) ;()))"], - ["({if:3})", - "program(expressionStmnt(parens(`(` object({ prop(idPropName(if) : number(3)) }) `)`) ;()))"], - // ES5 line continuations in string literals - ["var x = 'a\\\nb\\\nc';", - "program(varStmnt(var varDecl(x = string(`'a\\\nb\\\nc'`)) ;))"], - // ES5 trailing comma in object literal - ["({});", - "program(expressionStmnt(parens(`(` object({ }) `)`) ;))"], - ["({x:1});", - "program(expressionStmnt(parens(`(` object({ prop(idPropName(x) : number(1)) }) `)`) ;))"], - ["({x:1,});", - "program(expressionStmnt(parens(`(` object({ prop(idPropName(x) : number(1)) , }) `)`) ;))"], - ["({x:1,y:2});", - "program(expressionStmnt(parens(`(` object({ prop(idPropName(x) : number(1)) , " + - "prop(idPropName(y) : number(2)) }) `)`) ;))"], - ["({x:1,y:2,});", - "program(expressionStmnt(parens(`(` object({ prop(idPropName(x) : number(1)) , " + - "prop(idPropName(y) : number(2)) , }) `)`) ;))"] - ]; - _.each(trials, function (tr) { - tester.goodParse(tr[0], tr[1]); - }); -}); - -Tinytest.add("jsparse - bad parses", function (test) { - var tester = makeTester(test); - // string between backticks is pulled out and becomes what's "expected" - // at that location, according to the correct error message - var trials = [ - '{`statement`', - 'if (`expression`)', - 'if `(`else', - 'var`varDecl`;', - 'while (`expression`);', - 'while`(`;', - 'do a `semicolon`while b;', - 'do a\n while `(`b;', - '1 `semicolon`2', - 'for (`forSpec`);', - 'for (1\n`semicolon`2\n3);', - 'continue `semicolon`1+1;', - 'break `semicolon`1+1;', - 'throw`expression`', - 'throw`expression`;', - 'throw\n`expression`', - 'throw\n`expression``end of line`e', - 'throw `expression`=;', - 'with(`expression`);', - 'switch(`expression`)', - 'switch(x)`{`;', - 'try`block`', - 'try {}`catch`', - 'try {} catch`(`;', - 'try {} catch(e)`block`;', - '1+1`semicolon`:', - '{a:`statement`}', - 'function `IDENTIFIER`() {}', - 'foo: `statement`function foo() {}', - '[`expression`=', - '[,,`expression`=', - '({`propertyName`|:3})', - '({1:2,3`:`})', - '({1:2,`propertyName`', - 'x.`IDENTIFIER`,', - 'foo;`semicolon`:;', - '1;`statement`=', - 'a+b`semicolon`=c;', - 'for(1+1 `semicolon`in {});', - '`statement`=', - 'for(;`expression`var;) {}', - '({`propertyName`', - '({`propertyName`,})', - '({`propertyName`:})', - '({x`:`})', - '({x:1,`propertyName`', - '({x:1,`propertyName`,})', - '({x:1`,`', - '({x:1,`propertyName`,y:2})', - '({x:1,`propertyName`,})', - '({x:1,y:2`,`:', - '({x:1,y:2,`propertyName`', - '({x:1,y:2,`propertyName`:', - '({x:1,y:2,`propertyName`,})' - ]; - _.each(trials, function (tr) { - tester.badParse(tr); - }); -}); - -Tinytest.add("jsparse - regex division ambiguity", function (test) { - var tester = makeTester(test); - tester.goodParse("if (e) /f/g;", - "program(ifStmnt(if `(` identifier(e) `)` expressionStmnt(regex(/f/g) ;)))", - {4: true}); - tester.goodParse("++/x/.y;", - "program(expressionStmnt(unary(++ dot(regex(/x/) . y)) ;))", - {1: true}); - tester.goodParse("x++/2/g;", - "program(expressionStmnt(binary(binary(postfix(identifier(x) ++) / " + - "number(2)) / identifier(g)) ;))"); - tester.goodParse("(1+1)/2/g;", - "program(expressionStmnt(binary(binary(parens(`(` binary(number(1) + " + - "number(1)) `)`) / " + - "number(2)) / identifier(g)) ;))"); - tester.goodParse("/x/", - "program(expressionStmnt(regex(/x/) ;()))"); -}); - -Tinytest.add("jsparse - semicolon insertion", function (test) { - var tester = makeTester(test); - // Spec section 7.9.2 - tester.badParse("{ 1 `semicolon`2 } 3"); - tester.goodParse("{ 1\n2 } 3", "program(blockStmnt({ expressionStmnt(number(1) " + - ";()) expressionStmnt(number(2) ;()) }) expressionStmnt(number(3) ;()))"); - tester.badParse("for (a; b\n`semicolon`)"); - tester.goodParse("return\na + b", - "program(returnStmnt(return nil() ;()) " + - "expressionStmnt(binary(identifier(a) + identifier(b)) ;()))"); - tester.goodParse("a = b\n++c", - "program(expressionStmnt(assignment(identifier(a) = identifier(b)) ;())" + - "expressionStmnt(unary(++ identifier(c)) ;()))"); - tester.badParse("if (a > b)\n`statement`else c = d"); - tester.goodParse("a = b + c\n(d + e).print()", - "program(expressionStmnt(assignment(identifier(a) = " + - "binary(identifier(b) + call(dot(call(identifier(c) `(` " + - "binary(identifier(d) + identifier(e)) `)`) . print) `(` `)`))) ;()))"); -}); - -Tinytest.add("jsparse - comments", function (test) { - var tester = makeTester(test); - // newline in multi-line comment makes it into a line break for semicolon - // insertion purposes - tester.badParse("1/**/`semicolon`2"); - tester.goodParse("1/*\n*/2", - "program(expressionStmnt(number(1) ;()) expressionStmnt(number(2) ;()))"); -}); - -Tinytest.add("jsparse - initial lex error", function (test) { - var doTest = function (code) { - // this shouldn't throw - var parser = new JSParser(code, parserTestOptions); - // this should throw - try { - parser.getSyntaxTree(); - test.fail(); - } catch (e) { - test.isTrue(/^Bad token/.test(e.message), e.message); - } - }; - - doTest('/'); - doTest('@'); -}); diff --git a/packages/jsparse/parserlib.js b/packages/jsparse/parserlib.js deleted file mode 100644 index e17a5d9c05..0000000000 --- a/packages/jsparse/parserlib.js +++ /dev/null @@ -1,260 +0,0 @@ -///// TOKENIZER AND PARSER COMBINATORS - -// XXX track line/col position, for errors and maybe token info - -var isArray = function (obj) { - return obj && (typeof obj === 'object') && (typeof obj.length === 'number'); -}; - -ParseNode = function (name, children) { - this.name = name; - this.children = children; - - if (! isArray(children)) - throw new Error("Expected array in new ParseNode(" + name + ", ...)"); -}; - - -Parser = function (expecting, runFunc) { - this.expecting = expecting; - this._run = runFunc; -}; - -Parser.prototype.parse = function (t) { - return this._run(t); -}; - -Parser.prototype.parseRequired = function (t) { - return this.parseRequiredIf(t, true); -}; - -Parser.prototype.parseRequiredIf = function (t, required) { - var result = this._run(t); - - if (required && ! result) - throw t.getParseError(this.expecting); - - return result; -}; - -Parser.expecting = function (expecting, parser) { - return new Parser(expecting, parser._run); -}; - - -// A parser that consume()s has to succeed. -// Similarly, a parser that fails can't have consumed. - -Parsers = {}; - -Parsers.assertion = function (test) { - return new Parser( - null, function (t) { - return test(t) ? [] : null; - }); -}; - -Parsers.node = function (name, childrenParser) { - return new Parser(name, function (t) { - var children = childrenParser.parse(t); - if (! children) - return null; - if (! isArray(children)) - children = [children]; - return new ParseNode(name, children); - }); -}; - -Parsers.or = function (/*parsers*/) { - var args = arguments; - return new Parser( - args[args.length - 1].expecting, - function (t) { - var result; - for(var i = 0, N = args.length; i < N; i++) { - result = args[i].parse(t); - if (result) - return result; - } - return null; - }); -}; - -// Parses a left-recursive expression with zero or more occurrences -// of a binary op. Leaves the term unwrapped if no op. For example -// (in a hypothetical use case): -// `1` => "1" -// `1+2` => ["binary", "1", "+", "2"] -// `1+2+3` => ["binary", ["binary", "1", "+", "2"], "+", "3"] -// -// opParsers is an array of op parsers from high to low -// precedence (tightest-binding first) -Parsers.binaryLeft = function (name, termParser, opParsers) { - var opParser; - - if (opParsers.length === 1) { - // take single opParser out of its array - opParser = opParsers[0]; - } else { - // pop off last opParser (non-destructively) and replace - // termParser with a recursive binaryLeft on the remaining - // ops. - termParser = Parsers.binaryLeft(name, termParser, opParsers.slice(0, -1)); - opParser = opParsers[opParsers.length - 1]; - } - - return new Parser( - termParser.expecting, - function (t) { - var result = termParser.parse(t); - if (! result) - return null; - - var op; - while ((op = opParser.parse(t))) { - result = new ParseNode( - name, - [result, op, termParser.parseRequired(t)]); - } - return result; - }); -}; - -Parsers.unary = function (name, termParser, opParser) { - var unaryList = Parsers.opt(Parsers.list(opParser)); - return new Parser( - termParser.expecting, - function (t) { - var unaries = unaryList.parse(t); - // if we have unaries, we are committed and - // have to match a term or error. - var result = termParser.parseRequiredIf(t, unaries.length); - if (! result) - return null; - - while (unaries.length) - result = new ParseNode(name, [unaries.pop(), result]); - return result; - }); -}; - -// Parses a list of one or more items with a separator, listing the -// items and separators. (Separator is optional.) For example: -// `x` => ["x"] -// `x,y` => ["x", ",", "y"] -// `x,y,z` => ["x", ",", "y", ",", "z"] -// Unpacks. -Parsers.list = function (itemParser, sepParser) { - var push = function(array, newThing) { - if (isArray(newThing)) - array.push.apply(array, newThing); - else - array.push(newThing); - }; - return new Parser( - itemParser.expecting, - function (t) { - var result = []; - var firstItem = itemParser.parse(t); - if (! firstItem) - return null; - push(result, firstItem); - - if (sepParser) { - var sep; - while ((sep = sepParser.parse(t))) { - push(result, sep); - push(result, itemParser.parseRequired(t)); - } - } else { - var item; - while ((item = itemParser.parse(t))) - push(result, item); - } - return result; - }); -}; - -// Unpacks arrays (nested seqs). -Parsers.seq = function (/*parsers*/) { - var args = arguments; - if (! args.length) - return Parsers.constant([]); - - return new Parser( - args[0].expecting, - function (t) { - var result = []; - for (var i = 0, N = args.length; i < N; i++) { - // first item in sequence can fail, and we - // fail (without error); after that, error on failure - var r = args[i].parseRequiredIf(t, i > 0); - if (! r) - return null; - - if (isArray(r)) // append array! - result.push.apply(result, r); - else - result.push(r); - } - return result; - }); -}; - -// parsers except last must never consume -Parsers.and = function (/*parsers*/) { - var args = arguments; - if (! args.length) - return Parsers.constant([]); - - return new Parser( - args[args.length - 1].expecting, - function (t) { - var result; - for(var i = 0, N = args.length; i < N; i++) { - result = args[i].parse(t); - if (! result) - return null; - } - return result; - }); -}; - -// parser must not consume -Parsers.not = function (parser) { - return new Parser( - null, - function (t) { - return parser.parse(t) ? null : []; - }); -}; - -// parser that looks at nothing and returns result -Parsers.constant = function (result) { - return new Parser(null, - function (t) { return result; }); -}; - -Parsers.opt = function (parser) { - return Parser.expecting( - parser.expecting, - Parsers.or(parser, Parsers.seq())); -}; - -Parsers.mapResult = function (parser, func) { - return new Parser( - parser.expecting, - function (t) { - var v = parser.parse(t); - return v ? func(v, t) : null; - }); -}; - -Parsers.lazy = function (expecting, parserFunc) { - var inner = null; - return new Parser(expecting, function (t) { - if (! inner) - inner = parserFunc(); - return inner.parse(t); - }); -}; diff --git a/packages/jsparse/stringify.js b/packages/jsparse/stringify.js deleted file mode 100644 index 121ebb46ea..0000000000 --- a/packages/jsparse/stringify.js +++ /dev/null @@ -1,118 +0,0 @@ -// The "tree string" format is a simple format for representing syntax trees. -// -// For example, the parse of `x++;` is written as: -// "program(expressionStmnt(postfix(identifier(x) ++) ;))" -// -// A Node is written as "name(item1 item2 item3)", with additional whitespace -// allowed anywhere between the name, parentheses, and items. -// -// Tokens don't need to be escaped unless they contain '(', ')', whitespace, or -// backticks, or are empty. If they do, they can be written enclosed in backticks. -// To escape a backtick within backticks, double it. -// -// `stringify` generates "canonical" tree strings, which have no extra escaping -// or whitespace, just one space between items in a Node. - - -ParseNode.prototype.stringify = function () { - return ParseNode.stringify(this); -}; - -var backtickEscape = function (str) { - if (/[\s()`]/.test(str)) - return '`' + str.replace(/`/g, '``') + '`'; - else if (! str) - return '``'; - else - return str; -}; - -var backtickUnescape = function (str) { - if (str.charAt(0) === '`') { - if (str.length === 1 || str.slice(-1) !== '`') - throw new Error("Mismatched ` in " + str); - if (str.length === 2) - str = ''; - else - str = str.slice(1, -1).replace(/``/g, '`'); - } - return str; -}; - -ParseNode.stringify = function (tree) { - if (tree instanceof ParseNode) { - var str = backtickEscape(tree.name); - str += '('; - var escapedChildren = []; - for(var i = 0, N = tree.children.length; i < N; i++) - escapedChildren.push(ParseNode.stringify(tree.children[i])); - str += escapedChildren.join(' '); - str += ')'; - return str; - } - - // Treat a token object or string as a token. - if (typeof tree.text === 'function') - tree = tree.text(); - else if (typeof tree.text === 'string') - tree = tree.text; - return backtickEscape(String(tree)); -}; - -ParseNode.unstringify = function (str) { - var lexemes = str.match(/\(|\)|`([^`]||``)*`|`|[^\s()`]+/g) || []; - var N = lexemes.length; - var state = { - i: 0, - getParseError: function (expecting) { - throw new Error("unstringify: Expecting " + expecting +", found " + - (lexemes[this.i] || "end of string")); - }, - peek: function () { return lexemes[this.i]; }, - advance: function () { this.i++; } - }; - var paren = function (chr) { - return new Parser(chr, function (t) { - if (t.peek() !== chr) - return null; - t.advance(); - return chr; - }); - }; - var EMPTY_STRING = [""]; - var token = new Parser('token', function (t) { - var txt = t.peek(); - if (!txt || txt.charAt(0) === '(' || txt.charAt(0) === ')') - return null; - - t.advance(); - // can't return falsy value from successful parser - return backtickUnescape(txt) || EMPTY_STRING; - }); - - // Make "item" lazy so it can be recursive. - var item = Parsers.lazy('token', function () { return item; }); - - // Parse a single node or token. - item = Parsers.mapResult( - Parsers.seq(token, - Parsers.opt(Parsers.seq( - paren('('), Parsers.opt(Parsers.list(item)), paren(')')))), - function (v) { - for(var i = 0, N = v.length; i < N; i++) - if (v[i] === EMPTY_STRING) - v[i] = ""; - - if (v.length === 1) - // token - return v[0]; - // node. exclude parens - return new ParseNode(v[0], v.slice(2, -1)); - }); - - var endOfString = new Parser("end of string", function (t) { - return t.i === N ? [] : null; - }); - - return Parsers.seq(item, endOfString).parseRequired(state)[0]; -}; diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 12cbcff9af..651e2fe3c2 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.10.1' + version: '1.10.2' }); Package.includeTool(); diff --git a/packages/meyerweb-reset/reset.css b/packages/meyerweb-reset/reset.css deleted file mode 100644 index ed11813c4e..0000000000 --- a/packages/meyerweb-reset/reset.css +++ /dev/null @@ -1,48 +0,0 @@ -/* http://meyerweb.com/eric/tools/css/reset/ - v2.0 | 20110126 - License: none (public domain) -*/ - -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -b, u, i, center, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, -menu, nav, output, ruby, section, summary, -time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} -/* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; -} -body { - line-height: 1; -} -ol, ul { - list-style: none; -} -blockquote, q { - quotes: none; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; -} -table { - border-collapse: collapse; - border-spacing: 0; -} diff --git a/packages/minimongo/matcher.js b/packages/minimongo/matcher.js index eabe16fb8a..15003628b3 100644 --- a/packages/minimongo/matcher.js +++ b/packages/minimongo/matcher.js @@ -5,6 +5,8 @@ import { nothingMatcher, } from './common.js'; +const Decimal = Package['mongo-decimal']?.Decimal || class DecimalStub {} + // The minimongo selector compiler! // Terminology: @@ -170,6 +172,10 @@ LocalCollection._f = { return 7; } + if (v instanceof Decimal) { + return 1; + } + // object return 3; @@ -260,8 +266,13 @@ LocalCollection._f = { b = b.getTime(); } - if (ta === 1) // double - return a - b; + if (ta === 1) { // double + if (a instanceof Decimal) { + return a.minus(b).toNumber(); + } else { + return a - b; + } + } if (tb === 2) // string return a < b ? -1 : a === b ? 0 : 1; diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index 51b5fbc057..ef6627f5a1 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.5.0' + version: '1.6.0' }); Package.onUse(api => { @@ -24,6 +24,10 @@ Package.onUse(api => { 'tracker' ]); + // Make weak use of Decimal type on client + api.use('mongo-decimal', 'client', {weak: true}); + api.use('mongo-decimal', 'server'); + api.mainModule('minimongo_client.js', 'client'); api.mainModule('minimongo_server.js', 'server'); }); diff --git a/packages/mongo/mongo_driver.js b/packages/mongo/mongo_driver.js index c6556aafdc..feb9a14bfa 100644 --- a/packages/mongo/mongo_driver.js +++ b/packages/mongo/mongo_driver.js @@ -7,6 +7,8 @@ * these outside of a fiber they will explode! */ +const path = require("path"); + var MongoDB = NpmModuleMongodb; var Future = Npm.require('fibers/future'); import { DocFetcher } from "./doc_fetcher.js"; @@ -26,6 +28,10 @@ MongoInternals.NpmModules = { // XXX COMPAT WITH 1.0.3.2 MongoInternals.NpmModule = MongoDB; +const FILE_ASSET_SUFFIX = 'Asset'; +const ASSETS_FOLDER = 'assets'; +const APP_FOLDER = 'app'; + // This is used to add or remove EJSON from the beginning of everything nested // inside an EJSON custom type. It should only be called on pure JSON! var replaceNames = function (filter, thing) { @@ -133,12 +139,17 @@ MongoConnection = function (url, options) { self._observeMultiplexers = {}; self._onFailoverHook = new Hook; + const userOptions = { + ...(Mongo._connectionOptions || {}), + ...(Meteor.settings?.packages?.mongo?.options || {}) + }; + var mongoOptions = Object.assign({ ignoreUndefined: true, // See https://github.com/meteor/meteor/issues/10925 for discussion of // why this option is not the default. useUnifiedTopology: !!options.useUnifiedTopology, - }, Mongo._connectionOptions); + }, userOptions); // The autoReconnect and reconnectTries options are incompatible with // useUnifiedTopology: https://github.com/meteor/meteor/pull/10861#commitcomment-37525845 @@ -171,6 +182,17 @@ MongoConnection = function (url, options) { mongoOptions.poolSize = options.poolSize; } + // Transform options like "tlsCAFileAsset": "filename.pem" into + // "tlsCAFile": "//filename.pem" + Object.entries(mongoOptions || {}) + .filter(([key]) => key && key.endsWith(FILE_ASSET_SUFFIX)) + .forEach(([key, value]) => { + const optionName = key.replace(FILE_ASSET_SUFFIX, ''); + mongoOptions[optionName] = path.join(Assets.getServerDir(), + ASSETS_FOLDER, APP_FOLDER, value); + delete mongoOptions[key]; + }); + self.db = null; // We keep track of the ReplSet's primary, so that we can trigger hooks when // it changes. The Node driver's joined callback seems to fire way too @@ -518,6 +540,8 @@ MongoConnection.prototype._update = function (collection_name, selector, mod, try { var collection = self.rawCollection(collection_name); var mongoOpts = {safe: true}; + // Add support for filtered positional operator + if (options.arrayFilters !== undefined) mongoOpts.arrayFilters = options.arrayFilters; // explictly enumerate options that minimongo supports if (options.upsert) mongoOpts.upsert = true; if (options.multi) mongoOpts.multi = true; diff --git a/packages/mongo/package.js b/packages/mongo/package.js index fd992c6fe8..7f699e47e5 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.9.0' + version: '1.10.0' }); Npm.depends({ @@ -38,8 +38,8 @@ Package.onUse(function (api) { ]); // Make weak use of Decimal type on client - api.use('mongo-decimal', 'client', {weak: true}); - api.use('mongo-decimal', 'server'); + api.use('mongo-decimal@0.1.1', 'client', {weak: true}); + api.use('mongo-decimal@0.1.1', 'server'); api.use('underscore', 'server'); diff --git a/packages/non-core/less/.npm/plugin/compileLessBatch/npm-shrinkwrap.json b/packages/non-core/less/.npm/plugin/compileLessBatch/npm-shrinkwrap.json index c48208a41b..56a9a953ef 100644 --- a/packages/non-core/less/.npm/plugin/compileLessBatch/npm-shrinkwrap.json +++ b/packages/non-core/less/.npm/plugin/compileLessBatch/npm-shrinkwrap.json @@ -2,24 +2,19 @@ "lockfileVersion": 1, "dependencies": { "@babel/runtime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", - "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==" + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==" }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=" - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==" }, "asap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", - "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0=" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, "asn1": { "version": "0.2.4", @@ -42,9 +37,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -56,15 +51,15 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==" }, "core-util-is": { "version": "1.0.2", @@ -102,14 +97,14 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "forever-agent": { "version": "0.6.1", @@ -117,9 +112,9 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=" + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==" }, "getpass": { "version": "0.1.7", @@ -127,9 +122,9 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=" }, "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" }, "har-schema": { "version": "2.0.0", @@ -137,9 +132,9 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==" + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==" }, "http-signature": { "version": "1.2.0", @@ -147,9 +142,9 @@ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=" }, "image-size": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.3.5.tgz", - "integrity": "sha1-gyQOqy+1sAsEqrjHSwRx6cunrYw=" + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=" }, "is-typedarray": { "version": "1.0.0", @@ -172,9 +167,9 @@ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stringify-safe": { "version": "5.0.1", @@ -187,8 +182,9 @@ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=" }, "less": { - "version": "https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6", - "integrity": "sha512-514pMpzrABW11ploVaRcbHLf3MhollYYCJj9SyJmNT1O8ZeLCiIeqZ2SjZUM1uudohPlHgTRwmCZouzIJFJ7Jw==" + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/less/-/less-3.11.1.tgz", + "integrity": "sha512-tlWX341RECuTOvoDIvtFqXsKj072hm3+9ymRBe76/mD6O5ZZecnlAOVDlWAleF2+aohFrxNidXhv2773f6kY7g==" }, "mime": { "version": "1.6.0", @@ -196,29 +192,24 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" }, "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==" + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==" }, "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=" - }, - "natives": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz", - "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==" + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==" }, "oauth-sign": { "version": "0.9.0", @@ -231,9 +222,9 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "promise": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz", - "integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=" + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==" }, "prr": { "version": "1.0.1", @@ -241,14 +232,14 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" }, "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "qs": { "version": "6.5.2", @@ -256,19 +247,19 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==" + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==" }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" }, "safer-buffer": { "version": "2.1.2", @@ -276,19 +267,24 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=" + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=" + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==" }, "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==" + }, + "tslib": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", + "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" }, "tunnel-agent": { "version": "0.6.0", @@ -300,10 +296,15 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==" + }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "verror": { "version": "1.10.0", diff --git a/packages/non-core/less/README.md b/packages/non-core/less/README.md index 6762ed7b80..f01e49aa63 100644 --- a/packages/non-core/less/README.md +++ b/packages/non-core/less/README.md @@ -1,10 +1,18 @@ # Less -[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/less) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/less) +[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/non-core/less) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/non-core/less) *** The Less package provides a compiler build plugin for the Meteor build tool. It handles the compilation of `*.less` files to CSS. +## Changelog + +### 3.0.0 + +- Updated less to 3.11.1. +- Import files without ending as less files, according to less import rules. +- Add `javascriptEnabled` option to less, to be backwards compatible to previous version of this package. + ## Usage If you want to use it in your app, just run: diff --git a/packages/non-core/less/package.js b/packages/non-core/less/package.js index e95864fbb2..f758c45978 100644 --- a/packages/non-core/less/package.js +++ b/packages/non-core/less/package.js @@ -1,20 +1,22 @@ Package.describe({ name: 'less', - version: '2.8.0', + version: '3.0.1', summary: 'Leaner CSS language', documentation: 'README.md' }); Package.registerBuildPlugin({ name: "compileLessBatch", - use: ['caching-compiler', 'ecmascript', 'underscore'], + use: [ + "caching-compiler@1.2.2", + "ecmascript@0.14.3", + ], sources: [ 'plugin/compile-less.js' ], npmDependencies: { - "@babel/runtime": "7.0.0", - // Fork of 2.5.0, deleted large unused files in dist directory. - "less": "https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6" + "@babel/runtime": "7.9.2", + "less": "3.11.1" } }); diff --git a/packages/non-core/less/plugin/compile-less.js b/packages/non-core/less/plugin/compile-less.js index ffd8bbb25a..a04c834785 100644 --- a/packages/non-core/less/plugin/compile-less.js +++ b/packages/non-core/less/plugin/compile-less.js @@ -62,6 +62,8 @@ class LessCompiler extends MultiFileCachingCompiler { return less.render(inputFile.getContentsAsBuffer().toString('utf8'), { filename: this.getAbsoluteImportPath(inputFile), plugins: [importPlugin], + // Enabled as it was default true before less v3.0.0 + javascriptEnabled: true, // Generate a source map, and include the source files in the // sourcesContent field. (Note that source files which don't // themselves produce text (eg, are entirely variable definitions) @@ -81,11 +83,11 @@ class LessCompiler extends MultiFileCachingCompiler { }; const referencedImportPaths = []; - output.imports.forEach((path) => { + output.imports.forEach((outputPath) => { // Some files that show up in output.imports are not actually files; for // example @import url("..."); - if (allFiles.has(path)) { - referencedImportPaths.push(path); + if (allFiles.has(outputPath)) { + referencedImportPaths.push(outputPath); } }); @@ -109,22 +111,18 @@ class LessCompiler extends MultiFileCachingCompiler { addCompileResult(inputFile, compileResult) { inputFile.addStylesheet({ data: compileResult.css, - path: inputFile.getPathInPackage() + '.css', + path: `${inputFile.getPathInPackage()}.css`, sourceMap: compileResult.sourceMap }); } } -class MeteorImportLessPlugin { - constructor(allFiles) { - this.allFiles = allFiles; - this.minVersion = [2, 5, 0]; - } +function MeteorImportLessPlugin(allFiles) { + this.minVersion = [3, 6, 0]; - install(less, pluginManager) { - pluginManager.addFileManager( - new MeteorImportLessFileManager(this.allFiles)); - } + this.install = (l, pluginManager) => { + pluginManager.addFileManager(new MeteorImportLessFileManager(allFiles)); + }; } class MeteorImportLessFileManager extends less.AbstractFileManager { @@ -138,20 +136,17 @@ class MeteorImportLessFileManager extends less.AbstractFileManager { // We shouldn't process files that start with `//` or a protocol because // those are not relative to the app at all; they are probably native // CSS imports - if (! filename.match(/^(https?:)?\/\//)) { - return true; - } - - return false; + return !filename.match(/^(https?:)?\/\//); } - loadFile(filename, currentDirectory, options, environment, cb) { + loadFile(filename, currentDirectory) { const packageMatch = currentDirectory.match(/^(\{[^}]*\})/); - if (! packageMatch) { + if (!packageMatch) { // shouldn't happen. all filenames less ever sees should involve this {} // thing! - cb(new Error('file without Meteor context? ' + currentDirectory)); - return; + return Promise.reject( + new Error(`file without Meteor context? ${currentDirectory}`) + ); } const currentPackagePrefix = packageMatch[1]; @@ -164,28 +159,41 @@ class MeteorImportLessFileManager extends less.AbstractFileManager { } else { resolvedFilename = path.join(currentDirectory, filename); } + // Import rule from less: + // If it does not have an extension, .less will be appended and it will be included as a imported Less file. + if ( + !this.allFiles.has(resolvedFilename) && + this.allFiles.has(`${resolvedFilename}.less`) + ) { + resolvedFilename = `${resolvedFilename}.less`; + } if (!this.allFiles.has(resolvedFilename)) { - cb({type: 'File', message: 'Unknown import: ' + filename}); - return; + return Promise.reject(new Error(`Unknown import: ${filename}`)); } - cb(null, { + + return Promise.resolve({ contents: this.allFiles.get(resolvedFilename) .getContentsAsBuffer().toString('utf8'), - filename: resolvedFilename + filename: resolvedFilename, }); } } -function decodeFilePath (filePath) { +function decodeFilePath(filePath) { const match = filePath.match(/^{(.*)}\/(.*)$/); - if (! match) - throw new Error('Failed to decode Less path: ' + filePath); + + if (!match) { + // Sometimes a filePath may be an URL, such as when loading fonts from + // https://fonts.googleapis.com/css. Preserve those URLs instead of + // trying to rewrite them. + return filePath; + } if (match[1] === '') { - // app + // Importing from the application, not from a Meteor package. return match[2]; } - return 'packages/' + match[1] + '/' + match[2]; + return `packages/${match[1]}/${match[2]}`; } diff --git a/packages/socket-stream-client/node.js b/packages/socket-stream-client/node.js index a66b45b798..72fd7b84fc 100644 --- a/packages/socket-stream-client/node.js +++ b/packages/socket-stream-client/node.js @@ -107,10 +107,21 @@ export class ClientStream extends StreamClientCommon { _getProxyUrl(targetUrl) { // Similar to code in tools/http-helpers.js. var proxy = process.env.HTTP_PROXY || process.env.http_proxy || null; + var noproxy = process.env.NO_PROXY || process.env.no_proxy || null; // if we're going to a secure url, try the https_proxy env variable first. - if (targetUrl.match(/^wss:/)) { + if (targetUrl.match(/^wss:/) || targetUrl.match(/^https:/)) { proxy = process.env.HTTPS_PROXY || process.env.https_proxy || proxy; } + if (targetUrl.indexOf('localhost') != -1 || targetUrl.indexOf('127.0.0.1') != -1) { + return null; + } + if (noproxy) { + for (let item of noproxy.split(',')) { + if (targetUrl.indexOf(item.trim().replace(/\*/, '')) !== -1) { + proxy = null; + } + } + } return proxy; } diff --git a/packages/socket-stream-client/package.js b/packages/socket-stream-client/package.js index 5a30a73e70..e7cf7d1831 100644 --- a/packages/socket-stream-client/package.js +++ b/packages/socket-stream-client/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "socket-stream-client", - version: "0.2.3", + version: "0.3.0", summary: "Provides the ClientStream abstraction used by ddp-client", documentation: "README.md" }); diff --git a/packages/srp/biginteger.js b/packages/srp/biginteger.js index 7566f48663..1229add23c 100644 --- a/packages/srp/biginteger.js +++ b/packages/srp/biginteger.js @@ -1,5 +1,5 @@ /// METEOR WRAPPER -BigInteger = (function () { +export default BigInteger = (function () { /// BEGIN jsbn.js diff --git a/packages/srp/package.js b/packages/srp/package.js index 2f0d18cbae..cdb1e54d3b 100644 --- a/packages/srp/package.js +++ b/packages/srp/package.js @@ -5,7 +5,7 @@ Package.describe({ summary: "Library for Secure Remote Password (SRP) exchanges", - version: "1.0.12" + version: "1.1.0" }); Package.onUse(function (api) { @@ -16,12 +16,11 @@ Package.onUse(function (api) { 'sha' ], ['client', 'server']); api.export('SRP'); - api.addFiles(['biginteger.js', 'srp.js'], - ['client', 'server']); + api.mainModule('srp.js'); }); Package.onTest(function (api) { - api.use('tinytest'); + api.use(['ecmascript', 'tinytest']); api.use('srp', ['client', 'server']); api.addFiles(['srp_tests.js'], ['client', 'server']); }); diff --git a/packages/srp/srp.js b/packages/srp/srp.js index 7e66e288d1..f9369f7606 100644 --- a/packages/srp/srp.js +++ b/packages/srp/srp.js @@ -1,3 +1,6 @@ +import { Random } from 'meteor/random'; +import BigInteger from './biginteger'; + // This package contains just enough of the original SRP code to // support the backwards-compatibility upgrade path. // @@ -5,7 +8,7 @@ // available in Atmosphere so that users can continue to use SRP if they // want to. -SRP = {}; +export const SRP = {}; /** * Generate a new SRP verifier. Password is the plaintext password. @@ -19,24 +22,24 @@ SRP = {}; * - SRP parameters (see _defaults and paramsFromOptions below) */ SRP.generateVerifier = function (password, options) { - var params = paramsFromOptions(options); + const params = paramsFromOptions(options); - var salt = (options && options.salt) || Random.secret(); + const salt = (options && options.salt) || Random.secret(); - var identity; - var hashedIdentityAndPassword = options && options.hashedIdentityAndPassword; + let identity; + let hashedIdentityAndPassword = options && options.hashedIdentityAndPassword; if (!hashedIdentityAndPassword) { identity = (options && options.identity) || Random.secret(); hashedIdentityAndPassword = params.hash(identity + ":" + password); } - var x = params.hash(salt + hashedIdentityAndPassword); - var xi = new BigInteger(x, 16); - var v = params.g.modPow(xi, params.N); + const x = params.hash(salt + hashedIdentityAndPassword); + const xi = new BigInteger(x, 16); + const v = params.g.modPow(xi, params.N); return { - identity: identity, - salt: salt, + identity, + salt, verifier: v.toString(16) }; }; @@ -53,11 +56,12 @@ SRP.matchVerifier = { * Default parameter values for SRP. * */ -var _defaults = { - hash: function (x) { return SHA256(x).toLowerCase(); }, +const _defaults = { + hash: x => SHA256(x).toLowerCase(), N: new BigInteger("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3", 16), g: new BigInteger("2") }; + _defaults.k = new BigInteger( _defaults.hash( _defaults.N.toString(16) + @@ -73,13 +77,13 @@ _defaults.k = new BigInteger( * - g: String or BigInteger. Defaults to 2. * - k: String or BigInteger. Defaults to hash(N, g) */ -var paramsFromOptions = function (options) { +const paramsFromOptions = function (options) { if (!options) // fast path return _defaults; var ret = { ..._defaults }; - ['N', 'g', 'k'].forEach(function (p) { + ['N', 'g', 'k'].forEach(p => { if (options[p]) { if (typeof options[p] === "string") ret[p] = new BigInteger(options[p], 16); @@ -91,7 +95,7 @@ var paramsFromOptions = function (options) { }); if (options.hash) - ret.hash = function (x) { return options.hash(x).toLowerCase(); }; + ret.hash = x => options.hash(x).toLowerCase(); if (!options.k && (options.N || options.g || options.hash)) { ret.k = ret.hash(ret.N.toString(16) + ret.g.toString(16)); diff --git a/packages/srp/srp_tests.js b/packages/srp/srp_tests.js index 597b4cf4df..4fdc8a6e44 100644 --- a/packages/srp/srp_tests.js +++ b/packages/srp/srp_tests.js @@ -1,3 +1,5 @@ +import { SRP } from 'meteor/srp'; + Tinytest.add("srp - fixed values", function(test) { // Test exact values outputted by `generateVerifier`. We have to be very // careful about changing the SRP code, because changes could render @@ -5,13 +7,11 @@ Tinytest.add("srp - fixed values", function(test) { // intentionally brittle to catch change that could affect the // validity of user passwords. - var identity = "b73d9af9-4e74-4ce0-879c-484828b08436"; - var salt = "85f8b9d3-744a-487d-8982-a50e4c9f552a"; - var password = "95109251-3d8a-4777-bdec-44ffe8d86dfb"; - var a = "dc99c646fa4cb7c24314bb6f4ca2d391297acd0dacb0430a13bbf1e37dcf8071"; - var b = "cf878e00c9f2b6aa48a10f66df9706e64fef2ca399f396d65f5b0a27cb8ae237"; + const identity = "b73d9af9-4e74-4ce0-879c-484828b08436"; + const salt = "85f8b9d3-744a-487d-8982-a50e4c9f552a"; + const password = "95109251-3d8a-4777-bdec-44ffe8d86dfb"; - var verifier = SRP.generateVerifier( + const verifier = SRP.generateVerifier( password, {identity: identity, salt: salt}); test.equal(verifier.identity, identity); test.equal(verifier.salt, salt); diff --git a/packages/typescript/package.js b/packages/typescript/package.js index 706fc47fc2..34928b8d30 100644 --- a/packages/typescript/package.js +++ b/packages/typescript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "typescript", - version: "3.7.5", + version: "3.7.6", summary: "Compiler plugin that compiles TypeScript and ECMAScript in .ts and .tsx files", documentation: "README.md" }); diff --git a/packages/url/.npm/package/.gitignore b/packages/url/.npm/package/.gitignore new file mode 100644 index 0000000000..3c3629e647 --- /dev/null +++ b/packages/url/.npm/package/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/packages/url/.npm/package/README b/packages/url/.npm/package/README new file mode 100644 index 0000000000..3d492553a4 --- /dev/null +++ b/packages/url/.npm/package/README @@ -0,0 +1,7 @@ +This directory and the files immediately inside it are automatically generated +when you change this package's NPM dependencies. Commit the files in this +directory (npm-shrinkwrap.json, .gitignore, and this README) to source control +so that others run the same versions of sub-dependencies. + +You should NOT check in the node_modules directory that Meteor automatically +creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/packages/url/.npm/package/npm-shrinkwrap.json b/packages/url/.npm/package/npm-shrinkwrap.json new file mode 100644 index 0000000000..cf5cf0c559 --- /dev/null +++ b/packages/url/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,10 @@ +{ + "lockfileVersion": 1, + "dependencies": { + "core-js": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.5.0.tgz", + "integrity": "sha512-Ifh3kj78gzQ7NAoJXeTu+XwzDld0QRIwjBLRqAMhuLhP3d2Av5wmgE9ycfnvK6NAEjTkQ1sDPeoEZAWO3Hx1Uw==" + } + } +} diff --git a/packages/url/url_client.js b/packages/url/bc/url_client.js similarity index 64% rename from packages/url/url_client.js rename to packages/url/bc/url_client.js index a54b9f3d00..9a52aaaceb 100644 --- a/packages/url/url_client.js +++ b/packages/url/bc/url_client.js @@ -1,7 +1,6 @@ var common = require("./url_common.js"); -var URL = exports.URL = common.URL; -URL._constructUrl = function (url, query, params) { +exports._constructUrl = function (url, query, params) { var query_match = /^(.*?)(\?.*)?$/.exec(url); return common.buildUrl( query_match[1], @@ -10,3 +9,5 @@ URL._constructUrl = function (url, query, params) { params ); }; + +exports._encodeParams = common._encodeParams; \ No newline at end of file diff --git a/packages/url/url_common.js b/packages/url/bc/url_common.js similarity index 90% rename from packages/url/url_common.js rename to packages/url/bc/url_common.js index c0e04d4a9c..9538c5d368 100644 --- a/packages/url/url_common.js +++ b/packages/url/bc/url_common.js @@ -1,12 +1,10 @@ -var URL = exports.URL = {}; - function encodeString(str) { return encodeURIComponent(str).replace(/\*/g, '%2A'); } // Encode URL parameters into a query string, handling nested objects and // arrays properly. -URL._encodeParams = function (params, prefix) { +var _encodeParams = function (params, prefix) { var str = []; var isParamsArray = Array.isArray(params); for (var p in params) { @@ -25,6 +23,8 @@ URL._encodeParams = function (params, prefix) { return str.join('&').replace(/%20/g, '+'); }; +exports._encodeParams = _encodeParams; + exports.buildUrl = function(before_qmark, from_qmark, opt_query, opt_params) { var url_without_query = before_qmark; var query = from_qmark ? from_qmark.slice(1) : null; @@ -34,7 +34,7 @@ exports.buildUrl = function(before_qmark, from_qmark, opt_query, opt_params) { if (opt_params) { query = query || ""; - var prms = URL._encodeParams(opt_params); + var prms = _encodeParams(opt_params); if (query && prms) query += '&'; query += prms; diff --git a/packages/url/url_server.js b/packages/url/bc/url_server.js similarity index 71% rename from packages/url/url_server.js rename to packages/url/bc/url_server.js index 27534bfc82..21349958d8 100644 --- a/packages/url/url_server.js +++ b/packages/url/bc/url_server.js @@ -1,8 +1,7 @@ var url_util = require('url'); var common = require("./url_common.js"); -var URL = exports.URL = common.URL; -URL._constructUrl = function (url, query, params) { +exports._constructUrl = function (url, query, params) { var url_parts = url_util.parse(url); return common.buildUrl( url_parts.protocol + "//" + url_parts.host + url_parts.pathname, @@ -11,3 +10,5 @@ URL._constructUrl = function (url, query, params) { params ); }; + +exports._encodeParams = common._encodeParams; \ No newline at end of file diff --git a/packages/url/url_tests.js b/packages/url/bc/url_tests.js similarity index 90% rename from packages/url/url_tests.js rename to packages/url/bc/url_tests.js index b2d98af6a9..eaf8359256 100644 --- a/packages/url/url_tests.js +++ b/packages/url/bc/url_tests.js @@ -1,3 +1,5 @@ +import { Tinytest } from "meteor/tinytest"; + Tinytest.add('url - serializes params to query correctly', function (test) { var hash = { filter: { diff --git a/packages/url/legacy.js b/packages/url/legacy.js new file mode 100644 index 0000000000..5324357c05 --- /dev/null +++ b/packages/url/legacy.js @@ -0,0 +1,14 @@ +try { + require("core-js/proposals/url"); +} catch (e) { + throw new Error([ + "The core-js npm package could not be found in your node_modules ", + "directory. Please run the following command to install it:", + "", + " meteor npm install --save core-js", + "" + ].join("\n")); +} + +// backwards compatability +require('./modern.js'); diff --git a/packages/url/modern.js b/packages/url/modern.js new file mode 100644 index 0000000000..26cde8e385 --- /dev/null +++ b/packages/url/modern.js @@ -0,0 +1,8 @@ +URL = global.URL; +URLSearchParams = global.URLSearchParams; + +exports.URL = URL; +exports.URLSearchParams = URLSearchParams; + +// backwards compatability +Object.assign(URL, require('./bc/url_client')); diff --git a/packages/url/package.js b/packages/url/package.js index b050428d43..5cab425ab1 100644 --- a/packages/url/package.js +++ b/packages/url/package.js @@ -1,18 +1,29 @@ Package.describe({ - summary: "Utility code for constructing URLs", - version: "1.2.0" + name: "url", + version: "1.3.0", + summary: "Isomorphic modern/legacy/Node polyfill for WHATWG URL/URLSearchParams", + documentation: "README.md" +}); + +Npm.depends({ + "core-js": "3.5.0" }); Package.onUse(function(api) { - api.use('modules'); - api.mainModule('url_client.js', 'client'); - api.mainModule('url_server.js', 'server'); - api.export('URL'); + api.use("modules"); + api.use("modern-browsers"); + + api.mainModule("modern.js", "web.browser"); + api.mainModule("legacy.js", "legacy"); + api.mainModule("server.js", "server"); + + api.export("URL"); + api.export("URLSearchParams"); }); -Package.onTest(function (api) { - api.use(['tinytest', 'url']); - api.addFiles('url_tests.js'); +Package.onTest(function(api) { + api.use("ecmascript"); + api.use("tinytest"); + api.use("url"); + api.mainModule("tests/main.js"); }); - -// More tests can be found in the http package diff --git a/packages/url/server.js b/packages/url/server.js new file mode 100644 index 0000000000..612c33fd20 --- /dev/null +++ b/packages/url/server.js @@ -0,0 +1,25 @@ +const { URL, URLSearchParams } = require('url'); + +exports.URL = URL; +exports.URLSearchParams = URLSearchParams; + +const { setMinimumBrowserVersions } = require("meteor/modern-browsers"); + +// https://caniuse.com/#feat=url +setMinimumBrowserVersions({ + // Since there is no IE12, this effectively excludes Internet Explorer + // (pre-Edge) from the modern classification. #9818 #9839 + ie: 12, + chrome: 32, + edge: 12, + firefox: 26, + mobile_safari: 8, + opera: 36, + safari: [7, 1], + phantomjs: Infinity, + // https://github.com/Kilian/electron-to-chromium/blob/master/full-versions.js + electron: [0, 20], +}, module.id); + +// backwards compatability +Object.assign(exports.URL, require('./bc/url_server')); \ No newline at end of file diff --git a/packages/url/tests/main.js b/packages/url/tests/main.js new file mode 100644 index 0000000000..51bd5f1c26 --- /dev/null +++ b/packages/url/tests/main.js @@ -0,0 +1,9 @@ +import { Tinytest } from "meteor/tinytest"; + +Tinytest.add("url - sanity", function (test) { + test.equal(typeof URL, "function"); + test.equal(typeof URLSearchParams, "function"); +}); + +// backwards compatability +require('../bc/url_tests'); diff --git a/packages/webapp/package.js b/packages/webapp/package.js index 5e61cdf23c..057c4e0026 100644 --- a/packages/webapp/package.js +++ b/packages/webapp/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Serves a Meteor app over HTTP", - version: '1.9.0' + version: '1.9.1' }); Npm.depends({"basic-auth-connect": "1.0.0", diff --git a/packages/webapp/webapp_server.js b/packages/webapp/webapp_server.js index b4652fee34..bb81e549e7 100644 --- a/packages/webapp/webapp_server.js +++ b/packages/webapp/webapp_server.js @@ -130,10 +130,63 @@ var identifyBrowser = function (userAgentString) { WebAppInternals.identifyBrowser = identifyBrowser; WebApp.categorizeRequest = function (req) { - return _.extend({ - browser: identifyBrowser(req.headers['user-agent']), - url: parseUrl(req.url, true) - }, _.pick(req, 'dynamicHead', 'dynamicBody', 'headers', 'cookies')); + if (req.browser && req.arch && typeof req.modern === "boolean") { + // Already categorized. + return req; + } + + const browser = identifyBrowser(req.headers["user-agent"]); + const modern = isModern(browser); + const path = typeof req.pathname === "string" + ? req.pathname + : parseRequest(req).pathname; + + const categorized = { + browser, + modern, + path, + arch: WebApp.defaultArch, + url: parseUrl(req.url, true), + dynamicHead: req.dynamicHead, + dynamicBody: req.dynamicBody, + headers: req.headers, + cookies: req.cookies, + }; + + const pathParts = path.split("/"); + const archKey = pathParts[1]; + + if (archKey.startsWith("__")) { + const archCleaned = "web." + archKey.slice(2); + if (hasOwn.call(WebApp.clientPrograms, archCleaned)) { + pathParts.splice(1, 1); // Remove the archKey part. + return Object.assign(categorized, { + arch: archCleaned, + path: pathParts.join("/"), + }); + } + } + + // TODO Perhaps one day we could infer Cordova clients here, so that we + // wouldn't have to use prefixed "/__cordova/..." URLs. + const preferredArchOrder = isModern(browser) + ? ["web.browser", "web.browser.legacy"] + : ["web.browser.legacy", "web.browser"]; + + for (const arch of preferredArchOrder) { + // If our preferred arch is not available, it's better to use another + // client arch that is available than to guarantee the site won't work + // by returning an unknown arch. For example, if web.browser.legacy is + // excluded using the --exclude-archs command-line option, legacy + // clients are better off receiving web.browser (which might actually + // work) than receiving an HTTP 404 response. If none of the archs in + // preferredArchOrder are defined, only then should we send a 404. + if (hasOwn.call(WebApp.clientPrograms, arch)) { + return Object.assign(categorized, { arch }); + } + } + + return categorized; }; // HTML attribute hooks: functions to be called to determine any attributes to @@ -399,10 +452,7 @@ WebAppInternals.staticFilesMiddleware = async function ( return; } - const { arch, path } = getArchAndPath( - pathname, - identifyBrowser(req.headers["user-agent"]), - ); + const { arch, path } = WebApp.categorizeRequest(req); if (! hasOwn.call(WebApp.clientPrograms, arch)) { // We could come here in case we run with some architectures excluded @@ -525,7 +575,7 @@ function getStaticFileInfo(staticFilesByArch, originalPath, path, arch) { return finalize(originalPath); } - // If getArchAndPath returned an alternate path, try that instead. + // If categorizeRequest returned an alternate path, try that instead. if (path !== originalPath && hasOwn.call(staticFiles, path)) { return finalize(path); @@ -535,37 +585,6 @@ function getStaticFileInfo(staticFilesByArch, originalPath, path, arch) { return info; } -function getArchAndPath(path, browser) { - const pathParts = path.split("/"); - const archKey = pathParts[1]; - - if (archKey.startsWith("__")) { - const archCleaned = "web." + archKey.slice(2); - if (hasOwn.call(WebApp.clientPrograms, archCleaned)) { - pathParts.splice(1, 1); // Remove the archKey part. - return { - arch: archCleaned, - path: pathParts.join("/"), - }; - } - } - - // TODO Perhaps one day we could infer Cordova clients here, so that we - // wouldn't have to use prefixed "/__cordova/..." URLs. - const arch = isModern(browser) - ? "web.browser" - : "web.browser.legacy"; - - if (hasOwn.call(WebApp.clientPrograms, arch)) { - return { arch, path }; - } - - return { - arch: WebApp.defaultArch, - path, - }; -} - // Parse the passed in port value. Return the port as-is if it's a String // (e.g. a Windows Server style named pipe), otherwise return the port as an // integer. @@ -886,7 +905,7 @@ function runWebAppServer() { if (isPrefixOf(prefixParts, pathParts)) { request.url = "/" + pathParts.slice(prefixParts.length).join("/"); if (search) { - request.url += search; + request.url += search; } return next(); } @@ -991,10 +1010,8 @@ function runWebAppServer() { return; } - const { arch } = getArchAndPath( - parseRequest(req).pathname, - request.browser, - ); + const { arch } = request; + assert.strictEqual(typeof arch, "string", { arch }); if (! hasOwn.call(WebApp.clientPrograms, arch)) { // We could come here in case we run with some architectures excluded diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index e5448e98ab..bb569315d0 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.10-rc.5", + "version": "1.10.2-rc.0", "recommended": false, "official": false, "description": "Meteor" diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index f83b2f042d..49c3725fd8 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.10.1", + "version": "1.10.2", "recommended": false, "official": true, "description": "The Official Meteor Distribution" diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 38b49a357f..026a66f569 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -6,7 +6,7 @@ set -u UNAME=$(uname) ARCH=$(uname -m) NODE_VERSION=12.16.1 -MONGO_VERSION_64BIT=4.2.1 +MONGO_VERSION_64BIT=4.2.5 MONGO_VERSION_32BIT=3.2.22 NPM_VERSION=6.14.0 diff --git a/scripts/dev-bundle-server-package.js b/scripts/dev-bundle-server-package.js index b91c2579c1..8f400155d7 100644 --- a/scripts/dev-bundle-server-package.js +++ b/scripts/dev-bundle-server-package.js @@ -14,7 +14,7 @@ var packageJson = { "meteor-promise": "0.8.7", promise: "8.0.2", reify: "0.20.12", - "@babel/parser": "7.8.4", + "@babel/parser": "7.9.4", "@types/underscore": "1.9.2", underscore: "1.9.1", "source-map-support": "https://github.com/meteor/node-source-map-support/tarball/1912478769d76e5df4c365e147f25896aee6375e", diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 6a53ea7db7..266f2d7fd8 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -14,15 +14,15 @@ var packageJson = { pacote: "https://github.com/meteor/pacote/tarball/a81b0324686e85d22c7688c47629d4009000e8b8", "node-gyp": "6.0.1", "node-pre-gyp": "0.14.0", - typescript: "3.7.5", - "meteor-babel": "7.8.2", + typescript: "3.8.3", + "meteor-babel": "7.9.0", // Keep the versions of these packages consistent with the versions // found in dev-bundle-server-package.js. "meteor-promise": "0.8.7", fibers: "4.0.3", reify: "0.20.12", // So that Babel can emit require("@babel/runtime/helpers/...") calls. - "@babel/runtime": "7.8.4", + "@babel/runtime": "7.9.2", // For backwards compatibility with isopackets that still depend on // babel-runtime rather than @babel/runtime. "babel-runtime": "7.0.0-beta.3", diff --git a/scripts/windows/download-dev-bundle.ps1 b/scripts/windows/download-dev-bundle.ps1 index a16581ace2..40b4030307 100644 --- a/scripts/windows/download-dev-bundle.ps1 +++ b/scripts/windows/download-dev-bundle.ps1 @@ -41,7 +41,7 @@ if (Test-Path $devbundle_zip) { Write-Host "Extracting $TARBALL to the dev_bundle directory" -cmd /C "7z.exe x $devbundle_zip -so | 7z.exe x -aoa -si -ttar -o$CHECKOUT_DIR\dev_bundle_XXX" | out-null +cmd /C "7z.exe x `"$devbundle_zip`" -so | 7z.exe x -aoa -si -ttar -o`"$CHECKOUT_DIR\dev_bundle_XXX`"" | out-null if ($LASTEXITCODE -ne 0) { Exit 1 } diff --git a/tools/meteor-services/deploy.js b/tools/meteor-services/deploy.js index 85d97b46f6..af4ed72b18 100644 --- a/tools/meteor-services/deploy.js +++ b/tools/meteor-services/deploy.js @@ -782,9 +782,9 @@ export function changeAuthorized(site, action, username) { } const verbs = { - add: "added", - remove: "removed", - transfer: "transferred" + add: "added to", + remove: "removed from", + transfer: "transferred to" }; Console.info(`${site}: ${verbs[action]} ${username}`); return 0; diff --git a/tools/runners/run-app.js b/tools/runners/run-app.js index 9d67c146a8..5354188cdb 100644 --- a/tools/runners/run-app.js +++ b/tools/runners/run-app.js @@ -23,13 +23,13 @@ const hasOwn = Object.prototype.hasOwnProperty; // Parse out s as if it were a bash command line. var bashParse = function (s) { if (s.search("\"") !== -1 || s.search("'") !== -1) { - throw new Error("Meteor cannot currently handle quoted NODE_OPTIONS"); + throw new Error("Meteor cannot currently handle quoted SERVER_NODE_OPTIONS"); } return _.without(s.split(/\s+/), ''); }; var getNodeOptionsFromEnvironment = function () { - return bashParse(process.env.NODE_OPTIONS || ""); + return bashParse(process.env.SERVER_NODE_OPTIONS || ""); }; /////////////////////////////////////////////////////////////////////////////// diff --git a/tools/runners/run-proxy.js b/tools/runners/run-proxy.js index 10e416708b..3aa0513072 100644 --- a/tools/runners/run-proxy.js +++ b/tools/runners/run-proxy.js @@ -96,6 +96,15 @@ _.extend(Proxy.prototype, { // client->proxy connection has an error, though this may change; see // discussion at https://github.com/nodejitsu/node-http-proxy/pull/488 self.proxy.on('error', function (err, req, resOrSocket) { + if (err.code === 'HPE_HEADER_OVERFLOW') { + const logMessage = 'Error during proxy to server communication ' + + 'due to the header size exceeding Node\'s currently ' + + 'configured limit. This limit is configurable with a command ' + + 'line option (https://nodejs.org/api/cli.html#cli_max_http_header_size_size ' + + 'and https://docs.meteor.com/commandline.html#meteorrun).'; + runLog.log(logMessage); + } + if (resOrSocket instanceof http.ServerResponse) { if (!resOrSocket.headersSent) { // Return a 503, but only if we haven't already written headers (or diff --git a/tools/shell-client.ts b/tools/shell-client.ts index 7e46812bb8..344b7b3957 100644 --- a/tools/shell-client.ts +++ b/tools/shell-client.ts @@ -180,7 +180,7 @@ class Client { eachline(sock, (line: string) => { this.exitOnClose = line.indexOf(EXITING_MESSAGE) >= 0; - return line; + return undefined as unknown as string; }); sock.on("connect", onConnect); diff --git a/tools/static-assets/server/boot.js b/tools/static-assets/server/boot.js index c844f824dc..6e78d35170 100644 --- a/tools/static-assets/server/boot.js +++ b/tools/static-assets/server/boot.js @@ -369,6 +369,9 @@ var loadServerBundles = Profile("Load server bundles", function () { var filePath = path.join(serverDir, fileInfo.assets[assetPath]); return files.convertToOSPath(filePath); }, + getServerDir: function() { + return serverDir; + } }; var wrapParts = ["(function(Npm,Assets"]; diff --git a/tools/tests/apps/dynamic-import/.meteor/packages b/tools/tests/apps/dynamic-import/.meteor/packages index 4271d796fc..b74a849e52 100644 --- a/tools/tests/apps/dynamic-import/.meteor/packages +++ b/tools/tests/apps/dynamic-import/.meteor/packages @@ -5,18 +5,17 @@ # but you can also edit it by hand. meteor-base@1.4.0 # Packages every Meteor app needs to have -mobile-experience@1.0.5 # Packages for a great mobile UX -mongo@1.6.2 # The database Meteor supports right now +mobile-experience@1.1.0 # Packages for a great mobile UX +mongo@1.9.0 # The database Meteor supports right now blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views reactive-var@1.0.11 # Reactive variable for tracker -jquery # Helpful client-side library tracker@1.2.0 # Meteor's client-side reactive programming library -standard-minifier-css@1.5.3 # CSS minifier run for production mode -standard-minifier-js@2.4.1 # JS minifier run for production mode +standard-minifier-css@1.6.0 # CSS minifier run for production mode +standard-minifier-js@2.6.0 # JS minifier run for production mode es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers. -ecmascript@0.12.4 # Enable ECMAScript2015+ syntax in app code -shell-server@0.4.0 # Server-side component of the `meteor shell` command +ecmascript@0.14.2 # Enable ECMAScript2015+ syntax in app code +shell-server@0.5.0 # Server-side component of the `meteor shell` command autopublish@1.0.7 # Publish all data to the clients (for prototyping) insecure@1.0.7 # Allow all DB writes from clients (for prototyping) @@ -26,3 +25,4 @@ helper-package user:colon-name underscore@1.0.10 fetch@0.1.1 +jquery diff --git a/tools/tests/apps/dynamic-import/.meteor/release b/tools/tests/apps/dynamic-import/.meteor/release index 97064e1993..d259781110 100644 --- a/tools/tests/apps/dynamic-import/.meteor/release +++ b/tools/tests/apps/dynamic-import/.meteor/release @@ -1 +1 @@ -METEOR@1.8.1 +METEOR@1.10.1 diff --git a/tools/tests/apps/dynamic-import/.meteor/versions b/tools/tests/apps/dynamic-import/.meteor/versions index 74049f3d5b..a99df3012b 100644 --- a/tools/tests/apps/dynamic-import/.meteor/versions +++ b/tools/tests/apps/dynamic-import/.meteor/versions @@ -1,32 +1,32 @@ allow-deny@1.1.0 autopublish@1.0.7 autoupdate@1.6.0 -babel-compiler@7.3.4 -babel-runtime@1.3.0 -base64@1.0.11 +babel-compiler@7.5.3 +babel-runtime@1.5.0 +base64@1.0.12 binary-heap@1.0.11 -blaze@2.3.3 +blaze@2.3.4 blaze-html-templates@1.1.2 blaze-tools@1.0.10 -boilerplate-generator@1.6.0 +boilerplate-generator@1.7.0 caching-compiler@1.2.1 caching-html-compiler@1.1.3 -callback-hook@1.1.0 +callback-hook@1.3.0 check@1.3.1 -coffeescript@2.3.2_1 -coffeescript-compiler@2.3.2_1 +coffeescript@2.4.1 +coffeescript-compiler@2.4.1 ddp@1.4.0 ddp-client@2.3.3 ddp-common@1.4.0 -ddp-server@2.3.0 +ddp-server@2.3.1 deps@1.0.12 diff-sequence@1.1.1 dynamic-import@0.5.1 -ecmascript@0.12.7 +ecmascript@0.14.3 ecmascript-runtime@0.7.0 -ecmascript-runtime-client@0.8.0 -ecmascript-runtime-server@0.7.1 -ejson@1.1.0 +ecmascript-runtime-client@0.10.0 +ecmascript-runtime-server@0.9.0 +ejson@1.1.1 es5-shim@4.8.0 fetch@0.1.1 geojson-utils@1.0.10 @@ -36,41 +36,41 @@ html-tools@1.0.11 htmljs@1.0.11 id-map@1.1.0 insecure@1.0.7 -inter-process-messaging@0.1.0 -jquery@1.11.11 -launch-screen@1.1.1 +inter-process-messaging@0.1.1 +jquery@3.0.0 +launch-screen@1.2.0 lazy-test-package@0.0.1 livedata@1.0.18 logging@1.1.20 meteor@1.9.3 meteor-base@1.4.0 -minifier-css@1.4.2 -minifier-js@2.4.1 -minimongo@1.4.5 -mobile-experience@1.0.5 -mobile-status-bar@1.0.14 -modern-browsers@0.1.4 -modules@0.13.0 -modules-runtime@0.10.3 -mongo@1.6.2 +minifier-css@1.5.0 +minifier-js@2.6.0 +minimongo@1.5.0 +mobile-experience@1.1.0 +mobile-status-bar@1.1.0 +modern-browsers@0.1.5 +modules@0.15.0 +modules-runtime@0.12.0 +mongo@1.9.1 mongo-decimal@0.1.1 mongo-dev-server@1.1.0 mongo-id@1.0.7 -npm-mongo@3.1.2 +npm-mongo@3.7.0 observe-sequence@1.0.16 ordered-dict@1.1.0 promise@0.11.2 -random@1.1.0 +random@1.2.0 reactive-var@1.0.11 reload@1.3.0 retry@1.1.0 routepolicy@1.1.0 -shell-server@0.4.0 -socket-stream-client@0.2.2 +shell-server@0.5.0 +socket-stream-client@0.2.3 spacebars@1.0.15 spacebars-compiler@1.1.3 -standard-minifier-css@1.5.3 -standard-minifier-js@2.4.1 +standard-minifier-css@1.6.0 +standard-minifier-js@2.6.0 templating@1.3.2 templating-compiler@1.3.3 templating-runtime@1.3.2 @@ -79,5 +79,5 @@ tracker@1.2.0 ui@1.0.13 underscore@1.0.10 user:colon-name@0.0.1 -webapp@1.7.4 +webapp@1.9.0 webapp-hashing@1.0.9 diff --git a/tools/tests/apps/dynamic-import/package-lock.json b/tools/tests/apps/dynamic-import/package-lock.json index 65896c125a..53af0c9685 100644 --- a/tools/tests/apps/dynamic-import/package-lock.json +++ b/tools/tests/apps/dynamic-import/package-lock.json @@ -4,39 +4,35 @@ "lockfileVersion": 1, "dependencies": { "@babel/runtime": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.0.tgz", - "integrity": "sha512-2xsuyZ0R0RBFwjgae5NpXk8FcfH4qovj5cEM5VEeB7KXnKqzaisIu2HSV/mCEISolJJuR4wkViUGYujA8MH9tw==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", "requires": { - "regenerator-runtime": "^0.13.2" + "regenerator-runtime": "^0.13.4" } }, - "@types/node": { - "version": "12.0.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.12.tgz", - "integrity": "sha512-Uy0PN4R5vgBUXFoJrKryf5aTk3kJ8Rv3PdlHjl6UaX+Cqp1QE0yPQ68MPXGrZOfG7gZVNDIJZYyot0B9ubXUrQ==" + "@types/mime-types": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz", + "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=" }, "@wry/context": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.4.4.tgz", - "integrity": "sha512-LrKVLove/zw6h2Md/KZyWxIkFM6AoyKp71OqpH9Hiip1csjPVoD3tPxlbQUNxEnHENks3UGgNpSBCAfq9KWuag==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.5.1.tgz", + "integrity": "sha512-VfPjm79RbzEYZigvZFk7DdvYX+8Qb57xOZw8m2iaAmgmBMNhGDN5yKGiplubX958oFAQMXfaftgTa/VFnu2CsQ==", "requires": { - "@types/node": ">=6", "tslib": "^1.9.3" } }, "acorn": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", - "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==" + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==" }, "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "requires": { - "es6-promisify": "^5.0.0" - } + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==" }, "arson": { "version": "0.2.6", @@ -44,9 +40,9 @@ "integrity": "sha512-wVRnIfjOaCWu3jrf3j1CU/eotDf7tuM34cBswo32EwyLPaMiaWgETfROdYVv47VWEbWSOaZaDnkypGQtQduLbw==" }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "balanced-match": { "version": "1.0.0", @@ -62,6 +58,11 @@ "concat-map": "0.0.1" } }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -96,28 +97,15 @@ "ms": "^2.1.1" } }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "requires": { - "es6-promise": "^4.0.3" - } - }, "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" }, "dependencies": { "debug": { @@ -136,9 +124,9 @@ } }, "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "requires": { "pend": "~1.2.0" } @@ -149,9 +137,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -162,22 +150,12 @@ } }, "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } + "agent-base": "5", + "debug": "4" } }, "inflight": { @@ -199,6 +177,11 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "jquery": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", + "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -778,6 +761,19 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "requires": { + "mime-db": "1.43.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -787,16 +783,16 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "moment": { @@ -823,11 +819,11 @@ } }, "optimism": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.10.2.tgz", - "integrity": "sha512-zPfBIxFFWMmQboM9+Z4MSJqc1PXp82v1PFq/GfQaufI69mHKlup7ykGNnfuGIGssXJQkmhSodQ/k9EWwjd8O8A==", + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.11.5.tgz", + "integrity": "sha512-twCHmBb64DYzEZ8A3O+TLCuF/RmZPBhXPQYv4agoiALRLlW9SidMzd7lwUP9mL0jOZhzhnBmb8ajqA00ECo/7g==", "requires": { - "@wry/context": "^0.4.0" + "@wry/context": "^0.5.0" } }, "path-is-absolute": { @@ -866,19 +862,21 @@ } }, "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "puppeteer": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.18.1.tgz", - "integrity": "sha512-luUy0HPSuWPsPZ1wAp6NinE0zgetWtudf5zwZ6dHjMWfYpTQcmKveFRox7VBNhQ98OjNA9PQ9PzQyX8k/KrxTg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-2.1.1.tgz", + "integrity": "sha512-LWzaDVQkk1EPiuYeTOj+CZRIjda4k2s5w4MK4xoH2+kgWV/SDlkYHmxatDdtYrciHUKSXTsGgPgPP8ILVdBsxg==", "requires": { + "@types/mime-types": "^2.1.0", "debug": "^4.1.0", "extract-zip": "^1.6.6", - "https-proxy-agent": "^2.2.1", + "https-proxy-agent": "^4.0.0", "mime": "^2.0.3", + "mime-types": "^2.1.25", "progress": "^2.0.1", "proxy-from-env": "^1.0.0", "rimraf": "^2.6.1", @@ -886,25 +884,24 @@ } }, "react": { - "version": "16.8.6", - "resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz", - "integrity": "sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==", + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", + "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.13.6" + "prop-types": "^15.6.2" } }, "react-is": { - "version": "16.8.6", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", - "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -916,14 +913,14 @@ } }, "regenerator-runtime": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", - "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { "glob": "^7.1.3" } @@ -933,15 +930,6 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "scheduler": { - "version": "0.13.6", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", - "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -951,9 +939,9 @@ } }, "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", + "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" }, "typedarray": { "version": "0.0.6", @@ -966,9 +954,9 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz", + "integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==" }, "wrappy": { "version": "1.0.2", @@ -984,11 +972,12 @@ } }, "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "requires": { - "fd-slicer": "~1.0.1" + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" } } } diff --git a/tools/tests/apps/dynamic-import/package.json b/tools/tests/apps/dynamic-import/package.json index cb99c14f0d..95244ef029 100644 --- a/tools/tests/apps/dynamic-import/package.json +++ b/tools/tests/apps/dynamic-import/package.json @@ -6,17 +6,17 @@ "test": "TEST_BROWSER_DRIVER=puppeteer meteor test --full-app --driver-package meteortesting:mocha" }, "dependencies": { - "@babel/runtime": "^7.5.0", - "acorn": "^6.2.0", + "@babel/runtime": "^7.9.2", + "acorn": "^7.1.1", "arson": "^0.2.6", "jquery": "^3.4.1", "meteor-node-stubs": "^1.0.0", "moment": "^2.24.0", - "optimism": "^0.10.2", + "optimism": "^0.11.5", "private": "^0.1.8", - "puppeteer": "^1.18.1", - "react": "^16.8.6", - "regenerator-runtime": "^0.13.2", - "uuid": "^3.3.2" + "puppeteer": "^2.1.1", + "react": "^16.13.1", + "regenerator-runtime": "^0.13.5", + "uuid": "^7.0.2" } } diff --git a/tools/tests/apps/dynamic-import/tests.js b/tools/tests/apps/dynamic-import/tests.js index 3b0451d665..3dd68d24ee 100644 --- a/tools/tests/apps/dynamic-import/tests.js +++ b/tools/tests/apps/dynamic-import/tests.js @@ -247,15 +247,15 @@ describe("dynamic import(...)", function () { }); it('should support object-valued package.json "browser" fields', () => { - return import("uuid").then(({ default: uuid }) => { + return import("uuid").then(({ v4: uuid }) => { const id = uuid(); assert.strictEqual(typeof id, "string"); assert.strictEqual(id.split("-").length, 5); if (Meteor.isClient) { assert.strictEqual( - require.resolve("uuid/lib/rng.js"), - "/node_modules/uuid/lib/rng-browser.js" + require.resolve("uuid/dist/esm-node/index.js"), + "/node_modules/uuid/dist/esm-browser/index.js" ); const uuidPkgJsonId = ["uuid", "package.json"].join("/"); const { browser } = require(uuidPkgJsonId); diff --git a/tools/tests/apps/modules/.meteor/packages b/tools/tests/apps/modules/.meteor/packages index 25461e4426..1aec0f64f8 100644 --- a/tools/tests/apps/modules/.meteor/packages +++ b/tools/tests/apps/modules/.meteor/packages @@ -5,15 +5,15 @@ # but you can also edit it by hand. meteor-base@1.4.0 # Packages every Meteor app needs to have -mobile-experience@1.0.5 # Packages for a great mobile UX -mongo@1.8.0 # The database Meteor supports right now +mobile-experience@1.1.0 # Packages for a great mobile UX +mongo@1.9.0 # The database Meteor supports right now blaze-html-templates # Compile .html files into Meteor Blaze views session@1.2.0 # Client-side reactive dictionary for your app jquery # Helpful client-side library tracker@1.2.0 # Meteor's client-side reactive programming library es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers. -ecmascript@0.14.0 # Enable ECMAScript2015+ syntax in app code +ecmascript@0.14.2 # Enable ECMAScript2015+ syntax in app code coffeescript modules-test-package @@ -21,10 +21,10 @@ standard-minifier-css@1.6.0 standard-minifier-js@2.6.0 client-only-ecmascript modules-test-plugin -shell-server@0.4.0 +shell-server@0.5.0 dynamic-import@0.5.1 underscore@1.0.10 import-local-json-module akryum:vue-component dummy-compiler -typescript@3.7.2 +typescript@3.7.5 diff --git a/tools/tests/apps/modules/.meteor/release b/tools/tests/apps/modules/.meteor/release index c6ae8ec13c..d259781110 100644 --- a/tools/tests/apps/modules/.meteor/release +++ b/tools/tests/apps/modules/.meteor/release @@ -1 +1 @@ -METEOR@1.9 +METEOR@1.10.1 diff --git a/tools/tests/apps/modules/imports/links/acorn/.npmignore b/tools/tests/apps/modules/imports/links/acorn/.npmignore new file mode 100644 index 0000000000..0e574439e0 --- /dev/null +++ b/tools/tests/apps/modules/imports/links/acorn/.npmignore @@ -0,0 +1,3 @@ +.tern-* +/rollup.config.* +/src diff --git a/tools/tests/apps/modules/imports/links/acorn/CHANGELOG.md b/tools/tests/apps/modules/imports/links/acorn/CHANGELOG.md new file mode 100644 index 0000000000..93837a91a1 --- /dev/null +++ b/tools/tests/apps/modules/imports/links/acorn/CHANGELOG.md @@ -0,0 +1,580 @@ +## 6.4.1 (2020-03-09) + +### Bug fixes + +More carefully check for valid UTF16 surrogate pairs in regexp validator. + +## 7.1.1 (2020-03-01) + +### Bug fixes + +Treat `\8` and `\9` as invalid escapes in template strings. + +Allow unicode escapes in property names that are keywords. + +Don't error on an exponential operator expression as argument to `await`. + +More carefully check for valid UTF16 surrogate pairs in regexp validator. + +## 7.1.0 (2019-09-24) + +### Bug fixes + +Disallow trailing object literal commas when ecmaVersion is less than 5. + +### New features + +Add a static `acorn` property to the `Parser` class that contains the entire module interface, to allow plugins to access the instance of the library that they are acting on. + +## 7.0.0 (2019-08-13) + +### Breaking changes + +Changes the node format for dynamic imports to use the `ImportExpression` node type, as defined in [ESTree](https://github.com/estree/estree/blob/master/es2020.md#importexpression). + +Makes 10 (ES2019) the default value for the `ecmaVersion` option. + +## 6.3.0 (2019-08-12) + +### New features + +`sourceType: "module"` can now be used even when `ecmaVersion` is less than 6, to parse module-style code that otherwise conforms to an older standard. + +## 6.2.1 (2019-07-21) + +### Bug fixes + +Fix bug causing Acorn to treat some characters as identifier characters that shouldn't be treated as such. + +Fix issue where setting the `allowReserved` option to `"never"` allowed reserved words in some circumstances. + +## 6.2.0 (2019-07-04) + +### Bug fixes + +Improve valid assignment checking in `for`/`in` and `for`/`of` loops. + +Disallow binding `let` in patterns. + +### New features + +Support bigint syntax with `ecmaVersion` >= 11. + +Support dynamic `import` syntax with `ecmaVersion` >= 11. + +Upgrade to Unicode version 12. + +## 6.1.1 (2019-02-27) + +### Bug fixes + +Fix bug that caused parsing default exports of with names to fail. + +## 6.1.0 (2019-02-08) + +### Bug fixes + +Fix scope checking when redefining a `var` as a lexical binding. + +### New features + +Split up `parseSubscripts` to use an internal `parseSubscript` method to make it easier to extend with plugins. + +## 6.0.7 (2019-02-04) + +### Bug fixes + +Check that exported bindings are defined. + +Don't treat `\u180e` as a whitespace character. + +Check for duplicate parameter names in methods. + +Don't allow shorthand properties when they are generators or async methods. + +Forbid binding `await` in async arrow function's parameter list. + +## 6.0.6 (2019-01-30) + +### Bug fixes + +The content of class declarations and expressions is now always parsed in strict mode. + +Don't allow `let` or `const` to bind the variable name `let`. + +Treat class declarations as lexical. + +Don't allow a generator function declaration as the sole body of an `if` or `else`. + +Ignore `"use strict"` when after an empty statement. + +Allow string line continuations with special line terminator characters. + +Treat `for` bodies as part of the `for` scope when checking for conflicting bindings. + +Fix bug with parsing `yield` in a `for` loop initializer. + +Implement special cases around scope checking for functions. + +## 6.0.5 (2019-01-02) + +### Bug fixes + +Fix TypeScript type for `Parser.extend` and add `allowAwaitOutsideFunction` to options type. + +Don't treat `let` as a keyword when the next token is `{` on the next line. + +Fix bug that broke checking for parentheses around an object pattern in a destructuring assignment when `preserveParens` was on. + +## 6.0.4 (2018-11-05) + +### Bug fixes + +Further improvements to tokenizing regular expressions in corner cases. + +## 6.0.3 (2018-11-04) + +### Bug fixes + +Fix bug in tokenizing an expression-less return followed by a function followed by a regular expression. + +Remove stray symlink in the package tarball. + +## 6.0.2 (2018-09-26) + +### Bug fixes + +Fix bug where default expressions could fail to parse inside an object destructuring assignment expression. + +## 6.0.1 (2018-09-14) + +### Bug fixes + +Fix wrong value in `version` export. + +## 6.0.0 (2018-09-14) + +### Bug fixes + +Better handle variable-redefinition checks for catch bindings and functions directly under if statements. + +Forbid `new.target` in top-level arrow functions. + +Fix issue with parsing a regexp after `yield` in some contexts. + +### New features + +The package now comes with TypeScript definitions. + +### Breaking changes + +The default value of the `ecmaVersion` option is now 9 (2018). + +Plugins work differently, and will have to be rewritten to work with this version. + +The loose parser and walker have been moved into separate packages (`acorn-loose` and `acorn-walk`). + +## 5.7.3 (2018-09-10) + +### Bug fixes + +Fix failure to tokenize regexps after expressions like `x.of`. + +Better error message for unterminated template literals. + +## 5.7.2 (2018-08-24) + +### Bug fixes + +Properly handle `allowAwaitOutsideFunction` in for statements. + +Treat function declarations at the top level of modules like let bindings. + +Don't allow async function declarations as the only statement under a label. + +## 5.7.0 (2018-06-15) + +### New features + +Upgraded to Unicode 11. + +## 5.6.0 (2018-05-31) + +### New features + +Allow U+2028 and U+2029 in string when ECMAVersion >= 10. + +Allow binding-less catch statements when ECMAVersion >= 10. + +Add `allowAwaitOutsideFunction` option for parsing top-level `await`. + +## 5.5.3 (2018-03-08) + +### Bug fixes + +A _second_ republish of the code in 5.5.1, this time with yarn, to hopefully get valid timestamps. + +## 5.5.2 (2018-03-08) + +### Bug fixes + +A republish of the code in 5.5.1 in an attempt to solve an issue with the file timestamps in the npm package being 0. + +## 5.5.1 (2018-03-06) + +### Bug fixes + +Fix misleading error message for octal escapes in template strings. + +## 5.5.0 (2018-02-27) + +### New features + +The identifier character categorization is now based on Unicode version 10. + +Acorn will now validate the content of regular expressions, including new ES9 features. + +## 5.4.0 (2018-02-01) + +### Bug fixes + +Disallow duplicate or escaped flags on regular expressions. + +Disallow octal escapes in strings in strict mode. + +### New features + +Add support for async iteration. + +Add support for object spread and rest. + +## 5.3.0 (2017-12-28) + +### Bug fixes + +Fix parsing of floating point literals with leading zeroes in loose mode. + +Allow duplicate property names in object patterns. + +Don't allow static class methods named `prototype`. + +Disallow async functions directly under `if` or `else`. + +Parse right-hand-side of `for`/`of` as an assignment expression. + +Stricter parsing of `for`/`in`. + +Don't allow unicode escapes in contextual keywords. + +### New features + +Parsing class members was factored into smaller methods to allow plugins to hook into it. + +## 5.2.1 (2017-10-30) + +### Bug fixes + +Fix a token context corruption bug. + +## 5.2.0 (2017-10-30) + +### Bug fixes + +Fix token context tracking for `class` and `function` in property-name position. + +Make sure `%*` isn't parsed as a valid operator. + +Allow shorthand properties `get` and `set` to be followed by default values. + +Disallow `super` when not in callee or object position. + +### New features + +Support [`directive` property](https://github.com/estree/estree/compare/b3de58c9997504d6fba04b72f76e6dd1619ee4eb...1da8e603237144f44710360f8feb7a9977e905e0) on directive expression statements. + +## 5.1.2 (2017-09-04) + +### Bug fixes + +Disable parsing of legacy HTML-style comments in modules. + +Fix parsing of async methods whose names are keywords. + +## 5.1.1 (2017-07-06) + +### Bug fixes + +Fix problem with disambiguating regexp and division after a class. + +## 5.1.0 (2017-07-05) + +### Bug fixes + +Fix tokenizing of regexps in an object-desctructuring `for`/`of` loop and after `yield`. + +Parse zero-prefixed numbers with non-octal digits as decimal. + +Allow object/array patterns in rest parameters. + +Don't error when `yield` is used as a property name. + +Allow `async` as a shorthand object property. + +### New features + +Implement the [template literal revision proposal](https://github.com/tc39/proposal-template-literal-revision) for ES9. + +## 5.0.3 (2017-04-01) + +### Bug fixes + +Fix spurious duplicate variable definition errors for named functions. + +## 5.0.2 (2017-03-30) + +### Bug fixes + +A binary operator after a parenthesized arrow expression is no longer incorrectly treated as an error. + +## 5.0.0 (2017-03-28) + +### Bug fixes + +Raise an error for duplicated lexical bindings. + +Fix spurious error when an assignement expression occurred after a spread expression. + +Accept regular expressions after `of` (in `for`/`of`), `yield` (in a generator), and braced arrow functions. + +Allow labels in front or `var` declarations, even in strict mode. + +### Breaking changes + +Parse declarations following `export default` as declaration nodes, not expressions. This means that class and function declarations nodes can now have `null` as their `id`. + +## 4.0.11 (2017-02-07) + +### Bug fixes + +Allow all forms of member expressions to be parenthesized as lvalue. + +## 4.0.10 (2017-02-07) + +### Bug fixes + +Don't expect semicolons after default-exported functions or classes, even when they are expressions. + +Check for use of `'use strict'` directives in non-simple parameter functions, even when already in strict mode. + +## 4.0.9 (2017-02-06) + +### Bug fixes + +Fix incorrect error raised for parenthesized simple assignment targets, so that `(x) = 1` parses again. + +## 4.0.8 (2017-02-03) + +### Bug fixes + +Solve spurious parenthesized pattern errors by temporarily erring on the side of accepting programs that our delayed errors don't handle correctly yet. + +## 4.0.7 (2017-02-02) + +### Bug fixes + +Accept invalidly rejected code like `(x).y = 2` again. + +Don't raise an error when a function _inside_ strict code has a non-simple parameter list. + +## 4.0.6 (2017-02-02) + +### Bug fixes + +Fix exponential behavior (manifesting itself as a complete hang for even relatively small source files) introduced by the new 'use strict' check. + +## 4.0.5 (2017-02-02) + +### Bug fixes + +Disallow parenthesized pattern expressions. + +Allow keywords as export names. + +Don't allow the `async` keyword to be parenthesized. + +Properly raise an error when a keyword contains a character escape. + +Allow `"use strict"` to appear after other string literal expressions. + +Disallow labeled declarations. + +## 4.0.4 (2016-12-19) + +### Bug fixes + +Fix crash when `export` was followed by a keyword that can't be +exported. + +## 4.0.3 (2016-08-16) + +### Bug fixes + +Allow regular function declarations inside single-statement `if` branches in loose mode. Forbid them entirely in strict mode. + +Properly parse properties named `async` in ES2017 mode. + +Fix bug where reserved words were broken in ES2017 mode. + +## 4.0.2 (2016-08-11) + +### Bug fixes + +Don't ignore period or 'e' characters after octal numbers. + +Fix broken parsing for call expressions in default parameter values of arrow functions. + +## 4.0.1 (2016-08-08) + +### Bug fixes + +Fix false positives in duplicated export name errors. + +## 4.0.0 (2016-08-07) + +### Breaking changes + +The default `ecmaVersion` option value is now 7. + +A number of internal method signatures changed, so plugins might need to be updated. + +### Bug fixes + +The parser now raises errors on duplicated export names. + +`arguments` and `eval` can now be used in shorthand properties. + +Duplicate parameter names in non-simple argument lists now always produce an error. + +### New features + +The `ecmaVersion` option now also accepts year-style version numbers +(2015, etc). + +Support for `async`/`await` syntax when `ecmaVersion` is >= 8. + +Support for trailing commas in call expressions when `ecmaVersion` is >= 8. + +## 3.3.0 (2016-07-25) + +### Bug fixes + +Fix bug in tokenizing of regexp operator after a function declaration. + +Fix parser crash when parsing an array pattern with a hole. + +### New features + +Implement check against complex argument lists in functions that enable strict mode in ES7. + +## 3.2.0 (2016-06-07) + +### Bug fixes + +Improve handling of lack of unicode regexp support in host +environment. + +Properly reject shorthand properties whose name is a keyword. + +### New features + +Visitors created with `visit.make` now have their base as _prototype_, rather than copying properties into a fresh object. + +## 3.1.0 (2016-04-18) + +### Bug fixes + +Properly tokenize the division operator directly after a function expression. + +Allow trailing comma in destructuring arrays. + +## 3.0.4 (2016-02-25) + +### Fixes + +Allow update expressions as left-hand-side of the ES7 exponential operator. + +## 3.0.2 (2016-02-10) + +### Fixes + +Fix bug that accidentally made `undefined` a reserved word when parsing ES7. + +## 3.0.0 (2016-02-10) + +### Breaking changes + +The default value of the `ecmaVersion` option is now 6 (used to be 5). + +Support for comprehension syntax (which was dropped from the draft spec) has been removed. + +### Fixes + +`let` and `yield` are now “contextual keywords”, meaning you can mostly use them as identifiers in ES5 non-strict code. + +A parenthesized class or function expression after `export default` is now parsed correctly. + +### New features + +When `ecmaVersion` is set to 7, Acorn will parse the exponentiation operator (`**`). + +The identifier character ranges are now based on Unicode 8.0.0. + +Plugins can now override the `raiseRecoverable` method to override the way non-critical errors are handled. + +## 2.7.0 (2016-01-04) + +### Fixes + +Stop allowing rest parameters in setters. + +Disallow `y` rexexp flag in ES5. + +Disallow `\00` and `\000` escapes in strict mode. + +Raise an error when an import name is a reserved word. + +## 2.6.2 (2015-11-10) + +### Fixes + +Don't crash when no options object is passed. + +## 2.6.0 (2015-11-09) + +### Fixes + +Add `await` as a reserved word in module sources. + +Disallow `yield` in a parameter default value for a generator. + +Forbid using a comma after a rest pattern in an array destructuring. + +### New features + +Support parsing stdin in command-line tool. + +## 2.5.0 (2015-10-27) + +### Fixes + +Fix tokenizer support in the command-line tool. + +Stop allowing `new.target` outside of functions. + +Remove legacy `guard` and `guardedHandler` properties from try nodes. + +Stop allowing multiple `__proto__` properties on an object literal in strict mode. + +Don't allow rest parameters to be non-identifier patterns. + +Check for duplicate paramter names in arrow functions. diff --git a/tools/tests/apps/modules/imports/links/acorn/README.md b/tools/tests/apps/modules/imports/links/acorn/README.md new file mode 100644 index 0000000000..585f2736fc --- /dev/null +++ b/tools/tests/apps/modules/imports/links/acorn/README.md @@ -0,0 +1,270 @@ +# Acorn + +A tiny, fast JavaScript parser written in JavaScript. + +## Community + +Acorn is open source software released under an +[MIT license](https://github.com/acornjs/acorn/blob/master/acorn/LICENSE). + +You are welcome to +[report bugs](https://github.com/acornjs/acorn/issues) or create pull +requests on [github](https://github.com/acornjs/acorn). For questions +and discussion, please use the +[Tern discussion forum](https://discuss.ternjs.net). + +## Installation + +The easiest way to install acorn is from [`npm`](https://www.npmjs.com/): + +```sh +npm install acorn +``` + +Alternately, you can download the source and build acorn yourself: + +```sh +git clone https://github.com/acornjs/acorn.git +cd acorn +npm install +``` + +## Interface + +**parse**`(input, options)` is the main interface to the library. The +`input` parameter is a string, `options` can be undefined or an object +setting some of the options listed below. The return value will be an +abstract syntax tree object as specified by the [ESTree +spec](https://github.com/estree/estree). + +```javascript +let acorn = require("acorn"); +console.log(acorn.parse("1 + 1")); +``` + +When encountering a syntax error, the parser will raise a +`SyntaxError` object with a meaningful message. The error object will +have a `pos` property that indicates the string offset at which the +error occurred, and a `loc` object that contains a `{line, column}` +object referring to that same position. + +Options can be provided by passing a second argument, which should be +an object containing any of these fields: + +- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be + either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), 10 (2019) or 11 + (2020, partial support). This influences support for strict mode, + the set of reserved words, and support for new syntax features. + Default is 10. + + **NOTE**: Only 'stage 4' (finalized) ECMAScript features are being + implemented by Acorn. Other proposed new features can be implemented + through plugins. + +- **sourceType**: Indicate the mode the code should be parsed in. Can be + either `"script"` or `"module"`. This influences global strict mode + and parsing of `import` and `export` declarations. + + **NOTE**: If set to `"module"`, then static `import` / `export` syntax + will be valid, even if `ecmaVersion` is less than 6. + +- **onInsertedSemicolon**: If given a callback, that callback will be + called whenever a missing semicolon is inserted by the parser. The + callback will be given the character offset of the point where the + semicolon is inserted as argument, and if `locations` is on, also a + `{line, column}` object representing this position. + +- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing + commas. + +- **allowReserved**: If `false`, using a reserved word will generate + an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher + versions. When given the value `"never"`, reserved words and + keywords can also not be used as property names (as in Internet + Explorer's old parser). + +- **allowReturnOutsideFunction**: By default, a return statement at + the top level raises an error. Set this to `true` to accept such + code. + +- **allowImportExportEverywhere**: By default, `import` and `export` + declarations can only appear at a program's top level. Setting this + option to `true` allows them anywhere where a statement is allowed. + +- **allowAwaitOutsideFunction**: By default, `await` expressions can + only appear inside `async` functions. Setting this option to + `true` allows to have top-level `await` expressions. They are + still not allowed in non-`async` functions, though. + +- **allowHashBang**: When this is enabled (off by default), if the + code starts with the characters `#!` (as in a shellscript), the + first line will be treated as a comment. + +- **locations**: When `true`, each node has a `loc` object attached + with `start` and `end` subobjects, each of which contains the + one-based line and zero-based column numbers in `{line, column}` + form. Default is `false`. + +- **onToken**: If a function is passed for this option, each found + token will be passed in same format as tokens returned from + `tokenizer().getToken()`. + + If array is passed, each found token is pushed to it. + + Note that you are not allowed to call the parser from the + callback—that will corrupt its internal state. + +- **onComment**: If a function is passed for this option, whenever a + comment is encountered the function will be called with the + following parameters: + + - `block`: `true` if the comment is a block comment, false if it + is a line comment. + - `text`: The content of the comment. + - `start`: Character offset of the start of the comment. + - `end`: Character offset of the end of the comment. + + When the `locations` options is on, the `{line, column}` locations + of the comment’s start and end are passed as two additional + parameters. + + If array is passed for this option, each found comment is pushed + to it as object in Esprima format: + + ```javascript + { + "type": "Line" | "Block", + "value": "comment text", + "start": Number, + "end": Number, + // If `locations` option is on: + "loc": { + "start": {line: Number, column: Number} + "end": {line: Number, column: Number} + }, + // If `ranges` option is on: + "range": [Number, Number] + } + ``` + + Note that you are not allowed to call the parser from the + callback—that will corrupt its internal state. + +- **ranges**: Nodes have their start and end characters offsets + recorded in `start` and `end` properties (directly on the node, + rather than the `loc` object, which holds line/column data. To also + add a + [semi-standardized](https://bugzilla.mozilla.org/show_bug.cgi?id=745678) + `range` property holding a `[start, end]` array with the same + numbers, set the `ranges` option to `true`. + +- **program**: It is possible to parse multiple files into a single + AST by passing the tree produced by parsing the first file as the + `program` option in subsequent parses. This will add the toplevel + forms of the parsed file to the "Program" (top) node of an existing + parse tree. + +- **sourceFile**: When the `locations` option is `true`, you can pass + this option to add a `source` attribute in every node’s `loc` + object. Note that the contents of this option are not examined or + processed in any way; you are free to use whatever format you + choose. + +- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property + will be added (regardless of the `location` option) directly to the + nodes, rather than the `loc` object. + +- **preserveParens**: If this option is `true`, parenthesized expressions + are represented by (non-standard) `ParenthesizedExpression` nodes + that have a single `expression` property containing the expression + inside parentheses. + +**parseExpressionAt**`(input, offset, options)` will parse a single +expression in a string, and return its AST. It will not complain if +there is more of the string left after the expression. + +**tokenizer**`(input, options)` returns an object with a `getToken` +method that can be called repeatedly to get the next token, a `{start, +end, type, value}` object (with added `loc` property when the +`locations` option is enabled and `range` property when the `ranges` +option is enabled). When the token's type is `tokTypes.eof`, you +should stop calling the method, since it will keep returning that same +token forever. + +In ES6 environment, returned result can be used as any other +protocol-compliant iterable: + +```javascript +for (let token of acorn.tokenizer(str)) { + // iterate over the tokens +} + +// transform code to array of tokens: +var tokens = [...acorn.tokenizer(str)]; +``` + +**tokTypes** holds an object mapping names to the token type objects +that end up in the `type` properties of tokens. + +**getLineInfo**`(input, offset)` can be used to get a `{line, +column}` object for a given program string and offset. + +### The `Parser` class + +Instances of the **`Parser`** class contain all the state and logic +that drives a parse. It has static methods `parse`, +`parseExpressionAt`, and `tokenizer` that match the top-level +functions by the same name. + +When extending the parser with plugins, you need to call these methods +on the extended version of the class. To extend a parser with plugins, +you can use its static `extend` method. + +```javascript +var acorn = require("acorn"); +var jsx = require("acorn-jsx"); +var JSXParser = acorn.Parser.extend(jsx()); +JSXParser.parse("foo()"); +``` + +The `extend` method takes any number of plugin values, and returns a +new `Parser` class that includes the extra parser logic provided by +the plugins. + +## Command line interface + +The `bin/acorn` utility can be used to parse a file from the command +line. It accepts as arguments its input file and the following +options: + +- `--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|--ecma10`: Sets the ECMAScript version + to parse. Default is version 9. + +- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise. + +- `--locations`: Attaches a "loc" object to each node with "start" and + "end" subobjects, each of which contains the one-based line and + zero-based column numbers in `{line, column}` form. + +- `--allow-hash-bang`: If the code starts with the characters #! (as + in a shellscript), the first line will be treated as a comment. + +- `--compact`: No whitespace is used in the AST output. + +- `--silent`: Do not output the AST, just return the exit status. + +- `--help`: Print the usage information and quit. + +The utility spits out the syntax tree as JSON data. + +## Existing plugins + + - [`acorn-jsx`](https://github.com/RReverser/acorn-jsx): Parse [Facebook JSX syntax extensions](https://github.com/facebook/jsx) + +Plugins for ECMAScript proposals: + + - [`acorn-stage3`](https://github.com/acornjs/acorn-stage3): Parse most stage 3 proposals, bundling: + - [`acorn-class-fields`](https://github.com/acornjs/acorn-class-fields): Parse [class fields proposal](https://github.com/tc39/proposal-class-fields) + - [`acorn-import-meta`](https://github.com/acornjs/acorn-import-meta): Parse [import.meta proposal](https://github.com/tc39/proposal-import-meta) + - [`acorn-numeric-separator`](https://github.com/acornjs/acorn-numeric-separator): Parse [numeric separator proposal](https://github.com/tc39/proposal-numeric-separator) + - [`acorn-private-methods`](https://github.com/acornjs/acorn-private-methods): parse [private methods, getters and setters proposal](https://github.com/tc39/proposal-private-methods)n diff --git a/tools/tests/apps/modules/imports/links/acorn/package.json b/tools/tests/apps/modules/imports/links/acorn/package.json index 1b47c365cc..ad2b4564c2 100644 --- a/tools/tests/apps/modules/imports/links/acorn/package.json +++ b/tools/tests/apps/modules/imports/links/acorn/package.json @@ -2,50 +2,28 @@ "name": "acorn", "description": "ECMAScript parser", "homepage": "https://github.com/acornjs/acorn", - "main": "src/index.js", - "version": "5.5.3", - "engines": { - "node": ">=0.4.0" - }, + "module": "src/index.js", + "version": "7.1.1", + "engines": {"node": ">=0.4.0"}, "maintainers": [ { "name": "Marijn Haverbeke", "email": "marijnh@gmail.com", - "web": "http://marijnhaverbeke.nl" + "web": "https://marijnhaverbeke.nl" }, { "name": "Ingvar Stepanyan", "email": "me@rreverser.com", - "web": "http://rreverser.com/" + "web": "https://rreverser.com/" + }, + { + "name": "Adrian Heine", + "web": "http://adrianheine.de" } ], "repository": { "type": "git", "url": "https://github.com/acornjs/acorn.git" }, - "license": "MIT", - "scripts": { - "prepare": "npm test", - "test": "node test/run.js && node test/lint.js", - "pretest": "npm run build:main && npm run build:loose", - "test:test262": "node bin/run_test262.js", - "build": "npm run build:main && npm run build:walk && npm run build:loose && npm run build:bin", - "build:main": "rollup -c rollup/config.main.js", - "build:walk": "rollup -c rollup/config.walk.js", - "build:loose": "rollup -c rollup/config.loose.js && rollup -c rollup/config.loose_es.js", - "lint": "eslint src/" - }, - "devDependencies": { - "eslint": "^4.10.0", - "eslint-config-standard": "^10.2.1", - "eslint-plugin-import": "^2.2.0", - "eslint-plugin-node": "^5.2.1", - "eslint-plugin-promise": "^3.5.0", - "eslint-plugin-standard": "^3.0.1", - "rollup": "^0.45.0", - "rollup-plugin-buble": "^0.16.0", - "test262": "git+https://github.com/tc39/test262.git#18c1e799a01cc976695983b61e225ce7959bdd91", - "test262-parser-runner": "^0.3.1", - "unicode-10.0.0": "^0.7.5" - } + "license": "MIT" } diff --git a/tools/tests/apps/modules/imports/links/acorn/src/.eslintrc b/tools/tests/apps/modules/imports/links/acorn/src/.eslintrc index e636ee75db..181c1b3692 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/.eslintrc +++ b/tools/tests/apps/modules/imports/links/acorn/src/.eslintrc @@ -7,8 +7,8 @@ ], "rules": { "curly": "off", - "eqeqeq": "off", - "indent": ["error", 2, { "SwitchCase": 0, "VariableDeclarator": 2, "CallExpression": { arguments: "off" } }], + "eqeqeq": ["error", "always", { "null": "ignore" }], + "indent": ["error", 2, { "SwitchCase": 0, "VariableDeclarator": 2, "CallExpression": { "arguments": "off" } }], "new-parens": "off", "no-case-declarations": "off", "no-cond-assign": "off", @@ -25,7 +25,8 @@ "space-before-function-paren": ["error", "never"] }, "globals": { - "Packages": false + "Packages": false, + "BigInt": false }, "plugins": [ "import" diff --git a/tools/tests/apps/modules/imports/links/acorn/src/bin/acorn.js b/tools/tests/apps/modules/imports/links/acorn/src/bin/acorn.js index d5fe42521a..9a6712c874 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/bin/acorn.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/bin/acorn.js @@ -6,7 +6,7 @@ let infile, forceFile, silent = false, compact = false, tokenize = false const options = {} function help(status) { - const print = (status == 0) ? console.log : console.error + const print = (status === 0) ? console.log : console.error print("usage: " + basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|...|--ecma2015|--ecma2016|--ecma2017|--ecma2018|...]") print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]") process.exit(status) @@ -14,15 +14,15 @@ function help(status) { for (let i = 2; i < process.argv.length; ++i) { const arg = process.argv[i] - if ((arg == "-" || arg[0] != "-") && !infile) infile = arg - else if (arg == "--" && !infile && i + 2 == process.argv.length) forceFile = infile = process.argv[++i] - else if (arg == "--locations") options.locations = true - else if (arg == "--allow-hash-bang") options.allowHashBang = true - else if (arg == "--silent") silent = true - else if (arg == "--compact") compact = true - else if (arg == "--help") help(0) - else if (arg == "--tokenize") tokenize = true - else if (arg == "--module") options.sourceType = "module" + if ((arg === "-" || arg[0] !== "-") && !infile) infile = arg + else if (arg === "--" && !infile && i + 2 === process.argv.length) forceFile = infile = process.argv[++i] + else if (arg === "--locations") options.locations = true + else if (arg === "--allow-hash-bang") options.allowHashBang = true + else if (arg === "--silent") silent = true + else if (arg === "--compact") compact = true + else if (arg === "--help") help(0) + else if (arg === "--tokenize") tokenize = true + else if (arg === "--module") options.sourceType = "module" else { let match = arg.match(/^--ecma(\d+)$/) if (match) @@ -43,16 +43,16 @@ function run(code) { do { token = tokenizer.getToken() result.push(token) - } while (token.type != acorn.tokTypes.eof) + } while (token.type !== acorn.tokTypes.eof) } } catch (e) { - console.error(e.message) + console.error(infile && infile !== "-" ? e.message.replace(/\(\d+:\d+\)$/, m => m.slice(0, 1) + infile + " " + m.slice(1)) : e.message) process.exit(1) } if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2)) } -if (forceFile || infile && infile != "-") { +if (forceFile || infile && infile !== "-") { run(readFile(infile, "utf8")) } else { let code = "" diff --git a/tools/tests/apps/modules/imports/links/acorn/src/expression.js b/tools/tests/apps/modules/imports/links/acorn/src/expression.js index 79cd9b559f..a50ea7531e 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/expression.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/expression.js @@ -20,6 +20,7 @@ import {types as tt} from "./tokentype" import {Parser} from "./state" import {DestructuringErrors} from "./parseutil" import {lineBreak} from "./whitespace" +import {functionFlags, SCOPE_ARROW, SCOPE_SUPER, SCOPE_DIRECT_SUPER, BIND_OUTSIDE, BIND_VAR} from "./scopeflags" const pp = Parser.prototype @@ -43,9 +44,11 @@ pp.checkPropClash = function(prop, propHash, refDestructuringErrors) { if (this.options.ecmaVersion >= 6) { if (name === "__proto__" && kind === "init") { if (propHash.proto) { - if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) refDestructuringErrors.doubleProto = key.start - // Backwards-compat kludge. Can be removed in version 6.0 - else this.raiseRecoverable(key.start, "Redefinition of __proto__ property") + if (refDestructuringErrors) { + if (refDestructuringErrors.doubleProto < 0) + refDestructuringErrors.doubleProto = key.start + // Backwards-compat kludge. Can be removed in version 6.0 + } else this.raiseRecoverable(key.start, "Redefinition of __proto__ property") } propHash.proto = true } @@ -103,7 +106,12 @@ pp.parseExpression = function(noIn, refDestructuringErrors) { // operators like `+=`. pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { - if (this.inGenerator && this.isContextual("yield")) return this.parseYield() + if (this.isContextual("yield")) { + if (this.inGenerator) return this.parseYield(noIn) + // The tokenizer will assume an expression is allowed after + // `yield`, but this isn't that kind of yield + else this.exprAllowed = false + } let ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1 if (refDestructuringErrors) { @@ -116,7 +124,7 @@ pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { } let startPos = this.start, startLoc = this.startLoc - if (this.type == tt.parenL || this.type == tt.name) + if (this.type === tt.parenL || this.type === tt.name) this.potentialArrowAt = this.start let left = this.parseMaybeConditional(noIn, refDestructuringErrors) if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc) @@ -124,8 +132,11 @@ pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { let node = this.startNodeAt(startPos, startLoc) node.operator = this.value node.left = this.type === tt.eq ? this.toAssignable(left, false, refDestructuringErrors) : left - if (!ownDestructuringErrors) DestructuringErrors.call(refDestructuringErrors) - refDestructuringErrors.shorthandAssign = -1 // reset because shorthand default was used correctly + if (!ownDestructuringErrors) { + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1 + } + if (refDestructuringErrors.shorthandAssign >= node.left.start) + refDestructuringErrors.shorthandAssign = -1 // reset because shorthand default was used correctly this.checkLVal(left) this.next() node.right = this.parseMaybeAssign(noIn) @@ -161,7 +172,7 @@ pp.parseExprOps = function(noIn, refDestructuringErrors) { let startPos = this.start, startLoc = this.startLoc let expr = this.parseMaybeUnary(refDestructuringErrors, false) if (this.checkExpressionErrors(refDestructuringErrors)) return expr - return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) + return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) } // Parse binary operators with the operator precedence parsing @@ -198,7 +209,7 @@ pp.buildBinary = function(startPos, startLoc, left, right, op, logical) { pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { let startPos = this.start, startLoc = this.startLoc, expr - if (this.inAsync && this.isContextual("await")) { + if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) { expr = this.parseAwait() sawUnary = true } else if (this.type.prefix) { @@ -239,8 +250,8 @@ pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { pp.parseExprSubscripts = function(refDestructuringErrors) { let startPos = this.start, startLoc = this.startLoc let expr = this.parseExprAtom(refDestructuringErrors) - let skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")" - if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr + if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")") + return expr let result = this.parseSubscripts(expr, startPos, startLoc) if (refDestructuringErrors && result.type === "MemberExpression") { if (refDestructuringErrors.parenthesizedAssign >= result.start) refDestructuringErrors.parenthesizedAssign = -1 @@ -251,64 +262,82 @@ pp.parseExprSubscripts = function(refDestructuringErrors) { pp.parseSubscripts = function(base, startPos, startLoc, noCalls) { let maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && - this.lastTokEnd == base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async" - for (let computed;;) { - if ((computed = this.eat(tt.bracketL)) || this.eat(tt.dot)) { - let node = this.startNodeAt(startPos, startLoc) - node.object = base - node.property = computed ? this.parseExpression() : this.parseIdent(true) - node.computed = !!computed - if (computed) this.expect(tt.bracketR) - base = this.finishNode(node, "MemberExpression") - } else if (!noCalls && this.eat(tt.parenL)) { - let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos - this.yieldPos = 0 - this.awaitPos = 0 - let exprList = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors) - if (maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { - this.checkPatternErrors(refDestructuringErrors, false) - this.checkYieldAwaitInDefaultParams() - this.yieldPos = oldYieldPos - this.awaitPos = oldAwaitPos - return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true) - } - this.checkExpressionErrors(refDestructuringErrors, true) - this.yieldPos = oldYieldPos || this.yieldPos - this.awaitPos = oldAwaitPos || this.awaitPos - let node = this.startNodeAt(startPos, startLoc) - node.callee = base - node.arguments = exprList - base = this.finishNode(node, "CallExpression") - } else if (this.type === tt.backQuote) { - let node = this.startNodeAt(startPos, startLoc) - node.tag = base - node.quasi = this.parseTemplate({isTagged: true}) - base = this.finishNode(node, "TaggedTemplateExpression") - } else { - return base - } + this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && + this.potentialArrowAt === base.start + while (true) { + let element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow) + if (element === base || element.type === "ArrowFunctionExpression") return element + base = element } } +pp.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow) { + let computed = this.eat(tt.bracketL) + if (computed || this.eat(tt.dot)) { + let node = this.startNodeAt(startPos, startLoc) + node.object = base + node.property = computed ? this.parseExpression() : this.parseIdent(this.options.allowReserved !== "never") + node.computed = !!computed + if (computed) this.expect(tt.bracketR) + base = this.finishNode(node, "MemberExpression") + } else if (!noCalls && this.eat(tt.parenL)) { + let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos + this.yieldPos = 0 + this.awaitPos = 0 + this.awaitIdentPos = 0 + let exprList = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors) + if (maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { + this.checkPatternErrors(refDestructuringErrors, false) + this.checkYieldAwaitInDefaultParams() + if (this.awaitIdentPos > 0) + this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function") + this.yieldPos = oldYieldPos + this.awaitPos = oldAwaitPos + this.awaitIdentPos = oldAwaitIdentPos + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true) + } + this.checkExpressionErrors(refDestructuringErrors, true) + this.yieldPos = oldYieldPos || this.yieldPos + this.awaitPos = oldAwaitPos || this.awaitPos + this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos + let node = this.startNodeAt(startPos, startLoc) + node.callee = base + node.arguments = exprList + base = this.finishNode(node, "CallExpression") + } else if (this.type === tt.backQuote) { + let node = this.startNodeAt(startPos, startLoc) + node.tag = base + node.quasi = this.parseTemplate({isTagged: true}) + base = this.finishNode(node, "TaggedTemplateExpression") + } + return base +} + // Parse an atomic expression — either a single token that is an // expression, an expression started by a keyword like `function` or // `new`, or an expression wrapped in punctuation like `()`, `[]`, // or `{}`. pp.parseExprAtom = function(refDestructuringErrors) { - let node, canBeArrow = this.potentialArrowAt == this.start + // If a division operator appears in an expression position, the + // tokenizer got confused, and we force it to read a regexp instead. + if (this.type === tt.slash) this.readRegexp() + + let node, canBeArrow = this.potentialArrowAt === this.start switch (this.type) { case tt._super: - if (!this.inFunction) - this.raise(this.start, "'super' outside of function or class") + if (!this.allowSuper) + this.raise(this.start, "'super' keyword outside a method") node = this.startNode() this.next() + if (this.type === tt.parenL && !this.allowDirectSuper) + this.raise(node.start, "super() call outside constructor of a subclass") // The `super` keyword can appear at below: // SuperProperty: // super [ Expression ] // super . IdentifierName // SuperCall: - // super Arguments + // super ( Arguments ) if (this.type !== tt.dot && this.type !== tt.bracketL && this.type !== tt.parenL) this.unexpected() return this.finishNode(node, "Super") @@ -320,14 +349,14 @@ pp.parseExprAtom = function(refDestructuringErrors) { case tt.name: let startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc - let id = this.parseIdent(this.type !== tt.name) + let id = this.parseIdent(false) if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(tt._function)) - return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) + return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) if (canBeArrow && !this.canInsertSemicolon()) { if (this.eat(tt.arrow)) return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === tt.name && !containsEsc) { - id = this.parseIdent() + id = this.parseIdent(false) if (this.canInsertSemicolon() || !this.eat(tt.arrow)) this.unexpected() return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) @@ -373,7 +402,7 @@ pp.parseExprAtom = function(refDestructuringErrors) { case tt._function: node = this.startNode() this.next() - return this.parseFunction(node, false) + return this.parseFunction(node, 0) case tt._class: return this.parseClass(this.startNode(), false) @@ -384,15 +413,53 @@ pp.parseExprAtom = function(refDestructuringErrors) { case tt.backQuote: return this.parseTemplate() + case tt._import: + if (this.options.ecmaVersion >= 11) { + return this.parseExprImport() + } else { + return this.unexpected() + } + default: this.unexpected() } } +pp.parseExprImport = function() { + const node = this.startNode() + this.next() // skip `import` + switch (this.type) { + case tt.parenL: + return this.parseDynamicImport(node) + default: + this.unexpected() + } +} + +pp.parseDynamicImport = function(node) { + this.next() // skip `(` + + // Parse node.source. + node.source = this.parseMaybeAssign() + + // Verify ending. + if (!this.eat(tt.parenR)) { + const errorPos = this.start + if (this.eat(tt.comma) && this.eat(tt.parenR)) { + this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()") + } else { + this.unexpected(errorPos) + } + } + + return this.finishNode(node, "ImportExpression") +} + pp.parseLiteral = function(value) { let node = this.startNode() node.value = value node.raw = this.input.slice(this.start, this.end) + if (node.raw.charCodeAt(node.raw.length - 1) === 110) node.bigint = node.raw.slice(0, -1) this.next() return this.finishNode(node, "Literal") } @@ -414,6 +481,7 @@ pp.parseParenAndDistinguishExpression = function(canBeArrow) { let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart this.yieldPos = 0 this.awaitPos = 0 + // Do not save awaitIdentPos to allow checking awaits nested in parameters while (this.type !== tt.parenR) { first ? first = false : this.expect(tt.comma) if (allowTrailingComma && this.afterTrailingComma(tt.parenR, true)) { @@ -482,6 +550,7 @@ pp.parseParenArrowList = function(startPos, startLoc, exprList) { const empty = [] pp.parseNew = function() { + if (this.containsEsc) this.raiseRecoverable(this.start, "Escape sequence in keyword new") let node = this.startNode() let meta = this.parseIdent(true) if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) { @@ -490,12 +559,15 @@ pp.parseNew = function() { node.property = this.parseIdent(true) if (node.property.name !== "target" || containsEsc) this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target") - if (!this.inFunction) + if (!this.inNonArrowFunction()) this.raiseRecoverable(node.start, "new.target can only be used in functions") return this.finishNode(node, "MetaProperty") } - let startPos = this.start, startLoc = this.startLoc + let startPos = this.start, startLoc = this.startLoc, isImport = this.type === tt._import node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true) + if (isImport && node.callee.type === "ImportExpression") { + this.raise(startPos, "Cannot use new with import()") + } if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false) else node.arguments = empty return this.finishNode(node, "NewExpression") @@ -531,6 +603,7 @@ pp.parseTemplate = function({isTagged = false} = {}) { let curElt = this.parseTemplateElement({isTagged}) node.quasis = [curElt] while (!curElt.tail) { + if (this.type === tt.eof) this.raise(this.pos, "Unterminated template literal") this.expect(tt.dollarBraceL) node.expressions.push(this.parseExpression()) this.expect(tt.braceR) @@ -555,7 +628,7 @@ pp.parseObj = function(isPattern, refDestructuringErrors) { while (!this.eat(tt.braceR)) { if (!first) { this.expect(tt.comma) - if (this.afterTrailingComma(tt.braceR)) break + if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(tt.braceR)) break } else first = false const prop = this.parseProperty(isPattern, refDestructuringErrors) @@ -631,7 +704,7 @@ pp.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos } else if (!isPattern && !containsEsc && this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && - (this.type != tt.comma && this.type != tt.braceR)) { + (this.type !== tt.comma && this.type !== tt.braceR)) { if (isGenerator || isAsync) this.unexpected() prop.kind = prop.key.name this.parsePropertyName(prop) @@ -648,7 +721,10 @@ pp.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params") } } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { + if (isGenerator || isAsync) this.unexpected() this.checkUnreserved(prop.key) + if (prop.key.name === "await" && !this.awaitIdentPos) + this.awaitIdentPos = startPos prop.kind = "init" if (isPattern) { prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) @@ -674,26 +750,21 @@ pp.parsePropertyName = function(prop) { prop.computed = false } } - return prop.key = this.type === tt.num || this.type === tt.string ? this.parseExprAtom() : this.parseIdent(true) + return prop.key = this.type === tt.num || this.type === tt.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never") } // Initialize empty function node. pp.initFunction = function(node) { node.id = null - if (this.options.ecmaVersion >= 6) { - node.generator = false - node.expression = false - } - if (this.options.ecmaVersion >= 8) - node.async = false + if (this.options.ecmaVersion >= 6) node.generator = node.expression = false + if (this.options.ecmaVersion >= 8) node.async = false } // Parse object or class method. -pp.parseMethod = function(isGenerator, isAsync) { - let node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, - oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction +pp.parseMethod = function(isGenerator, isAsync, allowDirectSuper) { + let node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos this.initFunction(node) if (this.options.ecmaVersion >= 6) @@ -701,57 +772,47 @@ pp.parseMethod = function(isGenerator, isAsync) { if (this.options.ecmaVersion >= 8) node.async = !!isAsync - this.inGenerator = node.generator - this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 - this.inFunction = true - this.enterFunctionScope() + this.awaitIdentPos = 0 + this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0)) this.expect(tt.parenL) node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8) this.checkYieldAwaitInDefaultParams() - this.parseFunctionBody(node, false) + this.parseFunctionBody(node, false, true) - this.inGenerator = oldInGen - this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos - this.inFunction = oldInFunc + this.awaitIdentPos = oldAwaitIdentPos return this.finishNode(node, "FunctionExpression") } // Parse arrow function expression with given parameters. pp.parseArrowExpression = function(node, params, isAsync) { - let oldInGen = this.inGenerator, oldInAsync = this.inAsync, - oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction + let oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos - this.enterFunctionScope() + this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW) this.initFunction(node) - if (this.options.ecmaVersion >= 8) - node.async = !!isAsync + if (this.options.ecmaVersion >= 8) node.async = !!isAsync - this.inGenerator = false - this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 - this.inFunction = true + this.awaitIdentPos = 0 node.params = this.toAssignableList(params, true) - this.parseFunctionBody(node, true) + this.parseFunctionBody(node, true, false) - this.inGenerator = oldInGen - this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos - this.inFunction = oldInFunc + this.awaitIdentPos = oldAwaitIdentPos return this.finishNode(node, "ArrowFunctionExpression") } // Parse function body and check parameters. -pp.parseFunctionBody = function(node, isArrowFunction) { +pp.parseFunctionBody = function(node, isArrowFunction, isMethod) { let isExpression = isArrowFunction && this.type !== tt.braceL let oldStrict = this.strict, useStrict = false @@ -777,19 +838,15 @@ pp.parseFunctionBody = function(node, isArrowFunction) { // Add the params to varDeclaredNames to ensure that an error is thrown // if a let/const declaration in the function clashes with one of the params. - this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)) - node.body = this.parseBlock(false) + this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)) + // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' + if (this.strict && node.id) this.checkLVal(node.id, BIND_OUTSIDE) + node.body = this.parseBlock(false, undefined, useStrict && !oldStrict) node.expression = false this.adaptDirectivePrologue(node.body.body) this.labels = oldLabels } - this.exitFunctionScope() - - if (this.strict && node.id) { - // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' - this.checkLVal(node.id, "none") - } - this.strict = oldStrict + this.exitScope() } pp.isSimpleParamList = function(params) { @@ -804,7 +861,7 @@ pp.isSimpleParamList = function(params) { pp.checkParams = function(node, allowDuplicates) { let nameHash = {} for (let param of node.params) - this.checkLVal(param, "var", allowDuplicates ? null : nameHash) + this.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash) } // Parses a comma-separated list of expressions, and returns them as @@ -838,17 +895,17 @@ pp.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructur pp.checkUnreserved = function({start, end, name}) { if (this.inGenerator && name === "yield") - this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator") + this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator") if (this.inAsync && name === "await") - this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function") - if (this.isKeyword(name)) + this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function") + if (this.keywords.test(name)) this.raise(start, `Unexpected keyword '${name}'`) if (this.options.ecmaVersion < 6 && - this.input.slice(start, end).indexOf("\\") != -1) return + this.input.slice(start, end).indexOf("\\") !== -1) return const re = this.strict ? this.reservedWordsStrict : this.reservedWords if (re.test(name)) { if (!this.inAsync && name === "await") - this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function") + this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function") this.raiseRecoverable(start, `The keyword '${name}' is reserved`) } } @@ -859,7 +916,6 @@ pp.checkUnreserved = function({start, end, name}) { pp.parseIdent = function(liberal, isBinding) { let node = this.startNode() - if (liberal && this.options.allowReserved == "never") liberal = false if (this.type === tt.name) { node.name = this.value } else if (this.type.keyword) { @@ -876,25 +932,29 @@ pp.parseIdent = function(liberal, isBinding) { } else { this.unexpected() } - this.next() + this.next(!!liberal) this.finishNode(node, "Identifier") - if (!liberal) this.checkUnreserved(node) + if (!liberal) { + this.checkUnreserved(node) + if (node.name === "await" && !this.awaitIdentPos) + this.awaitIdentPos = node.start + } return node } // Parses yield expression inside generator. -pp.parseYield = function() { +pp.parseYield = function(noIn) { if (!this.yieldPos) this.yieldPos = this.start let node = this.startNode() this.next() - if (this.type == tt.semi || this.canInsertSemicolon() || (this.type != tt.star && !this.type.startsExpr)) { + if (this.type === tt.semi || this.canInsertSemicolon() || (this.type !== tt.star && !this.type.startsExpr)) { node.delegate = false node.argument = null } else { node.delegate = this.eat(tt.star) - node.argument = this.parseMaybeAssign() + node.argument = this.parseMaybeAssign(noIn) } return this.finishNode(node, "YieldExpression") } @@ -904,6 +964,6 @@ pp.parseAwait = function() { let node = this.startNode() this.next() - node.argument = this.parseMaybeUnary(null, true) + node.argument = this.parseMaybeUnary(null, false) return this.finishNode(node, "AwaitExpression") } diff --git a/tools/tests/apps/modules/imports/links/acorn/src/identifier.js b/tools/tests/apps/modules/imports/links/acorn/src/identifier.js index 5b6553b604..0d7c3d1364 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/identifier.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/identifier.js @@ -14,6 +14,7 @@ const ecma5AndLessKeywords = "break case catch continue debugger default do else export const keywords = { 5: ecma5AndLessKeywords, + "5module": ecma5AndLessKeywords + " export import", 6: ecma5AndLessKeywords + " const class extends export import super" } @@ -26,9 +27,8 @@ export const keywordRelationalOperator = /^in(stanceof)?$/ // are only applied when a character is found to actually have a // code point above 128. // Generated by `bin/generate-identifier-regex.js`. - -let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312e\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fea\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc" -let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d4-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f" +let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc" +let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf\u1ac0\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f" const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]") const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]") @@ -42,10 +42,10 @@ nonASCIIidentifierStartChars = nonASCIIidentifierChars = null // generated by bin/generate-identifier-regex.js // eslint-disable-next-line comma-spacing -const astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,257,0,11,39,8,0,22,0,12,39,3,3,55,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,698,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,1,31,6124,20,754,9486,286,82,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,15,7472,3104,541] +const astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,349,41,7,1,79,28,11,0,9,21,107,20,28,22,13,52,76,44,33,24,27,35,30,0,3,0,9,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,21,2,31,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,7,3,0,3,7,2,1,2,23,16,0,2,0,95,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,190,0,80,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,1237,43,8,8952,286,50,2,18,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42717,35,4148,12,221,3,5761,15,7472,3104,541,1507,4938] // eslint-disable-next-line comma-spacing -const astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,280,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,19719,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239] +const astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,370,1,154,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,2,11,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,71,5,2,1,3,3,2,0,2,1,13,9,120,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,82,0,12,1,19628,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,262,6,10,9,419,13,1495,6,110,6,6,9,4759,9,787719,239] // This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is diff --git a/tools/tests/apps/modules/imports/links/acorn/src/index.js b/tools/tests/apps/modules/imports/links/acorn/src/index.js index aaf664da6b..f466a3b9fc 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/index.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/index.js @@ -12,11 +12,6 @@ // // [ghbt]: https://github.com/acornjs/acorn/issues // -// This file defines the main parser interface. The library also comes -// with a [error-tolerant parser][dammit] and an -// [abstract syntax tree walker][walk], defined in other files. -// -// [dammit]: acorn_loose.js // [walk]: util/walk.js import {Parser} from "./state" @@ -27,17 +22,58 @@ import "./expression" import "./location" import "./scope" -export {Parser, plugins} from "./state" -export {defaultOptions} from "./options" -export {Position, SourceLocation, getLineInfo} from "./locutil" -export {Node} from "./node" -export {TokenType, types as tokTypes, keywords as keywordTypes} from "./tokentype" -export {TokContext, types as tokContexts} from "./tokencontext" -export {isIdentifierChar, isIdentifierStart} from "./identifier" -export {Token} from "./tokenize" -export {isNewLine, lineBreak, lineBreakG, nonASCIIwhitespace} from "./whitespace" +import {defaultOptions} from "./options" +import {Position, SourceLocation, getLineInfo} from "./locutil" +import {Node} from "./node" +import {TokenType, types as tokTypes, keywords as keywordTypes} from "./tokentype" +import {TokContext, types as tokContexts} from "./tokencontext" +import {isIdentifierChar, isIdentifierStart} from "./identifier" +import {Token} from "./tokenize" +import {isNewLine, lineBreak, lineBreakG, nonASCIIwhitespace} from "./whitespace" -export const version = "5.5.3" +export const version = "7.1.0" +export { + Parser, + defaultOptions, + Position, + SourceLocation, + getLineInfo, + Node, + TokenType, + tokTypes, + keywordTypes, + TokContext, + tokContexts, + isIdentifierChar, + isIdentifierStart, + Token, + isNewLine, + lineBreak, + lineBreakG, + nonASCIIwhitespace +} + +Parser.acorn = { + Parser, + version, + defaultOptions, + Position, + SourceLocation, + getLineInfo, + Node, + TokenType, + tokTypes, + keywordTypes, + TokContext, + tokContexts, + isIdentifierChar, + isIdentifierStart, + Token, + isNewLine, + lineBreak, + lineBreakG, + nonASCIIwhitespace +} // The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and @@ -47,7 +83,7 @@ export const version = "5.5.3" // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API export function parse(input, options) { - return new Parser(options, input).parse() + return Parser.parse(input, options) } // This function tries to parse a single expression at a given @@ -55,24 +91,12 @@ export function parse(input, options) { // that embed JavaScript expressions. export function parseExpressionAt(input, pos, options) { - let p = new Parser(options, input, pos) - p.nextToken() - return p.parseExpression() + return Parser.parseExpressionAt(input, pos, options) } // Acorn is organized as a tokenizer and a recursive-descent parser. // The `tokenizer` export provides an interface to the tokenizer. export function tokenizer(input, options) { - return new Parser(options, input) -} - -// This is a terrible kludge to support the existing, pre-ES6 -// interface where the loose parser module retroactively adds exports -// to this module. -export let parse_dammit, LooseParser, pluginsLoose // eslint-disable-line camelcase -export function addLooseExports(parse, Parser, plugins) { - parse_dammit = parse // eslint-disable-line camelcase - LooseParser = Parser - pluginsLoose = plugins + return Parser.tokenizer(input, options) } diff --git a/tools/tests/apps/modules/imports/links/acorn/src/loose/expression.js b/tools/tests/apps/modules/imports/links/acorn/src/loose/expression.js deleted file mode 100644 index b6c5ddbcb2..0000000000 --- a/tools/tests/apps/modules/imports/links/acorn/src/loose/expression.js +++ /dev/null @@ -1,582 +0,0 @@ -import {LooseParser} from "./state" -import {isDummy} from "./parseutil" -import {tokTypes as tt} from "../index" - -const lp = LooseParser.prototype - -lp.checkLVal = function(expr) { - if (!expr) return expr - switch (expr.type) { - case "Identifier": - case "MemberExpression": - return expr - - case "ParenthesizedExpression": - expr.expression = this.checkLVal(expr.expression) - return expr - - default: - return this.dummyIdent() - } -} - -lp.parseExpression = function(noIn) { - let start = this.storeCurrentPos() - let expr = this.parseMaybeAssign(noIn) - if (this.tok.type === tt.comma) { - let node = this.startNodeAt(start) - node.expressions = [expr] - while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn)) - return this.finishNode(node, "SequenceExpression") - } - return expr -} - -lp.parseParenExpression = function() { - this.pushCx() - this.expect(tt.parenL) - let val = this.parseExpression() - this.popCx() - this.expect(tt.parenR) - return val -} - -lp.parseMaybeAssign = function(noIn) { - if (this.toks.isContextual("yield")) { - let node = this.startNode() - this.next() - if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type != tt.star && !this.tok.type.startsExpr)) { - node.delegate = false - node.argument = null - } else { - node.delegate = this.eat(tt.star) - node.argument = this.parseMaybeAssign() - } - return this.finishNode(node, "YieldExpression") - } - - let start = this.storeCurrentPos() - let left = this.parseMaybeConditional(noIn) - if (this.tok.type.isAssign) { - let node = this.startNodeAt(start) - node.operator = this.tok.value - node.left = this.tok.type === tt.eq ? this.toAssignable(left) : this.checkLVal(left) - this.next() - node.right = this.parseMaybeAssign(noIn) - return this.finishNode(node, "AssignmentExpression") - } - return left -} - -lp.parseMaybeConditional = function(noIn) { - let start = this.storeCurrentPos() - let expr = this.parseExprOps(noIn) - if (this.eat(tt.question)) { - let node = this.startNodeAt(start) - node.test = expr - node.consequent = this.parseMaybeAssign() - node.alternate = this.expect(tt.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent() - return this.finishNode(node, "ConditionalExpression") - } - return expr -} - -lp.parseExprOps = function(noIn) { - let start = this.storeCurrentPos() - let indent = this.curIndent, line = this.curLineStart - return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line) -} - -lp.parseExprOp = function(left, start, minPrec, noIn, indent, line) { - if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) return left - let prec = this.tok.type.binop - if (prec != null && (!noIn || this.tok.type !== tt._in)) { - if (prec > minPrec) { - let node = this.startNodeAt(start) - node.left = left - node.operator = this.tok.value - this.next() - if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) { - node.right = this.dummyIdent() - } else { - let rightStart = this.storeCurrentPos() - node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line) - } - this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression") - return this.parseExprOp(node, start, minPrec, noIn, indent, line) - } - } - return left -} - -lp.parseMaybeUnary = function(sawUnary) { - let start = this.storeCurrentPos(), expr - if (this.options.ecmaVersion >= 8 && this.inAsync && this.toks.isContextual("await")) { - expr = this.parseAwait() - sawUnary = true - } else if (this.tok.type.prefix) { - let node = this.startNode(), update = this.tok.type === tt.incDec - if (!update) sawUnary = true - node.operator = this.tok.value - node.prefix = true - this.next() - node.argument = this.parseMaybeUnary(true) - if (update) node.argument = this.checkLVal(node.argument) - expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression") - } else if (this.tok.type === tt.ellipsis) { - let node = this.startNode() - this.next() - node.argument = this.parseMaybeUnary(sawUnary) - expr = this.finishNode(node, "SpreadElement") - } else { - expr = this.parseExprSubscripts() - while (this.tok.type.postfix && !this.canInsertSemicolon()) { - let node = this.startNodeAt(start) - node.operator = this.tok.value - node.prefix = false - node.argument = this.checkLVal(expr) - this.next() - expr = this.finishNode(node, "UpdateExpression") - } - } - - if (!sawUnary && this.eat(tt.starstar)) { - let node = this.startNodeAt(start) - node.operator = "**" - node.left = expr - node.right = this.parseMaybeUnary(false) - return this.finishNode(node, "BinaryExpression") - } - - return expr -} - -lp.parseExprSubscripts = function() { - let start = this.storeCurrentPos() - return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart) -} - -lp.parseSubscripts = function(base, start, noCalls, startIndent, line) { - for (;;) { - if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine()) { - if (this.tok.type == tt.dot && this.curIndent == startIndent) - --startIndent - else - return base - } - - let maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon() - - if (this.eat(tt.dot)) { - let node = this.startNodeAt(start) - node.object = base - if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine()) - node.property = this.dummyIdent() - else - node.property = this.parsePropertyAccessor() || this.dummyIdent() - node.computed = false - base = this.finishNode(node, "MemberExpression") - } else if (this.tok.type == tt.bracketL) { - this.pushCx() - this.next() - let node = this.startNodeAt(start) - node.object = base - node.property = this.parseExpression() - node.computed = true - this.popCx() - this.expect(tt.bracketR) - base = this.finishNode(node, "MemberExpression") - } else if (!noCalls && this.tok.type == tt.parenL) { - let exprList = this.parseExprList(tt.parenR) - if (maybeAsyncArrow && this.eat(tt.arrow)) - return this.parseArrowExpression(this.startNodeAt(start), exprList, true) - let node = this.startNodeAt(start) - node.callee = base - node.arguments = exprList - base = this.finishNode(node, "CallExpression") - } else if (this.tok.type == tt.backQuote) { - let node = this.startNodeAt(start) - node.tag = base - node.quasi = this.parseTemplate() - base = this.finishNode(node, "TaggedTemplateExpression") - } else { - return base - } - } -} - -lp.parseExprAtom = function() { - let node - switch (this.tok.type) { - case tt._this: - case tt._super: - let type = this.tok.type === tt._this ? "ThisExpression" : "Super" - node = this.startNode() - this.next() - return this.finishNode(node, type) - - case tt.name: - let start = this.storeCurrentPos() - let id = this.parseIdent() - let isAsync = false - if (id.name === "async" && !this.canInsertSemicolon()) { - if (this.eat(tt._function)) - return this.parseFunction(this.startNodeAt(start), false, true) - if (this.tok.type === tt.name) { - id = this.parseIdent() - isAsync = true - } - } - return this.eat(tt.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id - - case tt.regexp: - node = this.startNode() - let val = this.tok.value - node.regex = {pattern: val.pattern, flags: val.flags} - node.value = val.value - node.raw = this.input.slice(this.tok.start, this.tok.end) - this.next() - return this.finishNode(node, "Literal") - - case tt.num: case tt.string: - node = this.startNode() - node.value = this.tok.value - node.raw = this.input.slice(this.tok.start, this.tok.end) - this.next() - return this.finishNode(node, "Literal") - - case tt._null: case tt._true: case tt._false: - node = this.startNode() - node.value = this.tok.type === tt._null ? null : this.tok.type === tt._true - node.raw = this.tok.type.keyword - this.next() - return this.finishNode(node, "Literal") - - case tt.parenL: - let parenStart = this.storeCurrentPos() - this.next() - let inner = this.parseExpression() - this.expect(tt.parenR) - if (this.eat(tt.arrow)) { - // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy. - let params = inner.expressions || [inner] - if (params.length && isDummy(params[params.length - 1])) - params.pop() - return this.parseArrowExpression(this.startNodeAt(parenStart), params) - } - if (this.options.preserveParens) { - let par = this.startNodeAt(parenStart) - par.expression = inner - inner = this.finishNode(par, "ParenthesizedExpression") - } - return inner - - case tt.bracketL: - node = this.startNode() - node.elements = this.parseExprList(tt.bracketR, true) - return this.finishNode(node, "ArrayExpression") - - case tt.braceL: - return this.parseObj() - - case tt._class: - return this.parseClass(false) - - case tt._function: - node = this.startNode() - this.next() - return this.parseFunction(node, false) - - case tt._new: - return this.parseNew() - - case tt.backQuote: - return this.parseTemplate() - - default: - return this.dummyIdent() - } -} - -lp.parseNew = function() { - let node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart - let meta = this.parseIdent(true) - if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) { - node.meta = meta - node.property = this.parseIdent(true) - return this.finishNode(node, "MetaProperty") - } - let start = this.storeCurrentPos() - node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line) - if (this.tok.type == tt.parenL) { - node.arguments = this.parseExprList(tt.parenR) - } else { - node.arguments = [] - } - return this.finishNode(node, "NewExpression") -} - -lp.parseTemplateElement = function() { - let elem = this.startNode() - - // The loose parser accepts invalid unicode escapes even in untagged templates. - if (this.tok.type === tt.invalidTemplate) { - elem.value = { - raw: this.tok.value, - cooked: null - } - } else { - elem.value = { - raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), - cooked: this.tok.value - } - } - this.next() - elem.tail = this.tok.type === tt.backQuote - return this.finishNode(elem, "TemplateElement") -} - -lp.parseTemplate = function() { - let node = this.startNode() - this.next() - node.expressions = [] - let curElt = this.parseTemplateElement() - node.quasis = [curElt] - while (!curElt.tail) { - this.next() - node.expressions.push(this.parseExpression()) - if (this.expect(tt.braceR)) { - curElt = this.parseTemplateElement() - } else { - curElt = this.startNode() - curElt.value = {cooked: "", raw: ""} - curElt.tail = true - this.finishNode(curElt, "TemplateElement") - } - node.quasis.push(curElt) - } - this.expect(tt.backQuote) - return this.finishNode(node, "TemplateLiteral") -} - -lp.parseObj = function() { - let node = this.startNode() - node.properties = [] - this.pushCx() - let indent = this.curIndent + 1, line = this.curLineStart - this.eat(tt.braceL) - if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart } - while (!this.closes(tt.braceR, indent, line)) { - let prop = this.startNode(), isGenerator, isAsync, start - if (this.options.ecmaVersion >= 9 && this.eat(tt.ellipsis)) { - prop.argument = this.parseMaybeAssign() - node.properties.push(this.finishNode(prop, "SpreadElement")) - this.eat(tt.comma) - continue - } - if (this.options.ecmaVersion >= 6) { - start = this.storeCurrentPos() - prop.method = false - prop.shorthand = false - isGenerator = this.eat(tt.star) - } - this.parsePropertyName(prop) - if (this.toks.isAsyncProp(prop)) { - isAsync = true - isGenerator = this.options.ecmaVersion >= 9 && this.eat(tt.star) - this.parsePropertyName(prop) - } else { - isAsync = false - } - if (isDummy(prop.key)) { if (isDummy(this.parseMaybeAssign())) this.next(); this.eat(tt.comma); continue } - if (this.eat(tt.colon)) { - prop.kind = "init" - prop.value = this.parseMaybeAssign() - } else if (this.options.ecmaVersion >= 6 && (this.tok.type === tt.parenL || this.tok.type === tt.braceL)) { - prop.kind = "init" - prop.method = true - prop.value = this.parseMethod(isGenerator, isAsync) - } else if (this.options.ecmaVersion >= 5 && prop.key.type === "Identifier" && - !prop.computed && (prop.key.name === "get" || prop.key.name === "set") && - (this.tok.type != tt.comma && this.tok.type != tt.braceR && this.tok.type != tt.eq)) { - prop.kind = prop.key.name - this.parsePropertyName(prop) - prop.value = this.parseMethod(false) - } else { - prop.kind = "init" - if (this.options.ecmaVersion >= 6) { - if (this.eat(tt.eq)) { - let assign = this.startNodeAt(start) - assign.operator = "=" - assign.left = prop.key - assign.right = this.parseMaybeAssign() - prop.value = this.finishNode(assign, "AssignmentExpression") - } else { - prop.value = prop.key - } - } else { - prop.value = this.dummyIdent() - } - prop.shorthand = true - } - node.properties.push(this.finishNode(prop, "Property")) - this.eat(tt.comma) - } - this.popCx() - if (!this.eat(tt.braceR)) { - // If there is no closing brace, make the node span to the start - // of the next token (this is useful for Tern) - this.last.end = this.tok.start - if (this.options.locations) this.last.loc.end = this.tok.loc.start - } - return this.finishNode(node, "ObjectExpression") -} - -lp.parsePropertyName = function(prop) { - if (this.options.ecmaVersion >= 6) { - if (this.eat(tt.bracketL)) { - prop.computed = true - prop.key = this.parseExpression() - this.expect(tt.bracketR) - return - } else { - prop.computed = false - } - } - let key = (this.tok.type === tt.num || this.tok.type === tt.string) ? this.parseExprAtom() : this.parseIdent() - prop.key = key || this.dummyIdent() -} - -lp.parsePropertyAccessor = function() { - if (this.tok.type === tt.name || this.tok.type.keyword) return this.parseIdent() -} - -lp.parseIdent = function() { - let name = this.tok.type === tt.name ? this.tok.value : this.tok.type.keyword - if (!name) return this.dummyIdent() - let node = this.startNode() - this.next() - node.name = name - return this.finishNode(node, "Identifier") -} - -lp.initFunction = function(node) { - node.id = null - node.params = [] - if (this.options.ecmaVersion >= 6) { - node.generator = false - node.expression = false - } - if (this.options.ecmaVersion >= 8) - node.async = false -} - -// Convert existing expression atom to assignable pattern -// if possible. - -lp.toAssignable = function(node, binding) { - if (!node || node.type == "Identifier" || (node.type == "MemberExpression" && !binding)) { - // Okay - } else if (node.type == "ParenthesizedExpression") { - this.toAssignable(node.expression, binding) - } else if (this.options.ecmaVersion < 6) { - return this.dummyIdent() - } else if (node.type == "ObjectExpression") { - node.type = "ObjectPattern" - for (let prop of node.properties) - this.toAssignable(prop, binding) - } else if (node.type == "ArrayExpression") { - node.type = "ArrayPattern" - this.toAssignableList(node.elements, binding) - } else if (node.type == "Property") { - this.toAssignable(node.value, binding) - } else if (node.type == "SpreadElement") { - node.type = "RestElement" - this.toAssignable(node.argument, binding) - } else if (node.type == "AssignmentExpression") { - node.type = "AssignmentPattern" - delete node.operator - } else { - return this.dummyIdent() - } - return node -} - -lp.toAssignableList = function(exprList, binding) { - for (let expr of exprList) - this.toAssignable(expr, binding) - return exprList -} - -lp.parseFunctionParams = function(params) { - params = this.parseExprList(tt.parenR) - return this.toAssignableList(params, true) -} - -lp.parseMethod = function(isGenerator, isAsync) { - let node = this.startNode(), oldInAsync = this.inAsync - this.initFunction(node) - if (this.options.ecmaVersion >= 6) - node.generator = !!isGenerator - if (this.options.ecmaVersion >= 8) - node.async = !!isAsync - this.inAsync = node.async - node.params = this.parseFunctionParams() - node.body = this.parseBlock() - this.toks.adaptDirectivePrologue(node.body.body) - this.inAsync = oldInAsync - return this.finishNode(node, "FunctionExpression") -} - -lp.parseArrowExpression = function(node, params, isAsync) { - let oldInAsync = this.inAsync - this.initFunction(node) - if (this.options.ecmaVersion >= 8) - node.async = !!isAsync - this.inAsync = node.async - node.params = this.toAssignableList(params, true) - node.expression = this.tok.type !== tt.braceL - if (node.expression) { - node.body = this.parseMaybeAssign() - } else { - node.body = this.parseBlock() - this.toks.adaptDirectivePrologue(node.body.body) - } - this.inAsync = oldInAsync - return this.finishNode(node, "ArrowFunctionExpression") -} - -lp.parseExprList = function(close, allowEmpty) { - this.pushCx() - let indent = this.curIndent, line = this.curLineStart, elts = [] - this.next() // Opening bracket - while (!this.closes(close, indent + 1, line)) { - if (this.eat(tt.comma)) { - elts.push(allowEmpty ? null : this.dummyIdent()) - continue - } - let elt = this.parseMaybeAssign() - if (isDummy(elt)) { - if (this.closes(close, indent, line)) break - this.next() - } else { - elts.push(elt) - } - this.eat(tt.comma) - } - this.popCx() - if (!this.eat(close)) { - // If there is no closing brace, make the node span to the start - // of the next token (this is useful for Tern) - this.last.end = this.tok.start - if (this.options.locations) this.last.loc.end = this.tok.loc.start - } - return elts -} - -lp.parseAwait = function() { - let node = this.startNode() - this.next() - node.argument = this.parseMaybeUnary() - return this.finishNode(node, "AwaitExpression") -} diff --git a/tools/tests/apps/modules/imports/links/acorn/src/loose/index.js b/tools/tests/apps/modules/imports/links/acorn/src/loose/index.js deleted file mode 100644 index a698061a8b..0000000000 --- a/tools/tests/apps/modules/imports/links/acorn/src/loose/index.js +++ /dev/null @@ -1,47 +0,0 @@ -// Acorn: Loose parser -// -// This module provides an alternative parser (`parse_dammit`) that -// exposes that same interface as `parse`, but will try to parse -// anything as JavaScript, repairing syntax error the best it can. -// There are circumstances in which it will raise an error and give -// up, but they are very rare. The resulting AST will be a mostly -// valid JavaScript AST (as per the [Mozilla parser API][api], except -// that: -// -// - Return outside functions is allowed -// -// - Label consistency (no conflicts, break only to existing labels) -// is not enforced. -// -// - Bogus Identifier nodes with a name of `"✖"` are inserted whenever -// the parser got too confused to return anything meaningful. -// -// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API -// -// The expected use for this is to *first* try `acorn.parse`, and only -// if that fails switch to `parse_dammit`. The loose parser might -// parse badly indented code incorrectly, so **don't** use it as -// your default parser. -// -// Quite a lot of acorn.js is duplicated here. The alternative was to -// add a *lot* of extra cruft to that file, making it less readable -// and slower. Copying and editing the code allowed me to make -// invasive changes and simplifications without creating a complicated -// tangle. - -import {addLooseExports, defaultOptions} from "../index" -import {LooseParser, pluginsLoose} from "./state" -import "./tokenize" -import "./statement" -import "./expression" - -export {LooseParser, pluginsLoose} from "./state" - -defaultOptions.tabSize = 4 - -// eslint-disable-next-line camelcase -export function parse_dammit(input, options) { - return new LooseParser(input, options).parse() -} - -addLooseExports(parse_dammit, LooseParser, pluginsLoose) diff --git a/tools/tests/apps/modules/imports/links/acorn/src/loose/parseutil.js b/tools/tests/apps/modules/imports/links/acorn/src/loose/parseutil.js deleted file mode 100644 index b620fdaf0a..0000000000 --- a/tools/tests/apps/modules/imports/links/acorn/src/loose/parseutil.js +++ /dev/null @@ -1 +0,0 @@ -export function isDummy(node) { return node.name == "✖" } diff --git a/tools/tests/apps/modules/imports/links/acorn/src/loose/state.js b/tools/tests/apps/modules/imports/links/acorn/src/loose/state.js deleted file mode 100644 index da068edb51..0000000000 --- a/tools/tests/apps/modules/imports/links/acorn/src/loose/state.js +++ /dev/null @@ -1,170 +0,0 @@ -import {tokenizer, SourceLocation, tokTypes as tt, Node, lineBreak, isNewLine} from "../index" - -function noop() {} - -// Registered plugins -export const pluginsLoose = {} - -export class LooseParser { - constructor(input, options = {}) { - this.toks = tokenizer(input, options) - this.options = this.toks.options - this.input = this.toks.input - this.tok = this.last = {type: tt.eof, start: 0, end: 0} - this.tok.validateRegExpFlags = noop - this.tok.validateRegExpPattern = noop - if (this.options.locations) { - let here = this.toks.curPosition() - this.tok.loc = new SourceLocation(this.toks, here, here) - } - this.ahead = [] // Tokens ahead - this.context = [] // Indentation contexted - this.curIndent = 0 - this.curLineStart = 0 - this.nextLineStart = this.lineEnd(this.curLineStart) + 1 - this.inAsync = false - // Load plugins - this.options.pluginsLoose = options.pluginsLoose || {} - this.loadPlugins(this.options.pluginsLoose) - } - - startNode() { - return new Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null) - } - - storeCurrentPos() { - return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start - } - - startNodeAt(pos) { - if (this.options.locations) { - return new Node(this.toks, pos[0], pos[1]) - } else { - return new Node(this.toks, pos) - } - } - - finishNode(node, type) { - node.type = type - node.end = this.last.end - if (this.options.locations) - node.loc.end = this.last.loc.end - if (this.options.ranges) - node.range[1] = this.last.end - return node - } - - dummyNode(type) { - let dummy = this.startNode() - dummy.type = type - dummy.end = dummy.start - if (this.options.locations) - dummy.loc.end = dummy.loc.start - if (this.options.ranges) - dummy.range[1] = dummy.start - this.last = {type: tt.name, start: dummy.start, end: dummy.start, loc: dummy.loc} - return dummy - } - - dummyIdent() { - let dummy = this.dummyNode("Identifier") - dummy.name = "✖" - return dummy - } - - dummyString() { - let dummy = this.dummyNode("Literal") - dummy.value = dummy.raw = "✖" - return dummy - } - - eat(type) { - if (this.tok.type === type) { - this.next() - return true - } else { - return false - } - } - - isContextual(name) { - return this.tok.type === tt.name && this.tok.value === name - } - - eatContextual(name) { - return this.tok.value === name && this.eat(tt.name) - } - - canInsertSemicolon() { - return this.tok.type === tt.eof || this.tok.type === tt.braceR || - lineBreak.test(this.input.slice(this.last.end, this.tok.start)) - } - - semicolon() { - return this.eat(tt.semi) - } - - expect(type) { - if (this.eat(type)) return true - for (let i = 1; i <= 2; i++) { - if (this.lookAhead(i).type == type) { - for (let j = 0; j < i; j++) this.next() - return true - } - } - } - - pushCx() { - this.context.push(this.curIndent) - } - - popCx() { - this.curIndent = this.context.pop() - } - - lineEnd(pos) { - while (pos < this.input.length && !isNewLine(this.input.charCodeAt(pos))) ++pos - return pos - } - - indentationAfter(pos) { - for (let count = 0;; ++pos) { - let ch = this.input.charCodeAt(pos) - if (ch === 32) ++count - else if (ch === 9) count += this.options.tabSize - else return count - } - } - - closes(closeTok, indent, line, blockHeuristic) { - if (this.tok.type === closeTok || this.tok.type === tt.eof) return true - return line != this.curLineStart && this.curIndent < indent && this.tokenStartsLine() && - (!blockHeuristic || this.nextLineStart >= this.input.length || - this.indentationAfter(this.nextLineStart) < indent) - } - - tokenStartsLine() { - for (let p = this.tok.start - 1; p >= this.curLineStart; --p) { - let ch = this.input.charCodeAt(p) - if (ch !== 9 && ch !== 32) return false - } - return true - } - - extend(name, f) { - this[name] = f(this[name]) - } - - loadPlugins(pluginConfigs) { - for (let name in pluginConfigs) { - let plugin = pluginsLoose[name] - if (!plugin) throw new Error("Plugin '" + name + "' not found") - plugin(this, pluginConfigs[name]) - } - } - - parse() { - this.next() - return this.parseTopLevel() - } -} diff --git a/tools/tests/apps/modules/imports/links/acorn/src/loose/statement.js b/tools/tests/apps/modules/imports/links/acorn/src/loose/statement.js deleted file mode 100644 index aa30696c41..0000000000 --- a/tools/tests/apps/modules/imports/links/acorn/src/loose/statement.js +++ /dev/null @@ -1,459 +0,0 @@ -import {LooseParser} from "./state" -import {isDummy} from "./parseutil" -import {getLineInfo, tokTypes as tt} from "../index" - -const lp = LooseParser.prototype - -lp.parseTopLevel = function() { - let node = this.startNodeAt(this.options.locations ? [0, getLineInfo(this.input, 0)] : 0) - node.body = [] - while (this.tok.type !== tt.eof) node.body.push(this.parseStatement()) - this.toks.adaptDirectivePrologue(node.body) - this.last = this.tok - if (this.options.ecmaVersion >= 6) { - node.sourceType = this.options.sourceType - } - return this.finishNode(node, "Program") -} - -lp.parseStatement = function() { - let starttype = this.tok.type, node = this.startNode(), kind - - if (this.toks.isLet()) { - starttype = tt._var - kind = "let" - } - - switch (starttype) { - case tt._break: case tt._continue: - this.next() - let isBreak = starttype === tt._break - if (this.semicolon() || this.canInsertSemicolon()) { - node.label = null - } else { - node.label = this.tok.type === tt.name ? this.parseIdent() : null - this.semicolon() - } - return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") - - case tt._debugger: - this.next() - this.semicolon() - return this.finishNode(node, "DebuggerStatement") - - case tt._do: - this.next() - node.body = this.parseStatement() - node.test = this.eat(tt._while) ? this.parseParenExpression() : this.dummyIdent() - this.semicolon() - return this.finishNode(node, "DoWhileStatement") - - case tt._for: - this.next() // `for` keyword - let isAwait = this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await") - - this.pushCx() - this.expect(tt.parenL) - if (this.tok.type === tt.semi) return this.parseFor(node, null) - let isLet = this.toks.isLet() - if (isLet || this.tok.type === tt._var || this.tok.type === tt._const) { - let init = this.parseVar(true, isLet ? "let" : this.tok.value) - if (init.declarations.length === 1 && (this.tok.type === tt._in || this.isContextual("of"))) { - if (this.options.ecmaVersion >= 9 && this.tok.type !== tt._in) { - node.await = isAwait - } - return this.parseForIn(node, init) - } - return this.parseFor(node, init) - } - let init = this.parseExpression(true) - if (this.tok.type === tt._in || this.isContextual("of")) { - if (this.options.ecmaVersion >= 9 && this.tok.type !== tt._in) { - node.await = isAwait - } - return this.parseForIn(node, this.toAssignable(init)) - } - return this.parseFor(node, init) - - case tt._function: - this.next() - return this.parseFunction(node, true) - - case tt._if: - this.next() - node.test = this.parseParenExpression() - node.consequent = this.parseStatement() - node.alternate = this.eat(tt._else) ? this.parseStatement() : null - return this.finishNode(node, "IfStatement") - - case tt._return: - this.next() - if (this.eat(tt.semi) || this.canInsertSemicolon()) node.argument = null - else { node.argument = this.parseExpression(); this.semicolon() } - return this.finishNode(node, "ReturnStatement") - - case tt._switch: - let blockIndent = this.curIndent, line = this.curLineStart - this.next() - node.discriminant = this.parseParenExpression() - node.cases = [] - this.pushCx() - this.expect(tt.braceL) - - let cur - while (!this.closes(tt.braceR, blockIndent, line, true)) { - if (this.tok.type === tt._case || this.tok.type === tt._default) { - let isCase = this.tok.type === tt._case - if (cur) this.finishNode(cur, "SwitchCase") - node.cases.push(cur = this.startNode()) - cur.consequent = [] - this.next() - if (isCase) cur.test = this.parseExpression() - else cur.test = null - this.expect(tt.colon) - } else { - if (!cur) { - node.cases.push(cur = this.startNode()) - cur.consequent = [] - cur.test = null - } - cur.consequent.push(this.parseStatement()) - } - } - if (cur) this.finishNode(cur, "SwitchCase") - this.popCx() - this.eat(tt.braceR) - return this.finishNode(node, "SwitchStatement") - - case tt._throw: - this.next() - node.argument = this.parseExpression() - this.semicolon() - return this.finishNode(node, "ThrowStatement") - - case tt._try: - this.next() - node.block = this.parseBlock() - node.handler = null - if (this.tok.type === tt._catch) { - let clause = this.startNode() - this.next() - this.expect(tt.parenL) - clause.param = this.toAssignable(this.parseExprAtom(), true) - this.expect(tt.parenR) - clause.body = this.parseBlock() - node.handler = this.finishNode(clause, "CatchClause") - } - node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null - if (!node.handler && !node.finalizer) return node.block - return this.finishNode(node, "TryStatement") - - case tt._var: - case tt._const: - return this.parseVar(false, kind || this.tok.value) - - case tt._while: - this.next() - node.test = this.parseParenExpression() - node.body = this.parseStatement() - return this.finishNode(node, "WhileStatement") - - case tt._with: - this.next() - node.object = this.parseParenExpression() - node.body = this.parseStatement() - return this.finishNode(node, "WithStatement") - - case tt.braceL: - return this.parseBlock() - - case tt.semi: - this.next() - return this.finishNode(node, "EmptyStatement") - - case tt._class: - return this.parseClass(true) - - case tt._import: - return this.parseImport() - - case tt._export: - return this.parseExport() - - default: - if (this.toks.isAsyncFunction()) { - this.next() - this.next() - return this.parseFunction(node, true, true) - } - let expr = this.parseExpression() - if (isDummy(expr)) { - this.next() - if (this.tok.type === tt.eof) return this.finishNode(node, "EmptyStatement") - return this.parseStatement() - } else if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) { - node.body = this.parseStatement() - node.label = expr - return this.finishNode(node, "LabeledStatement") - } else { - node.expression = expr - this.semicolon() - return this.finishNode(node, "ExpressionStatement") - } - } -} - -lp.parseBlock = function() { - let node = this.startNode() - this.pushCx() - this.expect(tt.braceL) - let blockIndent = this.curIndent, line = this.curLineStart - node.body = [] - while (!this.closes(tt.braceR, blockIndent, line, true)) - node.body.push(this.parseStatement()) - this.popCx() - this.eat(tt.braceR) - return this.finishNode(node, "BlockStatement") -} - -lp.parseFor = function(node, init) { - node.init = init - node.test = node.update = null - if (this.eat(tt.semi) && this.tok.type !== tt.semi) node.test = this.parseExpression() - if (this.eat(tt.semi) && this.tok.type !== tt.parenR) node.update = this.parseExpression() - this.popCx() - this.expect(tt.parenR) - node.body = this.parseStatement() - return this.finishNode(node, "ForStatement") -} - -lp.parseForIn = function(node, init) { - let type = this.tok.type === tt._in ? "ForInStatement" : "ForOfStatement" - this.next() - node.left = init - node.right = this.parseExpression() - this.popCx() - this.expect(tt.parenR) - node.body = this.parseStatement() - return this.finishNode(node, type) -} - -lp.parseVar = function(noIn, kind) { - let node = this.startNode() - node.kind = kind - this.next() - node.declarations = [] - do { - let decl = this.startNode() - decl.id = this.options.ecmaVersion >= 6 ? this.toAssignable(this.parseExprAtom(), true) : this.parseIdent() - decl.init = this.eat(tt.eq) ? this.parseMaybeAssign(noIn) : null - node.declarations.push(this.finishNode(decl, "VariableDeclarator")) - } while (this.eat(tt.comma)) - if (!node.declarations.length) { - let decl = this.startNode() - decl.id = this.dummyIdent() - node.declarations.push(this.finishNode(decl, "VariableDeclarator")) - } - if (!noIn) this.semicolon() - return this.finishNode(node, "VariableDeclaration") -} - -lp.parseClass = function(isStatement) { - let node = this.startNode() - this.next() - if (this.tok.type === tt.name) node.id = this.parseIdent() - else if (isStatement === true) node.id = this.dummyIdent() - else node.id = null - node.superClass = this.eat(tt._extends) ? this.parseExpression() : null - node.body = this.startNode() - node.body.body = [] - this.pushCx() - let indent = this.curIndent + 1, line = this.curLineStart - this.eat(tt.braceL) - if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart } - while (!this.closes(tt.braceR, indent, line)) { - if (this.semicolon()) continue - let method = this.startNode(), isGenerator, isAsync - if (this.options.ecmaVersion >= 6) { - method.static = false - isGenerator = this.eat(tt.star) - } - this.parsePropertyName(method) - if (isDummy(method.key)) { if (isDummy(this.parseMaybeAssign())) this.next(); this.eat(tt.comma); continue } - if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" && - (this.tok.type != tt.parenL && this.tok.type != tt.braceL)) { - method.static = true - isGenerator = this.eat(tt.star) - this.parsePropertyName(method) - } else { - method.static = false - } - if (!method.computed && - method.key.type === "Identifier" && method.key.name === "async" && this.tok.type !== tt.parenL && - !this.canInsertSemicolon()) { - isAsync = true - isGenerator = this.options.ecmaVersion >= 9 && this.eat(tt.star) - this.parsePropertyName(method) - } else { - isAsync = false - } - if (this.options.ecmaVersion >= 5 && method.key.type === "Identifier" && - !method.computed && (method.key.name === "get" || method.key.name === "set") && - this.tok.type !== tt.parenL && this.tok.type !== tt.braceL) { - method.kind = method.key.name - this.parsePropertyName(method) - method.value = this.parseMethod(false) - } else { - if (!method.computed && !method.static && !isGenerator && !isAsync && ( - method.key.type === "Identifier" && method.key.name === "constructor" || - method.key.type === "Literal" && method.key.value === "constructor")) { - method.kind = "constructor" - } else { - method.kind = "method" - } - method.value = this.parseMethod(isGenerator, isAsync) - } - node.body.body.push(this.finishNode(method, "MethodDefinition")) - } - this.popCx() - if (!this.eat(tt.braceR)) { - // If there is no closing brace, make the node span to the start - // of the next token (this is useful for Tern) - this.last.end = this.tok.start - if (this.options.locations) this.last.loc.end = this.tok.loc.start - } - this.semicolon() - this.finishNode(node.body, "ClassBody") - return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") -} - -lp.parseFunction = function(node, isStatement, isAsync) { - let oldInAsync = this.inAsync - this.initFunction(node) - if (this.options.ecmaVersion >= 6) { - node.generator = this.eat(tt.star) - } - if (this.options.ecmaVersion >= 8) { - node.async = !!isAsync - } - if (this.tok.type === tt.name) node.id = this.parseIdent() - else if (isStatement === true) node.id = this.dummyIdent() - this.inAsync = node.async - node.params = this.parseFunctionParams() - node.body = this.parseBlock() - this.toks.adaptDirectivePrologue(node.body.body) - this.inAsync = oldInAsync - return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") -} - -lp.parseExport = function() { - let node = this.startNode() - this.next() - if (this.eat(tt.star)) { - node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString() - return this.finishNode(node, "ExportAllDeclaration") - } - if (this.eat(tt._default)) { - // export default (function foo() {}) // This is FunctionExpression. - let isAsync - if (this.tok.type === tt._function || (isAsync = this.toks.isAsyncFunction())) { - let fNode = this.startNode() - this.next() - if (isAsync) this.next() - node.declaration = this.parseFunction(fNode, "nullableID", isAsync) - } else if (this.tok.type === tt._class) { - node.declaration = this.parseClass("nullableID") - } else { - node.declaration = this.parseMaybeAssign() - this.semicolon() - } - return this.finishNode(node, "ExportDefaultDeclaration") - } - if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) { - node.declaration = this.parseStatement() - node.specifiers = [] - node.source = null - } else { - node.declaration = null - node.specifiers = this.parseExportSpecifierList() - node.source = this.eatContextual("from") ? this.parseExprAtom() : null - this.semicolon() - } - return this.finishNode(node, "ExportNamedDeclaration") -} - -lp.parseImport = function() { - let node = this.startNode() - this.next() - if (this.tok.type === tt.string) { - node.specifiers = [] - node.source = this.parseExprAtom() - } else { - let elt - if (this.tok.type === tt.name && this.tok.value !== "from") { - elt = this.startNode() - elt.local = this.parseIdent() - this.finishNode(elt, "ImportDefaultSpecifier") - this.eat(tt.comma) - } - node.specifiers = this.parseImportSpecifierList() - node.source = this.eatContextual("from") && this.tok.type == tt.string ? this.parseExprAtom() : this.dummyString() - if (elt) node.specifiers.unshift(elt) - } - this.semicolon() - return this.finishNode(node, "ImportDeclaration") -} - -lp.parseImportSpecifierList = function() { - let elts = [] - if (this.tok.type === tt.star) { - let elt = this.startNode() - this.next() - elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent() - elts.push(this.finishNode(elt, "ImportNamespaceSpecifier")) - } else { - let indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart - this.pushCx() - this.eat(tt.braceL) - if (this.curLineStart > continuedLine) continuedLine = this.curLineStart - while (!this.closes(tt.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { - let elt = this.startNode() - if (this.eat(tt.star)) { - elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent() - this.finishNode(elt, "ImportNamespaceSpecifier") - } else { - if (this.isContextual("from")) break - elt.imported = this.parseIdent() - if (isDummy(elt.imported)) break - elt.local = this.eatContextual("as") ? this.parseIdent() : elt.imported - this.finishNode(elt, "ImportSpecifier") - } - elts.push(elt) - this.eat(tt.comma) - } - this.eat(tt.braceR) - this.popCx() - } - return elts -} - -lp.parseExportSpecifierList = function() { - let elts = [] - let indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart - this.pushCx() - this.eat(tt.braceL) - if (this.curLineStart > continuedLine) continuedLine = this.curLineStart - while (!this.closes(tt.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { - if (this.isContextual("from")) break - let elt = this.startNode() - elt.local = this.parseIdent() - if (isDummy(elt.local)) break - elt.exported = this.eatContextual("as") ? this.parseIdent() : elt.local - this.finishNode(elt, "ExportSpecifier") - elts.push(elt) - this.eat(tt.comma) - } - this.eat(tt.braceR) - this.popCx() - return elts -} diff --git a/tools/tests/apps/modules/imports/links/acorn/src/loose/tokenize.js b/tools/tests/apps/modules/imports/links/acorn/src/loose/tokenize.js deleted file mode 100644 index 619b6ee9e4..0000000000 --- a/tools/tests/apps/modules/imports/links/acorn/src/loose/tokenize.js +++ /dev/null @@ -1,111 +0,0 @@ -import {tokTypes as tt, Token, isNewLine, SourceLocation, getLineInfo, lineBreakG} from "../index" -import {LooseParser} from "./state" - -const lp = LooseParser.prototype - -function isSpace(ch) { - return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || isNewLine(ch) -} - -lp.next = function() { - this.last = this.tok - if (this.ahead.length) - this.tok = this.ahead.shift() - else - this.tok = this.readToken() - - if (this.tok.start >= this.nextLineStart) { - while (this.tok.start >= this.nextLineStart) { - this.curLineStart = this.nextLineStart - this.nextLineStart = this.lineEnd(this.curLineStart) + 1 - } - this.curIndent = this.indentationAfter(this.curLineStart) - } -} - -lp.readToken = function() { - for (;;) { - try { - this.toks.next() - if (this.toks.type === tt.dot && - this.input.substr(this.toks.end, 1) === "." && - this.options.ecmaVersion >= 6) { - this.toks.end++ - this.toks.type = tt.ellipsis - } - return new Token(this.toks) - } catch (e) { - if (!(e instanceof SyntaxError)) throw e - - // Try to skip some text, based on the error message, and then continue - let msg = e.message, pos = e.raisedAt, replace = true - if (/unterminated/i.test(msg)) { - pos = this.lineEnd(e.pos + 1) - if (/string/.test(msg)) { - replace = {start: e.pos, end: pos, type: tt.string, value: this.input.slice(e.pos + 1, pos)} - } else if (/regular expr/i.test(msg)) { - let re = this.input.slice(e.pos, pos) - try { re = new RegExp(re) } catch (e) { /* ignore compilation error due to new syntax */ } - replace = {start: e.pos, end: pos, type: tt.regexp, value: re} - } else if (/template/.test(msg)) { - replace = { - start: e.pos, - end: pos, - type: tt.template, - value: this.input.slice(e.pos, pos) - } - } else { - replace = false - } - } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) { - while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) ++pos - } else if (/character escape|expected hexadecimal/i.test(msg)) { - while (pos < this.input.length) { - let ch = this.input.charCodeAt(pos++) - if (ch === 34 || ch === 39 || isNewLine(ch)) break - } - } else if (/unexpected character/i.test(msg)) { - pos++ - replace = false - } else if (/regular expression/i.test(msg)) { - replace = true - } else { - throw e - } - this.resetTo(pos) - if (replace === true) replace = {start: pos, end: pos, type: tt.name, value: "✖"} - if (replace) { - if (this.options.locations) - replace.loc = new SourceLocation( - this.toks, - getLineInfo(this.input, replace.start), - getLineInfo(this.input, replace.end)) - return replace - } - } - } -} - -lp.resetTo = function(pos) { - this.toks.pos = pos - let ch = this.input.charAt(pos - 1) - this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) || - /[enwfd]/.test(ch) && - /\b(case|else|return|throw|new|in|(instance|type)?of|delete|void)$/.test(this.input.slice(pos - 10, pos)) - - if (this.options.locations) { - this.toks.curLine = 1 - this.toks.lineStart = lineBreakG.lastIndex = 0 - let match - while ((match = lineBreakG.exec(this.input)) && match.index < pos) { - ++this.toks.curLine - this.toks.lineStart = match.index + match[0].length - } - } -} - -lp.lookAhead = function(n) { - while (n > this.ahead.length) - this.ahead.push(this.readToken()) - return this.ahead[n - 1] -} diff --git a/tools/tests/apps/modules/imports/links/acorn/src/lval.js b/tools/tests/apps/modules/imports/links/acorn/src/lval.js index 0fc1bc5284..8ad4b26390 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/lval.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/lval.js @@ -1,6 +1,7 @@ import {types as tt} from "./tokentype" import {Parser} from "./state" import {has} from "./util" +import {BIND_NONE, BIND_OUTSIDE, BIND_LEXICAL} from "./scopeflags" const pp = Parser.prototype @@ -12,7 +13,7 @@ pp.toAssignable = function(node, isBinding, refDestructuringErrors) { switch (node.type) { case "Identifier": if (this.inAsync && node.name === "await") - this.raise(node.start, "Can not use 'await' as identifier inside an async function") + this.raise(node.start, "Cannot use 'await' as identifier inside an async function") break case "ObjectPattern": @@ -40,7 +41,7 @@ pp.toAssignable = function(node, isBinding, refDestructuringErrors) { break case "Property": - // AssignmentProperty has type == "Property" + // AssignmentProperty has type === "Property" if (node.kind !== "init") this.raise(node.key.start, "Object pattern can't contain getter or setter") this.toAssignable(node.value, isBinding) break @@ -69,7 +70,7 @@ pp.toAssignable = function(node, isBinding, refDestructuringErrors) { break case "ParenthesizedExpression": - this.toAssignable(node.expression, isBinding) + this.toAssignable(node.expression, isBinding, refDestructuringErrors) break case "MemberExpression": @@ -185,9 +186,11 @@ pp.parseMaybeDefault = function(startPos, startLoc, left) { // 'let' indicating that the lval creates a lexical ('let' or 'const') binding // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references -pp.checkLVal = function(expr, bindingType, checkClashes) { +pp.checkLVal = function(expr, bindingType = BIND_NONE, checkClashes) { switch (expr.type) { case "Identifier": + if (bindingType === BIND_LEXICAL && expr.name === "let") + this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name") if (this.strict && this.reservedWordsStrictBind.test(expr.name)) this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode") if (checkClashes) { @@ -195,19 +198,7 @@ pp.checkLVal = function(expr, bindingType, checkClashes) { this.raiseRecoverable(expr.start, "Argument name clash") checkClashes[expr.name] = true } - if (bindingType && bindingType !== "none") { - if ( - bindingType === "var" && !this.canDeclareVarName(expr.name) || - bindingType !== "var" && !this.canDeclareLexicalName(expr.name) - ) { - this.raiseRecoverable(expr.start, `Identifier '${expr.name}' has already been declared`) - } - if (bindingType === "var") { - this.declareVarName(expr.name) - } else { - this.declareLexicalName(expr.name) - } - } + if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) this.declareName(expr.name, bindingType, expr.start) break case "MemberExpression": @@ -220,7 +211,7 @@ pp.checkLVal = function(expr, bindingType, checkClashes) { break case "Property": - // AssignmentProperty has type == "Property" + // AssignmentProperty has type === "Property" this.checkLVal(expr.value, bindingType, checkClashes) break diff --git a/tools/tests/apps/modules/imports/links/acorn/src/options.js b/tools/tests/apps/modules/imports/links/acorn/src/options.js index 9dda44ae88..807251fdfd 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/options.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/options.js @@ -5,18 +5,19 @@ import {SourceLocation} from "./locutil" // the parser process. These options are recognized: export const defaultOptions = { - // `ecmaVersion` indicates the ECMAScript version to parse. Must - // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support - // for strict mode, the set of reserved words, and support for - // new syntax features. The default is 7. - ecmaVersion: 7, + // `ecmaVersion` indicates the ECMAScript version to parse. Must be + // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10 + // (2019). This influences support for strict mode, the set of + // reserved words, and support for new syntax features. The default + // is 10. + ecmaVersion: 10, // `sourceType` indicates the mode the code should be parsed in. // Can be either `"script"` or `"module"`. This influences global // strict mode and parsing of `import` and `export` declarations. sourceType: "script", // `onInsertedSemicolon` can be a callback that will be called // when a semicolon is automatically inserted. It will be passed - // th position of the comma as an offset, and if `locations` is + // the position of the comma as an offset, and if `locations` is // enabled, it is given the location as a `{line, column}` object // as second argument. onInsertedSemicolon: null, @@ -34,6 +35,9 @@ export const defaultOptions = { // When enabled, import/export statements are not constrained to // appearing at the top of the program. allowImportExportEverywhere: false, + // When enabled, await identifiers are allowed to appear at the top-level scope, + // but they are still not allowed in non-async functions. + allowAwaitOutsideFunction: false, // When enabled, hashbang directive in the beginning of file // is allowed and treated as a line comment. allowHashBang: false, @@ -82,8 +86,7 @@ export const defaultOptions = { directSourceFile: null, // When enabled, parenthesized expressions are represented by // (non-standard) ParenthesizedExpression nodes - preserveParens: false, - plugins: {} + preserveParens: false } // Interpret and default an options object diff --git a/tools/tests/apps/modules/imports/links/acorn/src/parseutil.js b/tools/tests/apps/modules/imports/links/acorn/src/parseutil.js index e1736372e5..98e35237f5 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/parseutil.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/parseutil.js @@ -6,15 +6,29 @@ const pp = Parser.prototype // ## Parser utilities -const literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/ +const literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)")/ pp.strictDirective = function(start) { for (;;) { + // Try to find string literal. skipWhiteSpace.lastIndex = start start += skipWhiteSpace.exec(this.input)[0].length let match = literal.exec(this.input.slice(start)) if (!match) return false - if ((match[1] || match[2]) == "use strict") return true + if ((match[1] || match[2]) === "use strict") { + skipWhiteSpace.lastIndex = start + match[0].length + let spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length + let next = this.input.charAt(end) + return next === ";" || next === "}" || + (lineBreak.test(spaceAfter[0]) && + !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "=")) + } start += match[0].length + + // Skip semicolon, if any. + skipWhiteSpace.lastIndex = start + start += skipWhiteSpace.exec(this.input)[0].length + if (this.input[start] === ";") + start++ } } @@ -74,7 +88,7 @@ pp.semicolon = function() { } pp.afterTrailingComma = function(tokType, notNext) { - if (this.type == tokType) { + if (this.type === tokType) { if (this.options.onTrailingComma) this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc) if (!notNext) diff --git a/tools/tests/apps/modules/imports/links/acorn/src/regexp.js b/tools/tests/apps/modules/imports/links/acorn/src/regexp.js index c5953e3012..605bce5203 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/regexp.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/regexp.js @@ -1,6 +1,7 @@ import {isIdentifierStart, isIdentifierChar} from "./identifier.js" import {Parser} from "./state.js" import UNICODE_PROPERTY_VALUES from "./unicode-property-data.js" +import {has} from "./util.js" const pp = Parser.prototype @@ -8,6 +9,7 @@ export class RegExpValidationState { constructor(parser) { this.parser = parser this.validFlags = `gim${parser.options.ecmaVersion >= 6 ? "uy" : ""}${parser.options.ecmaVersion >= 9 ? "s" : ""}` + this.unicodeProperties = UNICODE_PROPERTY_VALUES[parser.options.ecmaVersion >= 11 ? 11 : parser.options.ecmaVersion] this.source = "" this.flags = "" this.start = 0 @@ -48,7 +50,8 @@ export class RegExpValidationState { if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { return c } - return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00 + const next = s.charCodeAt(i + 1) + return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c } nextIndex(i) { @@ -57,8 +60,9 @@ export class RegExpValidationState { if (i >= l) { return l } - const c = s.charCodeAt(i) - if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { + let c = s.charCodeAt(i), next + if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || + (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) { return i + 1 } return i + 2 @@ -103,7 +107,7 @@ pp.validateRegExpFlags = function(state) { for (let i = 0; i < flags.length; i++) { const flag = flags.charAt(i) - if (validFlags.indexOf(flag) == -1) { + if (validFlags.indexOf(flag) === -1) { this.raise(state.start, "Invalid regular expression flag") } if (flags.indexOf(flag, i + 1) > -1) { @@ -150,7 +154,7 @@ pp.regexp_pattern = function(state) { if (state.eat(0x29 /* ) */)) { state.raise("Unmatched ')'") } - if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) { + if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) { state.raise("Lone quantifier brackets") } } @@ -784,14 +788,14 @@ pp.regexp_eatUnicodePropertyValueExpression = function(state) { return false } pp.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { - if (!UNICODE_PROPERTY_VALUES.hasOwnProperty(name) || UNICODE_PROPERTY_VALUES[name].indexOf(value) === -1) { + if (!has(state.unicodeProperties.nonBinary, name)) state.raise("Invalid property name") - } + if (!state.unicodeProperties.nonBinary[name].test(value)) + state.raise("Invalid property value") } pp.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { - if (UNICODE_PROPERTY_VALUES.$LONE.indexOf(nameOrValue) === -1) { + if (!state.unicodeProperties.binary.test(nameOrValue)) state.raise("Invalid property name") - } } // UnicodePropertyName :: @@ -835,7 +839,7 @@ pp.regexp_eatCharacterClass = function(state) { if (state.eat(0x5B /* [ */)) { state.eat(0x5E /* ^ */) this.regexp_classRanges(state) - if (state.eat(0x5D /* [ */)) { + if (state.eat(0x5D /* ] */)) { return true } // Unreachable since it threw "unterminated regular expression" error before. @@ -883,7 +887,7 @@ pp.regexp_eatClassAtom = function(state) { } const ch = state.current() - if (ch !== 0x5D /* [ */) { + if (ch !== 0x5D /* ] */) { state.lastIntValue = ch state.advance() return true diff --git a/tools/tests/apps/modules/imports/links/acorn/src/scope.js b/tools/tests/apps/modules/imports/links/acorn/src/scope.js index eab0002c04..b0b9866611 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/scope.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/scope.js @@ -1,74 +1,95 @@ import {Parser} from "./state" -import {has} from "./util" +import {SCOPE_VAR, SCOPE_FUNCTION, SCOPE_TOP, SCOPE_ARROW, SCOPE_SIMPLE_CATCH, BIND_LEXICAL, BIND_SIMPLE_CATCH, BIND_FUNCTION} from "./scopeflags" const pp = Parser.prototype -// Object.assign polyfill -const assign = Object.assign || function(target, ...sources) { - for (let source of sources) { - for (const key in source) { - if (has(source, key)) { - target[key] = source[key] - } - } +class Scope { + constructor(flags) { + this.flags = flags + // A list of var-declared names in the current lexical scope + this.var = [] + // A list of lexically-declared names in the current lexical scope + this.lexical = [] + // A list of lexically-declared FunctionDeclaration names in the current lexical scope + this.functions = [] } - return target } // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. -pp.enterFunctionScope = function() { - // var: a hash of var-declared names in the current lexical scope - // lexical: a hash of lexically-declared names in the current lexical scope - // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) - // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) - this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}) +pp.enterScope = function(flags) { + this.scopeStack.push(new Scope(flags)) } -pp.exitFunctionScope = function() { +pp.exitScope = function() { this.scopeStack.pop() } -pp.enterLexicalScope = function() { - const parentScope = this.scopeStack[this.scopeStack.length - 1] - const childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}} - - this.scopeStack.push(childScope) - assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical) +// The spec says: +// > At the top level of a function, or script, function declarations are +// > treated like var declarations rather than like lexical declarations. +pp.treatFunctionsAsVarInScope = function(scope) { + return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP) } -pp.exitLexicalScope = function() { - const childScope = this.scopeStack.pop() - const parentScope = this.scopeStack[this.scopeStack.length - 1] - - assign(parentScope.childVar, childScope.var, childScope.childVar) +pp.declareName = function(name, bindingType, pos) { + let redeclared = false + if (bindingType === BIND_LEXICAL) { + const scope = this.currentScope() + redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1 + scope.lexical.push(name) + if (this.inModule && (scope.flags & SCOPE_TOP)) + delete this.undefinedExports[name] + } else if (bindingType === BIND_SIMPLE_CATCH) { + const scope = this.currentScope() + scope.lexical.push(name) + } else if (bindingType === BIND_FUNCTION) { + const scope = this.currentScope() + if (this.treatFunctionsAsVar) + redeclared = scope.lexical.indexOf(name) > -1 + else + redeclared = scope.lexical.indexOf(name) > -1 || scope.var.indexOf(name) > -1 + scope.functions.push(name) + } else { + for (let i = this.scopeStack.length - 1; i >= 0; --i) { + const scope = this.scopeStack[i] + if (scope.lexical.indexOf(name) > -1 && !((scope.flags & SCOPE_SIMPLE_CATCH) && scope.lexical[0] === name) || + !this.treatFunctionsAsVarInScope(scope) && scope.functions.indexOf(name) > -1) { + redeclared = true + break + } + scope.var.push(name) + if (this.inModule && (scope.flags & SCOPE_TOP)) + delete this.undefinedExports[name] + if (scope.flags & SCOPE_VAR) break + } + } + if (redeclared) this.raiseRecoverable(pos, `Identifier '${name}' has already been declared`) } -/** - * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` - * in the current lexical scope or any of the parent lexical scopes in this function. - */ -pp.canDeclareVarName = function(name) { - const currentScope = this.scopeStack[this.scopeStack.length - 1] - - return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) +pp.checkLocalExport = function(id) { + // scope.functions must be empty as Module code is always strict. + if (this.scopeStack[0].lexical.indexOf(id.name) === -1 && + this.scopeStack[0].var.indexOf(id.name) === -1) { + this.undefinedExports[id.name] = id + } } -/** - * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` - * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in - * any child lexical scopes in this function. - */ -pp.canDeclareLexicalName = function(name) { - const currentScope = this.scopeStack[this.scopeStack.length - 1] - - return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) +pp.currentScope = function() { + return this.scopeStack[this.scopeStack.length - 1] } -pp.declareVarName = function(name) { - this.scopeStack[this.scopeStack.length - 1].var[name] = true +pp.currentVarScope = function() { + for (let i = this.scopeStack.length - 1;; i--) { + let scope = this.scopeStack[i] + if (scope.flags & SCOPE_VAR) return scope + } } -pp.declareLexicalName = function(name) { - this.scopeStack[this.scopeStack.length - 1].lexical[name] = true +// Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`. +pp.currentThisScope = function() { + for (let i = this.scopeStack.length - 1;; i--) { + let scope = this.scopeStack[i] + if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) return scope + } } diff --git a/tools/tests/apps/modules/imports/links/acorn/src/scopeflags.js b/tools/tests/apps/modules/imports/links/acorn/src/scopeflags.js new file mode 100644 index 0000000000..ccb16ecc48 --- /dev/null +++ b/tools/tests/apps/modules/imports/links/acorn/src/scopeflags.js @@ -0,0 +1,24 @@ +// Each scope gets a bitset that may contain these flags +export const + SCOPE_TOP = 1, + SCOPE_FUNCTION = 2, + SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION, + SCOPE_ASYNC = 4, + SCOPE_GENERATOR = 8, + SCOPE_ARROW = 16, + SCOPE_SIMPLE_CATCH = 32, + SCOPE_SUPER = 64, + SCOPE_DIRECT_SUPER = 128 + +export function functionFlags(async, generator) { + return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0) +} + +// Used in checkLVal and declareName to determine the type of a binding +export const + BIND_NONE = 0, // Not a binding + BIND_VAR = 1, // Var-style binding + BIND_LEXICAL = 2, // Let- or const-style binding + BIND_FUNCTION = 3, // Function declaration + BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding + BIND_OUTSIDE = 5 // Special case for function names as bound inside the function diff --git a/tools/tests/apps/modules/imports/links/acorn/src/state.js b/tools/tests/apps/modules/imports/links/acorn/src/state.js index 185fe28648..eb4e0e1208 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/state.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/state.js @@ -2,29 +2,24 @@ import {reservedWords, keywords} from "./identifier" import {types as tt} from "./tokentype" import {lineBreak} from "./whitespace" import {getOptions} from "./options" - -// Registered plugins -export const plugins = {} - -function keywordRegexp(words) { - return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") -} +import {wordsRegexp} from "./util" +import {SCOPE_TOP, SCOPE_FUNCTION, SCOPE_ASYNC, SCOPE_GENERATOR, SCOPE_SUPER, SCOPE_DIRECT_SUPER} from "./scopeflags" export class Parser { constructor(options, input, startPos) { this.options = options = getOptions(options) this.sourceFile = options.sourceFile - this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]) + this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]) let reserved = "" - if (!options.allowReserved) { + if (options.allowReserved !== true) { for (let v = options.ecmaVersion;; v--) if (reserved = reservedWords[v]) break - if (options.sourceType == "module") reserved += " await" + if (options.sourceType === "module") reserved += " await" } - this.reservedWords = keywordRegexp(reserved) + this.reservedWords = wordsRegexp(reserved) let reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict - this.reservedWordsStrict = keywordRegexp(reservedStrict) - this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind) + this.reservedWordsStrict = wordsRegexp(reservedStrict) + this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind) this.input = String(input) // Used to signal to callers of `readWord1` whether the word @@ -32,9 +27,6 @@ export class Parser { // escape sequences must not be interpreted as keywords. this.containsEsc = false - // Load plugins - this.loadPlugins(options.plugins) - // Set up token state // The current position of the tokenizer in the input. @@ -75,12 +67,12 @@ export class Parser { // Used to signify the start of a potential arrow function this.potentialArrowAt = -1 - // Flags to track whether we are in a function, a generator, an async function. - this.inFunction = this.inGenerator = this.inAsync = false // Positions to delayed-check that yield/await does not exist in default parameters. - this.yieldPos = this.awaitPos = 0 + this.yieldPos = this.awaitPos = this.awaitIdentPos = 0 // Labels in scope. this.labels = [] + // Thus-far undefined exports. + this.undefinedExports = {} // If enabled, skip leading hashbang line. if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") @@ -88,31 +80,45 @@ export class Parser { // Scope tracking for duplicate variable names (see scope.js) this.scopeStack = [] - this.enterFunctionScope() + this.enterScope(SCOPE_TOP) // For RegExp validation this.regexpState = null } - // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them - isKeyword(word) { return this.keywords.test(word) } - isReservedWord(word) { return this.reservedWords.test(word) } - - extend(name, f) { - this[name] = f(this[name]) - } - - loadPlugins(pluginConfigs) { - for (let name in pluginConfigs) { - let plugin = plugins[name] - if (!plugin) throw new Error("Plugin '" + name + "' not found") - plugin(this, pluginConfigs[name]) - } - } - parse() { let node = this.options.program || this.startNode() this.nextToken() return this.parseTopLevel(node) } + + get inFunction() { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 } + get inGenerator() { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 } + get inAsync() { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 } + get allowSuper() { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 } + get allowDirectSuper() { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 } + get treatFunctionsAsVar() { return this.treatFunctionsAsVarInScope(this.currentScope()) } + + // Switch to a getter for 7.0.0. + inNonArrowFunction() { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 } + + static extend(...plugins) { + let cls = this + for (let i = 0; i < plugins.length; i++) cls = plugins[i](cls) + return cls + } + + static parse(input, options) { + return new this(options, input).parse() + } + + static parseExpressionAt(input, pos, options) { + let parser = new this(options, input, pos) + parser.nextToken() + return parser.parseExpression() + } + + static tokenizer(input, options) { + return new this(options, input) + } } diff --git a/tools/tests/apps/modules/imports/links/acorn/src/statement.js b/tools/tests/apps/modules/imports/links/acorn/src/statement.js index 2612125df3..8c7e171a9f 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/statement.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/statement.js @@ -4,6 +4,7 @@ import {lineBreak, skipWhiteSpace} from "./whitespace" import {isIdentifierStart, isIdentifierChar, keywordRelationalOperator} from "./identifier" import {has} from "./util" import {DestructuringErrors} from "./parseutil" +import {functionFlags, SCOPE_SIMPLE_CATCH, BIND_SIMPLE_CATCH, BIND_LEXICAL, BIND_VAR, BIND_FUNCTION} from "./scopeflags" const pp = Parser.prototype @@ -18,25 +19,33 @@ pp.parseTopLevel = function(node) { let exports = {} if (!node.body) node.body = [] while (this.type !== tt.eof) { - let stmt = this.parseStatement(true, true, exports) + let stmt = this.parseStatement(null, true, exports) node.body.push(stmt) } + if (this.inModule) + for (let name of Object.keys(this.undefinedExports)) + this.raiseRecoverable(this.undefinedExports[name].start, `Export '${name}' is not defined`) this.adaptDirectivePrologue(node.body) this.next() - if (this.options.ecmaVersion >= 6) { - node.sourceType = this.options.sourceType - } + node.sourceType = this.options.sourceType return this.finishNode(node, "Program") } const loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"} -pp.isLet = function() { +pp.isLet = function(context) { if (this.options.ecmaVersion < 6 || !this.isContextual("let")) return false skipWhiteSpace.lastIndex = this.pos let skip = skipWhiteSpace.exec(this.input) let next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next) - if (nextCh === 91 || nextCh == 123) return true // '{' and '[' + // For ambiguous cases, determine if a LexicalDeclaration (or only a + // Statement) is allowed here. If context is not empty then only a Statement + // is allowed. However, `let [` is an explicit negative lookahead for + // ExpressionStatement, so special-case it first. + if (nextCh === 91) return true // '[' + if (context) return false + + if (nextCh === 123) return true // '{' if (isIdentifierStart(nextCh, true)) { let pos = next + 1 while (isIdentifierChar(this.input.charCodeAt(pos), true)) ++pos @@ -58,7 +67,7 @@ pp.isAsyncFunction = function() { let next = this.pos + skip[0].length return !lineBreak.test(this.input.slice(this.pos, next)) && this.input.slice(next, next + 8) === "function" && - (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) + (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) } // Parse a single statement. @@ -68,10 +77,10 @@ pp.isAsyncFunction = function() { // `if (foo) /blah/.exec(foo)`, where looking at the previous token // does not help. -pp.parseStatement = function(declaration, topLevel, exports) { +pp.parseStatement = function(context, topLevel, exports) { let starttype = this.type, node = this.startNode(), kind - if (this.isLet()) { + if (this.isLet(context)) { starttype = tt._var kind = "let" } @@ -86,10 +95,13 @@ pp.parseStatement = function(declaration, topLevel, exports) { case tt._do: return this.parseDoStatement(node) case tt._for: return this.parseForStatement(node) case tt._function: - if (!declaration && this.options.ecmaVersion >= 6) this.unexpected() - return this.parseFunctionStatement(node, false) + // Function as sole body of either an if statement or a labeled statement + // works, but not when it is part of a labeled statement that is the sole + // body of an if statement. + if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) this.unexpected() + return this.parseFunctionStatement(node, false, !context) case tt._class: - if (!declaration) this.unexpected() + if (context) this.unexpected() return this.parseClass(node, true) case tt._if: return this.parseIfStatement(node) case tt._return: return this.parseReturnStatement(node) @@ -98,14 +110,22 @@ pp.parseStatement = function(declaration, topLevel, exports) { case tt._try: return this.parseTryStatement(node) case tt._const: case tt._var: kind = kind || this.value - if (!declaration && kind != "var") this.unexpected() + if (context && kind !== "var") this.unexpected() return this.parseVarStatement(node, kind) case tt._while: return this.parseWhileStatement(node) case tt._with: return this.parseWithStatement(node) - case tt.braceL: return this.parseBlock() + case tt.braceL: return this.parseBlock(true, node) case tt.semi: return this.parseEmptyStatement(node) case tt._export: case tt._import: + if (this.options.ecmaVersion > 10 && starttype === tt._import) { + skipWhiteSpace.lastIndex = this.pos + let skip = skipWhiteSpace.exec(this.input) + let next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next) + if (nextCh === 40) // '(' + return this.parseExpressionStatement(node, this.parseExpression()) + } + if (!this.options.allowImportExportEverywhere) { if (!topLevel) this.raise(this.start, "'import' and 'export' may only appear at the top level") @@ -121,20 +141,20 @@ pp.parseStatement = function(declaration, topLevel, exports) { // Identifier node, we switch to interpreting it as a label. default: if (this.isAsyncFunction()) { - if (!declaration) this.unexpected() + if (context) this.unexpected() this.next() - return this.parseFunctionStatement(node, true) + return this.parseFunctionStatement(node, true, !context) } let maybeName = this.value, expr = this.parseExpression() if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) - return this.parseLabeledStatement(node, maybeName, expr) + return this.parseLabeledStatement(node, maybeName, expr, context) else return this.parseExpressionStatement(node, expr) } } pp.parseBreakContinueStatement = function(node, keyword) { - let isBreak = keyword == "break" + let isBreak = keyword === "break" this.next() if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null else if (this.type !== tt.name) this.unexpected() @@ -166,7 +186,7 @@ pp.parseDebuggerStatement = function(node) { pp.parseDoStatement = function(node) { this.next() this.labels.push(loopLabel) - node.body = this.parseStatement(false) + node.body = this.parseStatement("do") this.labels.pop() this.expect(tt._while) node.test = this.parseParenExpression() @@ -187,9 +207,9 @@ pp.parseDoStatement = function(node) { pp.parseForStatement = function(node) { this.next() - let awaitAt = (this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await")) ? this.lastTokStart : -1 + let awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1 this.labels.push(loopLabel) - this.enterLexicalScope() + this.enterScope(0) this.expect(tt.parenL) if (this.type === tt.semi) { if (awaitAt > -1) this.unexpected(awaitAt) @@ -201,8 +221,7 @@ pp.parseForStatement = function(node) { this.next() this.parseVar(init, true, kind) this.finishNode(init, "VariableDeclaration") - if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1 && - !(kind !== "var" && init.declarations[0].init)) { + if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1) { if (this.options.ecmaVersion >= 9) { if (this.type === tt._in) { if (awaitAt > -1) this.unexpected(awaitAt) @@ -231,17 +250,17 @@ pp.parseForStatement = function(node) { return this.parseFor(node, init) } -pp.parseFunctionStatement = function(node, isAsync) { +pp.parseFunctionStatement = function(node, isAsync, declarationPosition) { this.next() - return this.parseFunction(node, true, false, isAsync) + return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync) } pp.parseIfStatement = function(node) { this.next() node.test = this.parseParenExpression() // allow function declarations in branches, but only in non-strict mode - node.consequent = this.parseStatement(!this.strict && this.type == tt._function) - node.alternate = this.eat(tt._else) ? this.parseStatement(!this.strict && this.type == tt._function) : null + node.consequent = this.parseStatement("if") + node.alternate = this.eat(tt._else) ? this.parseStatement("if") : null return this.finishNode(node, "IfStatement") } @@ -265,14 +284,14 @@ pp.parseSwitchStatement = function(node) { node.cases = [] this.expect(tt.braceL) this.labels.push(switchLabel) - this.enterLexicalScope() + this.enterScope(0) // Statements under must be grouped (by label) in SwitchCase // nodes. `cur` is used to keep the node that we are currently // adding statements to. let cur - for (let sawDefault = false; this.type != tt.braceR;) { + for (let sawDefault = false; this.type !== tt.braceR;) { if (this.type === tt._case || this.type === tt._default) { let isCase = this.type === tt._case if (cur) this.finishNode(cur, "SwitchCase") @@ -289,10 +308,10 @@ pp.parseSwitchStatement = function(node) { this.expect(tt.colon) } else { if (!cur) this.unexpected() - cur.consequent.push(this.parseStatement(true)) + cur.consequent.push(this.parseStatement(null)) } } - this.exitLexicalScope() + this.exitScope() if (cur) this.finishNode(cur, "SwitchCase") this.next() // Closing brace this.labels.pop() @@ -319,13 +338,19 @@ pp.parseTryStatement = function(node) { if (this.type === tt._catch) { let clause = this.startNode() this.next() - this.expect(tt.parenL) - clause.param = this.parseBindingAtom() - this.enterLexicalScope() - this.checkLVal(clause.param, "let") - this.expect(tt.parenR) + if (this.eat(tt.parenL)) { + clause.param = this.parseBindingAtom() + let simple = clause.param.type === "Identifier" + this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0) + this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL) + this.expect(tt.parenR) + } else { + if (this.options.ecmaVersion < 10) this.unexpected() + clause.param = null + this.enterScope(0) + } clause.body = this.parseBlock(false) - this.exitLexicalScope() + this.exitScope() node.handler = this.finishNode(clause, "CatchClause") } node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null @@ -345,7 +370,7 @@ pp.parseWhileStatement = function(node) { this.next() node.test = this.parseParenExpression() this.labels.push(loopLabel) - node.body = this.parseStatement(false) + node.body = this.parseStatement("while") this.labels.pop() return this.finishNode(node, "WhileStatement") } @@ -354,7 +379,7 @@ pp.parseWithStatement = function(node) { if (this.strict) this.raise(this.start, "'with' in strict mode") this.next() node.object = this.parseParenExpression() - node.body = this.parseStatement(false) + node.body = this.parseStatement("with") return this.finishNode(node, "WithStatement") } @@ -363,25 +388,21 @@ pp.parseEmptyStatement = function(node) { return this.finishNode(node, "EmptyStatement") } -pp.parseLabeledStatement = function(node, maybeName, expr) { +pp.parseLabeledStatement = function(node, maybeName, expr, context) { for (let label of this.labels) if (label.name === maybeName) this.raise(expr.start, "Label '" + maybeName + "' is already declared") let kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null for (let i = this.labels.length - 1; i >= 0; i--) { let label = this.labels[i] - if (label.statementStart == node.start) { + if (label.statementStart === node.start) { // Update information about previous labels on this node label.statementStart = this.start label.kind = kind } else break } this.labels.push({name: maybeName, kind, statementStart: this.start}) - node.body = this.parseStatement(true) - if (node.body.type == "ClassDeclaration" || - node.body.type == "VariableDeclaration" && node.body.kind != "var" || - node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) - this.raiseRecoverable(node.body.start, "Invalid labeled declaration") + node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label") this.labels.pop() node.label = expr return this.finishNode(node, "LabeledStatement") @@ -397,20 +418,17 @@ pp.parseExpressionStatement = function(node, expr) { // strict"` declarations when `allowStrict` is true (used for // function bodies). -pp.parseBlock = function(createNewLexicalScope = true) { - let node = this.startNode() +pp.parseBlock = function(createNewLexicalScope = true, node = this.startNode(), exitStrict) { node.body = [] this.expect(tt.braceL) - if (createNewLexicalScope) { - this.enterLexicalScope() - } - while (!this.eat(tt.braceR)) { - let stmt = this.parseStatement(true) + if (createNewLexicalScope) this.enterScope(0) + while (this.type !== tt.braceR) { + let stmt = this.parseStatement(null) node.body.push(stmt) } - if (createNewLexicalScope) { - this.exitLexicalScope() - } + if (exitStrict) this.strict = false + this.next() + if (createNewLexicalScope) this.exitScope() return this.finishNode(node, "BlockStatement") } @@ -425,8 +443,8 @@ pp.parseFor = function(node, init) { this.expect(tt.semi) node.update = this.type === tt.parenR ? null : this.parseExpression() this.expect(tt.parenR) - this.exitLexicalScope() - node.body = this.parseStatement(false) + node.body = this.parseStatement("for") + this.exitScope() this.labels.pop() return this.finishNode(node, "ForStatement") } @@ -435,21 +453,36 @@ pp.parseFor = function(node, init) { // same from parser's perspective. pp.parseForIn = function(node, init) { - let type = this.type === tt._in ? "ForInStatement" : "ForOfStatement" + const isForIn = this.type === tt._in this.next() - if (type == "ForInStatement") { - if (init.type === "AssignmentPattern" || - (init.type === "VariableDeclaration" && init.declarations[0].init != null && - (this.strict || init.declarations[0].id.type !== "Identifier"))) - this.raise(init.start, "Invalid assignment in for-in loop head") + + if ( + init.type === "VariableDeclaration" && + init.declarations[0].init != null && + ( + !isForIn || + this.options.ecmaVersion < 8 || + this.strict || + init.kind !== "var" || + init.declarations[0].id.type !== "Identifier" + ) + ) { + this.raise( + init.start, + `${ + isForIn ? "for-in" : "for-of" + } loop variable declaration may not have an initializer` + ) + } else if (init.type === "AssignmentPattern") { + this.raise(init.start, "Invalid left-hand side in for-loop") } node.left = init - node.right = type == "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign() + node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign() this.expect(tt.parenR) - this.exitLexicalScope() - node.body = this.parseStatement(false) + node.body = this.parseStatement("for") + this.exitScope() this.labels.pop() - return this.finishNode(node, type) + return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement") } // Parse a list of variable declarations. @@ -464,7 +497,7 @@ pp.parseVar = function(node, isFor, kind) { decl.init = this.parseMaybeAssign(isFor) } else if (kind === "const" && !(this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { this.unexpected() - } else if (decl.id.type != "Identifier" && !(isFor && (this.type === tt._in || this.isContextual("of")))) { + } else if (decl.id.type !== "Identifier" && !(isFor && (this.type === tt._in || this.isContextual("of")))) { this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value") } else { decl.init = null @@ -476,48 +509,52 @@ pp.parseVar = function(node, isFor, kind) { } pp.parseVarId = function(decl, kind) { - decl.id = this.parseBindingAtom(kind) - this.checkLVal(decl.id, kind, false) + decl.id = this.parseBindingAtom() + this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false) } -// Parse a function declaration or literal (depending on the -// `isStatement` parameter). +const FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4 -pp.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { +// Parse a function declaration or literal (depending on the +// `statement & FUNC_STATEMENT`). + +// Remove `allowExpressionBody` for 7.0.0, as it is only called with false +pp.parseFunction = function(node, statement, allowExpressionBody, isAsync) { this.initFunction(node) - if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) + if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { + if (this.type === tt.star && (statement & FUNC_HANGING_STATEMENT)) + this.unexpected() node.generator = this.eat(tt.star) + } if (this.options.ecmaVersion >= 8) node.async = !!isAsync - if (isStatement) { - node.id = isStatement === "nullableID" && this.type != tt.name ? null : this.parseIdent() - if (node.id) { - this.checkLVal(node.id, "var") - } + if (statement & FUNC_STATEMENT) { + node.id = (statement & FUNC_NULLABLE_ID) && this.type !== tt.name ? null : this.parseIdent() + if (node.id && !(statement & FUNC_HANGING_STATEMENT)) + // If it is a regular function declaration in sloppy mode, then it is + // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding + // mode depends on properties of the current scope (see + // treatFunctionsAsVar). + this.checkLVal(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION) } - let oldInGen = this.inGenerator, oldInAsync = this.inAsync, - oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction - this.inGenerator = node.generator - this.inAsync = node.async + let oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos this.yieldPos = 0 this.awaitPos = 0 - this.inFunction = true - this.enterFunctionScope() + this.awaitIdentPos = 0 + this.enterScope(functionFlags(node.async, node.generator)) - if (!isStatement) - node.id = this.type == tt.name ? this.parseIdent() : null + if (!(statement & FUNC_STATEMENT)) + node.id = this.type === tt.name ? this.parseIdent() : null this.parseFunctionParams(node) - this.parseFunctionBody(node, allowExpressionBody) + this.parseFunctionBody(node, allowExpressionBody, false) - this.inGenerator = oldInGen - this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos - this.inFunction = oldInFunc - return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") + this.awaitIdentPos = oldAwaitIdentPos + return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression") } pp.parseFunctionParams = function(node) { @@ -532,24 +569,34 @@ pp.parseFunctionParams = function(node) { pp.parseClass = function(node, isStatement) { this.next() + // ecma-262 14.6 Class Definitions + // A class definition is always strict mode code. + const oldStrict = this.strict + this.strict = true + this.parseClassId(node, isStatement) this.parseClassSuper(node) let classBody = this.startNode() let hadConstructor = false classBody.body = [] this.expect(tt.braceL) - while (!this.eat(tt.braceR)) { - const member = this.parseClassMember(classBody) - if (member && member.type === "MethodDefinition" && member.kind === "constructor") { - if (hadConstructor) this.raise(member.start, "Duplicate constructor in the same class") - hadConstructor = true + while (this.type !== tt.braceR) { + const element = this.parseClassElement(node.superClass !== null) + if (element) { + classBody.body.push(element) + if (element.type === "MethodDefinition" && element.kind === "constructor") { + if (hadConstructor) this.raise(element.start, "Duplicate constructor in the same class") + hadConstructor = true + } } } + this.strict = oldStrict + this.next() node.body = this.finishNode(classBody, "ClassBody") return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") } -pp.parseClassMember = function(classBody) { +pp.parseClassElement = function(constructorAllowsSuper) { if (this.eat(tt.semi)) return null let method = this.startNode() @@ -581,16 +628,18 @@ pp.parseClassMember = function(classBody) { } if (!method.key) this.parsePropertyName(method) let {key} = method + let allowsDirectSuper = false if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) { if (method.kind !== "method") this.raise(key.start, "Constructor can't have get/set modifier") if (isGenerator) this.raise(key.start, "Constructor can't be a generator") if (isAsync) this.raise(key.start, "Constructor can't be an async method") method.kind = "constructor" + allowsDirectSuper = constructorAllowsSuper } else if (method.static && key.type === "Identifier" && key.name === "prototype") { this.raise(key.start, "Classes may not have a static property named prototype") } - this.parseClassMethod(classBody, method, isGenerator, isAsync) + this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper) if (method.kind === "get" && method.value.params.length !== 0) this.raiseRecoverable(method.value.start, "getter should have no params") if (method.kind === "set" && method.value.params.length !== 1) @@ -600,13 +649,21 @@ pp.parseClassMember = function(classBody) { return method } -pp.parseClassMethod = function(classBody, method, isGenerator, isAsync) { - method.value = this.parseMethod(isGenerator, isAsync) - classBody.body.push(this.finishNode(method, "MethodDefinition")) +pp.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) { + method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper) + return this.finishNode(method, "MethodDefinition") } pp.parseClassId = function(node, isStatement) { - node.id = this.type === tt.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null + if (this.type === tt.name) { + node.id = this.parseIdent() + if (isStatement) + this.checkLVal(node.id, BIND_LEXICAL, false) + } else { + if (isStatement === true) + this.unexpected() + node.id = null + } } pp.parseClassSuper = function(node) { @@ -619,6 +676,14 @@ pp.parseExport = function(node, exports) { this.next() // export * from '...' if (this.eat(tt.star)) { + if (this.options.ecmaVersion >= 11) { + if (this.eatContextual("as")) { + node.exported = this.parseIdent(true) + this.checkExport(exports, node.exported.name, this.lastTokStart) + } else { + node.exported = null + } + } this.expectContextual("from") if (this.type !== tt.string) this.unexpected() node.source = this.parseExprAtom() @@ -632,7 +697,7 @@ pp.parseExport = function(node, exports) { let fNode = this.startNode() this.next() if (isAsync) this.next() - node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync) + node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync) } else if (this.type === tt._class) { let cNode = this.startNode() node.declaration = this.parseClass(cNode, "nullableID") @@ -644,7 +709,7 @@ pp.parseExport = function(node, exports) { } // export var|const|let|function|class ... if (this.shouldParseExportStatement()) { - node.declaration = this.parseStatement(true) + node.declaration = this.parseStatement(null) if (node.declaration.type === "VariableDeclaration") this.checkVariableExport(exports, node.declaration.declarations) else @@ -658,9 +723,11 @@ pp.parseExport = function(node, exports) { if (this.type !== tt.string) this.unexpected() node.source = this.parseExprAtom() } else { - // check for keywords used as local names for (let spec of node.specifiers) { + // check for keywords used as local names this.checkUnreserved(spec.local) + // check if export is defined + this.checkLocalExport(spec.local) } node.source = null @@ -679,22 +746,22 @@ pp.checkExport = function(exports, name, pos) { pp.checkPatternExport = function(exports, pat) { let type = pat.type - if (type == "Identifier") + if (type === "Identifier") this.checkExport(exports, pat.name, pat.start) - else if (type == "ObjectPattern") + else if (type === "ObjectPattern") for (let prop of pat.properties) this.checkPatternExport(exports, prop) - else if (type == "ArrayPattern") + else if (type === "ArrayPattern") for (let elt of pat.elements) { if (elt) this.checkPatternExport(exports, elt) } - else if (type == "Property") + else if (type === "Property") this.checkPatternExport(exports, pat.value) - else if (type == "AssignmentPattern") + else if (type === "AssignmentPattern") this.checkPatternExport(exports, pat.left) - else if (type == "RestElement") + else if (type === "RestElement") this.checkPatternExport(exports, pat.argument) - else if (type == "ParenthesizedExpression") + else if (type === "ParenthesizedExpression") this.checkPatternExport(exports, pat.expression) } @@ -759,7 +826,7 @@ pp.parseImportSpecifiers = function() { // import defaultObj, { x, y as z } from '...' let node = this.startNode() node.local = this.parseIdent() - this.checkLVal(node.local, "let") + this.checkLVal(node.local, BIND_LEXICAL) nodes.push(this.finishNode(node, "ImportDefaultSpecifier")) if (!this.eat(tt.comma)) return nodes } @@ -768,7 +835,7 @@ pp.parseImportSpecifiers = function() { this.next() this.expectContextual("as") node.local = this.parseIdent() - this.checkLVal(node.local, "let") + this.checkLVal(node.local, BIND_LEXICAL) nodes.push(this.finishNode(node, "ImportNamespaceSpecifier")) return nodes } @@ -787,7 +854,7 @@ pp.parseImportSpecifiers = function() { this.checkUnreserved(node.imported) node.local = node.imported } - this.checkLVal(node.local, "let") + this.checkLVal(node.local, BIND_LEXICAL) nodes.push(this.finishNode(node, "ImportSpecifier")) } return nodes diff --git a/tools/tests/apps/modules/imports/links/acorn/src/tokencontext.js b/tools/tests/apps/modules/imports/links/acorn/src/tokencontext.js index 18dda85ce6..1ff5556879 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/tokencontext.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/tokencontext.js @@ -45,13 +45,13 @@ pp.braceIsBlock = function(prevType) { // The check for `tt.name && exprAllowed` detects whether we are // after a `yield` or `of` construct. See the `updateContext` for // `tt.name`. - if (prevType === tt._return || prevType == tt.name && this.exprAllowed) + if (prevType === tt._return || prevType === tt.name && this.exprAllowed) return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) - if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR || prevType == tt.arrow) + if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR || prevType === tt.arrow) return true - if (prevType == tt.braceL) + if (prevType === tt.braceL) return parent === types.b_stat - if (prevType == tt._var || prevType == tt.name) + if (prevType === tt._var || prevType === tt._const || prevType === tt.name) return false return !this.exprAllowed } @@ -67,7 +67,7 @@ pp.inGeneratorContext = function() { pp.updateContext = function(prevType) { let update, type = this.type - if (type.keyword && prevType == tt.dot) + if (type.keyword && prevType === tt.dot) this.exprAllowed = false else if (update = type.updateContext) update.call(this, prevType) @@ -78,7 +78,7 @@ pp.updateContext = function(prevType) { // Token-specific context update code tt.parenR.updateContext = tt.braceR.updateContext = function() { - if (this.context.length == 1) { + if (this.context.length === 1) { this.exprAllowed = true return } @@ -111,6 +111,7 @@ tt.incDec.updateContext = function() { tt._function.updateContext = tt._class.updateContext = function(prevType) { if (prevType.beforeExpr && prevType !== tt.semi && prevType !== tt._else && + !(prevType === tt._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) && !((prevType === tt.colon || prevType === tt.braceL) && this.curContext() === types.b_stat)) this.context.push(types.f_expr) else @@ -127,7 +128,7 @@ tt.backQuote.updateContext = function() { } tt.star.updateContext = function(prevType) { - if (prevType == tt._function) { + if (prevType === tt._function) { let index = this.context.length - 1 if (this.context[index] === types.f_expr) this.context[index] = types.f_expr_gen @@ -139,9 +140,9 @@ tt.star.updateContext = function(prevType) { tt.name.updateContext = function(prevType) { let allowed = false - if (this.options.ecmaVersion >= 6) { - if (this.value == "of" && !this.exprAllowed || - this.value == "yield" && this.inGeneratorContext()) + if (this.options.ecmaVersion >= 6 && prevType !== tt.dot) { + if (this.value === "of" && !this.exprAllowed || + this.value === "yield" && this.inGeneratorContext()) allowed = true } this.exprAllowed = allowed diff --git a/tools/tests/apps/modules/imports/links/acorn/src/tokenize.js b/tools/tests/apps/modules/imports/links/acorn/src/tokenize.js index 3afb8386f2..835fdcd962 100644 --- a/tools/tests/apps/modules/imports/links/acorn/src/tokenize.js +++ b/tools/tests/apps/modules/imports/links/acorn/src/tokenize.js @@ -28,7 +28,9 @@ const pp = Parser.prototype // Move to the next token -pp.next = function() { +pp.next = function(ignoreEscapeSequenceInKeyword) { + if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc) + this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword) if (this.options.onToken) this.options.onToken(new Token(this)) @@ -219,7 +221,7 @@ pp.readToken_mult_modulo_exp = function(code) { // '%*' let tokentype = code === 42 ? tt.star : tt.modulo // exponentiation operator ** and **= - if (this.options.ecmaVersion >= 7 && code == 42 && next === 42) { + if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { ++size tokentype = tt.starstar next = this.input.charCodeAt(this.pos + 2) @@ -245,7 +247,7 @@ pp.readToken_caret = function() { // '^' pp.readToken_plus_min = function(code) { // '+-' let next = this.input.charCodeAt(this.pos + 1) if (next === code) { - if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 && + if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { // A `-->` line comment this.skipLineComment(3) @@ -266,8 +268,8 @@ pp.readToken_lt_gt = function(code) { // '<>' if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1) return this.finishOp(tt.bitShift, size) } - if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 && - this.input.charCodeAt(this.pos + 3) == 45) { + if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && + this.input.charCodeAt(this.pos + 3) === 45) { // `