From 643272e0d11a28bd56491719b75f95147bb66ac7 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sun, 17 Sep 2023 21:53:04 +0200 Subject: [PATCH] [v4.0] Switch parser to SWC and introduce native/WASM code (#5073) * Add native compilation for local NodeJS * Link instead of copying for faster dev cycles for now * Parse AST * Convert first trivial AST to a buffer * Use SWC for parsing * Extend AST conversion * Make AST more similar * Fix line number issue by creating a new sourcemap (and thus compiler) for each run * Collect timings * Add code_length to struct * Refine parsing * Extend parsing * Extend AST: ImportDefaultSpecifier, LiteralBoolean, LiteralNull, ExportDefaultExpression * Extend AST: ImportNamespaceSpecifier, ExportAll * Extend AST: BinaryExpression, ArrayPattern, ObjectPattern, AssignmentPatternProperty, ArrayLiteral, ImportExpression * Extend AST: ConditionalExpression * Extend AST: FunctionDeclaration, ClassDeclaration, ClassBody, ReturnStatement * Extend AST: ObjectLiteral, KeyValueProperty * Extend AST: ShorthandProperty * Extend AST: GetterProperty, AssignmentExpression, NewExpression, FunctionExpression * Extend AST: ThrowStatement * Extend AST: ExportDefaultDeclaration * Extend AST: AssignmentPattern, AwaitExpression, BreakStatement Start sorting AST nodes * Extend AST: TryStatement, CatchClause, ChainExpression * Extend AST: ClassExpression, ContinueStatement, DebuggerStatement, DoWhileStatement, EmptyStatement * Extend AST: ExportNamedDeclaration, ForInStatement, ForOfStatement, ForStatement * Extend AST: IfStatement * Extend AST: Import attributes * Extend AST: Literal, Literal * Extend AST: LogicalExpression * Extend AST: MetaProperty * Extend AST: Various Property types * Extend AST: Progress on classes * Extend AST: MethodDefinition, PropertyDefinition, PrivateName, ThisExpression * Extend AST: StaticBlock, Super * Extend AST: RestElement, SequenceExpression, SwitchCase, SwitchStatement * Extend AST: TaggedTemplateExpression, TemplateElement, TemplateLiteral, UnaryExpression, UpdateExpression, YieldExpression * Extend AST: Properties in object patterns * Finishing Fixes * More fixes * Run cargo fmt * Handle directives * Minor fixes * Unicode support * Fix optional chain expressions * Adapt tests * Do not run acorn anymore * Update lockfile * Minor fixes * Move to rust folder * Separate Rust Node bindings to allow adding WASM bindings in another workspace * Make Napi build closer to how rs.napi works * Fix path issues * Disable browser build for now * Add native package directories * Refine runWithEcho * Try initial steps with Github flow * Trigger change * Temporarily add yarn lockfile until we figured out if we get it to work with npm * Use nightly toolchain * Use default locations for Napi files to make things easier * Adapt workflow * Skip regular tests for now * Attempt to fix broken workflows * Attempt to fix broken workflows * Attempt to fix broken workflows * Test MacOS/WIndows * Fix bootstrap build * Skip tests * Rename workflow * Add additional tests * Use zig differently * Try to fix musl build * Skip musl again for now * Add publish to workflow * 4.0.0-0 * Remove yarn lock again * Fix coverage job * Fix artefact handling * Revert "4.0.0-0" This reverts commit 734806f0ae9a4cfa63e996c2d9be099b2a4580bf. * 4.0.0-0 * Do not include default triples twice * Fix native npm packages * 4.0.0-1 * Add missing additional tests except browser tests * Try to fix publish and tests * 4.0.0-2 * Switch to faster utf-16 conversion * 4.0.0-3 * Fix positioning algorithm when manually searching the code * 4.0.0-4 * feat: Add WASM browser build (#5077) * feat: add wasm browser build * move wasm binding into a separate cargo workspace * use imports replacing * set the targetEnv option of wasm to browser in browser build * add the wasm build to build command * fix lint error and ci error * add more comments to silence the linter * big change * trigger change * run browser tests * trigger change * tweak wasm build on CI * Increase build timeout * Use shared string constants * Extract fixed strings into constants * Remove comment * Get rid of dbg! calls * Add lockfile hash to cargo cache * Use if let over match in some cases * Return the buffer of the syntax error in parse_ast * Initial annotation support * Put annotation types into string table * Remove invalid annotations * Support nested calls and new expressions * Improve tree-shaking for annotations * Adapt test * Properly handle line-breaks, commas etc. * Mark nested pure annotations as pure * Remove sourcemap comments * Handle function side effect annotatinos * Remove old comment-handling code * Increase timeout for browser tests * Only skip the tests that still fail * Run coverage again on CI * Get the buffer of pos and message from the Syntax error * Handle the lint errors from SWC * Reenable tests about parse errors and adjust some relevant code * Emit native.js to native.cjs * Add cjs extension for native importee when bundling for ESM * Change native importee with replace plugin and emit native.cjs in napi build * Silence the linter for importing native * Use node:path to resolve native binding files * Add Node WASM files to Native packages for StackBlitz and similar use cases * Unignore *.d.ts in the wasm dir * 4.0.0-5 * Fix copy-wasm-node.js * 4.0.0-6 * Remove .gitignore in wasm-node directory * 4.0.0-7 * Include .cjs files when publishing rollup to npm * 4.0.0-8 * Get readString function at runtime * eslint: ignore wasm-node and set node extensions of import/resolver * 4.0.0-9 * Change the required node to >=14.18.0 as before * 4.0.0-10 * Prepare to fix ESM build Still requires bug-fix on Rollup side for relative external dependencies outside the ouput directory * Update Rollup * Enable ESM tests * Re-enable another test * Remove CJS eslint configuration * Fix extension * Fix test * Fix entension for native import * Support for publishing a completely separate package @rollup/wasm-node * 4.0.0-11 * Fix publish for wasm node package * Add AST verification to function tests * Only use plugin arrays in form and function tests * Fix spans in function tests * Verify AST in form tests as well * Try to publish @rollup/browser and fix publish-wasm-node-package.js * 4.0.0-12 * Tweak publish scripts * Fix importing wasm file in browser * Parse code as unknown module type for greater compatibility * Remove acorn options * Tweak getReadStringFunction * Fix browser tests * 4.0.0-13 * Remove polyfills that are no longer needed in browser tests * Convert to new import attributes AST format * Rename assertions to attributes * Deprecate externalImportAssertions in favor of externalImportAttributes * Update SWC version * Remove max-call-stack test SWC is not capable of handling it and we cannot fix it * Improve coverage * re-enable repl-artefacts workflow * Fix test * Preload wasm file in docs * docs: add functions to get full path of url * Delete the build plugin handleImportMetaUrl * Make 'npm install github/branch' work * Verify there is a valid changelog entry before releasing * Create release notes and comments from CI Minor change to maybe trigger a CI run * Fix RegExp * 4.0.0-14 * Minor changes for a test PR (#5139) * Fix RegExp use * 4.0.0-15 * Do not rely on current branch to find the PR * 4.0.0-16 * Fix how to determine git commit range * 4.0.0-17 * Make sure we fetch all history on publish * 4.0.0-18 * Add proper permissions * 4.0.0-19 * Use Double quotation marks instead of Single quotation marks if concurrently scripts with flags * Remove "engines" from native packages * Update CONTRIBUTING.md --------- Co-authored-by: XiaoPi <530257315@qq.com> --- .eslintrc.js | 6 +- .github/workflows/build-and-tests.yml | 348 +++ .github/workflows/tests.yml | 136 - .nycrc | 2 +- CONTRIBUTING.md | 8 +- LICENSE.md | 65 - browser/LICENSE.md | 65 - browser/package.json | 3 +- browser/src/initWasm.ts | 6 + browser/src/wasm.ts | 6 + build-plugins/aliases.ts | 1 - build-plugins/emit-native-entry.ts | 15 + build-plugins/emit-wasm-file.ts | 15 + build-plugins/external-native-import.ts | 17 + build-plugins/replace-browser-modules.ts | 29 +- cli/help.md | 2 +- docs/.vitepress/verify-anchors.ts | 2 +- docs/command-line-interface/index.md | 6 +- docs/configuration-options/index.md | 45 +- .../en/slugs-and-pages-by-legacy-slugs.json | 2 +- docs/javascript-api/index.md | 4 +- docs/plugin-development/index.md | 12 +- docs/repl/stores/options.ts | 6 +- docs/repl/stores/rollup.ts | 47 +- native.d.ts | 6 + native.js | 257 ++ npm/android-arm-eabi/README.md | 3 + npm/android-arm-eabi/package.json | 19 + npm/android-arm64/README.md | 3 + npm/android-arm64/package.json | 19 + npm/darwin-arm64/README.md | 3 + npm/darwin-arm64/package.json | 19 + npm/darwin-x64/README.md | 3 + npm/darwin-x64/package.json | 19 + npm/linux-arm-gnueabihf/README.md | 3 + npm/linux-arm-gnueabihf/package.json | 19 + npm/linux-arm64-gnu/README.md | 3 + npm/linux-arm64-gnu/package.json | 22 + npm/linux-arm64-musl/README.md | 3 + npm/linux-arm64-musl/package.json | 22 + npm/linux-x64-gnu/README.md | 3 + npm/linux-x64-gnu/package.json | 22 + npm/linux-x64-musl/README.md | 3 + npm/linux-x64-musl/package.json | 22 + npm/win32-arm64-msvc/README.md | 3 + npm/win32-arm64-msvc/package.json | 19 + npm/win32-ia32-msvc/README.md | 3 + npm/win32-ia32-msvc/package.json | 19 + npm/win32-x64-msvc/README.md | 3 + npm/win32-x64-msvc/package.json | 19 + package-lock.json | 642 ++-- package.json | 66 +- rollup.config.ts | 33 +- rust/Cargo.lock | 2452 +++++++++++++++ rust/Cargo.toml | 10 + rust/bindings_napi/Cargo.toml | 18 + rust/bindings_napi/build.rs | 5 + rust/bindings_napi/src/lib.rs | 10 + rust/bindings_wasm/Cargo.toml | 11 + rust/bindings_wasm/src/lib.rs | 7 + rust/parse_ast/Cargo.toml | 18 + rust/parse_ast/src/convert_ast.rs | 2 + rust/parse_ast/src/convert_ast/annotations.rs | 129 + rust/parse_ast/src/convert_ast/converter.rs | 2762 +++++++++++++++++ .../src/convert_ast/converter/analyze_code.rs | 40 + .../src/convert_ast/converter/node_types.rs | 78 + .../convert_ast/converter/string_constants.rs | 62 + .../convert_ast/converter/utf16_positions.rs | 142 + rust/parse_ast/src/error_emit.rs | 129 + rust/parse_ast/src/lib.rs | 69 + rust/rustfmt.toml | 2 + scripts/check-release.js | 1 + scripts/colors.js | 2 +- scripts/helpers.js | 31 +- scripts/postpublish.js | 91 + scripts/{release.js => prepare-release.js} | 202 +- scripts/prepublish.js | 65 + scripts/publish-wasm-node-package.js | 54 + scripts/release-constants.js | 6 + scripts/release-helpers.js | 111 + scripts/test-options.js | 9 +- src/Bundle.ts | 4 +- src/Chunk.ts | 16 +- src/ExternalChunk.ts | 18 +- src/ExternalModule.ts | 4 +- src/Graph.ts | 40 +- src/Module.ts | 38 +- src/ModuleLoader.ts | 79 +- src/ast/keys.ts | 3 - src/ast/nodes/BinaryExpression.ts | 4 + src/ast/nodes/ChainExpression.ts | 5 + src/ast/nodes/ConditionalExpression.ts | 7 +- src/ast/nodes/ExportAllDeclaration.ts | 2 +- src/ast/nodes/ExportDefaultDeclaration.ts | 4 + src/ast/nodes/ExportNamedDeclaration.ts | 6 +- src/ast/nodes/ExpressionStatement.ts | 8 +- src/ast/nodes/Identifier.ts | 11 - src/ast/nodes/ImportDeclaration.ts | 4 +- src/ast/nodes/ImportExpression.ts | 21 +- src/ast/nodes/LogicalExpression.ts | 7 +- src/ast/nodes/SequenceExpression.ts | 4 + src/ast/nodes/VariableDeclaration.ts | 4 + src/ast/nodes/VariableDeclarator.ts | 4 + src/ast/nodes/shared/Node.ts | 37 +- src/finalisers/es.ts | 4 +- src/rollup/rollup.ts | 3 + src/rollup/types.d.ts | 32 +- src/utils/PluginContext.ts | 4 +- src/utils/commentAnnotations.ts | 212 -- src/utils/convert-ast-strings.ts | 62 + src/utils/convert-ast.ts | 1235 ++++++++ src/utils/getReadStringFunction.ts | 14 + src/utils/initWasm.ts | 1 + src/utils/logs.ts | 55 +- src/utils/options/mergeOptions.ts | 6 +- src/utils/options/normalizeInputOptions.ts | 17 - src/utils/options/normalizeOutputOptions.ts | 20 +- ...Assertions.ts => parseImportAttributes.ts} | 45 +- src/utils/resolveId.ts | 4 +- src/utils/resolveIdViaPlugins.ts | 8 +- src/utils/treeshakeNode.ts | 22 +- src/utils/urls.ts | 2 + test/browser/index.js | 9 +- .../_config.js | 30 +- .../implicitly-dependent-entry/_config.js | 30 +- .../multiple-dependencies/_config.js | 103 +- .../single-dependency/_config.js | 30 +- test/cli/samples/validate/_config.js | 2 +- .../cli/samples/watch/bundle-error/_config.js | 2 +- test/form/index.js | 17 +- test/form/samples/absolute-path-resolver/a.js | 2 +- .../samples/acorn-external-plugins/_config.js | 8 - .../acorn-external-plugins/_expected.js | 3 - .../samples/acorn-external-plugins/main.js | 1 - test/form/samples/big-int/_config.js | 2 +- .../_config.js | 12 +- .../removes-dynamic-assertions/_config.js | 3 +- .../removes-dynamic-assertions/_expected.js | 0 .../removes-dynamic-assertions}/main.js | 0 .../removes-static-attributes}/_config.js | 3 +- .../removes-static-attributes}/_expected.js | 0 .../removes-static-attributes}/main.js | 0 test/form/samples/emit-asset-file/_config.js | 66 +- .../emit-file-tree-shaken-access/_config.js | 32 +- .../emit-uint8array-no-buffer/_config.js | 30 +- .../_config.js | 12 +- test/form/samples/export-globals/_config.js | 3 - .../_expected.js | 2 +- .../assertion-shapes/_config.js | 6 - .../attribute-shapes/_config.js | 7 + .../attribute-shapes}/_expected.js | 0 .../attribute-shapes}/main.js | 0 .../keep-dynamic-attributes}/_config.js | 2 +- .../keep-dynamic-attributes}/_expected/amd.js | 0 .../keep-dynamic-attributes}/_expected/cjs.js | 0 .../keep-dynamic-attributes}/_expected/es.js | 0 .../_expected/iife.js | 0 .../_expected/system.js | 0 .../keep-dynamic-attributes}/_expected/umd.js | 0 .../keep-dynamic-attributes}/main.js | 0 .../keeps-static-attributes}/_config.js | 2 +- .../keeps-static-attributes}/_expected/amd.js | 0 .../keeps-static-attributes}/_expected/cjs.js | 0 .../keeps-static-attributes}/_expected/es.js | 0 .../_expected/iife.js | 0 .../_expected/system.js | 0 .../keeps-static-attributes}/_expected/umd.js | 0 .../keeps-static-attributes}/main.js | 0 .../_config.js | 6 +- .../_expected.js | 0 .../main.js | 0 .../plugin-attributes-resolveid}/_config.js | 6 +- .../plugin-attributes-resolveid}/_expected.js | 0 .../plugin-attributes-resolveid}/main.js | 0 .../removes-dynamic-attributes/_config.js | 29 + .../removes-dynamic-attributes/_expected.js | 6 + .../removes-dynamic-attributes/main.js | 6 + .../removes-static-attributes/_config.js | 11 + .../removes-static-attributes/_expected.js | 7 + .../removes-static-attributes/main.js | 9 + .../_config.js | 3 - .../make-relative-false/_config.js | 52 +- .../make-relative-relative/_config.js | 58 +- .../make-relative-true/_config.js | 62 +- .../samples/module-no-treeshake/_config.js | 50 +- .../form/samples/nested-pure-comments/main.js | 2 + .../_config.js | 2 - .../_expected.js | 21 +- .../functions.js | 21 +- .../_config.js | 2 - .../functions.js | 16 +- .../ns-external-star-reexport/_config.js | 20 +- .../pure-comment-line-break/_expected.js | 48 +- .../samples/pure-comment-line-break/dep.js | 2 +- .../samples/pure-comment-line-break/main.js | 51 +- .../_expected.js | 12 +- .../samples/relative-external-ids/_config.js | 38 +- test/form/samples/resolution-order/_config.js | 12 +- .../side-effects-internal-modules/_config.js | 24 +- test/form/samples/supports-core-js/_config.js | 1 + .../samples/system-uninitialized/_config.js | 3 - .../_expected.js | 18 +- .../samples/unknown-token-effects/_config.js | 17 - .../unknown-token-effects/_expected.js | 34 - .../samples/unknown-token-effects/main.js | 32 - test/function/index.js | 18 +- .../add-watch-file-generate/_config.js | 12 +- .../samples/allow-reserved/_config.js | 8 - test/function/samples/allow-reserved/main.js | 4 - .../samples/bundle-facade-order/_config.js | 28 +- .../_config.js | 6 +- .../_config.js | 12 +- .../_config.js | 14 +- .../samples/context-resolve/_config.js | 18 +- .../dynamic-import-name-warn/_config.js | 10 +- .../deprecated/dynamic-import-name/_config.js | 10 +- .../inline-dynamic-imports-bundle/_config.js | 16 +- .../deprecated/manual-chunks-info/_config.js | 18 +- .../deprecated/plugin-module-ids/_config.js | 20 +- .../deprecated/resolve-id-external/_config.js | 80 +- .../samples/deprecated/resolve-id/_config.js | 100 +- .../externalImportAssertions/_config.js | 12 + .../externalImportAssertions/_expected.js | 6 + .../externalImportAssertions/main.js | 6 + .../deprecations/plugin-module-ids/_config.js | 12 +- .../samples/double-default-export/_config.js | 17 +- .../samples/double-named-export/_config.js | 11 +- .../samples/double-named-reexport/_config.js | 11 +- .../samples/duplicate-import-fails/_config.js | 11 +- .../_config.js | 11 +- .../samples/emit-chunk-hash/_config.js | 16 +- .../emit-chunk-manual-asset-source/_config.js | 28 +- .../samples/emit-chunk-manual/_config.js | 18 +- .../emit-file/asset-source-invalid/_config.js | 14 +- .../asset-source-invalid2/_config.js | 14 +- .../asset-source-invalid3/_config.js | 14 +- .../asset-source-invalid4/_config.js | 12 +- .../emit-file/asset-source-missing/_config.js | 12 +- .../asset-source-missing2/_config.js | 12 +- .../asset-source-missing3/_config.js | 14 +- .../asset-source-missing4/_config.js | 14 +- .../asset-source-missing5/_config.js | 18 +- .../_config.js | 18 +- .../_config.js | 18 +- .../chunk-filename-not-available/_config.js | 14 +- .../emit-file/chunk-not-found/_config.js | 10 +- .../emit-from-output-options/_config.js | 16 +- .../file-references-in-bundle/_config.js | 44 +- .../emit-file/invalid-asset-name/_config.js | 12 +- .../emit-file/invalid-asset-name3/_config.js | 12 +- .../emit-file/invalid-chunk-id/_config.js | 12 +- .../emit-file/invalid-file-type/_config.js | 12 +- .../_config.js | 18 +- .../invalid-prebuit-chunk-code/_config.js | 18 +- .../emit-file/invalid-reference-id/_config.js | 12 +- .../invalid-set-asset-source-id/_config.js | 12 +- .../emit-file/modules-loaded/_config.js | 12 +- .../samples/emit-file/no-input/_config.js | 12 +- .../set-asset-source-chunk/_config.js | 14 +- .../set-asset-source-transform/_config.js | 16 +- .../set-asset-source-twice/_config.js | 16 +- .../set-asset-source-twice2/_config.js | 16 +- .../set-source-in-output-options/_config.js | 16 +- .../samples/error-parse-json/_config.js | 10 +- .../error-parse-unknown-extension/_config.js | 10 +- .../function/samples/export-global/_config.js | 7 +- test/function/samples/export-global/main.js | 2 +- .../export-not-at-top-level-fails/_config.js | 9 +- .../external-entry-point-object/_config.js | 10 +- .../samples/external-entry-point/_config.js | 10 +- .../samples/external-resolved/_config.js | 40 +- .../samples/function-asm-directive/main.js | 2 +- .../function-directive-not-first/main.js | 2 +- .../handle-missing-export-source/_config.js | 17 +- .../_config.js | 20 +- .../_config.js | 30 +- .../dependant-not-part-of-graph/_config.js | 40 +- .../external-dependant/_config.js | 20 +- .../missing-dependant/_config.js | 28 +- .../plugin-assertions-this-resolve/_config.js | 14 +- .../warn-assertion-conflicts/_config.js | 22 +- .../warn-unresolvable-assertions/_config.js | 141 + .../warn-unresolvable-assertions/main.js | 8 + .../import-not-at-top-level-fails/_config.js | 9 +- .../inline-dynamic-imports-bundle/_config.js | 16 +- .../_config.js | 20 +- .../samples/invalid-addon-hook/_config.js | 4 +- .../samples/manual-chunks-info/_config.js | 18 +- .../samples/module-parsed-hook/_config.js | 236 +- .../module-side-effects/array/_config.js | 30 +- .../external-false/_config.js | 40 +- .../global-false/_config.js | 30 +- .../module-side-effects/load/_config.js | 32 +- .../resolve-id-external/_config.js | 82 +- .../module-side-effects/resolve-id/_config.js | 102 +- .../non-function-hook-async/_config.js | 4 +- .../samples/non-function-hook-sync/_config.js | 8 +- .../samples/optional-catch-binding/_config.js | 2 +- .../samples/options-async-hook/_config.js | 1 + test/function/samples/options-hook/_config.js | 86 +- .../samples/options-in-renderstart/_config.js | 24 +- .../samples/output-options-hook/_config.js | 127 +- .../plugin-cache/anonymous-delete/_config.js | 10 +- .../plugin-cache/anonymous-get/_config.js | 10 +- .../plugin-cache/anonymous-has/_config.js | 10 +- .../plugin-cache/anonymous-set/_config.js | 10 +- .../_config.js | 2 +- .../plugin-module-information/_config.js | 797 ++--- .../_config.js | 24 - .../main.js | 4 - .../samples/preload-module/_config.js | 4 +- .../samples/preserve-symlink/_config.js | 2 +- .../samples/reassign-import-fails/_config.js | 11 +- .../samples/reassign-import-fails/foo.js | 1 - .../_config.js | 11 +- .../foo.js | 1 - .../samples/resolve-id-object/_config.js | 28 +- .../resolve-relative-external-id/_config.js | 40 +- .../_config.js | 10 +- test/function/samples/symlink/_config.js | 2 +- .../_config.js | 12 +- .../samples/transform-empty-string/_config.js | 14 +- .../_config.js | 12 +- .../_config.js | 12 +- .../samples/transform-without-code/_config.js | 48 +- .../_config.js | 11 +- .../update-expression-of-import-fails/foo.js | 1 - .../samples/uses-supplied-ast/_config.js | 1 + .../samples/validate-output/_config.js | 5 +- .../_config.js | 23 +- .../samples/warnings-to-string/_config.js | 12 +- test/incremental/index.js | 31 +- test/misc/acorn-plugins.js | 45 - test/misc/index.js | 1 - test/misc/misc.js | 28 - test/misc/optionList.js | 6 +- test/utils.js | 56 + test/watch/index.js | 8 +- tsconfig.json | 2 +- wasm.d.ts | 6 + wasm/bindings_wasm.d.ts | 47 + wasm/bindings_wasm_bg.wasm.d.ts | 10 + 342 files changed, 11987 insertions(+), 3503 deletions(-) create mode 100644 .github/workflows/build-and-tests.yml delete mode 100644 .github/workflows/tests.yml create mode 100644 browser/src/initWasm.ts create mode 100644 browser/src/wasm.ts create mode 100644 build-plugins/emit-native-entry.ts create mode 100644 build-plugins/emit-wasm-file.ts create mode 100644 build-plugins/external-native-import.ts create mode 100644 native.d.ts create mode 100644 native.js create mode 100644 npm/android-arm-eabi/README.md create mode 100644 npm/android-arm-eabi/package.json create mode 100644 npm/android-arm64/README.md create mode 100644 npm/android-arm64/package.json create mode 100644 npm/darwin-arm64/README.md create mode 100644 npm/darwin-arm64/package.json create mode 100644 npm/darwin-x64/README.md create mode 100644 npm/darwin-x64/package.json create mode 100644 npm/linux-arm-gnueabihf/README.md create mode 100644 npm/linux-arm-gnueabihf/package.json create mode 100644 npm/linux-arm64-gnu/README.md create mode 100644 npm/linux-arm64-gnu/package.json create mode 100644 npm/linux-arm64-musl/README.md create mode 100644 npm/linux-arm64-musl/package.json create mode 100644 npm/linux-x64-gnu/README.md create mode 100644 npm/linux-x64-gnu/package.json create mode 100644 npm/linux-x64-musl/README.md create mode 100644 npm/linux-x64-musl/package.json create mode 100644 npm/win32-arm64-msvc/README.md create mode 100644 npm/win32-arm64-msvc/package.json create mode 100644 npm/win32-ia32-msvc/README.md create mode 100644 npm/win32-ia32-msvc/package.json create mode 100644 npm/win32-x64-msvc/README.md create mode 100644 npm/win32-x64-msvc/package.json create mode 100644 rust/Cargo.lock create mode 100644 rust/Cargo.toml create mode 100644 rust/bindings_napi/Cargo.toml create mode 100644 rust/bindings_napi/build.rs create mode 100644 rust/bindings_napi/src/lib.rs create mode 100644 rust/bindings_wasm/Cargo.toml create mode 100644 rust/bindings_wasm/src/lib.rs create mode 100644 rust/parse_ast/Cargo.toml create mode 100644 rust/parse_ast/src/convert_ast.rs create mode 100644 rust/parse_ast/src/convert_ast/annotations.rs create mode 100644 rust/parse_ast/src/convert_ast/converter.rs create mode 100644 rust/parse_ast/src/convert_ast/converter/analyze_code.rs create mode 100644 rust/parse_ast/src/convert_ast/converter/node_types.rs create mode 100644 rust/parse_ast/src/convert_ast/converter/string_constants.rs create mode 100644 rust/parse_ast/src/convert_ast/converter/utf16_positions.rs create mode 100644 rust/parse_ast/src/error_emit.rs create mode 100644 rust/parse_ast/src/lib.rs create mode 100644 rust/rustfmt.toml create mode 100644 scripts/postpublish.js rename scripts/{release.js => prepare-release.js} (53%) create mode 100755 scripts/prepublish.js create mode 100644 scripts/publish-wasm-node-package.js create mode 100644 scripts/release-constants.js create mode 100644 scripts/release-helpers.js delete mode 100644 src/utils/commentAnnotations.ts create mode 100644 src/utils/convert-ast-strings.ts create mode 100644 src/utils/convert-ast.ts create mode 100644 src/utils/getReadStringFunction.ts create mode 100644 src/utils/initWasm.ts rename src/utils/{parseAssertions.ts => parseImportAttributes.ts} (51%) delete mode 100644 test/form/samples/acorn-external-plugins/_config.js delete mode 100644 test/form/samples/acorn-external-plugins/_expected.js delete mode 100644 test/form/samples/acorn-external-plugins/main.js rename test/form/samples/{import-assertions => deprecated}/removes-dynamic-assertions/_config.js (88%) rename test/form/samples/{import-assertions => deprecated}/removes-dynamic-assertions/_expected.js (100%) rename test/form/samples/{import-assertions/keep-dynamic-assertions => deprecated/removes-dynamic-assertions}/main.js (100%) rename test/form/samples/{import-assertions/removes-static-assertions => deprecated/removes-static-attributes}/_config.js (72%) rename test/form/samples/{import-assertions/removes-static-assertions => deprecated/removes-static-attributes}/_expected.js (100%) rename test/form/samples/{import-assertions/keeps-static-assertions => deprecated/removes-static-attributes}/main.js (100%) delete mode 100644 test/form/samples/import-assertions/assertion-shapes/_config.js create mode 100644 test/form/samples/import-attributes/attribute-shapes/_config.js rename test/form/samples/{import-assertions/assertion-shapes => import-attributes/attribute-shapes}/_expected.js (100%) rename test/form/samples/{import-assertions/assertion-shapes => import-attributes/attribute-shapes}/main.js (100%) rename test/form/samples/{import-assertions/keep-dynamic-assertions => import-attributes/keep-dynamic-attributes}/_config.js (91%) rename test/form/samples/{import-assertions/keep-dynamic-assertions => import-attributes/keep-dynamic-attributes}/_expected/amd.js (100%) rename test/form/samples/{import-assertions/keep-dynamic-assertions => import-attributes/keep-dynamic-attributes}/_expected/cjs.js (100%) rename test/form/samples/{import-assertions/keep-dynamic-assertions => import-attributes/keep-dynamic-attributes}/_expected/es.js (100%) rename test/form/samples/{import-assertions/keep-dynamic-assertions => import-attributes/keep-dynamic-attributes}/_expected/iife.js (100%) rename test/form/samples/{import-assertions/keep-dynamic-assertions => import-attributes/keep-dynamic-attributes}/_expected/system.js (100%) rename test/form/samples/{import-assertions/keep-dynamic-assertions => import-attributes/keep-dynamic-attributes}/_expected/umd.js (100%) rename test/form/samples/{import-assertions/removes-dynamic-assertions => import-attributes/keep-dynamic-attributes}/main.js (100%) rename test/form/samples/{import-assertions/keeps-static-assertions => import-attributes/keeps-static-attributes}/_config.js (78%) rename test/form/samples/{import-assertions/keeps-static-assertions => import-attributes/keeps-static-attributes}/_expected/amd.js (100%) rename test/form/samples/{import-assertions/keeps-static-assertions => import-attributes/keeps-static-attributes}/_expected/cjs.js (100%) rename test/form/samples/{import-assertions/keeps-static-assertions => import-attributes/keeps-static-attributes}/_expected/es.js (100%) rename test/form/samples/{import-assertions/keeps-static-assertions => import-attributes/keeps-static-attributes}/_expected/iife.js (100%) rename test/form/samples/{import-assertions/keeps-static-assertions => import-attributes/keeps-static-attributes}/_expected/system.js (100%) rename test/form/samples/{import-assertions/keeps-static-assertions => import-attributes/keeps-static-attributes}/_expected/umd.js (100%) rename test/form/samples/{import-assertions/removes-static-assertions => import-attributes/keeps-static-attributes}/main.js (100%) rename test/form/samples/{import-assertions/plugin-assertions-resolvedynamicimport => import-attributes/plugin-attributes-resolvedynamicimport}/_config.js (71%) rename test/form/samples/{import-assertions/plugin-assertions-resolvedynamicimport => import-attributes/plugin-attributes-resolvedynamicimport}/_expected.js (100%) rename test/form/samples/{import-assertions/plugin-assertions-resolvedynamicimport => import-attributes/plugin-attributes-resolvedynamicimport}/main.js (100%) rename test/form/samples/{import-assertions/plugin-assertions-resolveid => import-attributes/plugin-attributes-resolveid}/_config.js (56%) rename test/form/samples/{import-assertions/plugin-assertions-resolveid => import-attributes/plugin-attributes-resolveid}/_expected.js (100%) rename test/form/samples/{import-assertions/plugin-assertions-resolveid => import-attributes/plugin-attributes-resolveid}/main.js (100%) create mode 100644 test/form/samples/import-attributes/removes-dynamic-attributes/_config.js create mode 100644 test/form/samples/import-attributes/removes-dynamic-attributes/_expected.js create mode 100644 test/form/samples/import-attributes/removes-dynamic-attributes/main.js create mode 100644 test/form/samples/import-attributes/removes-static-attributes/_config.js create mode 100644 test/form/samples/import-attributes/removes-static-attributes/_expected.js create mode 100644 test/form/samples/import-attributes/removes-static-attributes/main.js delete mode 100644 test/form/samples/unknown-token-effects/_config.js delete mode 100644 test/form/samples/unknown-token-effects/_expected.js delete mode 100644 test/form/samples/unknown-token-effects/main.js delete mode 100644 test/function/samples/allow-reserved/_config.js delete mode 100644 test/function/samples/allow-reserved/main.js create mode 100644 test/function/samples/deprecations/externalImportAssertions/_config.js create mode 100644 test/function/samples/deprecations/externalImportAssertions/_expected.js create mode 100644 test/function/samples/deprecations/externalImportAssertions/main.js create mode 100644 test/function/samples/import-assertions/warn-unresolvable-assertions/_config.js create mode 100644 test/function/samples/import-assertions/warn-unresolvable-assertions/main.js delete mode 100644 test/function/samples/plugin-parse-ast-receives-comments/_config.js delete mode 100644 test/function/samples/plugin-parse-ast-receives-comments/main.js delete mode 100644 test/function/samples/reassign-import-fails/foo.js delete mode 100644 test/function/samples/reassign-import-not-at-top-level-fails/foo.js delete mode 100644 test/function/samples/update-expression-of-import-fails/foo.js delete mode 100644 test/misc/acorn-plugins.js create mode 100644 wasm.d.ts create mode 100644 wasm/bindings_wasm.d.ts create mode 100644 wasm/bindings_wasm_bg.wasm.d.ts diff --git a/.eslintrc.js b/.eslintrc.js index c69d2b749..ca86abc8d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,11 +21,13 @@ module.exports = { 'coverage', '_tmp', 'cache', - 'wasm', + 'native*.*', '/test/*/samples/**/*.*', '!/test/*/samples/**/_config.js', '!/test/*/samples/**/rollup.config.js', - '!.vitepress' + '!.vitepress', + '/wasm/', + '/wasm-node/' ], overrides: [ { diff --git a/.github/workflows/build-and-tests.yml b/.github/workflows/build-and-tests.yml new file mode 100644 index 000000000..bdef57256 --- /dev/null +++ b/.github/workflows/build-and-tests.yml @@ -0,0 +1,348 @@ +name: CI +env: + DEBUG: napi:* + APP_NAME: rollup + MACOSX_DEPLOYMENT_TARGET: '10.13' + +on: + push: + branches: + - master + tags: + - 'v*.*.**' + pull_request: + types: + - synchronize + - opened + - reopened + merge_group: + +permissions: + contents: read + +jobs: + lint: + name: Lint and Audit + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout Commit + uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 20 + - name: Cache Node Modules + id: cache-node-modules + uses: actions/cache@v3 + with: + path: node_modules + key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} + - name: Install dependencies + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: npm ci --ignore-scripts + - name: Lint + run: npm run ci:lint + - name: Vulnerabilities + run: npm audit + - name: Optional Dependencies + run: npm run test:package + - name: CLI Docs + run: npm run test:options + + build: + strategy: + fail-fast: false + matrix: + settings: + - host: windows-latest + target: x86_64-pc-windows-msvc + name: wasm + is-wasm-build: true + build: npm run build:wasm + path: | + wasm/ + .empty + - host: windows-latest + target: x86_64-pc-windows-msvc + name: wasm-node + is-wasm-build: true + build: npm run build:wasm:node + path: | + wasm-node/ + .empty + - host: macos-latest + target: x86_64-apple-darwin + build: | + npm run build:napi -- --release + strip -x *.node + - host: windows-latest + build: npm run build:napi -- --release + target: x86_64-pc-windows-msvc + - host: windows-latest + build: | + npm run build:napi -- --release --target i686-pc-windows-msvc + target: i686-pc-windows-msvc + - host: ubuntu-latest + target: x86_64-unknown-linux-gnu + docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian + build: |- + set -e && + rustup default nightly && + npm run build:napi -- --release --target x86_64-unknown-linux-gnu && + strip *.node + - host: ubuntu-latest + target: x86_64-unknown-linux-musl + docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine + build: |- + set -e && + rustup default nightly && + npm run build:napi -- --release && strip *.node + - host: macos-latest + target: aarch64-apple-darwin + build: | + npm run build:napi -- --release --target aarch64-apple-darwin + strip -x *.node + - host: ubuntu-latest + target: aarch64-unknown-linux-gnu + docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64 + build: |- + set -e && + rustup default nightly && + rustup target add aarch64-unknown-linux-gnu && + npm run build:napi -- --release --target aarch64-unknown-linux-gnu && + aarch64-unknown-linux-gnu-strip *.node + - host: ubuntu-latest + target: armv7-unknown-linux-gnueabihf + zig: true + setup: | + sudo apt-get update + sudo apt-get install gcc-arm-linux-gnueabihf -y + build: | + npm run build:napi -- --release --target armv7-unknown-linux-gnueabihf + arm-linux-gnueabihf-strip *.node + - host: ubuntu-latest + target: aarch64-linux-android + build: | + npm run build:napi -- --release --target aarch64-linux-android + ${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip *.node + - host: ubuntu-latest + target: armv7-linux-androideabi + build: | + npm run build:napi -- --release --target armv7-linux-androideabi + ${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip *.node + # TODO SWC this does not work yet, also add back in package.json + # - host: ubuntu-latest + # target: aarch64-unknown-linux-musl + # docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine + # build: |- + # set -e && + # rustup default nightly && + # rustup target add aarch64-unknown-linux-musl && + # npm run build:napi -- --release --target aarch64-unknown-linux-musl && + # /aarch64-linux-musl-cross/bin/aarch64-linux-musl-strip *.node + - host: windows-latest + target: aarch64-pc-windows-msvc + build: npm run build:napi -- --release --target aarch64-pc-windows-msvc + name: Build ${{ matrix.settings.name || matrix.settings.target }} + runs-on: ${{ matrix.settings.host }} + timeout-minutes: 30 + steps: + - name: Checkout Commit + uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@v3 + if: ${{ !matrix.settings.docker }} + with: + node-version: 20 + - name: Install Toolchain + uses: dtolnay/rust-toolchain@stable + if: ${{ !matrix.settings.docker }} + with: + toolchain: nightly + targets: ${{ matrix.settings.target }} + - name: Cache cargo + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + .cargo-cache + rust/target/ + key: ${{ matrix.settings.name || matrix.settings.target }}-cargo-${{ matrix.settings.host }}-${{ hashFiles('rust/Cargo.lock') }} + restore-keys: ${{ matrix.settings.name || matrix.settings.target }}-cargo-${{ matrix.settings.host }} + - uses: goto-bus-stop/setup-zig@v2 + if: ${{ matrix.settings.zig }} + with: + version: 0.10.1 + - name: Setup toolchain + run: ${{ matrix.settings.setup }} + if: ${{ matrix.settings.setup }} + shell: bash + - name: Cache Node Modules + id: cache-node-modules + uses: actions/cache@v3 + with: + path: node_modules + key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} + - name: Install dependencies + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: npm ci --ignore-scripts + - name: Build in docker + uses: addnab/docker-run-action@v3 + if: ${{ matrix.settings.docker }} + with: + image: ${{ matrix.settings.docker }} + options: '--user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build' + run: ${{ matrix.settings.build }} + - name: Build + run: ${{ matrix.settings.build }} + if: ${{ !matrix.settings.docker }} + shell: bash + - name: Upload wasm artifact + uses: actions/upload-artifact@v3 + with: + name: bindings-${{ matrix.settings.name }} + path: ${{ matrix.settings.path }} + if-no-files-found: error + if: ${{ matrix.settings.is-wasm-build }} + - name: Upload napi artifact + uses: actions/upload-artifact@v3 + with: + name: bindings-${{ matrix.settings.target }} + path: ${{ env.APP_NAME }}.*.node + if-no-files-found: error + if: ${{ !matrix.settings.is-wasm-build }} + + test: + name: Test${{ matrix.additionalName || '' }} Node ${{ matrix.node }} (${{ matrix.settings.target }}) + needs: + - build + strategy: + fail-fast: false + matrix: + settings: + - host: ubuntu-latest + target: x86_64-unknown-linux-gnu + - host: windows-latest + target: x86_64-pc-windows-msvc + - host: macos-latest + target: x86_64-apple-darwin + node: + - '18.0.0' + - '20' + include: + - settings: + host: ubuntu-latest + target: x86_64-unknown-linux-gnu + node: '20' + command: 'ci:coverage' + additionalName: ' with Coverage' + coverage: true + - settings: + host: ubuntu-latest + target: x86_64-unknown-linux-gnu + node: '18.0.0' + command: 'ci:test:all' + additionalName: ' with Additional Tests' + runs-on: ${{ matrix.settings.host }} + timeout-minutes: 15 + steps: + - name: Checkout Commit + uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node }} + check-latest: true + - name: Cache Node Modules + id: cache-node-modules + uses: actions/cache@v3 + with: + path: node_modules + key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} + - name: Install dependencies + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: npm ci --ignore-scripts + - name: Download napi artifacts + uses: actions/download-artifact@v3 + with: + name: bindings-${{ matrix.settings.target }} + path: . + - name: Download wasm artifacts + uses: actions/download-artifact@v3 + with: + name: bindings-wasm + - name: Build and test Rollup + run: npm run ${{ matrix.command || 'ci:test:only' }} + env: + CI: true + - name: Upload coverage + uses: codecov/codecov-action@v3 + if: matrix.coverage + with: +# It appears adding the token may result in the coverage comment not being added +# token: ${{ secrets.CODECOV_TOKEN }} + commit_parent: ${{ github.event.pull_request.head.sha }} + + publish: + permissions: + pull-requests: write # for writing comments + name: Publish + runs-on: ubuntu-latest + timeout-minutes: 15 + needs: + - test + - lint + # TODO SWC once v4 is live, this should be changed + if: startsWith(github.ref_name, 'v4') + steps: + - name: Checkout Commit + uses: actions/checkout@v4 + with: + # Necessary to find the commits included in the release + fetch-depth: 0 + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node }} + check-latest: true + - name: Cache Node Modules + id: cache-node-modules + uses: actions/cache@v3 + with: + path: node_modules + key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} + - name: Install dependencies + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: npm ci --ignore-scripts + - name: Download all artifacts + uses: actions/download-artifact@v3 + with: + path: artifacts + - name: Copy wasm files + run: cp -R artifacts/bindings-wasm/wasm . + - name: Build JavaScript + run: npm run build:cjs && cp artifacts/*/*.node dist/ && npm run build:bootstrap + - name: Move artifacts + run: npm run ci:artifacts + - name: Publish + run: | + if git --no-pager log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+$"; + then + echo "Publishing regular release" + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc + npm publish --access public + elif git --no-pager log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+-[0-9]\+$"; + then + echo "Publishing beta release" + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc + npm publish --tag beta --access public + else + echo "Not a release, skipping publish" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + ROLLUP_RELEASE: 'releasing' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index c776458a8..000000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,136 +0,0 @@ -name: Tests - -on: - push: - branches: - - master - pull_request: - types: [synchronize, opened, reopened] - merge_group: - -permissions: - contents: read - -jobs: - linux18: - runs-on: ubuntu-latest - timeout-minutes: 15 - name: Node 18 + Coverage (Linux) - steps: - - name: Checkout Commit - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: '18' - - name: Cache Node Modules - id: cache-node-modules - uses: actions/cache@v3 - with: - path: node_modules - key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} - - name: Install dependencies - if: steps.cache-node-modules.outputs.cache-hit != 'true' - run: npm ci --ignore-scripts - - name: Run tests with coverage - run: npm run ci:coverage - env: - CI: true - - uses: codecov/codecov-action@v3 - with: -# It appears that with the token, the comment is not created -# token: ${{ secrets.CODECOV_TOKEN }} - commit_parent: ${{ github.event.pull_request.head.sha }} - - linux16: - runs-on: ubuntu-latest - timeout-minutes: 15 - name: Node 18 + Extra Tests (Linux) - steps: - - name: Checkout Commit - uses: actions/checkout@v4 - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: '18' - - name: Cache Node Modules - id: cache-node-modules - uses: actions/cache@v3 - with: - path: node_modules - key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} - - name: Install dependencies - if: steps.cache-node-modules.outputs.cache-hit != 'true' - run: npm ci --ignore-scripts - - name: Lint - run: npm run ci:lint - - name: Vulnerabilities - run: npm audit - - name: Run all tests - run: npm run ci:test - env: - CI: true - - macos: - runs-on: macos-latest - timeout-minutes: 15 - strategy: - matrix: - node: ['18'] - name: Node ${{ matrix.node }} (macOS) - steps: - - name: Checkout Commit - uses: actions/checkout@v4 - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - - name: Cache Node Modules - id: cache-node-modules - uses: actions/cache@v3 - with: - path: node_modules - key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} - - name: Update npm - if: (matrix.node == '14.18.0') && (steps.cache-node-modules.outputs.cache-hit != 'true') - run: npm i -g npm@8 - - name: Install dependencies - if: steps.cache-node-modules.outputs.cache-hit != 'true' - run: npm ci --ignore-scripts - - name: Run tests - run: npm run ci:test:only - env: - CI: true - - windows: - runs-on: windows-latest - timeout-minutes: 15 - strategy: - matrix: - node: ['18'] - name: Node ${{ matrix.node }} (Windows) - steps: - - name: Checkout Commit - uses: actions/checkout@v4 - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - - name: Cache Node Modules - id: cache-node-modules - uses: actions/cache@v3 - with: - path: node_modules - key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} - - name: Update npm - if: (matrix.node == '14.18.0') && (steps.cache-node-modules.outputs.cache-hit != 'true') - run: npm i -g npm@8 - - name: Install dependencies - if: steps.cache-node-modules.outputs.cache-hit != 'true' - run: npm ci --ignore-scripts - - name: Run tests - run: npm run ci:test:only - env: - CI: true diff --git a/.nycrc b/.nycrc index af7db356d..9f64cae9e 100644 --- a/.nycrc +++ b/.nycrc @@ -1,4 +1,4 @@ { - "exclude": ["test"], + "exclude": ["test", "native.js"], "extension": [".ts", ""] } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 33ef921d0..f8bd53cad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,6 +16,12 @@ We welcome any type of contribution, not only code. You can help with Working on your first Pull Request? You can learn how from this _free_ course, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github). +### Setting up the Rust toolchain + +Rollup now includes some Rust code. To compile it, you need to set up Rust nightly. If you haven't installed it yet, please first see https://www.rust-lang.org/tools/install to learn how to download Rustup and install Rust, then see https://rust-lang.github.io/rustup/concepts/channels.html to learn how to install Rust nightly. If everything is set up correctly, `npm run build` should complete successfully. The first build will be rather slow, but subsequent builds will be much faster. + +For local development and tests, it is even faster to run `npm run build:quick`, which does not perform a Rust production build, does not build WASM artefacts, and only builds the CommonJS version of Rollup. Note that with this build, a few tests will fail that rely on the other artefacts, see below. + ### Git configuration to enable symlinks The unit tests in this projects make use of symlinks in the git project. On Windows, this may not work as expected without extra configuration. To configure git to create symlinks on windows, you need to enable the Windows "Developer Mode" setting, and also set the `core.symlinks` git feature using either of the following commands: @@ -43,7 +49,7 @@ To save time for quick iterations, you can add `solo:true` to the `_config.js` f For those tests, it is enough to run ```shell -npm run build:cjs +npm run build:quick npm run test:quick ``` diff --git a/LICENSE.md b/LICENSE.md index a199a3149..238cabc51 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -52,71 +52,6 @@ Repository: rollup/plugins --------------------------------------- -## acorn -License: MIT -By: Marijn Haverbeke, Ingvar Stepanyan, Adrian Heine -Repository: https://github.com/acornjs/acorn.git - -> MIT License -> -> Copyright (C) 2012-2022 by various contributors (see AUTHORS) -> -> Permission is hereby granted, free of charge, to any person obtaining a copy -> of this software and associated documentation files (the "Software"), to deal -> in the Software without restriction, including without limitation the rights -> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -> copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: -> -> The above copyright notice and this permission notice shall be included in -> all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -> THE SOFTWARE. - ---------------------------------------- - -## acorn-import-assertions -License: MIT -By: Sven Sauleau -Repository: https://github.com/xtuc/acorn-import-assertions - ---------------------------------------- - -## acorn-walk -License: MIT -By: Marijn Haverbeke, Ingvar Stepanyan, Adrian Heine -Repository: https://github.com/acornjs/acorn.git - -> MIT License -> -> Copyright (C) 2012-2020 by various contributors (see AUTHORS) -> -> Permission is hereby granted, free of charge, to any person obtaining a copy -> of this software and associated documentation files (the "Software"), to deal -> in the Software without restriction, including without limitation the rights -> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -> copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: -> -> The above copyright notice and this permission notice shall be included in -> all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -> THE SOFTWARE. - ---------------------------------------- - ## anymatch License: ISC By: Elan Shanker diff --git a/browser/LICENSE.md b/browser/LICENSE.md index 356f756a3..98239aca4 100644 --- a/browser/LICENSE.md +++ b/browser/LICENSE.md @@ -52,71 +52,6 @@ Repository: rollup/plugins --------------------------------------- -## acorn -License: MIT -By: Marijn Haverbeke, Ingvar Stepanyan, Adrian Heine -Repository: https://github.com/acornjs/acorn.git - -> MIT License -> -> Copyright (C) 2012-2022 by various contributors (see AUTHORS) -> -> Permission is hereby granted, free of charge, to any person obtaining a copy -> of this software and associated documentation files (the "Software"), to deal -> in the Software without restriction, including without limitation the rights -> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -> copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: -> -> The above copyright notice and this permission notice shall be included in -> all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -> THE SOFTWARE. - ---------------------------------------- - -## acorn-import-assertions -License: MIT -By: Sven Sauleau -Repository: https://github.com/xtuc/acorn-import-assertions - ---------------------------------------- - -## acorn-walk -License: MIT -By: Marijn Haverbeke, Ingvar Stepanyan, Adrian Heine -Repository: https://github.com/acornjs/acorn.git - -> MIT License -> -> Copyright (C) 2012-2020 by various contributors (see AUTHORS) -> -> Permission is hereby granted, free of charge, to any person obtaining a copy -> of this software and associated documentation files (the "Software"), to deal -> in the Software without restriction, including without limitation the rights -> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -> copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: -> -> The above copyright notice and this permission notice shall be included in -> all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -> THE SOFTWARE. - ---------------------------------------- - ## builtin-modules License: MIT By: Sindre Sorhus diff --git a/browser/package.json b/browser/package.json index 401c1c9cf..0b03a6a38 100644 --- a/browser/package.json +++ b/browser/package.json @@ -1,6 +1,6 @@ { "name": "@rollup/browser", - "version": "3.29.4", + "version": "4.0.0-19", "description": "Next-generation ES module bundler browser build", "main": "dist/rollup.browser.js", "module": "dist/es/rollup.browser.js", @@ -20,6 +20,7 @@ }, "homepage": "https://rollupjs.org/", "files": [ + "dist/**/*.wasm", "dist/**/*.js", "dist/*.d.ts", "dist/es/package.json", diff --git a/browser/src/initWasm.ts b/browser/src/initWasm.ts new file mode 100644 index 000000000..ccd5e8d56 --- /dev/null +++ b/browser/src/initWasm.ts @@ -0,0 +1,6 @@ +// eslint-disable-next-line import/no-unresolved +import init from '../../wasm/bindings_wasm'; + +export default async function initWasm() { + await init(); +} diff --git a/browser/src/wasm.ts b/browser/src/wasm.ts new file mode 100644 index 000000000..2e9f2391a --- /dev/null +++ b/browser/src/wasm.ts @@ -0,0 +1,6 @@ +// eslint-disable-next-line import/no-unresolved +import { parse } from '../../wasm/bindings_wasm.js'; + +export default { + parse +}; diff --git a/build-plugins/aliases.ts b/build-plugins/aliases.ts index 3989f8477..85a59dc4a 100644 --- a/build-plugins/aliases.ts +++ b/build-plugins/aliases.ts @@ -2,7 +2,6 @@ import { fileURLToPath } from 'node:url'; export const moduleAliases = { entries: { - acorn: fileURLToPath(new URL('../node_modules/acorn/dist/acorn.mjs', import.meta.url)), 'help.md': fileURLToPath(new URL('../cli/help.md', import.meta.url)), 'package.json': fileURLToPath(new URL('../package.json', import.meta.url)) }, diff --git a/build-plugins/emit-native-entry.ts b/build-plugins/emit-native-entry.ts new file mode 100644 index 000000000..8b4e0ffa6 --- /dev/null +++ b/build-plugins/emit-native-entry.ts @@ -0,0 +1,15 @@ +import { readFile } from 'node:fs/promises'; +import type { Plugin } from 'rollup'; + +export function emitNativeEntry(): Plugin { + return { + async generateBundle() { + this.emitFile({ + fileName: 'native.js', + source: await readFile(new URL('../native.js', import.meta.url)), + type: 'asset' + }); + }, + name: 'emit-native-entry' + }; +} diff --git a/build-plugins/emit-wasm-file.ts b/build-plugins/emit-wasm-file.ts new file mode 100644 index 000000000..713f637c0 --- /dev/null +++ b/build-plugins/emit-wasm-file.ts @@ -0,0 +1,15 @@ +import fs from 'node:fs/promises'; +import type { Plugin } from 'rollup'; + +export default function emitWasmFile(): Plugin { + return { + async generateBundle() { + this.emitFile({ + fileName: 'bindings_wasm_bg.wasm', + source: await fs.readFile('wasm/bindings_wasm_bg.wasm'), + type: 'asset' + }); + }, + name: 'emit-wasm-file' + }; +} diff --git a/build-plugins/external-native-import.ts b/build-plugins/external-native-import.ts new file mode 100644 index 000000000..842dfddc9 --- /dev/null +++ b/build-plugins/external-native-import.ts @@ -0,0 +1,17 @@ +import type { Plugin } from 'rollup'; + +export function externalNativeImport(): Plugin { + return { + name: 'external-native-import', + async resolveId(id, importer) { + if (id.includes('/native')) { + const resolved = await this.resolve(id, importer!, { skipSelf: true }); + const resolvedId = resolved!.id; + return { + external: 'relative', + id: resolvedId.endsWith('.js') ? resolvedId : `${resolvedId}.js` + }; + } + } + }; +} diff --git a/build-plugins/replace-browser-modules.ts b/build-plugins/replace-browser-modules.ts index e00234124..f8a8af2e9 100644 --- a/build-plugins/replace-browser-modules.ts +++ b/build-plugins/replace-browser-modules.ts @@ -4,26 +4,31 @@ import type { Plugin } from 'vite'; const resolve = (path: string) => fileURLToPath(new URL(`../${path}`, import.meta.url)); -const REPLACED_MODULES = [ +const JS_REPLACED_MODULES = [ 'crypto', 'fs', 'hookActions', 'path', 'performance', 'process', - 'resolveId' + 'resolveId', + 'initWasm' ]; -const resolutions: ReadonlyMap = new Map( - REPLACED_MODULES.flatMap(module => { - const originalId = resolve(`src/utils/${module}`); - const replacementId = resolve(`browser/src/${module}.ts`); - return [ - [originalId, replacementId], - [`${originalId}.ts`, replacementId] - ]; - }) -); +type ModulesMap = [string, string][]; + +const jsModulesMap: ModulesMap = JS_REPLACED_MODULES.flatMap(module => { + const originalId = resolve(`src/utils/${module}`); + const replacementId = resolve(`browser/src/${module}.ts`); + return [ + [originalId, replacementId], + [`${originalId}.ts`, replacementId] + ]; +}); + +const wasmModulesMap: ModulesMap = [[resolve('native'), resolve('browser/src/wasm.ts')]]; + +const resolutions: ReadonlyMap = new Map([...jsModulesMap, ...wasmModulesMap]); export default function replaceBrowserModules(): Plugin { return { diff --git a/cli/help.md b/cli/help.md index 74afadf40..99ce75d39 100644 --- a/cli/help.md +++ b/cli/help.md @@ -35,7 +35,7 @@ Basic options: --no-esModule Do not add __esModule property --exports Specify export mode (auto, default, named, none) --extend Extend global variable defined by --name ---no-externalImportAssertions Omit import assertions in "es" output +--no-externalImportAttributes Omit import attributes in "es" output --no-externalLiveBindings Do not generate code to support live bindings --failAfterWarnings Exit with an error if the build produced warnings --filterLogs Filter log messages diff --git a/docs/.vitepress/verify-anchors.ts b/docs/.vitepress/verify-anchors.ts index 37c75eaa1..09122401e 100644 --- a/docs/.vitepress/verify-anchors.ts +++ b/docs/.vitepress/verify-anchors.ts @@ -30,7 +30,7 @@ function updateLegacySlugsFile() { if (originalSlugsFileText !== slugsFileText) { writeFileSync(slugsFile, slugsFileText); throw new Error( - `The content of the legacy anchor mapping file has changed. You should run "npm run build" locally and commit the updated file.` + `The content of the legacy anchor mapping file has changed. You should run "npm run build:docs" locally and commit the updated file.` ); } } diff --git a/docs/command-line-interface/index.md b/docs/command-line-interface/index.md index b223f7caa..73d5f073f 100755 --- a/docs/command-line-interface/index.md +++ b/docs/command-line-interface/index.md @@ -57,8 +57,6 @@ export default { strictDeprecations, // danger zone - acorn, - acornInjectPlugins, context, moduleContext, preserveSymlinks, @@ -89,7 +87,7 @@ export default { dynamicImportInCjs, entryFileNames, extend, - externalImportAssertions, + externalImportAttributes, footer, generatedCode, hoistTransitiveImports, @@ -387,7 +385,7 @@ Many options have command line equivalents. In those cases, any arguments passed --no-esModule Do not add __esModule property --exports Specify export mode (auto, default, named, none) --extend Extend global variable defined by --name ---no-externalImportAssertions Omit import assertions in "es" output +--no-externalImportAttributes Omit import attributes in "es" output --no-externalLiveBindings Do not generate code to support live bindings --failAfterWarnings Exit with an error if the build produced warnings --filterLogs Filter log messages diff --git a/docs/configuration-options/index.md b/docs/configuration-options/index.md index 08485f511..543e81b0f 100755 --- a/docs/configuration-options/index.md +++ b/docs/configuration-options/index.md @@ -678,15 +678,15 @@ This pattern will also be used for every file when setting the [`output.preserve Whether to extend the global variable defined by the `name` option in `umd` or `iife` formats. When `true`, the global variable will be defined as `(global.name = global.name || {})`. When false, the global defined by `name` will be overwritten like `(global.name = {})`. -### output.externalImportAssertions +### output.externalImportAttributes | | | | -------: | :----------------------------------------------------------- | | Type: | `boolean` | -| CLI: | `--externalImportAssertions`/`--no-externalImportAssertions` | +| CLI: | `--externalImportAttributes`/`--no-externalImportAttributes` | | Default: | `true` | -Whether to add import assertions to external imports in the output if the output format is `es`. By default, assertions are taken from the input files, but plugins can add or remove assertions later. E.g. `import "foo" assert {type: "json"}` will cause the same import to appear in the output unless the option is set to `false`. Note that all imports of a module need to have consistent assertions, otherwise a warning is emitted. +Whether to add import attributes to external imports in the output if the output format is `es`. By default, attributes are taken from the input files, but plugins can add or remove attributes later. E.g. `import "foo" assert {type: "json"}` will cause the same import to appear in the output unless the option is set to `false`. Note that all imports of a module need to have consistent attributes, otherwise a warning is emitted. ### output.generatedCode @@ -1653,33 +1653,6 @@ This flag is intended to be used by e.g. plugin authors to be able to adjust the You probably don't need to use these options unless you know what you are doing! -### acorn - -| | | -| ----: | :------------- | -| Type: | `AcornOptions` | - -Any options that should be passed through to Acorn's `parse` function, such as `allowReserved: true`. Cf. the [Acorn documentation](https://github.com/acornjs/acorn/tree/master/acorn#interface) for more available options. - -### acornInjectPlugins - -| | | -| ----: | :--------------------------------------------- | -| Type: | `AcornPluginFunction \| AcornPluginFunction[]` | - -A single plugin or an array of plugins to be injected into Acorn. For instance to use JSX syntax, you can specify - -```javascript -import jsx from 'acorn-jsx'; - -export default { - // … other options … - acornInjectPlugins: [jsx()] -}; -``` - -in your rollup configuration. Note that this is different from using Babel in that the generated output will still contain JSX while Babel will replace it with valid JavaScript. - ### context | | | @@ -2627,6 +2600,18 @@ _This option is no longer needed._ This option was used to prevent performance issues with the full chunk optimization algorithm. As the algorithm is much faster now, this option is now ignored by Rollup and should no longer be used. +### output.externalImportAssertions + +_Use the [`output.externalImportAttributes`](#output-externalimportattributes) option instead._ + +| | | +| -------: | :----------------------------------------------------------- | +| Type: | `boolean` | +| CLI: | `--externalImportAssertions`/`--no-externalImportAssertions` | +| Default: | `true` | + +Whether to add import assertions to external imports in the output if the output format is `es`. By default, assertions are taken from the input files, but plugins can add or remove assertions later. E.g. `import "foo" assert {type: "json"}` will cause the same import to appear in the output unless the option is set to `false`. Note that all imports of a module need to have consistent assertions, otherwise a warning is emitted. + ### output.preferConst _Use the [`output.generatedCode.constBindings`](#output-generatedcode-constbindings) option instead._ diff --git a/docs/guide/en/slugs-and-pages-by-legacy-slugs.json b/docs/guide/en/slugs-and-pages-by-legacy-slugs.json index fc59c07d5..07eacc06d 100644 --- a/docs/guide/en/slugs-and-pages-by-legacy-slugs.json +++ b/docs/guide/en/slugs-and-pages-by-legacy-slugs.json @@ -1 +1 @@ -{"--bundleconfigascjs":["command-line-interface","bundleconfigascjs"],"--configplugin-plugin":["command-line-interface","configplugin-plugin"],"--environment-values":["command-line-interface","environment-values"],"--failafterwarnings":["command-line-interface","failafterwarnings"],"--no-stdin":["command-line-interface","no-stdin"],"--silent":["command-line-interface","silent"],"--stdinext":["command-line-interface","stdin-ext"],"--waitforbundleinput":["command-line-interface","waitforbundleinput"],"--watchonstart-cmd---watchonbundlestart-cmd---watchonbundleend-cmd---watchonend-cmd---watchonerror-cmd":["command-line-interface","watch-onstart-cmd-watch-onbundlestart-cmd-watch-onbundleend-cmd-watch-onend-cmd-watch-onerror-cmd"],"-h--help":["command-line-interface","h-help"],"-p-plugin---plugin-plugin":["command-line-interface","p-plugin-plugin-plugin"],"-v--version":["command-line-interface","v-version"],"-w--watch":["command-line-interface","w-watch"],"a-simple-example":["plugin-development","a-simple-example"],"acorn":["configuration-options","acorn"],"acorninjectplugins":["configuration-options","acorninjectplugins"],"advanced-functionality":["configuration-options","advanced-functionality"],"augmentchunkhash":["plugin-development","augmentchunkhash"],"avoiding-eval":["troubleshooting","avoiding-eval"],"babel":["tools","babel"],"banner":["plugin-development","banner"],"big-list-of-options":["configuration-options",""],"build-hooks":["plugin-development","build-hooks"],"buildend":["plugin-development","buildend"],"buildstart":["plugin-development","buildstart"],"cache":["configuration-options","cache"],"caveats-when-using-native-node-es-modules":["command-line-interface","caveats-when-using-native-node-es-modules"],"changed-defaults":["migration","changed-defaults"],"changes-to-the-plugin-api":["migration","changes-to-the-plugin-api"],"closebundle":["plugin-development","closebundle"],"closewatcher":["plugin-development","closewatcher"],"code-splitting":["tutorial","code-splitting"],"command-line-flags":["command-line-interface","command-line-flags"],"command-line-reference":["command-line-interface",""],"compatibility":["introduction","compatibility"],"config-intellisense":["command-line-interface","config-intellisense"],"configuration-files":["command-line-interface","configuration-files"],"context":["configuration-options","context"],"conventions":["plugin-development","conventions"],"core-functionality":["configuration-options","core-functionality"],"creating-your-first-bundle":["tutorial","creating-your-first-bundle"],"custom-module-meta-data":["plugin-development","custom-module-meta-data"],"custom-resolver-options":["plugin-development","custom-resolver-options"],"danger-zone":["configuration-options","danger-zone"],"default-export":["es-module-syntax","default-export"],"default-import":["es-module-syntax","default-import"],"deno":["tools","deno"],"deprecated-context-functions":["plugin-development","deprecated-context-functions"],"deprecated-options":["configuration-options","deprecated-options"],"differences-to-the-javascript-api":["command-line-interface","differences-to-the-javascript-api"],"direct-plugin-communication":["plugin-development","direct-plugin-communication"],"dynamic-import":["es-module-syntax","dynamic-import"],"dynamic-import-in-commonjs-output":["migration","dynamic-import-in-commonjs-output"],"empty-import":["es-module-syntax","empty-import"],"error-emfile-too-many-open-files":["troubleshooting","error-emfile-too-many-open-files"],"error-javascript-heap-out-of-memory":["troubleshooting","error-javascript-heap-out-of-memory"],"error-name-is-not-exported-by-module":["troubleshooting","error-name-is-not-exported-by-module"],"error-node-tried-to-load-your-configuration-file-as-commonjs-even-though-it-is-likely-an-es-module":["troubleshooting","error-node-tried-to-load-your-configuration-file-as-commonjs-even-though-it-is-likely-an-es-module"],"error-this-is-undefined":["troubleshooting","error-this-is-undefined"],"es-module-syntax":["es-module-syntax",""],"eval2--eval":["troubleshooting","eval2-eval"],"example-transformer":["plugin-development","example-transformer"],"experimental-options":["configuration-options","experimental-options"],"experimentalcacheexpiry":["configuration-options","experimentalcacheexpiry"],"exporting":["es-module-syntax","exporting"],"external":["configuration-options","external"],"faqs":["faqs",""],"file-urls":["plugin-development","file-urls"],"footer":["plugin-development","footer"],"generatebundle":["plugin-development","generatebundle"],"getting-the-current-directory":["command-line-interface","getting-the-current-directory"],"gulp":["tools","gulp"],"how-bindings-work":["es-module-syntax","how-bindings-work"],"how-do-i-add-polyfills-to-a-rollup-bundle":["faqs","how-do-i-add-polyfills-to-a-rollup-bundle"],"how-do-i-run-rollup-itself-in-a-browser":["faqs","how-do-i-run-rollup-itself-in-a-browser"],"how-do-i-use-rollup-in-nodejs-with-commonjs-modules":["faqs","how-do-i-use-rollup-in-node-js-with-commonjs-modules"],"importing":["es-module-syntax","importing"],"importing-commonjs":["introduction","importing-commonjs"],"importing-packagejson":["command-line-interface","importing-package-json"],"inlinedynamicimports":["configuration-options","inlinedynamicimports"],"input":["configuration-options","input"],"inputoptions-object":["javascript-api","inputoptions-object"],"installation":["introduction","installation"],"installing-rollup-locally":["tutorial","installing-rollup-locally"],"inter-plugin-communication":["plugin-development","inter-plugin-communication"],"intro":["plugin-development","intro"],"introduction":["introduction",""],"is-rollup-meant-for-building-libraries-or-applications":["faqs","is-rollup-meant-for-building-libraries-or-applications"],"javascript-api":["javascript-api",""],"load":["plugin-development","load"],"loading-a-configuration-from-a-node-package":["command-line-interface","loading-a-configuration-from-a-node-package"],"makeabsoluteexternalsrelative":["configuration-options","makeabsoluteexternalsrelative"],"manualchunks":["configuration-options","manualchunks"],"maxparallelfileops":["configuration-options","maxparallelfileops"],"maxparallelfilereads":["configuration-options","maxparallelfilereads"],"migration":["migration",""],"modulecontext":["configuration-options","modulecontext"],"moduleparsed":["plugin-development","moduleparsed"],"more-changed-options":["migration","more-changed-options"],"name":["plugin-development","name"],"named-exports":["es-module-syntax","named-exports"],"named-imports":["es-module-syntax","named-imports"],"namespace-imports":["es-module-syntax","namespace-imports"],"new-function":["troubleshooting","new-function"],"onwarn":["configuration-options","onwarn"],"options":["plugin-development","options"],"output-generation-hooks":["plugin-development","output-generation-hooks"],"outputamd":["configuration-options","output-amd"],"outputassetfilenames":["configuration-options","output-assetfilenames"],"outputbanneroutputfooter":["configuration-options","output-banner-output-footer"],"outputchunkfilenames":["configuration-options","output-chunkfilenames"],"outputcompact":["configuration-options","output-compact"],"outputdir":["configuration-options","output-dir"],"outputdynamicimportfunction":["configuration-options","output-dynamicimportfunction"],"outputdynamicimportincjs":["configuration-options","output-dynamicimportincjs"],"outputentryfilenames":["configuration-options","output-entryfilenames"],"outputesmodule":["configuration-options","output-esmodule"],"outputexports":["configuration-options","output-exports"],"outputextend":["configuration-options","output-extend"],"outputexternalimportassertions":["configuration-options","output-externalimportassertions"],"outputexternallivebindings":["configuration-options","output-externallivebindings"],"outputfile":["configuration-options","output-file"],"outputformat":["configuration-options","output-format"],"outputfreeze":["configuration-options","output-freeze"],"outputgeneratedcode":["configuration-options","output-generatedcode"],"outputglobals":["configuration-options","output-globals"],"outputhoisttransitiveimports":["configuration-options","output-hoisttransitiveimports"],"outputindent":["configuration-options","output-indent"],"outputinlinedynamicimports":["configuration-options","output-inlinedynamicimports"],"outputinterop":["configuration-options","output-interop"],"outputintrooutputoutro":["configuration-options","output-intro-output-outro"],"outputmanualchunks":["configuration-options","output-manualchunks"],"outputminifyinternalexports":["configuration-options","output-minifyinternalexports"],"outputname":["configuration-options","output-name"],"outputnamespacetostringtag":["configuration-options","output-namespacetostringtag"],"outputnoconflict":["configuration-options","output-noconflict"],"outputoptions":["plugin-development","outputoptions"],"outputoptions-object":["javascript-api","outputoptions-object"],"outputpaths":["configuration-options","output-paths"],"outputplugins":["configuration-options","output-plugins"],"outputpreferconst":["configuration-options","output-preferconst"],"outputpreservemodules":["configuration-options","output-preservemodules"],"outputpreservemodulesroot":["configuration-options","output-preservemodulesroot"],"outputsanitizefilename":["configuration-options","output-sanitizefilename"],"outputsourcemap":["configuration-options","output-sourcemap"],"outputsourcemapbaseurl":["configuration-options","output-sourcemapbaseurl"],"outputsourcemapexcludesources":["configuration-options","output-sourcemapexcludesources"],"outputsourcemapfile":["configuration-options","output-sourcemapfile"],"outputsourcemappathtransform":["configuration-options","output-sourcemappathtransform"],"outputstrict":["configuration-options","output-strict"],"outputsystemnullsetters":["configuration-options","output-systemnullsetters"],"outputvalidate":["configuration-options","output-validate"],"outro":["plugin-development","outro"],"overview":["introduction","overview"],"peer-dependencies":["tools","peer-dependencies"],"perf":["configuration-options","perf"],"plugin-context":["plugin-development","plugin-context"],"plugin-development":["plugin-development",""],"plugins":["configuration-options","plugins"],"plugins-overview":["plugin-development","plugins-overview"],"prerequisites":["migration","prerequisites"],"preserveentrysignatures":["configuration-options","preserveentrysignatures"],"preservemodules":["configuration-options","preservemodules"],"preservesymlinks":["configuration-options","preservesymlinks"],"programmatically-loading-a-config-file":["javascript-api","programmatically-loading-a-config-file"],"properties":["plugin-development","properties"],"publishing-es-modules":["introduction","publishing-es-modules"],"quick-start":["introduction","quick-start"],"reading-a-file-from-stdin":["command-line-interface","reading-a-file-from-stdin"],"renderchunk":["plugin-development","renderchunk"],"renderdynamicimport":["plugin-development","renderdynamicimport"],"rendererror":["plugin-development","rendererror"],"renderstart":["plugin-development","renderstart"],"resolvedynamicimport":["plugin-development","resolvedynamicimport"],"resolvefileurl":["plugin-development","resolvefileurl"],"resolveid":["plugin-development","resolveid"],"resolveimportmeta":["plugin-development","resolveimportmeta"],"rollupplugin-commonjs":["tools","rollup-plugin-commonjs"],"rollupplugin-node-resolve":["tools","rollup-plugin-node-resolve"],"rolluprollup":["javascript-api","rollup-rollup"],"rollupwatch":["javascript-api","rollup-watch"],"shimmissingexports":["configuration-options","shimmissingexports"],"shouldtransformcachedmodule":["plugin-development","shouldtransformcachedmodule"],"source-code-transformations":["plugin-development","source-code-transformations"],"strictdeprecations":["configuration-options","strictdeprecations"],"synthetic-named-exports":["plugin-development","synthetic-named-exports"],"the-why":["introduction","the-why"],"thisaddwatchfile":["plugin-development","this-addwatchfile"],"thisemitfile":["plugin-development","this-emitfile"],"thiserror":["plugin-development","this-error"],"thisgetcombinedsourcemap":["plugin-development","this-getcombinedsourcemap"],"thisgetfilename":["plugin-development","this-getfilename"],"thisgetmoduleids":["plugin-development","this-getmoduleids"],"thisgetmoduleinfo":["plugin-development","this-getmoduleinfo"],"thisgetwatchfiles":["plugin-development","this-getwatchfiles"],"thisload":["plugin-development","this-load"],"thismeta":["plugin-development","this-meta"],"thisparse":["plugin-development","this-parse"],"thisresolve":["plugin-development","this-resolve"],"thissetassetsource":["plugin-development","this-setassetsource"],"thiswarn":["plugin-development","this-warn"],"tools":["tools",""],"transform":["plugin-development","transform"],"transformers":["plugin-development","transformers"],"tree-shaking":["introduction","tree-shaking"],"tree-shaking-doesnt-seem-to-be-working":["troubleshooting","tree-shaking-doesn-t-seem-to-be-working"],"treeshake":["configuration-options","treeshake"],"troubleshooting":["troubleshooting",""],"tutorial":["tutorial",""],"using-config-files":["tutorial","using-config-files"],"using-configuration-files":["migration","using-configuration-files"],"using-output-plugins":["tutorial","using-output-plugins"],"using-plugins":["tutorial","using-plugins"],"warning-sourcemap-is-likely-to-be-incorrect":["troubleshooting","warning-sourcemap-is-likely-to-be-incorrect"],"warning-treating-module-as-external-dependency":["troubleshooting","warning-treating-module-as-external-dependency"],"watch-options":["configuration-options","watch"],"watchbuilddelay":["configuration-options","watch-builddelay"],"watchchange":["plugin-development","watchchange"],"watchchokidar":["configuration-options","watch-chokidar"],"watchclearscreen":["configuration-options","watch-clearscreen"],"watchexclude":["configuration-options","watch-exclude"],"watchinclude":["configuration-options","watch-include"],"watchoptions":["javascript-api","watchoptions"],"watchskipwrite":["configuration-options","watch-skipwrite"],"what-is-tree-shaking":["faqs","what-is-tree-shaking"],"who-made-the-rollup-logo-its-lovely":["faqs","who-made-the-rollup-logo-it-s-lovely"],"why-are-es-modules-better-than-commonjs-modules":["faqs","why-are-es-modules-better-than-commonjs-modules"],"why-do-additional-imports-turn-up-in-my-entry-chunks-when-code-splitting":["faqs","why-do-additional-imports-turn-up-in-my-entry-chunks-when-code-splitting"],"why-isnt-node-resolve-a-built-in-feature":["faqs","why-isn-t-node-resolve-a-built-in-feature"],"with-npm-packages":["tools","with-npm-packages"],"writebundle":["plugin-development","writebundle"]} \ No newline at end of file +{"--bundleconfigascjs":["command-line-interface","bundleconfigascjs"],"--configplugin-plugin":["command-line-interface","configplugin-plugin"],"--environment-values":["command-line-interface","environment-values"],"--failafterwarnings":["command-line-interface","failafterwarnings"],"--no-stdin":["command-line-interface","no-stdin"],"--silent":["command-line-interface","silent"],"--stdinext":["command-line-interface","stdin-ext"],"--waitforbundleinput":["command-line-interface","waitforbundleinput"],"--watchonstart-cmd---watchonbundlestart-cmd---watchonbundleend-cmd---watchonend-cmd---watchonerror-cmd":["command-line-interface","watch-onstart-cmd-watch-onbundlestart-cmd-watch-onbundleend-cmd-watch-onend-cmd-watch-onerror-cmd"],"-h--help":["command-line-interface","h-help"],"-p-plugin---plugin-plugin":["command-line-interface","p-plugin-plugin-plugin"],"-v--version":["command-line-interface","v-version"],"-w--watch":["command-line-interface","w-watch"],"a-simple-example":["plugin-development","a-simple-example"],"advanced-functionality":["configuration-options","advanced-functionality"],"augmentchunkhash":["plugin-development","augmentchunkhash"],"avoiding-eval":["troubleshooting","avoiding-eval"],"babel":["tools","babel"],"banner":["plugin-development","banner"],"big-list-of-options":["configuration-options",""],"build-hooks":["plugin-development","build-hooks"],"buildend":["plugin-development","buildend"],"buildstart":["plugin-development","buildstart"],"cache":["configuration-options","cache"],"caveats-when-using-native-node-es-modules":["command-line-interface","caveats-when-using-native-node-es-modules"],"changed-defaults":["migration","changed-defaults"],"changes-to-the-plugin-api":["migration","changes-to-the-plugin-api"],"closebundle":["plugin-development","closebundle"],"closewatcher":["plugin-development","closewatcher"],"code-splitting":["tutorial","code-splitting"],"command-line-flags":["command-line-interface","command-line-flags"],"command-line-reference":["command-line-interface",""],"compatibility":["introduction","compatibility"],"config-intellisense":["command-line-interface","config-intellisense"],"configuration-files":["command-line-interface","configuration-files"],"context":["configuration-options","context"],"conventions":["plugin-development","conventions"],"core-functionality":["configuration-options","core-functionality"],"creating-your-first-bundle":["tutorial","creating-your-first-bundle"],"custom-module-meta-data":["plugin-development","custom-module-meta-data"],"custom-resolver-options":["plugin-development","custom-resolver-options"],"danger-zone":["configuration-options","danger-zone"],"default-export":["es-module-syntax","default-export"],"default-import":["es-module-syntax","default-import"],"deno":["tools","deno"],"deprecated-context-functions":["plugin-development","deprecated-context-functions"],"deprecated-options":["configuration-options","deprecated-options"],"differences-to-the-javascript-api":["command-line-interface","differences-to-the-javascript-api"],"direct-plugin-communication":["plugin-development","direct-plugin-communication"],"dynamic-import":["es-module-syntax","dynamic-import"],"dynamic-import-in-commonjs-output":["migration","dynamic-import-in-commonjs-output"],"empty-import":["es-module-syntax","empty-import"],"error-emfile-too-many-open-files":["troubleshooting","error-emfile-too-many-open-files"],"error-javascript-heap-out-of-memory":["troubleshooting","error-javascript-heap-out-of-memory"],"error-name-is-not-exported-by-module":["troubleshooting","error-name-is-not-exported-by-module"],"error-node-tried-to-load-your-configuration-file-as-commonjs-even-though-it-is-likely-an-es-module":["troubleshooting","error-node-tried-to-load-your-configuration-file-as-commonjs-even-though-it-is-likely-an-es-module"],"error-this-is-undefined":["troubleshooting","error-this-is-undefined"],"es-module-syntax":["es-module-syntax",""],"eval2--eval":["troubleshooting","eval2-eval"],"example-transformer":["plugin-development","example-transformer"],"experimental-options":["configuration-options","experimental-options"],"experimentalcacheexpiry":["configuration-options","experimentalcacheexpiry"],"exporting":["es-module-syntax","exporting"],"external":["configuration-options","external"],"faqs":["faqs",""],"file-urls":["plugin-development","file-urls"],"footer":["plugin-development","footer"],"generatebundle":["plugin-development","generatebundle"],"getting-the-current-directory":["command-line-interface","getting-the-current-directory"],"gulp":["tools","gulp"],"how-bindings-work":["es-module-syntax","how-bindings-work"],"how-do-i-add-polyfills-to-a-rollup-bundle":["faqs","how-do-i-add-polyfills-to-a-rollup-bundle"],"how-do-i-run-rollup-itself-in-a-browser":["faqs","how-do-i-run-rollup-itself-in-a-browser"],"how-do-i-use-rollup-in-nodejs-with-commonjs-modules":["faqs","how-do-i-use-rollup-in-node-js-with-commonjs-modules"],"importing":["es-module-syntax","importing"],"importing-commonjs":["introduction","importing-commonjs"],"importing-packagejson":["command-line-interface","importing-package-json"],"inlinedynamicimports":["configuration-options","inlinedynamicimports"],"input":["configuration-options","input"],"inputoptions-object":["javascript-api","inputoptions-object"],"installation":["introduction","installation"],"installing-rollup-locally":["tutorial","installing-rollup-locally"],"inter-plugin-communication":["plugin-development","inter-plugin-communication"],"intro":["plugin-development","intro"],"introduction":["introduction",""],"is-rollup-meant-for-building-libraries-or-applications":["faqs","is-rollup-meant-for-building-libraries-or-applications"],"javascript-api":["javascript-api",""],"load":["plugin-development","load"],"loading-a-configuration-from-a-node-package":["command-line-interface","loading-a-configuration-from-a-node-package"],"makeabsoluteexternalsrelative":["configuration-options","makeabsoluteexternalsrelative"],"manualchunks":["configuration-options","manualchunks"],"maxparallelfileops":["configuration-options","maxparallelfileops"],"maxparallelfilereads":["configuration-options","maxparallelfilereads"],"migration":["migration",""],"modulecontext":["configuration-options","modulecontext"],"moduleparsed":["plugin-development","moduleparsed"],"more-changed-options":["migration","more-changed-options"],"name":["plugin-development","name"],"named-exports":["es-module-syntax","named-exports"],"named-imports":["es-module-syntax","named-imports"],"namespace-imports":["es-module-syntax","namespace-imports"],"new-function":["troubleshooting","new-function"],"onwarn":["configuration-options","onwarn"],"options":["plugin-development","options"],"output-generation-hooks":["plugin-development","output-generation-hooks"],"outputamd":["configuration-options","output-amd"],"outputassetfilenames":["configuration-options","output-assetfilenames"],"outputbanneroutputfooter":["configuration-options","output-banner-output-footer"],"outputchunkfilenames":["configuration-options","output-chunkfilenames"],"outputcompact":["configuration-options","output-compact"],"outputdir":["configuration-options","output-dir"],"outputdynamicimportfunction":["configuration-options","output-dynamicimportfunction"],"outputdynamicimportincjs":["configuration-options","output-dynamicimportincjs"],"outputentryfilenames":["configuration-options","output-entryfilenames"],"outputesmodule":["configuration-options","output-esmodule"],"outputexports":["configuration-options","output-exports"],"outputextend":["configuration-options","output-extend"],"outputexternalimportassertions":["configuration-options","output-externalimportassertions"],"outputexternallivebindings":["configuration-options","output-externallivebindings"],"outputfile":["configuration-options","output-file"],"outputformat":["configuration-options","output-format"],"outputfreeze":["configuration-options","output-freeze"],"outputgeneratedcode":["configuration-options","output-generatedcode"],"outputglobals":["configuration-options","output-globals"],"outputhoisttransitiveimports":["configuration-options","output-hoisttransitiveimports"],"outputindent":["configuration-options","output-indent"],"outputinlinedynamicimports":["configuration-options","output-inlinedynamicimports"],"outputinterop":["configuration-options","output-interop"],"outputintrooutputoutro":["configuration-options","output-intro-output-outro"],"outputmanualchunks":["configuration-options","output-manualchunks"],"outputminifyinternalexports":["configuration-options","output-minifyinternalexports"],"outputname":["configuration-options","output-name"],"outputnamespacetostringtag":["configuration-options","output-namespacetostringtag"],"outputnoconflict":["configuration-options","output-noconflict"],"outputoptions":["plugin-development","outputoptions"],"outputoptions-object":["javascript-api","outputoptions-object"],"outputpaths":["configuration-options","output-paths"],"outputplugins":["configuration-options","output-plugins"],"outputpreferconst":["configuration-options","output-preferconst"],"outputpreservemodules":["configuration-options","output-preservemodules"],"outputpreservemodulesroot":["configuration-options","output-preservemodulesroot"],"outputsanitizefilename":["configuration-options","output-sanitizefilename"],"outputsourcemap":["configuration-options","output-sourcemap"],"outputsourcemapbaseurl":["configuration-options","output-sourcemapbaseurl"],"outputsourcemapexcludesources":["configuration-options","output-sourcemapexcludesources"],"outputsourcemapfile":["configuration-options","output-sourcemapfile"],"outputsourcemappathtransform":["configuration-options","output-sourcemappathtransform"],"outputstrict":["configuration-options","output-strict"],"outputsystemnullsetters":["configuration-options","output-systemnullsetters"],"outputvalidate":["configuration-options","output-validate"],"outro":["plugin-development","outro"],"overview":["introduction","overview"],"peer-dependencies":["tools","peer-dependencies"],"perf":["configuration-options","perf"],"plugin-context":["plugin-development","plugin-context"],"plugin-development":["plugin-development",""],"plugins":["configuration-options","plugins"],"plugins-overview":["plugin-development","plugins-overview"],"prerequisites":["migration","prerequisites"],"preserveentrysignatures":["configuration-options","preserveentrysignatures"],"preservemodules":["configuration-options","preservemodules"],"preservesymlinks":["configuration-options","preservesymlinks"],"programmatically-loading-a-config-file":["javascript-api","programmatically-loading-a-config-file"],"properties":["plugin-development","properties"],"publishing-es-modules":["introduction","publishing-es-modules"],"quick-start":["introduction","quick-start"],"reading-a-file-from-stdin":["command-line-interface","reading-a-file-from-stdin"],"renderchunk":["plugin-development","renderchunk"],"renderdynamicimport":["plugin-development","renderdynamicimport"],"rendererror":["plugin-development","rendererror"],"renderstart":["plugin-development","renderstart"],"resolvedynamicimport":["plugin-development","resolvedynamicimport"],"resolvefileurl":["plugin-development","resolvefileurl"],"resolveid":["plugin-development","resolveid"],"resolveimportmeta":["plugin-development","resolveimportmeta"],"rollupplugin-commonjs":["tools","rollup-plugin-commonjs"],"rollupplugin-node-resolve":["tools","rollup-plugin-node-resolve"],"rolluprollup":["javascript-api","rollup-rollup"],"rollupwatch":["javascript-api","rollup-watch"],"shimmissingexports":["configuration-options","shimmissingexports"],"shouldtransformcachedmodule":["plugin-development","shouldtransformcachedmodule"],"source-code-transformations":["plugin-development","source-code-transformations"],"strictdeprecations":["configuration-options","strictdeprecations"],"synthetic-named-exports":["plugin-development","synthetic-named-exports"],"the-why":["introduction","the-why"],"thisaddwatchfile":["plugin-development","this-addwatchfile"],"thisemitfile":["plugin-development","this-emitfile"],"thiserror":["plugin-development","this-error"],"thisgetcombinedsourcemap":["plugin-development","this-getcombinedsourcemap"],"thisgetfilename":["plugin-development","this-getfilename"],"thisgetmoduleids":["plugin-development","this-getmoduleids"],"thisgetmoduleinfo":["plugin-development","this-getmoduleinfo"],"thisgetwatchfiles":["plugin-development","this-getwatchfiles"],"thisload":["plugin-development","this-load"],"thismeta":["plugin-development","this-meta"],"thisparse":["plugin-development","this-parse"],"thisresolve":["plugin-development","this-resolve"],"thissetassetsource":["plugin-development","this-setassetsource"],"thiswarn":["plugin-development","this-warn"],"tools":["tools",""],"transform":["plugin-development","transform"],"transformers":["plugin-development","transformers"],"tree-shaking":["introduction","tree-shaking"],"tree-shaking-doesnt-seem-to-be-working":["troubleshooting","tree-shaking-doesn-t-seem-to-be-working"],"treeshake":["configuration-options","treeshake"],"troubleshooting":["troubleshooting",""],"tutorial":["tutorial",""],"using-config-files":["tutorial","using-config-files"],"using-configuration-files":["migration","using-configuration-files"],"using-output-plugins":["tutorial","using-output-plugins"],"using-plugins":["tutorial","using-plugins"],"warning-sourcemap-is-likely-to-be-incorrect":["troubleshooting","warning-sourcemap-is-likely-to-be-incorrect"],"warning-treating-module-as-external-dependency":["troubleshooting","warning-treating-module-as-external-dependency"],"watch-options":["configuration-options","watch"],"watchbuilddelay":["configuration-options","watch-builddelay"],"watchchange":["plugin-development","watchchange"],"watchchokidar":["configuration-options","watch-chokidar"],"watchclearscreen":["configuration-options","watch-clearscreen"],"watchexclude":["configuration-options","watch-exclude"],"watchinclude":["configuration-options","watch-include"],"watchoptions":["javascript-api","watchoptions"],"watchskipwrite":["configuration-options","watch-skipwrite"],"what-is-tree-shaking":["faqs","what-is-tree-shaking"],"who-made-the-rollup-logo-its-lovely":["faqs","who-made-the-rollup-logo-it-s-lovely"],"why-are-es-modules-better-than-commonjs-modules":["faqs","why-are-es-modules-better-than-commonjs-modules"],"why-do-additional-imports-turn-up-in-my-entry-chunks-when-code-splitting":["faqs","why-do-additional-imports-turn-up-in-my-entry-chunks-when-code-splitting"],"why-isnt-node-resolve-a-built-in-feature":["faqs","why-isn-t-node-resolve-a-built-in-feature"],"with-npm-packages":["tools","with-npm-packages"],"writebundle":["plugin-development","writebundle"]} \ No newline at end of file diff --git a/docs/javascript-api/index.md b/docs/javascript-api/index.md index e23428449..dee42b402 100755 --- a/docs/javascript-api/index.md +++ b/docs/javascript-api/index.md @@ -127,8 +127,6 @@ const inputOptions = { strictDeprecations, // danger zone - acorn, - acornInjectPlugins, context, moduleContext, preserveSymlinks, @@ -164,7 +162,7 @@ const outputOptions = { dynamicImportInCjs, entryFileNames, extend, - externalImportAssertions, + externalImportAttributes, footer, generatedCode, hoistTransitiveImports, diff --git a/docs/plugin-development/index.md b/docs/plugin-development/index.md index 370ce9535..404fa9c2b 100644 --- a/docs/plugin-development/index.md +++ b/docs/plugin-development/index.md @@ -417,7 +417,7 @@ Like the [`onLog`](#onlog) hook, this hook does not have access to most [plugin ```typescript type ResolveDynamicImportHook = ( - specifier: string | AcornNode, + specifier: string | AstNode, importer: string, options: { assertions: Record } ) => ResolveIdResult; @@ -613,7 +613,7 @@ In watch mode or when using the cache explicitly, the resolved imports of a cach ```typescript type ShouldTransformCachedModuleHook = (options: { - ast: AcornNode; + ast: AstNode; code: string; id: string; meta: { [plugin: string]: any }; @@ -1666,11 +1666,11 @@ An object containing potentially useful Rollup metadata: ### this.parse -| | | -| ----: | :-------------------------------------------------------------- | -| Type: | `(code: string, acornOptions?: AcornOptions) => ESTree.Program` | +| | | +| ----: | :--------------------------------- | +| Type: | `(code: string) => ESTree.Program` | -Use Rollup's internal acorn instance to parse code to an AST. +Use Rollup's internal SWC-based parser to parse code to an AST. ### this.resolve diff --git a/docs/repl/stores/options.ts b/docs/repl/stores/options.ts index 33cafd18e..20057c600 100644 --- a/docs/repl/stores/options.ts +++ b/docs/repl/stores/options.ts @@ -191,10 +191,10 @@ export const useOptions = defineStore('options2', () => { defaultValue: true, name: 'output.externalLiveBindings' }); - const optionOutputExternalImportAssertions = getBoolean({ + const optionOutputExternalImportAttributes = getBoolean({ available: () => optionOutputFormat.value.value === 'es', defaultValue: true, - name: 'output.externalImportAssertions' + name: 'output.externalImportAttributes' }); const optionOutputFreeze = getBoolean({ defaultValue: true, @@ -417,7 +417,7 @@ export const useOptions = defineStore('options2', () => { optionOutputExports, optionOutputExtend, optionOutputExternalLiveBindings, - optionOutputExternalImportAssertions, + optionOutputExternalImportAttributes, optionOutputFreeze, optionOutputFooter, optionOutputFormat, diff --git a/docs/repl/stores/rollup.ts b/docs/repl/stores/rollup.ts index e67e968fb..a0b3f51e3 100644 --- a/docs/repl/stores/rollup.ts +++ b/docs/repl/stores/rollup.ts @@ -4,33 +4,56 @@ import type { RollupBuild, RollupOptions } from '../../../src/rollup/types'; import type * as Rollup from '../helpers/importRollup'; import { isRollupVersionAtLeast } from '../helpers/rollupVersion'; -function getRollupUrl({ type, version }: RollupRequest) { +const ROLLUP_JS_FILE = 'rollup.browser.js'; +const ROLLUP_WASM_FILE = 'bindings_wasm_bg.wasm'; + +function isLoadLocalRollup({ type }: RollupRequest) { + return import.meta.env.DEV && type === 'local'; +} + +function getFullUrlFromUnpkg(version: string | undefined, file: string) { + return `https://unpkg.com/@rollup/browser${version ? `@${version}` : ''}/dist/${file}`; +} + +function getFullUrlFromAWS(version: string, file: string) { + return `https://rollup-ci-artefacts.s3.amazonaws.com/${version}/${file}`; +} + +function getRollupJsUrl({ type, version }: RollupRequest) { if (type === 'pr') { - return `https://rollup-ci-artefacts.s3.amazonaws.com/${version}/rollup.browser.js`; + return getFullUrlFromAWS(version, ROLLUP_JS_FILE); } else if (version) { - if (isRollupVersionAtLeast(version, 4, 0)) { - return `https://unpkg.com/@rollup/browser@${version}/dist/rollup.browser.js`; - } if (isRollupVersionAtLeast(version, 3, 0)) { - return `https://unpkg.com/@rollup/browser@${version}`; + return getFullUrlFromUnpkg(version, ROLLUP_JS_FILE); } if (isRollupVersionAtLeast(version, 1, 0)) { return `https://unpkg.com/rollup@${version}/dist/rollup.browser.js`; } throw new Error('The REPL only supports Rollup versions >= 1.0.0.'); } - return 'https://unpkg.com/@rollup/browser'; + return getFullUrlFromUnpkg(undefined, ROLLUP_JS_FILE); +} + +function getRollupWasmFileUrl({ type, version }: RollupRequest) { + if (type === 'pr') { + return getFullUrlFromAWS(version, ROLLUP_WASM_FILE); + } else if (type === 'version' && version && isRollupVersionAtLeast(version, 4, 0)) { + return getFullUrlFromUnpkg(version, ROLLUP_WASM_FILE); + } } -function loadRollup(rollupRequest: RollupRequest): Promise { - if (import.meta.env.DEV && rollupRequest.type === 'local') { +async function loadRollup(rollupRequest: RollupRequest): Promise { + if (isLoadLocalRollup(rollupRequest)) { return import('../helpers/importRollup'); } - const url = getRollupUrl(rollupRequest); + const url = getRollupJsUrl(rollupRequest); + const rollupWasmFileUrl = getRollupWasmFileUrl(rollupRequest); + const preloadRollupWasmFile = rollupWasmFileUrl && fetch(rollupWasmFileUrl).catch(() => {}); return new Promise((fulfil, reject) => { const script = document.createElement('script'); script.src = url; - script.addEventListener('load', () => { + script.addEventListener('load', async () => { + preloadRollupWasmFile && (await preloadRollupWasmFile); fulfil((window as any).rollup); }); script.addEventListener('error', () => { @@ -78,7 +101,7 @@ export const useRollup = defineStore('rollup', () => { try { request.value = rollupRequest; const instance = await loadRollup(rollupRequest); - if (import.meta.env.DEV) { + if (isLoadLocalRollup(rollupRequest)) { instance.onUpdate(newInstance => { loaded.value = { error: false, instance: newInstance }; }); diff --git a/native.d.ts b/native.d.ts new file mode 100644 index 000000000..6976f78bb --- /dev/null +++ b/native.d.ts @@ -0,0 +1,6 @@ +/* tslint:disable */ +/* eslint-disable */ + +/* auto-generated by NAPI-RS */ + +export function parse(code: string): Buffer diff --git a/native.js b/native.js new file mode 100644 index 000000000..a16b23546 --- /dev/null +++ b/native.js @@ -0,0 +1,257 @@ +/* tslint:disable */ +/* eslint-disable */ +/* prettier-ignore */ + +/* auto-generated by NAPI-RS */ + +const { existsSync, readFileSync } = require('fs') +const { join } = require('path') + +const { platform, arch } = process + +let nativeBinding = null +let localFileExisted = false +let loadError = null + +function isMusl() { + // For Node 10 + if (!process.report || typeof process.report.getReport !== 'function') { + try { + const lddPath = require('child_process').execSync('which ldd').toString().trim() + return readFileSync(lddPath, 'utf8').includes('musl') + } catch (e) { + return true + } + } else { + const { glibcVersionRuntime } = process.report.getReport().header + return !glibcVersionRuntime + } +} + +switch (platform) { + case 'android': + switch (arch) { + case 'arm64': + localFileExisted = existsSync(join(__dirname, 'rollup.android-arm64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.android-arm64.node') + } else { + nativeBinding = require('@rollup/rollup-android-arm64') + } + } catch (e) { + loadError = e + } + break + case 'arm': + localFileExisted = existsSync(join(__dirname, 'rollup.android-arm-eabi.node')) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.android-arm-eabi.node') + } else { + nativeBinding = require('@rollup/rollup-android-arm-eabi') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Android ${arch}`) + } + break + case 'win32': + switch (arch) { + case 'x64': + localFileExisted = existsSync( + join(__dirname, 'rollup.win32-x64-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.win32-x64-msvc.node') + } else { + nativeBinding = require('@rollup/rollup-win32-x64-msvc') + } + } catch (e) { + loadError = e + } + break + case 'ia32': + localFileExisted = existsSync( + join(__dirname, 'rollup.win32-ia32-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.win32-ia32-msvc.node') + } else { + nativeBinding = require('@rollup/rollup-win32-ia32-msvc') + } + } catch (e) { + loadError = e + } + break + case 'arm64': + localFileExisted = existsSync( + join(__dirname, 'rollup.win32-arm64-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.win32-arm64-msvc.node') + } else { + nativeBinding = require('@rollup/rollup-win32-arm64-msvc') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Windows: ${arch}`) + } + break + case 'darwin': + localFileExisted = existsSync(join(__dirname, 'rollup.darwin-universal.node')) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.darwin-universal.node') + } else { + nativeBinding = require('@rollup/rollup-darwin-universal') + } + break + } catch {} + switch (arch) { + case 'x64': + localFileExisted = existsSync(join(__dirname, 'rollup.darwin-x64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.darwin-x64.node') + } else { + nativeBinding = require('@rollup/rollup-darwin-x64') + } + } catch (e) { + loadError = e + } + break + case 'arm64': + localFileExisted = existsSync( + join(__dirname, 'rollup.darwin-arm64.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.darwin-arm64.node') + } else { + nativeBinding = require('@rollup/rollup-darwin-arm64') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on macOS: ${arch}`) + } + break + case 'freebsd': + if (arch !== 'x64') { + throw new Error(`Unsupported architecture on FreeBSD: ${arch}`) + } + localFileExisted = existsSync(join(__dirname, 'rollup.freebsd-x64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.freebsd-x64.node') + } else { + nativeBinding = require('@rollup/rollup-freebsd-x64') + } + } catch (e) { + loadError = e + } + break + case 'linux': + switch (arch) { + case 'x64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'rollup.linux-x64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.linux-x64-musl.node') + } else { + nativeBinding = require('@rollup/rollup-linux-x64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'rollup.linux-x64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.linux-x64-gnu.node') + } else { + nativeBinding = require('@rollup/rollup-linux-x64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 'arm64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'rollup.linux-arm64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.linux-arm64-musl.node') + } else { + nativeBinding = require('@rollup/rollup-linux-arm64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'rollup.linux-arm64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.linux-arm64-gnu.node') + } else { + nativeBinding = require('@rollup/rollup-linux-arm64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 'arm': + localFileExisted = existsSync( + join(__dirname, 'rollup.linux-arm-gnueabihf.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./rollup.linux-arm-gnueabihf.node') + } else { + nativeBinding = require('@rollup/rollup-linux-arm-gnueabihf') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Linux: ${arch}`) + } + break + default: + throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`) +} + +if (!nativeBinding) { + if (loadError) { + throw loadError + } + throw new Error(`Failed to load native binding`) +} + +const { parse } = nativeBinding + +module.exports.parse = parse diff --git a/npm/android-arm-eabi/README.md b/npm/android-arm-eabi/README.md new file mode 100644 index 000000000..b75a36c99 --- /dev/null +++ b/npm/android-arm-eabi/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-android-arm-eabi` + +This is the **armv7-linux-androideabi** binary for `rollup` diff --git a/npm/android-arm-eabi/package.json b/npm/android-arm-eabi/package.json new file mode 100644 index 000000000..265fac014 --- /dev/null +++ b/npm/android-arm-eabi/package.json @@ -0,0 +1,19 @@ +{ + "name": "@rollup/rollup-android-arm-eabi", + "version": "0.0.0", + "os": [ + "android" + ], + "cpu": [ + "arm" + ], + "files": [ + "rollup.android-arm-eabi.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "main": "./rollup.android-arm-eabi.node" +} diff --git a/npm/android-arm64/README.md b/npm/android-arm64/README.md new file mode 100644 index 000000000..7aa827a92 --- /dev/null +++ b/npm/android-arm64/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-android-arm64` + +This is the **aarch64-linux-android** binary for `rollup` diff --git a/npm/android-arm64/package.json b/npm/android-arm64/package.json new file mode 100644 index 000000000..19c500eee --- /dev/null +++ b/npm/android-arm64/package.json @@ -0,0 +1,19 @@ +{ + "name": "@rollup/rollup-android-arm64", + "version": "0.0.0", + "os": [ + "android" + ], + "cpu": [ + "arm64" + ], + "files": [ + "rollup.android-arm64.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "main": "./rollup.android-arm64.node" +} diff --git a/npm/darwin-arm64/README.md b/npm/darwin-arm64/README.md new file mode 100644 index 000000000..c29619c30 --- /dev/null +++ b/npm/darwin-arm64/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-darwin-arm64` + +This is the **aarch64-apple-darwin** binary for `rollup` diff --git a/npm/darwin-arm64/package.json b/npm/darwin-arm64/package.json new file mode 100644 index 000000000..693f1fcef --- /dev/null +++ b/npm/darwin-arm64/package.json @@ -0,0 +1,19 @@ +{ + "name": "@rollup/rollup-darwin-arm64", + "version": "0.0.0", + "os": [ + "darwin" + ], + "cpu": [ + "arm64" + ], + "files": [ + "rollup.darwin-arm64.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "main": "./rollup.darwin-arm64.node" +} diff --git a/npm/darwin-x64/README.md b/npm/darwin-x64/README.md new file mode 100644 index 000000000..156d37a87 --- /dev/null +++ b/npm/darwin-x64/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-darwin-x64` + +This is the **x86_64-apple-darwin** binary for `rollup` diff --git a/npm/darwin-x64/package.json b/npm/darwin-x64/package.json new file mode 100644 index 000000000..70a6d96c8 --- /dev/null +++ b/npm/darwin-x64/package.json @@ -0,0 +1,19 @@ +{ + "name": "@rollup/rollup-darwin-x64", + "version": "0.0.0", + "os": [ + "darwin" + ], + "cpu": [ + "x64" + ], + "files": [ + "rollup.darwin-x64.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "main": "./rollup.darwin-x64.node" +} diff --git a/npm/linux-arm-gnueabihf/README.md b/npm/linux-arm-gnueabihf/README.md new file mode 100644 index 000000000..1b58b1c47 --- /dev/null +++ b/npm/linux-arm-gnueabihf/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-linux-arm-gnueabihf` + +This is the **armv7-unknown-linux-gnueabihf** binary for `rollup` diff --git a/npm/linux-arm-gnueabihf/package.json b/npm/linux-arm-gnueabihf/package.json new file mode 100644 index 000000000..ff1c7a151 --- /dev/null +++ b/npm/linux-arm-gnueabihf/package.json @@ -0,0 +1,19 @@ +{ + "name": "@rollup/rollup-linux-arm-gnueabihf", + "version": "0.0.0", + "os": [ + "linux" + ], + "cpu": [ + "arm" + ], + "files": [ + "rollup.linux-arm-gnueabihf.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "main": "./rollup.linux-arm-gnueabihf.node" +} diff --git a/npm/linux-arm64-gnu/README.md b/npm/linux-arm64-gnu/README.md new file mode 100644 index 000000000..48e68cb4c --- /dev/null +++ b/npm/linux-arm64-gnu/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-linux-arm64-gnu` + +This is the **aarch64-unknown-linux-gnu** binary for `rollup` diff --git a/npm/linux-arm64-gnu/package.json b/npm/linux-arm64-gnu/package.json new file mode 100644 index 000000000..948275f9f --- /dev/null +++ b/npm/linux-arm64-gnu/package.json @@ -0,0 +1,22 @@ +{ + "name": "@rollup/rollup-linux-arm64-gnu", + "version": "0.0.0", + "os": [ + "linux" + ], + "cpu": [ + "arm64" + ], + "files": [ + "rollup.linux-arm64-gnu.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "libc": [ + "glibc" + ], + "main": "./rollup.linux-arm64-gnu.node" +} diff --git a/npm/linux-arm64-musl/README.md b/npm/linux-arm64-musl/README.md new file mode 100644 index 000000000..3db2751ae --- /dev/null +++ b/npm/linux-arm64-musl/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-linux-arm64-musl` + +This is the **aarch64-unknown-linux-musl** binary for `rollup` diff --git a/npm/linux-arm64-musl/package.json b/npm/linux-arm64-musl/package.json new file mode 100644 index 000000000..d6d4b0c66 --- /dev/null +++ b/npm/linux-arm64-musl/package.json @@ -0,0 +1,22 @@ +{ + "name": "@rollup/rollup-linux-arm64-musl", + "version": "0.0.0", + "os": [ + "linux" + ], + "cpu": [ + "arm64" + ], + "files": [ + "rollup.linux-arm64-musl.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "libc": [ + "musl" + ], + "main": "./rollup.linux-arm64-musl.node" +} diff --git a/npm/linux-x64-gnu/README.md b/npm/linux-x64-gnu/README.md new file mode 100644 index 000000000..cabe280f1 --- /dev/null +++ b/npm/linux-x64-gnu/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-linux-x64-gnu` + +This is the **x86_64-unknown-linux-gnu** binary for `rollup` diff --git a/npm/linux-x64-gnu/package.json b/npm/linux-x64-gnu/package.json new file mode 100644 index 000000000..8d5228dab --- /dev/null +++ b/npm/linux-x64-gnu/package.json @@ -0,0 +1,22 @@ +{ + "name": "@rollup/rollup-linux-x64-gnu", + "version": "0.0.0", + "os": [ + "linux" + ], + "cpu": [ + "x64" + ], + "files": [ + "rollup.linux-x64-gnu.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "libc": [ + "glibc" + ], + "main": "./rollup.linux-x64-gnu.node" +} diff --git a/npm/linux-x64-musl/README.md b/npm/linux-x64-musl/README.md new file mode 100644 index 000000000..5848a6c6e --- /dev/null +++ b/npm/linux-x64-musl/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-linux-x64-musl` + +This is the **x86_64-unknown-linux-musl** binary for `rollup` diff --git a/npm/linux-x64-musl/package.json b/npm/linux-x64-musl/package.json new file mode 100644 index 000000000..7b1ca2564 --- /dev/null +++ b/npm/linux-x64-musl/package.json @@ -0,0 +1,22 @@ +{ + "name": "@rollup/rollup-linux-x64-musl", + "version": "0.0.0", + "os": [ + "linux" + ], + "cpu": [ + "x64" + ], + "files": [ + "rollup.linux-x64-musl.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "libc": [ + "musl" + ], + "main": "./rollup.linux-x64-musl.node" +} diff --git a/npm/win32-arm64-msvc/README.md b/npm/win32-arm64-msvc/README.md new file mode 100644 index 000000000..26ef53bf7 --- /dev/null +++ b/npm/win32-arm64-msvc/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-win32-arm64-msvc` + +This is the **aarch64-pc-windows-msvc** binary for `rollup` diff --git a/npm/win32-arm64-msvc/package.json b/npm/win32-arm64-msvc/package.json new file mode 100644 index 000000000..ddd14a219 --- /dev/null +++ b/npm/win32-arm64-msvc/package.json @@ -0,0 +1,19 @@ +{ + "name": "@rollup/rollup-win32-arm64-msvc", + "version": "0.0.0", + "os": [ + "win32" + ], + "cpu": [ + "arm64" + ], + "files": [ + "rollup.win32-arm64-msvc.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "main": "./rollup.win32-arm64-msvc.node" +} diff --git a/npm/win32-ia32-msvc/README.md b/npm/win32-ia32-msvc/README.md new file mode 100644 index 000000000..9a03e8c74 --- /dev/null +++ b/npm/win32-ia32-msvc/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-win32-ia32-msvc` + +This is the **i686-pc-windows-msvc** binary for `rollup` diff --git a/npm/win32-ia32-msvc/package.json b/npm/win32-ia32-msvc/package.json new file mode 100644 index 000000000..0716a9e8e --- /dev/null +++ b/npm/win32-ia32-msvc/package.json @@ -0,0 +1,19 @@ +{ + "name": "@rollup/rollup-win32-ia32-msvc", + "version": "0.0.0", + "os": [ + "win32" + ], + "cpu": [ + "ia32" + ], + "files": [ + "rollup.win32-ia32-msvc.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "main": "./rollup.win32-ia32-msvc.node" +} diff --git a/npm/win32-x64-msvc/README.md b/npm/win32-x64-msvc/README.md new file mode 100644 index 000000000..7382dbc4f --- /dev/null +++ b/npm/win32-x64-msvc/README.md @@ -0,0 +1,3 @@ +# `@rollup/rollup-win32-x64-msvc` + +This is the **x86_64-pc-windows-msvc** binary for `rollup` diff --git a/npm/win32-x64-msvc/package.json b/npm/win32-x64-msvc/package.json new file mode 100644 index 000000000..cb8094fb7 --- /dev/null +++ b/npm/win32-x64-msvc/package.json @@ -0,0 +1,19 @@ +{ + "name": "@rollup/rollup-win32-x64-msvc", + "version": "0.0.0", + "os": [ + "win32" + ], + "cpu": [ + "x64" + ], + "files": [ + "rollup.win32-x64-msvc.node" + ], + "description": "Native bindings for Rollup", + "author": "Lukas Taegert-Atkinson", + "homepage": "https://rollupjs.org/", + "license": "MIT", + "repository": "rollup/rollup", + "main": "./rollup.win32-x64-msvc.node" +} diff --git a/package-lock.json b/package-lock.json index 72442a541..11e70f240 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rollup", - "version": "4.0.0-0", + "version": "4.0.0-19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rollup", - "version": "4.0.0-0", + "version": "4.0.0-19", "license": "MIT", "bin": { "rollup": "dist/bin/rollup" @@ -20,6 +20,7 @@ "@codemirror/view": "^6.20.2", "@jridgewell/sourcemap-codec": "^1.4.15", "@mermaid-js/mermaid-cli": "^10.4.0", + "@napi-rs/cli": "^2.16.2", "@rollup/plugin-alias": "^5.0.0", "@rollup/plugin-buble": "^1.0.2", "@rollup/plugin-commonjs": "^25.0.4", @@ -31,7 +32,7 @@ "@rollup/pluginutils": "^5.0.4", "@types/estree": "1.0.2", "@types/mocha": "^10.0.1", - "@types/node": "~14.18.63", + "@types/node": "18.0.0", "@types/yargs-parser": "^21.0.1", "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", @@ -39,8 +40,6 @@ "@vue/eslint-config-typescript": "^12.0.0", "acorn": "^8.10.0", "acorn-import-assertions": "^1.9.0", - "acorn-jsx": "^5.3.2", - "acorn-walk": "^8.2.0", "buble": "^0.20.0", "builtin-modules": "^3.3.0", "chokidar": "^3.5.3", @@ -90,6 +89,7 @@ "vite": "^4.4.9", "vitepress": "^1.0.0-rc.20", "vue": "^3.3.4", + "wasm-pack": "^0.12.1", "weak-napi": "^2.0.2", "yargs-parser": "^21.1.1" }, @@ -156,132 +156,132 @@ } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.20.0.tgz", - "integrity": "sha512-uujahcBt4DxduBTvYdwO3sBfHuJvJokiC3BP1+O70fglmE1ShkH8lpXqZBac1rrU3FnNYSUs4pL9lBdTKeRPOQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.19.1.tgz", + "integrity": "sha512-FYAZWcGsFTTaSAwj9Std8UML3Bu8dyWDncM7Ls8g+58UOe4XYdlgzXWbrIgjaguP63pCCbMoExKr61B+ztK3tw==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.20.0" + "@algolia/cache-common": "4.19.1" } }, "node_modules/@algolia/cache-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.20.0.tgz", - "integrity": "sha512-vCfxauaZutL3NImzB2G9LjLt36vKAckc6DhMp05An14kVo8F1Yofb6SIl6U3SaEz8pG2QOB9ptwM5c+zGevwIQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.19.1.tgz", + "integrity": "sha512-XGghi3l0qA38HiqdoUY+wvGyBsGvKZ6U3vTiMBT4hArhP3fOGLXpIINgMiiGjTe4FVlTa5a/7Zf2bwlIHfRqqg==", "dev": true }, "node_modules/@algolia/cache-in-memory": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.20.0.tgz", - "integrity": "sha512-Wm9ak/IaacAZXS4mB3+qF/KCoVSBV6aLgIGFEtQtJwjv64g4ePMapORGmCyulCFwfePaRAtcaTbMcJF+voc/bg==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.19.1.tgz", + "integrity": "sha512-+PDWL+XALGvIginigzu8oU6eWw+o76Z8zHbBovWYcrtWOEtinbl7a7UTt3x3lthv+wNuFr/YD1Gf+B+A9V8n5w==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.20.0" + "@algolia/cache-common": "4.19.1" } }, "node_modules/@algolia/client-account": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.20.0.tgz", - "integrity": "sha512-GGToLQvrwo7am4zVkZTnKa72pheQeez/16sURDWm7Seyz+HUxKi3BM6fthVVPUEBhtJ0reyVtuK9ArmnaKl10Q==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.19.1.tgz", + "integrity": "sha512-Oy0ritA2k7AMxQ2JwNpfaEcgXEDgeyKu0V7E7xt/ZJRdXfEpZcwp9TOg4TJHC7Ia62gIeT2Y/ynzsxccPw92GA==", "dev": true, "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/client-search": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/client-analytics": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.20.0.tgz", - "integrity": "sha512-EIr+PdFMOallRdBTHHdKI3CstslgLORQG7844Mq84ib5oVFRVASuuPmG4bXBgiDbcsMLUeOC6zRVJhv1KWI0ug==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.19.1.tgz", + "integrity": "sha512-5QCq2zmgdZLIQhHqwl55ZvKVpLM3DNWjFI4T+bHr3rGu23ew2bLO4YtyxaZeChmDb85jUdPDouDlCumGfk6wOg==", "dev": true, "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/client-search": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/client-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.20.0.tgz", - "integrity": "sha512-P3WgMdEss915p+knMMSd/fwiHRHKvDu4DYRrCRaBrsfFw7EQHon+EbRSm4QisS9NYdxbS04kcvNoavVGthyfqQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.19.1.tgz", + "integrity": "sha512-3kAIVqTcPrjfS389KQvKzliC559x+BDRxtWamVJt8IVp7LGnjq+aVAXg4Xogkur1MUrScTZ59/AaUd5EdpyXgA==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/client-personalization": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.20.0.tgz", - "integrity": "sha512-N9+zx0tWOQsLc3K4PVRDV8GUeOLAY0i445En79Pr3zWB+m67V+n/8w4Kw1C5LlbHDDJcyhMMIlqezh6BEk7xAQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.19.1.tgz", + "integrity": "sha512-8CWz4/H5FA+krm9HMw2HUQenizC/DxUtsI5oYC0Jxxyce1vsr8cb1aEiSJArQT6IzMynrERif1RVWLac1m36xw==", "dev": true, "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/client-search": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.20.0.tgz", - "integrity": "sha512-zgwqnMvhWLdpzKTpd3sGmMlr4c+iS7eyyLGiaO51zDZWGMkpgoNVmltkzdBwxOVXz0RsFMznIxB9zuarUv4TZg==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.19.1.tgz", + "integrity": "sha512-mBecfMFS4N+yK/p0ZbK53vrZbL6OtWMk8YmnOv1i0LXx4pelY8TFhqKoTit3NPVPwoSNN0vdSN9dTu1xr1XOVw==", "dev": true, "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/logger-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.20.0.tgz", - "integrity": "sha512-xouigCMB5WJYEwvoWW5XDv7Z9f0A8VoXJc3VKwlHJw/je+3p2RcDXfksLI4G4lIVncFUYMZx30tP/rsdlvvzHQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.19.1.tgz", + "integrity": "sha512-i6pLPZW/+/YXKis8gpmSiNk1lOmYCmRI6+x6d2Qk1OdfvX051nRVdalRbEcVTpSQX6FQAoyeaui0cUfLYW5Elw==", "dev": true }, "node_modules/@algolia/logger-console": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.20.0.tgz", - "integrity": "sha512-THlIGG1g/FS63z0StQqDhT6bprUczBI8wnLT3JWvfAQDZX5P6fCg7dG+pIrUBpDIHGszgkqYEqECaKKsdNKOUA==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.19.1.tgz", + "integrity": "sha512-jj72k9GKb9W0c7TyC3cuZtTr0CngLBLmc8trzZlXdfvQiigpUdvTi1KoWIb2ZMcRBG7Tl8hSb81zEY3zI2RlXg==", "dev": true, "dependencies": { - "@algolia/logger-common": "4.20.0" + "@algolia/logger-common": "4.19.1" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.20.0.tgz", - "integrity": "sha512-HbzoSjcjuUmYOkcHECkVTwAelmvTlgs48N6Owt4FnTOQdwn0b8pdht9eMgishvk8+F8bal354nhx/xOoTfwiAw==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.19.1.tgz", + "integrity": "sha512-09K/+t7lptsweRTueHnSnmPqIxbHMowejAkn9XIcJMLdseS3zl8ObnS5GWea86mu3vy4+8H+ZBKkUN82Zsq/zg==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.20.0" + "@algolia/requester-common": "4.19.1" } }, "node_modules/@algolia/requester-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.20.0.tgz", - "integrity": "sha512-9h6ye6RY/BkfmeJp7Z8gyyeMrmmWsMOCRBXQDs4mZKKsyVlfIVICpcSibbeYcuUdurLhIlrOUkH3rQEgZzonng==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.19.1.tgz", + "integrity": "sha512-BisRkcWVxrDzF1YPhAckmi2CFYK+jdMT60q10d7z3PX+w6fPPukxHRnZwooiTUrzFe50UBmLItGizWHP5bDzVQ==", "dev": true }, "node_modules/@algolia/requester-node-http": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.20.0.tgz", - "integrity": "sha512-ocJ66L60ABSSTRFnCHIEZpNHv6qTxsBwJEPfYaSBsLQodm0F9ptvalFkHMpvj5DfE22oZrcrLbOYM2bdPJRHng==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.19.1.tgz", + "integrity": "sha512-6DK52DHviBHTG2BK/Vv2GIlEw7i+vxm7ypZW0Z7vybGCNDeWzADx+/TmxjkES2h15+FZOqVf/Ja677gePsVItA==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.20.0" + "@algolia/requester-common": "4.19.1" } }, "node_modules/@algolia/transporter": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.20.0.tgz", - "integrity": "sha512-Lsii1pGWOAISbzeyuf+r/GPhvHMPHSPrTDWNcIzOE1SG1inlJHICaVe2ikuoRjcpgxZNU54Jl+if15SUCsaTUg==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.19.1.tgz", + "integrity": "sha512-nkpvPWbpuzxo1flEYqNIbGz7xhfhGOKGAZS7tzC+TELgEmi7z99qRyTfNSUlW7LZmB3ACdnqAo+9A9KFBENviQ==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.20.0", - "@algolia/logger-common": "4.20.0", - "@algolia/requester-common": "4.20.0" + "@algolia/cache-common": "4.19.1", + "@algolia/logger-common": "4.19.1", + "@algolia/requester-common": "4.19.1" } }, "node_modules/@ampproject/remapping": { @@ -489,12 +489,12 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -507,7 +507,7 @@ "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-module-imports": "^7.22.5", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", "@babel/helper-validator-identifier": "^7.22.20" @@ -737,14 +737,14 @@ } }, "node_modules/@codemirror/autocomplete": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.9.1.tgz", - "integrity": "sha512-yma56tqD7khIZK4gy4X5lX3/k5ArMiCGat7HEWRF/8L2kqOjVdp2qKZqpcJjwTIjSj6fqKAHqi7IjtH3QFE+Bw==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.9.0.tgz", + "integrity": "sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog==", "dev": true, "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", + "@codemirror/view": "^6.6.0", "@lezer/common": "^1.0.0" }, "peerDependencies": { @@ -796,9 +796,9 @@ } }, "node_modules/@codemirror/lint": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.4.2.tgz", - "integrity": "sha512-wzRkluWb1ptPKdzlsrbwwjYCPLgzU6N88YBAmlZi8WFyuiEduSd05MnJYNogzyc8rPK7pj6m95ptUApc8sHKVA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.4.0.tgz", + "integrity": "sha512-6VZ44Ysh/Zn07xrGkdtNfmHCbGSHZzFBdzWi0pbd7chAQ/iUcpLGX99NYRZTa7Ugqg4kEHCqiHhcZnH0gLIgSg==", "dev": true, "dependencies": { "@codemirror/state": "^6.0.0", @@ -1549,6 +1549,22 @@ "node": "^14.13 || >=16.0" } }, + "node_modules/@napi-rs/cli": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.2.tgz", + "integrity": "sha512-U2aZfnr0s9KkXpZlYC0l5WxWCXL7vJUNpCnWMwq3T9GG9rhYAAUM9CTZsi1Z+0iR2LcHbfq9EfMgoqnuTyUjfg==", + "dev": true, + "bin": { + "napi": "scripts/index.js" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2606,15 +2622,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -2657,25 +2664,25 @@ } }, "node_modules/algoliasearch": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.20.0.tgz", - "integrity": "sha512-y+UHEjnOItoNy0bYO+WWmLWBlPwDjKHW6mNHrPi0NkuhpQOOEbrkwQH/wgKFDLh7qlKjzoKeiRtlpewDPDG23g==", - "dev": true, - "dependencies": { - "@algolia/cache-browser-local-storage": "4.20.0", - "@algolia/cache-common": "4.20.0", - "@algolia/cache-in-memory": "4.20.0", - "@algolia/client-account": "4.20.0", - "@algolia/client-analytics": "4.20.0", - "@algolia/client-common": "4.20.0", - "@algolia/client-personalization": "4.20.0", - "@algolia/client-search": "4.20.0", - "@algolia/logger-common": "4.20.0", - "@algolia/logger-console": "4.20.0", - "@algolia/requester-browser-xhr": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/requester-node-http": "4.20.0", - "@algolia/transporter": "4.20.0" + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.19.1.tgz", + "integrity": "sha512-IJF5b93b2MgAzcE/tuzW0yOPnuUyRgGAtaPv5UUywXM8kzqfdwZTO4sPJBzoGz1eOy6H9uEchsJsBFTELZSu+g==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.19.1", + "@algolia/cache-common": "4.19.1", + "@algolia/cache-in-memory": "4.19.1", + "@algolia/client-account": "4.19.1", + "@algolia/client-analytics": "4.19.1", + "@algolia/client-common": "4.19.1", + "@algolia/client-personalization": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/logger-common": "4.19.1", + "@algolia/logger-console": "4.19.1", + "@algolia/requester-browser-xhr": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/requester-node-http": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/ansi-colors": { @@ -2801,15 +2808,15 @@ } }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", "is-string": "^1.0.7" }, "engines": { @@ -2829,16 +2836,16 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", + "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "get-intrinsic": "^1.1.3" }, "engines": { "node": ">= 0.4" @@ -2848,14 +2855,14 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -2866,14 +2873,14 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -2884,15 +2891,14 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", "get-intrinsic": "^1.2.1", "is-array-buffer": "^3.0.2", "is-shared-array-buffer": "^1.0.2" @@ -2969,6 +2975,29 @@ "node": ">=8" } }, + "node_modules/binary-install": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/binary-install/-/binary-install-1.1.0.tgz", + "integrity": "sha512-rkwNGW+3aQVSZoD0/o3mfPN6Yxh3Id0R/xzTVBVVpGNlVz8EGwusksxRlbk/A5iKTZt9zkMn3qIqmAt3vpfbzg==", + "dev": true, + "dependencies": { + "axios": "^0.26.1", + "rimraf": "^3.0.2", + "tar": "^6.1.11" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/binary-install/node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -3416,9 +3445,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", + "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", "dev": true, "engines": { "node": ">=6" @@ -3926,20 +3955,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", - "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", @@ -3953,12 +3968,11 @@ } }, "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -4051,18 +4065,18 @@ } }, "node_modules/es-abstract": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", - "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.1", "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", + "function.prototype.name": "^1.1.5", "get-intrinsic": "^1.2.1", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", @@ -4078,23 +4092,23 @@ "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", "typed-array-buffer": "^1.0.0", "typed-array-byte-length": "^1.0.0", "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.10" }, "engines": { "node": ">= 0.4" @@ -4915,17 +4929,16 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "dependencies": { - "flatted": "^3.2.7", - "keyv": "^4.5.3", + "flatted": "^3.1.0", "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -5040,6 +5053,36 @@ "node": ">=14.14" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5066,15 +5109,15 @@ "dev": true }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" }, "engines": { "node": ">= 0.4" @@ -6252,12 +6295,6 @@ "node": ">=6" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -6306,15 +6343,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6904,12 +6932,52 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/minisearch": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-6.1.0.tgz", "integrity": "sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==", "dev": true }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/mitt": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", @@ -6917,18 +6985,15 @@ "dev": true }, "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { - "mkdirp": "dist/cjs/src/bin.js" + "mkdirp": "bin/cmd.js" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, "node_modules/mkdirp-classic": { @@ -7202,9 +7267,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", - "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", "dev": true, "bin": { "node-gyp-build": "bin.js", @@ -7507,14 +7572,14 @@ } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { "node": ">= 0.4" @@ -7524,26 +7589,26 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz", + "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", + "es-abstract": "^1.21.2", "get-intrinsic": "^1.2.1" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { "node": ">= 0.4" @@ -7941,9 +8006,9 @@ } }, "node_modules/pinia/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "dev": true, "hasInstallScript": true, "bin": { @@ -8465,14 +8530,14 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -8765,6 +8830,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup-plugin-license/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup-plugin-string": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/rollup-plugin-string/-/rollup-plugin-string-3.0.0.tgz", @@ -8950,13 +9030,13 @@ } }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "get-intrinsic": "^1.2.0", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -9012,7 +9092,10 @@ "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.8.3.tgz", "integrity": "sha512-W9rZfQ9XEfF0O6ntgQOTI7Txc8nkZrO4eJ/pTHK0Br6wWND2sPGPoWg+yGhdIW7wMbLqk8dc23IyEtLlNGpeNw==", "dev": true, - "peer": true + "peer": true, + "engines": { + "node": ">=8.16.0" + } }, "node_modules/semver": { "version": "7.5.4", @@ -9062,20 +9145,6 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, - "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setimmediate-napi": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/setimmediate-napi/-/setimmediate-napi-1.0.6.tgz", @@ -9431,14 +9500,14 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { "node": ">= 0.4" @@ -9448,28 +9517,28 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9593,6 +9662,23 @@ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", "dev": true }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -9621,6 +9707,21 @@ "node": ">=6" } }, + "node_modules/tar/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/terser": { "version": "5.20.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", @@ -9764,9 +9865,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.2.tgz", + "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==", "dev": true, "engines": { "node": ">=16.13.0" @@ -10238,6 +10339,19 @@ "node": "10.* || >= 12.*" } }, + "node_modules/wasm-pack": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/wasm-pack/-/wasm-pack-0.12.1.tgz", + "integrity": "sha512-dIyKWUumPFsGohdndZjDXRFaokUT/kQS+SavbbiXVAvA/eN4riX5QNdB6AhXQx37zNxluxQkuixZUgJ8adKjOg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "binary-install": "^1.0.1" + }, + "bin": { + "wasm-pack": "run.js" + } + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/package.json b/package.json index 172f5bc44..f7b063869 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rollup", - "version": "4.0.0-0", + "version": "4.0.0-19", "description": "Next-generation ES module bundler", "main": "dist/rollup.js", "module": "dist/es/rollup.js", @@ -8,27 +8,64 @@ "bin": { "rollup": "dist/bin/rollup" }, + "napi": { + "name": "rollup", + "package": { + "name": "@rollup/rollup" + }, + "triples": { + "defaults": false, + "additional": [ + "aarch64-apple-darwin", + "aarch64-linux-android", + "aarch64-pc-windows-msvc", + "aarch64-unknown-linux-gnu", + "armv7-linux-androideabi", + "armv7-unknown-linux-gnueabihf", + "i686-pc-windows-msvc", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-musl" + ] + } + }, "scripts": { - "build": "rollup --config rollup.config.ts --configPlugin typescript", + "build": "npm run build:wasm && concurrently -c green,blue \"npm run build:napi -- --release\" \"npm:build:js\" && npm run build:copy-native", + "build:quick": "concurrently -c green,blue 'npm:build:napi' 'npm:build:cjs' && npm run build:copy-native", + "build:napi": "napi build --platform --dts native.d.ts --js native.js --cargo-cwd rust -p bindings_napi --cargo-name bindings_napi", + "build:wasm": "wasm-pack build rust/bindings_wasm --out-dir ../../wasm --target web --no-pack && shx rm wasm/.gitignore", + "build:wasm:node": "wasm-pack build rust/bindings_wasm --out-dir ../../wasm-node --target nodejs --no-pack && shx rm wasm-node/.gitignore", + "update:napi": "npm run build:napi && npm run build:copy-native", + "build:js": "rollup --config rollup.config.ts --configPlugin typescript", + "build:js:node": "rollup --config rollup.config.ts --configPlugin typescript --configIsBuildNode", + "build:prepare": "concurrently -c green,blue \"npm run build:napi -- --release\" \"npm:build:js:node\" && npm run build:copy-native", + "update:js": "npm run build:js && npm run build:copy-native", + "build:copy-native": "shx mkdir -p dist && shx cp rollup.*.node dist/", "dev": "vitepress dev docs", "build:cjs": "rollup --config rollup.config.ts --configPlugin typescript --configTest", - "build:bootstrap": "node dist/bin/rollup --config rollup.config.ts --configPlugin typescript", + "build:bootstrap": "shx mv dist dist-build && node dist-build/bin/rollup --config rollup.config.ts --configPlugin typescript && shx rm -rf dist-build", "build:docs": "vitepress build docs", "preview:docs": "vitepress preview docs", - "ci:lint": "concurrently 'npm:lint:js:nofix' 'npm:lint:markdown:nofix'", - "ci:test": "npm run build:cjs && npm run build:bootstrap && npm run test:all", - "ci:test:only": "npm run build:cjs && npm run build:bootstrap && npm run test:only", - "ci:coverage": "npm run build:cjs && npm run build:bootstrap && nyc --reporter lcovonly mocha", - "lint": "concurrently -c red,green 'npm:lint:js' 'npm:lint:markdown'", + "ci:artifacts": "napi artifacts", + "ci:lint": "concurrently -c red,green,blue 'npm:lint:js:nofix' 'npm:lint:markdown:nofix' 'npm:lint:rust:nofix'", + "ci:test:only": "npm run build:cjs && npm run build:copy-native && npm run build:bootstrap && npm run build:copy-native && npm run test:only", + "ci:test:all": "npm run build:cjs && npm run build:copy-native && npm run build:bootstrap && npm run build:copy-native && concurrently --kill-others-on-fail -c green,blue,magenta,cyan 'npm:test:only' 'npm:test:typescript' 'npm:test:leak' 'npm:test:browser'", + "ci:coverage": "npm run build:cjs && npm run build:copy-native && npm run build:bootstrap && npm run build:copy-native && nyc --reporter lcovonly mocha", + "lint": "concurrently -c red,green,blue 'npm:lint:js' 'npm:lint:markdown' 'npm:lint:rust'", "lint:js": "eslint . --fix --cache", "lint:js:nofix": "eslint . --cache", "lint:markdown": "prettier --write \"**/*.md\"", "lint:markdown:nofix": "prettier --check \"**/*.md\"", + "lint:rust": "cd rust && cargo fmt", + "lint:rust:nofix": "cd rust && cargo fmt --check", "perf": "npm run build:cjs && node --expose-gc scripts/perf.js", "perf:init": "node scripts/perf-init.js", - "prepare": "husky install && node scripts/check-release.js || npm run build", - "prepublishOnly": "node scripts/check-release.js", - "release": "node scripts/release.js", + "prepare": "husky install && node scripts/check-release.js || npm run build:prepare", + "prepublishOnly": "node scripts/check-release.js && node scripts/prepublish.js", + "postpublish": "node scripts/postpublish.js", + "prepublish:napi": "napi prepublish --skip-gh-release", + "release": "node scripts/prepare-release.js", "release:docs": "git fetch --update-head-ok origin master:master && git branch --force documentation-published master && git push origin documentation-published", "test": "npm run build && npm run test:all", "test:update-snapshots": "node scripts/update-snapshots.js", @@ -74,6 +111,7 @@ "@codemirror/view": "^6.20.2", "@jridgewell/sourcemap-codec": "^1.4.15", "@mermaid-js/mermaid-cli": "^10.4.0", + "@napi-rs/cli": "^2.16.2", "@rollup/plugin-alias": "^5.0.0", "@rollup/plugin-buble": "^1.0.2", "@rollup/plugin-commonjs": "^25.0.4", @@ -85,7 +123,7 @@ "@rollup/pluginutils": "^5.0.4", "@types/estree": "1.0.2", "@types/mocha": "^10.0.1", - "@types/node": "~14.18.63", + "@types/node": "18.0.0", "@types/yargs-parser": "^21.0.1", "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", @@ -93,8 +131,6 @@ "@vue/eslint-config-typescript": "^12.0.0", "acorn": "^8.10.0", "acorn-import-assertions": "^1.9.0", - "acorn-jsx": "^5.3.2", - "acorn-walk": "^8.2.0", "buble": "^0.20.0", "builtin-modules": "^3.3.0", "chokidar": "^3.5.3", @@ -144,6 +180,7 @@ "vite": "^4.4.9", "vitepress": "^1.0.0-rc.20", "vue": "^3.3.4", + "wasm-pack": "^0.12.1", "weak-napi": "^2.0.2", "yargs-parser": "^21.1.1" }, @@ -151,6 +188,7 @@ "semver": "^7.5.4" }, "files": [ + "dist/*.node", "dist/**/*.js", "dist/*.d.ts", "dist/bin/rollup", diff --git a/rollup.config.ts b/rollup.config.ts index 83de4618f..dae1d86f6 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -13,7 +13,10 @@ import { moduleAliases } from './build-plugins/aliases'; import cleanBeforeWrite from './build-plugins/clean-before-write'; import { copyBrowserTypes, copyNodeTypes } from './build-plugins/copy-types'; import emitModulePackageFile from './build-plugins/emit-module-package-file'; +import { emitNativeEntry } from './build-plugins/emit-native-entry'; +import emitWasmFile from './build-plugins/emit-wasm-file'; import esmDynamicImport from './build-plugins/esm-dynamic-import'; +import { externalNativeImport } from './build-plugins/external-native-import'; import { fsEventsReplacement } from './build-plugins/fs-events-replacement'; import getLicenseHandler from './build-plugins/generate-license-file'; import getBanner from './build-plugins/get-banner'; @@ -46,7 +49,8 @@ const nodePlugins: readonly Plugin[] = [ include: 'node_modules/**' }), typescript(), - cleanBeforeWrite('dist') + cleanBeforeWrite('dist'), + externalNativeImport() ]; export default async function ( @@ -80,6 +84,7 @@ export default async function ( }, plugins: [ ...nodePlugins, + emitNativeEntry(), addCliEntry(), esmDynamicImport(), !command.configTest && collectLicenses(), @@ -93,6 +98,16 @@ export default async function ( return commonJSBuild; } + const exitOnCloseBundle: Plugin = { + closeBundle() { + // On CI, macOS runs sometimes do not close properly. This is a hack + // to fix this until the problem is understood. + console.log('Force quit.'); + setTimeout(() => process.exit(0)); + }, + name: 'force-close' + }; + const esmBuild: RollupOptions = { ...commonJSBuild, input: { @@ -109,6 +124,11 @@ export default async function ( plugins: [...nodePlugins, emitModulePackageFile(), collectLicenses(), writeLicense()] }; + if (command.configIsBuildNode) { + (esmBuild.plugins as Plugin[]).push(exitOnCloseBundle); + return [commonJSBuild, esmBuild]; + } + const { collectLicenses: collectLicensesBrowser, writeLicense: writeLicenseBrowser } = getLicenseHandler(fileURLToPath(new URL('browser', import.meta.url))); @@ -142,15 +162,8 @@ export default async function ( collectLicensesBrowser(), writeLicenseBrowser(), cleanBeforeWrite('browser/dist'), - { - closeBundle() { - // On CI, macOS runs sometimes do not close properly. This is a hack - // to fix this until the problem is understood. - console.log('Force quit.'); - setTimeout(() => process.exit(0)); - }, - name: 'force-close' - } + emitWasmFile(), + exitOnCloseBundle ], strictDeprecations: true, treeshake diff --git a/rust/Cargo.lock b/rust/Cargo.lock new file mode 100644 index 000000000..f6bb6ea8a --- /dev/null +++ b/rust/Cargo.lock @@ -0,0 +1,2452 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "serde", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "ast_node" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c09c69dffe06d222d072c878c3afe86eee2179806f20503faec97250268b4c24" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.27", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "better_scoped_tls" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794edcc9b3fb07bb4aecaa11f093fd45663b4feadb782d68303a2268bc2701de" +dependencies = [ + "scoped-tls", +] + +[[package]] +name = "bindings_napi" +version = "0.0.0" +dependencies = [ + "napi", + "napi-build", + "napi-derive", + "parse_ast", +] + +[[package]] +name = "bindings_wasm" +version = "0.0.0" +dependencies = [ + "parse_ast", + "wasm-bindgen", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "browserslist-rs" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9bda9b4595376bf255f68dafb5dcc5b0e2842b38dc2a7b52c4e0bfe9fd1c651" +dependencies = [ + "ahash", + "anyhow", + "chrono", + "either", + "getrandom", + "itertools", + "js-sys", + "nom", + "once_cell", + "quote", + "serde", + "serde-wasm-bindgen", + "serde_json", + "string_cache", + "string_cache_codegen", + "thiserror", + "wasm-bindgen", +] + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f34ba9a9bcb8645379e9de8cb3ecfcf4d1c85ba66d90deb3259206fa5aa193b" +dependencies = [ + "quote", + "syn 2.0.27", +] + +[[package]] +name = "dashmap" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" +dependencies = [ + "cfg-if", + "hashbrown 0.14.0", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "from_variant" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ec5dc38ee19078d84a692b1c41181ff9f94331c76cee66ff0208c770b5e54f" +dependencies = [ + "pmutil", + "proc-macro2", + "swc_macros_common", + "syn 2.0.27", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "is-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4467ed1321b310c2625c5aa6c1b1ffc5de4d9e42668cf697a08fb033ee8265e" +dependencies = [ + "Inflector", + "pmutil", + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "is_ci" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonc-parser" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b56a20e76235284255a09fcd1f45cf55d3c524ea657ebd3854735925c57743d" +dependencies = [ + "serde_json", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "lru" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" +dependencies = [ + "hashbrown 0.13.2", +] + +[[package]] +name = "memchr" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miette" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c90329e44f9208b55f45711f9558cec15d7ef8295cc65ecd6d4188ae8edc58c" +dependencies = [ + "atty", + "backtrace", + "miette-derive", + "once_cell", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b5bc45b761bcf1b5e6e6c4128cd93b84c218721a8d9b894aa0aff4ed180174c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "napi" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ede2d12cd6fce44da537a4be1f5510c73be2506c2e32dfaaafd1f36968f3a0e" +dependencies = [ + "bitflags 2.3.3", + "ctor", + "napi-derive", + "napi-sys", + "once_cell", +] + +[[package]] +name = "napi-build" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e" + +[[package]] +name = "napi-derive" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1c6a8fa84d549aa8708fcd062372bf8ec6e849de39016ab921067d21bde367" +dependencies = [ + "cfg-if", + "convert_case", + "napi-derive-backend", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "napi-derive-backend" +version = "1.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20bbc7c69168d06a848f925ec5f0e0997f98e8c8d4f2cc30157f0da51c009e17" +dependencies = [ + "convert_case", + "once_cell", + "proc-macro2", + "quote", + "regex", + "semver 1.0.18", + "syn 1.0.109", +] + +[[package]] +name = "napi-sys" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "166b5ef52a3ab5575047a9fe8d4a030cdd0f63c96f071cd6907674453b07bae3" +dependencies = [ + "libloading", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "normpath" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a9da8c9922c35a1033d76f7272dfc2e7ee20392083d75aeea6ced23c6266578" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.2", + "libc", +] + +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "parse_ast" +version = "0.0.0" +dependencies = [ + "anyhow", + "parking_lot", + "swc", + "swc_common", + "swc_ecma_ast", + "swc_ecma_lints", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_visit", + "swc_error_reporters", +] + +[[package]] +name = "path-clean" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "petgraph" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros", + "phf_shared", + "proc-macro-hack", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" + +[[package]] +name = "pmutil" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a40bc70c2c58040d2d8b167ba9a5ff59fc9dab7ad44771cfde3dcfde7a09c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "preset_env_base" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae83c5857727636a1f2c7188632c8a57986d2f1d2e2cf45f2642f5856c5b8e85" +dependencies = [ + "ahash", + "anyhow", + "browserslist-rs", + "dashmap", + "from_variant", + "once_cell", + "semver 1.0.18", + "serde", + "st-map", + "tracing", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "quote" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radix_fmt" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce082a9940a7ace2ad4a8b7d0b1eac6aa378895f18be598230c5f2284ac05426" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "ryu-js" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_derive" +version = "1.0.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "serde_json" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "static_assertions", + "version_check", +] + +[[package]] +name = "smawk" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" + +[[package]] +name = "sourcemap" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8df03d85f2767c45e61b4453eb6144153c80399e4fdd6407a6d16cb87cc0347" +dependencies = [ + "data-encoding", + "debugid", + "if_chain", + "rustc_version", + "serde", + "serde_json", + "unicode-id", + "url", +] + +[[package]] +name = "st-map" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f352d5d14be5a1f956d76ae0c8060c3487aaa2a080f10a4b4ff023c7c05a9047" +dependencies = [ + "arrayvec", + "static-map-macro", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + +[[package]] +name = "static-map-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7628ae0bd92555d3de4303da41a5c8b1c5363e892001325f34e4be9ed024d0d7" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", +] + +[[package]] +name = "string_enum" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fa4d4f81d7c05b9161f8de839975d3326328b8ba2831164b465524cc2f55252" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.27", +] + +[[package]] +name = "supports-color" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f" +dependencies = [ + "atty", + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "590b34f7c5f01ecc9d78dba4b3f445f31df750a67621cf31626f3b7441ce6406" +dependencies = [ + "atty", +] + +[[package]] +name = "supports-unicode" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8b945e45b417b125a8ec51f1b7df2f8df7920367700d1f98aedd21e5735f8b2" +dependencies = [ + "atty", +] + +[[package]] +name = "swc" +version = "0.265.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d5177297253ff4013d2730770b4d28d227d168dbb5b3d7bc9dd785d1b07dc0" +dependencies = [ + "anyhow", + "base64", + "dashmap", + "either", + "indexmap", + "jsonc-parser", + "lru", + "once_cell", + "parking_lot", + "pathdiff", + "regex", + "rustc-hash", + "serde", + "serde_json", + "sourcemap", + "swc_atoms", + "swc_cached", + "swc_common", + "swc_config", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_ext_transforms", + "swc_ecma_lints", + "swc_ecma_loader", + "swc_ecma_minifier", + "swc_ecma_parser", + "swc_ecma_preset_env", + "swc_ecma_transforms", + "swc_ecma_transforms_base", + "swc_ecma_transforms_compat", + "swc_ecma_transforms_optimization", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_error_reporters", + "swc_node_comments", + "swc_timer", + "swc_visit", + "tracing", + "url", +] + +[[package]] +name = "swc_atoms" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f54563d7dcba626d4acfe14ed12def7ecc28e004debe3ecd2c3ee07cc47e449" +dependencies = [ + "once_cell", + "rustc-hash", + "serde", + "string_cache", + "string_cache_codegen", + "triomphe", +] + +[[package]] +name = "swc_cached" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b8051bbf1c23817f9f2912fce18d9a6efcaaf8f8e1a4c69dbaf72bcaf71136" +dependencies = [ + "ahash", + "anyhow", + "dashmap", + "once_cell", + "regex", + "serde", +] + +[[package]] +name = "swc_common" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cb7fcd56655c8ae7dcf2344f0be6cbff4d9c7cb401fe3ec8e56e1de8dfe582" +dependencies = [ + "ahash", + "ast_node", + "better_scoped_tls", + "cfg-if", + "either", + "from_variant", + "new_debug_unreachable", + "num-bigint", + "once_cell", + "parking_lot", + "rustc-hash", + "serde", + "siphasher", + "sourcemap", + "string_cache", + "swc_atoms", + "swc_eq_ignore_macros", + "swc_visit", + "tracing", + "unicode-width", + "url", +] + +[[package]] +name = "swc_config" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba1c7a40d38f9dd4e9a046975d3faf95af42937b34b2b963be4d8f01239584b" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "swc_config_macro", +] + +[[package]] +name = "swc_config_macro" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5b5aaca9a0082be4515f0fbbecc191bf5829cd25b5b9c0a2810f6a2bb0d6829" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.27", +] + +[[package]] +name = "swc_ecma_ast" +version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc2286cedd688a68f214faa1c19bb5cceab7c9c54d0cbe3273e4c1704e38f69" +dependencies = [ + "bitflags 2.3.3", + "is-macro", + "num-bigint", + "scoped-tls", + "serde", + "string_enum", + "swc_atoms", + "swc_common", + "unicode-id", +] + +[[package]] +name = "swc_ecma_codegen" +version = "0.144.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e62ba2c0ed1f119fc1a76542d007f1b2c12854d54dea15f5491363227debe11" +dependencies = [ + "memchr", + "num-bigint", + "once_cell", + "rustc-hash", + "serde", + "sourcemap", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_codegen_macros", + "tracing", +] + +[[package]] +name = "swc_ecma_codegen_macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdff076dccca6cc6a0e0b2a2c8acfb066014382bc6df98ec99e755484814384" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.27", +] + +[[package]] +name = "swc_ecma_ext_transforms" +version = "0.108.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57eb7bbfbd7d0b4c2d5abf6936efb16d5a228508246a19795d59c849dbff073e" +dependencies = [ + "phf", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_lints" +version = "0.87.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5f56635e73df9d6f4fa1ecbc1c65e9175ad2593fada76b13b05c5d2895b8a1d" +dependencies = [ + "auto_impl", + "dashmap", + "parking_lot", + "rayon", + "regex", + "serde", + "swc_atoms", + "swc_common", + "swc_config", + "swc_ecma_ast", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_loader" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d7c322462657ae27ac090a2c89f7e456c94416284a2f5ecf66c43a6a3c19d1" +dependencies = [ + "anyhow", + "dashmap", + "lru", + "normpath", + "once_cell", + "parking_lot", + "path-clean", + "pathdiff", + "serde", + "serde_json", + "swc_cached", + "swc_common", + "tracing", +] + +[[package]] +name = "swc_ecma_minifier" +version = "0.186.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17745ea0c4f10846a29dfc1fe8d5e5141b57682a5645373be1252efa04d6937c" +dependencies = [ + "arrayvec", + "indexmap", + "num-bigint", + "num_cpus", + "once_cell", + "parking_lot", + "radix_fmt", + "regex", + "rustc-hash", + "ryu-js", + "serde", + "serde_json", + "swc_atoms", + "swc_cached", + "swc_common", + "swc_config", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_transforms_optimization", + "swc_ecma_usage_analyzer", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_timer", + "tracing", +] + +[[package]] +name = "swc_ecma_parser" +version = "0.139.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eab46cb863bc5cd61535464e07e5b74d5f792fa26a27b9f6fd4c8daca9903b7" +dependencies = [ + "either", + "num-bigint", + "num-traits", + "serde", + "smallvec", + "smartstring", + "stacker", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "tracing", + "typed-arena", +] + +[[package]] +name = "swc_ecma_preset_env" +version = "0.200.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb0e2940accc1b1d9f6bbe06190a84a43b1b7436d3fdae93f486a1971a045727" +dependencies = [ + "anyhow", + "dashmap", + "indexmap", + "once_cell", + "preset_env_base", + "rustc-hash", + "semver 1.0.18", + "serde", + "serde_json", + "st-map", + "string_enum", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_transforms" +version = "0.223.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18ab21459fd0b85928da4654852ec875bb0f86d4ff17cc3de90ede6997e0ae56" +dependencies = [ + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_transforms_compat", + "swc_ecma_transforms_module", + "swc_ecma_transforms_optimization", + "swc_ecma_transforms_proposal", + "swc_ecma_transforms_react", + "swc_ecma_transforms_typescript", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_transforms_base" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e082ff07a2d31fd8e480dc590dd81efb75106e79bec24483dbece03630ca67b3" +dependencies = [ + "better_scoped_tls", + "bitflags 2.3.3", + "indexmap", + "once_cell", + "phf", + "rustc-hash", + "serde", + "smallvec", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_utils", + "swc_ecma_visit", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_classes" +version = "0.121.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71f54c8ce83b25e89dc60d09686ebc8c4d0376bc82c21ac1a14a1b0a339c714f" +dependencies = [ + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_transforms_compat" +version = "0.158.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4da9073b7bfa9b2fd0a46f98fae9c1a205d1c7e8b91d8cd43c4077ce598c75b7" +dependencies = [ + "arrayvec", + "indexmap", + "is-macro", + "num-bigint", + "serde", + "smallvec", + "swc_atoms", + "swc_common", + "swc_config", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_transforms_classes", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_trace_macro", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_macros" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188eab297da773836ef5cf2af03ee5cca7a563e1be4b146f8141452c28cc690" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.27", +] + +[[package]] +name = "swc_ecma_transforms_module" +version = "0.175.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18db89901084ec9dddd7e2c32f00df335dfcd3b1e99dc146918223a625dc4638" +dependencies = [ + "Inflector", + "anyhow", + "bitflags 2.3.3", + "indexmap", + "is-macro", + "path-clean", + "pathdiff", + "regex", + "serde", + "swc_atoms", + "swc_cached", + "swc_common", + "swc_ecma_ast", + "swc_ecma_loader", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_utils", + "swc_ecma_visit", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_optimization" +version = "0.192.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a364e8747c2f2ef9715bf9626eefd3462e3b50fa137927dfa156276bf53f38aa" +dependencies = [ + "dashmap", + "indexmap", + "once_cell", + "petgraph", + "rustc-hash", + "serde_json", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_fast_graph", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_proposal" +version = "0.166.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2e61b71de4a1b403e6451d0c0fbeb66e27ef369c341a52b3827c9cf6df052c" +dependencies = [ + "either", + "rustc-hash", + "serde", + "smallvec", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_transforms_classes", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_transforms_react" +version = "0.178.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2313ff98bf87985b16be2d6ca7a3a9988888b6a02550a0eaa2a74cf2d2c7347" +dependencies = [ + "base64", + "dashmap", + "indexmap", + "once_cell", + "serde", + "sha-1", + "string_enum", + "swc_atoms", + "swc_common", + "swc_config", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_transforms_typescript" +version = "0.182.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4be392ce94eecdb6e7afacec9080fb5be3cc36cfc376cd33f7e933ce6600768" +dependencies = [ + "serde", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_transforms_react", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_usage_analyzer" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1aabf52dfd20abdbe5087107273d250d134f5b0fa2251cbb42bbfbec88404af" +dependencies = [ + "indexmap", + "rustc-hash", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_timer", + "tracing", +] + +[[package]] +name = "swc_ecma_utils" +version = "0.122.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11006a3398ffd4693c4d3b0a1b1a5030edbdc04228159f5301120a6178144708" +dependencies = [ + "indexmap", + "num_cpus", + "once_cell", + "rustc-hash", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_visit", + "tracing", + "unicode-id", +] + +[[package]] +name = "swc_ecma_visit" +version = "0.95.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f628ec196e76e67892441e14eef2e423a738543d32bffdabfeec20c29582117" +dependencies = [ + "num-bigint", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_visit", + "tracing", +] + +[[package]] +name = "swc_eq_ignore_macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05a95d367e228d52484c53336991fdcf47b6b553ef835d9159db4ba40efb0ee8" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "swc_error_reporters" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6530d0def50c33d14064a43837b7e3c1fe8716ee6c3495a478835793caae2c97" +dependencies = [ + "anyhow", + "miette", + "once_cell", + "parking_lot", + "swc_common", +] + +[[package]] +name = "swc_fast_graph" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a407fff2eb5ce3bee7513bdd9531a7be0285bc1213500b6d98ad235428d94cce" +dependencies = [ + "indexmap", + "petgraph", + "rustc-hash", + "swc_common", +] + +[[package]] +name = "swc_macros_common" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a273205ccb09b51fabe88c49f3b34c5a4631c4c00a16ae20e03111d6a42e832" +dependencies = [ + "pmutil", + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "swc_node_comments" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73cee5dededc1e0d19e53dd0a41a343a43e21ed9b62c3df0fdd5801c11533bc9" +dependencies = [ + "dashmap", + "swc_atoms", + "swc_common", +] + +[[package]] +name = "swc_timer" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95c548665c811d1c5def583d3d6ca0291e5397122c0de6362bb201cc2de8beff" +dependencies = [ + "tracing", +] + +[[package]] +name = "swc_trace_macro" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff9719b6085dd2824fd61938a881937be14b08f95e2d27c64c825a9f65e052ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "swc_visit" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87c337fbb2d191bf371173dea6a957f01899adb8f189c6c31b122a6cfc98fc3" +dependencies = [ + "either", + "swc_visit_macros", +] + +[[package]] +name = "swc_visit_macros" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f322730fb82f3930a450ac24de8c98523af7d34ab8cb2f46bcb405839891a99" +dependencies = [ + "Inflector", + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.27", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "triomphe" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" +dependencies = [ + "serde", + "stable_deref_trait", +] + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-id" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "url" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.27", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.27", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 000000000..c6b84b979 --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,10 @@ +[profile.release] +lto = true + +[workspace] +resolver = "2" +members = [ + "bindings_napi", + "bindings_wasm", + "parse_ast", +] diff --git a/rust/bindings_napi/Cargo.toml b/rust/bindings_napi/Cargo.toml new file mode 100644 index 000000000..516950089 --- /dev/null +++ b/rust/bindings_napi/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "bindings_napi" +version = "0.0.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib"] + +[dependencies] +# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix +napi = { version = "2.12.2", default-features = false, features = ["napi4"] } +napi-derive = "2.12.2" +parse_ast = { path = "../parse_ast" } + +[build-dependencies] +napi-build = "2.0.1" diff --git a/rust/bindings_napi/build.rs b/rust/bindings_napi/build.rs new file mode 100644 index 000000000..1f866b6a3 --- /dev/null +++ b/rust/bindings_napi/build.rs @@ -0,0 +1,5 @@ +extern crate napi_build; + +fn main() { + napi_build::setup(); +} diff --git a/rust/bindings_napi/src/lib.rs b/rust/bindings_napi/src/lib.rs new file mode 100644 index 000000000..2a0087abf --- /dev/null +++ b/rust/bindings_napi/src/lib.rs @@ -0,0 +1,10 @@ +#![deny(clippy::all)] + +use napi::bindgen_prelude::*; +use napi_derive::napi; +use parse_ast::parse_ast; + +#[napi] +pub fn parse(code: String) -> Buffer { + parse_ast(code).into() +} diff --git a/rust/bindings_wasm/Cargo.toml b/rust/bindings_wasm/Cargo.toml new file mode 100644 index 000000000..50a988942 --- /dev/null +++ b/rust/bindings_wasm/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "bindings_wasm" +version = "0.0.0" +edition = "2021" + +[dependencies] +wasm-bindgen = "0.2.87" +parse_ast = { path = "../parse_ast" } + +[lib] +crate-type = ["cdylib", "rlib"] diff --git a/rust/bindings_wasm/src/lib.rs b/rust/bindings_wasm/src/lib.rs new file mode 100644 index 000000000..f75a62ab3 --- /dev/null +++ b/rust/bindings_wasm/src/lib.rs @@ -0,0 +1,7 @@ +use parse_ast::parse_ast; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn parse(code: String) -> Vec { + parse_ast(code) +} diff --git a/rust/parse_ast/Cargo.toml b/rust/parse_ast/Cargo.toml new file mode 100644 index 000000000..faefca303 --- /dev/null +++ b/rust/parse_ast/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "parse_ast" +version = "0.0.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.71" +swc = "0.265.7" +swc_common = "0.32.0" +swc_ecma_ast = "0.109.0" +swc_ecma_parser = "0.139.0" +swc_error_reporters = "0.16.0" +parking_lot = "0.12.1" +swc_ecma_lints = "0.87.2" +swc_ecma_transforms_base = "0.132.2" +swc_ecma_visit = "0.95.0" diff --git a/rust/parse_ast/src/convert_ast.rs b/rust/parse_ast/src/convert_ast.rs new file mode 100644 index 000000000..e7d6154cd --- /dev/null +++ b/rust/parse_ast/src/convert_ast.rs @@ -0,0 +1,2 @@ +pub mod annotations; +pub mod converter; diff --git a/rust/parse_ast/src/convert_ast/annotations.rs b/rust/parse_ast/src/convert_ast/annotations.rs new file mode 100644 index 000000000..6128718a7 --- /dev/null +++ b/rust/parse_ast/src/convert_ast/annotations.rs @@ -0,0 +1,129 @@ +use std::cell::RefCell; + +use swc_common::comments::{Comment, Comments}; +use swc_common::BytePos; + +#[derive(Default)] +pub struct SequentialComments { + annotations: RefCell>, +} + +impl SequentialComments { + pub fn add_comment(&self, comment: Comment) { + if comment.text.starts_with('#') && comment.text.contains("sourceMappingURL=") { + self.annotations.borrow_mut().push(AnnotationWithType { + comment, + kind: AnnotationKind::SourceMappingUrl, + }); + return; + } + let mut search_position = 1; + while let Some(Some(match_position)) = comment.text.get(search_position..).map(|s| s.find("__")) + { + search_position += match_position; + match &comment.text[search_position - 1..search_position] { + "@" | "#" => { + let annotation_slice = &comment.text[search_position..]; + if annotation_slice.starts_with("__PURE__") { + self.annotations.borrow_mut().push(AnnotationWithType { + comment, + kind: AnnotationKind::Pure, + }); + return; + } + if annotation_slice.starts_with("__NO_SIDE_EFFECTS__") { + self.annotations.borrow_mut().push(AnnotationWithType { + comment, + kind: AnnotationKind::NoSideEffects, + }); + return; + } + } + _ => {} + } + search_position += 3; + } + } + + pub fn take_annotations(self) -> Vec { + self.annotations.take() + } +} + +impl Comments for SequentialComments { + fn add_leading(&self, _: BytePos, comment: Comment) { + self.add_comment(comment); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn add_leading_comments(&self, _: BytePos, _: Vec) { + panic!("add_leading_comments"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn has_leading(&self, _: BytePos) -> bool { + panic!("has_leading"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn move_leading(&self, _: BytePos, _: BytePos) { + panic!("move_leading"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn take_leading(&self, _: BytePos) -> Option> { + panic!("take_leading"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn get_leading(&self, _: BytePos) -> Option> { + panic!("get_leading"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn add_trailing(&self, _: BytePos, comment: Comment) { + self.add_comment(comment); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn add_trailing_comments(&self, _: BytePos, _: Vec) { + panic!("add_trailing_comments"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn has_trailing(&self, _: BytePos) -> bool { + panic!("has_trailing"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn move_trailing(&self, _: BytePos, _: BytePos) { + panic!("move_trailing"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn take_trailing(&self, _: BytePos) -> Option> { + panic!("take_trailing"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn get_trailing(&self, _: BytePos) -> Option> { + panic!("get_trailing"); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn add_pure_comment(&self, _: BytePos) { + panic!("add_pure_comment"); + } +} + +pub struct AnnotationWithType { + pub comment: Comment, + pub kind: AnnotationKind, +} + +#[derive(Clone, PartialEq, Debug)] +pub enum AnnotationKind { + Pure, + NoSideEffects, + SourceMappingUrl, +} diff --git a/rust/parse_ast/src/convert_ast/converter.rs b/rust/parse_ast/src/convert_ast/converter.rs new file mode 100644 index 000000000..0f65625d6 --- /dev/null +++ b/rust/parse_ast/src/convert_ast/converter.rs @@ -0,0 +1,2762 @@ +use swc::atoms::JsWord; +use swc_common::Span; +use swc_ecma_ast::{ + ArrayLit, ArrayPat, ArrowExpr, AssignExpr, AssignOp, AssignPat, AssignPatProp, AwaitExpr, BigInt, + BinExpr, BinaryOp, BindingIdent, BlockStmt, BlockStmtOrExpr, Bool, BreakStmt, CallExpr, Callee, + CatchClause, Class, ClassDecl, ClassExpr, ClassMember, ClassMethod, ClassProp, ComputedPropName, + CondExpr, Constructor, ContinueStmt, DebuggerStmt, Decl, DefaultDecl, DoWhileStmt, EmptyStmt, + ExportAll, ExportDecl, ExportDefaultDecl, ExportDefaultExpr, ExportNamedSpecifier, + ExportSpecifier, Expr, ExprOrSpread, ExprStmt, FnExpr, ForHead, ForInStmt, ForOfStmt, ForStmt, + Function, GetterProp, Ident, IfStmt, ImportDecl, ImportDefaultSpecifier, ImportNamedSpecifier, + ImportSpecifier, ImportStarAsSpecifier, KeyValuePatProp, KeyValueProp, LabeledStmt, Lit, + MemberExpr, MemberProp, MetaPropExpr, MetaPropKind, MethodKind, MethodProp, ModuleDecl, + ModuleExportName, ModuleItem, NamedExport, NewExpr, Null, Number, ObjectLit, ObjectPat, + ObjectPatProp, OptCall, OptChainBase, OptChainExpr, ParamOrTsParamProp, ParenExpr, Pat, + PatOrExpr, PrivateMethod, PrivateName, PrivateProp, Program, Prop, PropName, PropOrSpread, Regex, + RestPat, ReturnStmt, SeqExpr, SetterProp, SpreadElement, StaticBlock, Stmt, Str, Super, + SuperProp, SuperPropExpr, SwitchCase, SwitchStmt, TaggedTpl, ThisExpr, ThrowStmt, Tpl, + TplElement, TryStmt, UnaryExpr, UnaryOp, UpdateExpr, UpdateOp, VarDecl, VarDeclKind, + VarDeclOrExpr, VarDeclarator, WhileStmt, YieldExpr, +}; + +use crate::convert_ast::annotations::{AnnotationKind, AnnotationWithType}; +use crate::convert_ast::converter::analyze_code::find_first_occurrence_outside_comment; +use crate::convert_ast::converter::node_types::*; +use crate::convert_ast::converter::string_constants::*; +use crate::convert_ast::converter::utf16_positions::{ + ConvertedAnnotation, Utf8ToUtf16ByteIndexConverterAndAnnotationHandler, +}; + +mod analyze_code; +pub mod node_types; +mod string_constants; +mod utf16_positions; + +pub struct AstConverter<'a> { + buffer: Vec, + code: &'a [u8], + index_converter: Utf8ToUtf16ByteIndexConverterAndAnnotationHandler<'a>, +} + +impl<'a> AstConverter<'a> { + pub fn new(code: &'a str, annotations: &'a Vec) -> Self { + Self { + // TODO SWC This is just a wild guess and should be refined with a large + // block of minified code + buffer: Vec::with_capacity(20 * code.len()), + code: code.as_bytes(), + index_converter: Utf8ToUtf16ByteIndexConverterAndAnnotationHandler::new(code, annotations), + } + } + + pub fn convert_ast_to_buffer(mut self, node: &Program) -> Vec { + self.convert_program(node); + self.buffer.shrink_to_fit(); + self.buffer + } + + // === helpers + fn add_type_and_positions(&mut self, node_type: &[u8; 4], span: &Span) { + // type + self.buffer.extend_from_slice(node_type); + // start + self + .buffer + .extend_from_slice(&(self.index_converter.convert(span.lo.0 - 1, false)).to_ne_bytes()); + // end + self + .buffer + .extend_from_slice(&(self.index_converter.convert(span.hi.0 - 1, false)).to_ne_bytes()); + } + + fn add_type_and_explicit_start(&mut self, node_type: &[u8; 4], start: u32) -> usize { + // type + self.buffer.extend_from_slice(node_type); + // start + self + .buffer + .extend_from_slice(&(self.index_converter.convert(start, false)).to_ne_bytes()); + // end + let end_position = self.buffer.len(); + self.buffer.resize(end_position + 4, 0); + end_position + } + + fn add_explicit_end(&mut self, end_position: usize, end: u32) { + self.buffer[end_position..end_position + 4] + .copy_from_slice(&(self.index_converter.convert(end, false)).to_ne_bytes()); + } + + fn add_type_and_start(&mut self, node_type: &[u8; 4], span: &Span) -> usize { + self.add_type_and_start_and_handle_annotations(node_type, span, false) + } + + fn add_type_and_start_and_handle_annotations( + &mut self, + node_type: &[u8; 4], + span: &Span, + keep_annotations: bool, + ) -> usize { + // type + self.buffer.extend_from_slice(node_type); + // start + let start = self + .index_converter + .convert(span.lo.0 - 1, keep_annotations); + self.buffer.extend_from_slice(&start.to_ne_bytes()); + // end + let end_position = self.buffer.len(); + self.buffer.resize(end_position + 4, 0); + end_position + } + + fn add_end(&mut self, end_position: usize, span: &Span) { + self.buffer[end_position..end_position + 4] + .copy_from_slice(&(self.index_converter.convert(span.hi.0 - 1, false)).to_ne_bytes()); + } + + fn convert_item_list(&mut self, item_list: &[T], convert_item: F) + where + F: Fn(&mut AstConverter, &T) -> bool, + { + // store number of items in first position + self + .buffer + .extend_from_slice(&(item_list.len() as u32).to_ne_bytes()); + let mut reference_position = self.buffer.len(); + // make room for the reference positions of the items + self + .buffer + .resize(self.buffer.len() + item_list.len() * 4, 0); + for item in item_list { + let insert_position = (self.buffer.len() as u32) >> 2; + if convert_item(self, item) { + self.buffer[reference_position..reference_position + 4] + .copy_from_slice(&insert_position.to_ne_bytes()); + } + reference_position += 4; + } + } + + fn convert_item_list_with_state( + &mut self, + item_list: &[T], + state: &mut S, + convert_item: F, + ) where + F: Fn(&mut AstConverter, &T, &mut S) -> bool, + { + // store number of items in first position + self + .buffer + .extend_from_slice(&(item_list.len() as u32).to_ne_bytes()); + let mut reference_position = self.buffer.len(); + // make room for the reference positions of the items + self + .buffer + .resize(self.buffer.len() + item_list.len() * 4, 0); + for item in item_list { + let insert_position = (self.buffer.len() as u32) >> 2; + if convert_item(self, item, state) { + self.buffer[reference_position..reference_position + 4] + .copy_from_slice(&insert_position.to_ne_bytes()); + } + reference_position += 4; + } + } + + // TODO SWC deduplicate strings and see if we can easily compare atoms + fn convert_string(&mut self, string: &str) { + convert_string(&mut self.buffer, string); + } + + fn convert_boolean(&mut self, boolean: bool) { + self + .buffer + .extend_from_slice(&(if boolean { 1u32 } else { 0u32 }).to_ne_bytes()); + } + + fn reserve_reference_positions(&mut self, item_count: usize) -> usize { + let reference_position = self.buffer.len(); + self + .buffer + .resize(reference_position + (item_count << 2), 0); + reference_position + } + + fn update_reference_position(&mut self, reference_position: usize) { + let insert_position = (self.buffer.len() as u32) >> 2; + self.buffer[reference_position..reference_position + 4] + .copy_from_slice(&insert_position.to_ne_bytes()); + } + + // === enums + fn convert_program(&mut self, node: &Program) { + match node { + Program::Module(module) => { + self.store_program(ModuleItemsOrStatements::ModuleItems(&module.body)) + } + Program::Script(script) => { + self.store_program(ModuleItemsOrStatements::Statements(&script.body)) + } + } + } + + fn convert_module_item(&mut self, module_item: &ModuleItem) { + match module_item { + ModuleItem::Stmt(statement) => self.convert_statement(statement), + ModuleItem::ModuleDecl(module_declaration) => { + self.convert_module_declaration(module_declaration); + } + } + } + + fn convert_statement(&mut self, statement: &Stmt) { + match statement { + Stmt::Break(break_statement) => self.convert_break_statement(break_statement), + Stmt::Block(block_statement) => self.convert_block_statement(block_statement, false), + Stmt::Continue(continue_statement) => self.convert_continue_statement(continue_statement), + Stmt::Decl(declaration) => self.convert_declaration(declaration), + Stmt::Debugger(debugger_statement) => self.convert_debugger_statement(debugger_statement), + Stmt::DoWhile(do_while_statement) => self.convert_do_while_statement(do_while_statement), + Stmt::Empty(empty_statement) => self.convert_empty_statement(empty_statement), + Stmt::Expr(expression_statement) => { + self.convert_expression_statement(expression_statement, None) + } + Stmt::For(for_statement) => self.convert_for_statement(for_statement), + Stmt::ForIn(for_in_statement) => self.convert_for_in_statement(for_in_statement), + Stmt::ForOf(for_of_statement) => self.convert_for_of_statement(for_of_statement), + Stmt::If(if_statement) => self.convert_if_statement(if_statement), + Stmt::Labeled(labeled_statement) => self.convert_labeled_statement(labeled_statement), + Stmt::Return(return_statement) => self.convert_return_statement(return_statement), + Stmt::Switch(switch_statement) => self.convert_switch_statement(switch_statement), + Stmt::Throw(throw_statement) => self.convert_throw_statement(throw_statement), + Stmt::Try(try_statement) => self.convert_try_statement(try_statement), + Stmt::While(while_statement) => self.convert_while_statement(while_statement), + Stmt::With(_) => unimplemented!("Cannot convert Stmt::With"), + } + } + + fn convert_expression(&mut self, expression: &Expr) -> Option<(u32, u32)> { + match expression { + Expr::Array(array_literal) => { + self.convert_array_literal(array_literal); + None + } + Expr::Arrow(arrow_expression) => { + self.convert_arrow_expression(arrow_expression); + None + } + Expr::Assign(assignment_expression) => { + self.convert_assignment_expression(assignment_expression); + None + } + Expr::Await(await_expression) => { + self.convert_await_expression(await_expression); + None + } + Expr::Bin(binary_expression) => { + self.convert_binary_expression(binary_expression); + None + } + Expr::Call(call_expression) => { + self.convert_call_expression(call_expression, false, false); + None + } + Expr::Class(class_expression) => { + self.convert_class_expression(class_expression, &TYPE_CLASS_EXPRESSION); + None + } + Expr::Cond(conditional_expression) => { + self.convert_conditional_expression(conditional_expression); + None + } + Expr::Fn(function_expression) => { + self.convert_function( + &function_expression.function, + &TYPE_FUNCTION_EXPRESSION, + function_expression.ident.as_ref(), + ); + None + } + Expr::Ident(identifier) => { + self.convert_identifier(identifier); + None + } + Expr::Lit(literal) => { + self.convert_literal(literal); + None + } + Expr::Member(member_expression) => { + self.convert_member_expression(member_expression, false, false); + None + } + Expr::MetaProp(meta_property) => { + self.convert_meta_property(meta_property); + None + } + Expr::New(new_expression) => { + self.convert_new_expression(new_expression); + None + } + Expr::Object(object_literal) => { + self.convert_object_literal(object_literal); + None + } + Expr::OptChain(optional_chain_expression) => { + self.convert_optional_chain_expression(optional_chain_expression, false); + None + } + Expr::Paren(parenthesized_expression) => { + Some(self.convert_parenthesized_expression(parenthesized_expression)) + } + Expr::PrivateName(private_name) => { + self.convert_private_name(&private_name); + None + } + Expr::Seq(sequence_expression) => { + self.convert_sequence_expression(sequence_expression); + None + } + Expr::SuperProp(super_property) => { + self.convert_super_property(super_property); + None + } + Expr::TaggedTpl(tagged_template_expression) => { + self.convert_tagged_template_expression(tagged_template_expression); + None + } + Expr::This(this_expression) => { + self.convert_this_expression(this_expression); + None + } + Expr::Tpl(template_literal) => { + self.convert_template_literal(template_literal); + None + } + Expr::Unary(unary_expression) => { + self.convert_unary_expression(unary_expression); + None + } + Expr::Update(update_expression) => { + self.convert_update_expression(update_expression); + None + } + Expr::Yield(yield_expression) => { + self.convert_yield_expression(yield_expression); + None + } + Expr::JSXMember(_) => unimplemented!("Cannot convert Expr::JSXMember"), + Expr::JSXNamespacedName(_) => unimplemented!("Cannot convert Expr::JSXNamespacedName"), + Expr::JSXEmpty(_) => unimplemented!("Cannot convert Expr::JSXEmpty"), + Expr::JSXElement(_) => unimplemented!("Cannot convert Expr::JSXElement"), + Expr::JSXFragment(_) => unimplemented!("Cannot convert Expr::JSXFragment"), + Expr::TsTypeAssertion(_) => unimplemented!("Cannot convert Expr::TsTypeAssertion"), + Expr::TsConstAssertion(_) => unimplemented!("Cannot convert Expr::TsConstAssertion"), + Expr::TsNonNull(_) => unimplemented!("Cannot convert Expr::TsNonNull"), + Expr::TsAs(_) => unimplemented!("Cannot convert Expr::TsAs"), + Expr::TsInstantiation(_) => unimplemented!("Cannot convert Expr::TsInstantiation"), + Expr::TsSatisfies(_) => unimplemented!("Cannot convert Expr::TsSatisfies"), + Expr::Invalid(_) => unimplemented!("Cannot convert Expr::Invalid"), + } + } + + fn get_expression_span(&mut self, expression: &Expr) -> Span { + match expression { + Expr::Array(array_literal) => array_literal.span, + Expr::Arrow(arrow_expression) => arrow_expression.span, + Expr::Assign(assignment_expression) => assignment_expression.span, + Expr::Await(await_expression) => await_expression.span, + Expr::Bin(binary_expression) => binary_expression.span, + Expr::Call(call_expression) => call_expression.span, + Expr::Class(class_expression) => class_expression.class.span, + Expr::Cond(conditional_expression) => conditional_expression.span, + Expr::Fn(function_expression) => function_expression.function.span, + Expr::Ident(identifier) => identifier.span, + Expr::Lit(Lit::Str(literal)) => literal.span, + Expr::Lit(Lit::Bool(literal)) => literal.span, + Expr::Lit(Lit::Null(literal)) => literal.span, + Expr::Lit(Lit::Num(literal)) => literal.span, + Expr::Lit(Lit::BigInt(literal)) => literal.span, + Expr::Lit(Lit::Regex(literal)) => literal.span, + Expr::Member(member_expression) => member_expression.span, + Expr::MetaProp(meta_property) => meta_property.span, + Expr::New(new_expression) => new_expression.span, + Expr::Object(object_literal) => object_literal.span, + Expr::OptChain(optional_chain_expression) => optional_chain_expression.span, + Expr::Paren(parenthesized_expression) => parenthesized_expression.span, + Expr::PrivateName(private_name) => private_name.span, + Expr::Seq(sequence_expression) => sequence_expression.span, + Expr::SuperProp(super_property) => super_property.span, + Expr::TaggedTpl(tagged_template_expression) => tagged_template_expression.span, + Expr::This(this_expression) => this_expression.span, + Expr::Tpl(template_literal) => template_literal.span, + Expr::Unary(unary_expression) => unary_expression.span, + Expr::Update(update_expression) => update_expression.span, + Expr::Yield(yield_expression) => yield_expression.span, + Expr::JSXMember(_) => unimplemented!("Cannot convert Expr::JSXMember"), + Expr::JSXNamespacedName(_) => unimplemented!("Cannot convert Expr::JSXNamespacedName"), + Expr::JSXEmpty(_) => unimplemented!("Cannot convert Expr::JSXEmpty"), + Expr::JSXElement(_) => unimplemented!("Cannot convert Expr::JSXElement"), + Expr::JSXFragment(_) => unimplemented!("Cannot convert Expr::JSXFragment"), + Expr::TsTypeAssertion(_) => unimplemented!("Cannot convert Expr::TsTypeAssertion"), + Expr::TsConstAssertion(_) => unimplemented!("Cannot convert Expr::TsConstAssertion"), + Expr::TsNonNull(_) => unimplemented!("Cannot convert Expr::TsNonNull"), + Expr::TsAs(_) => unimplemented!("Cannot convert Expr::TsAs"), + Expr::TsInstantiation(_) => unimplemented!("Cannot convert Expr::TsInstantiation"), + Expr::TsSatisfies(_) => unimplemented!("Cannot convert Expr::TsSatisfies"), + Expr::Invalid(_) => unimplemented!("Cannot convert Expr::Invalid"), + Expr::Lit(Lit::JSXText(_)) => unimplemented!("Cannot convert Lit::JSXText"), + } + } + + fn convert_literal(&mut self, literal: &Lit) { + match literal { + Lit::BigInt(bigint_literal) => self.convert_literal_bigint(bigint_literal), + Lit::Bool(boolean_literal) => { + self.convert_literal_boolean(boolean_literal); + } + Lit::Null(null_literal) => { + self.convert_literal_null(null_literal); + } + Lit::Num(number_literal) => { + self.convert_literal_number(number_literal); + } + Lit::Regex(regex_literal) => { + self.convert_literal_regex(regex_literal); + } + Lit::Str(string_literal) => { + self.convert_literal_string(string_literal); + } + Lit::JSXText(_) => unimplemented!("Lit::JSXText"), + } + } + + fn convert_module_declaration(&mut self, module_declaration: &ModuleDecl) { + match module_declaration { + ModuleDecl::ExportDecl(export_declaration) => { + self.convert_export_declaration(export_declaration) + } + ModuleDecl::ExportNamed(export_named) => self.convert_export_named_declaration(export_named), + ModuleDecl::Import(import_declaration) => self.convert_import_declaration(import_declaration), + ModuleDecl::ExportDefaultExpr(export_default_expression) => { + self.convert_export_default_expression(export_default_expression) + } + ModuleDecl::ExportAll(export_all) => self.convert_export_all(export_all), + ModuleDecl::ExportDefaultDecl(export_default_declaration) => { + self.convert_export_default_declaration(export_default_declaration) + } + ModuleDecl::TsImportEquals(_) => unimplemented!("Cannot convert ModuleDecl::TsImportEquals"), + ModuleDecl::TsExportAssignment(_) => { + unimplemented!("Cannot convert ModuleDecl::TsExportAssignment") + } + ModuleDecl::TsNamespaceExport(_) => { + unimplemented!("Cannot convert ModuleDecl::TsNamespaceExport") + } + } + } + + fn convert_declaration(&mut self, declaration: &Decl) { + match declaration { + Decl::Var(variable_declaration) => self.convert_variable_declaration(variable_declaration), + Decl::Fn(function_declaration) => self.convert_function( + &function_declaration.function, + &TYPE_FUNCTION_DECLARATION, + Some(&function_declaration.ident), + ), + Decl::Class(class_declaration) => self.convert_class_declaration(class_declaration), + Decl::Using(_) => unimplemented!("Cannot convert Decl::Using"), + Decl::TsInterface(_) => unimplemented!("Cannot convert Decl::TsInterface"), + Decl::TsTypeAlias(_) => unimplemented!("Cannot convert Decl::TsTypeAlias"), + Decl::TsEnum(_) => unimplemented!("Cannot convert Decl::TsEnum"), + Decl::TsModule(_) => unimplemented!("Cannot convert Decl::TsModule"), + } + } + + fn convert_pattern(&mut self, pattern: &Pat) -> Option<(u32, u32)> { + match pattern { + Pat::Array(array_pattern) => { + self.convert_array_pattern(array_pattern); + None + } + Pat::Assign(assignment_pattern) => { + self.convert_assignment_pattern(assignment_pattern); + None + } + Pat::Expr(expression) => self.convert_expression(expression), + Pat::Ident(binding_identifier) => { + self.convert_binding_identifier(binding_identifier); + None + } + Pat::Object(object) => { + self.convert_object_pattern(object); + None + } + Pat::Rest(rest_pattern) => { + self.convert_rest_pattern(rest_pattern); + None + } + Pat::Invalid(_) => unimplemented!("Cannot convert invalid pattern"), + } + } + + fn convert_binding_identifier(&mut self, binding_identifier: &BindingIdent) { + self.convert_identifier(&binding_identifier.id); + } + + fn convert_export_specifier(&mut self, export_specifier: &ExportSpecifier) { + match export_specifier { + ExportSpecifier::Named(export_named_specifier) => { + self.convert_export_named_specifier(export_named_specifier) + } + ExportSpecifier::Namespace(_) => unimplemented!("Cannot convert ExportSpecifier::Namespace"), + ExportSpecifier::Default(_) => unimplemented!("Cannot convert ExportSpecifier::Default"), + } + } + + fn convert_module_export_name(&mut self, module_export_name: &ModuleExportName) { + match module_export_name { + ModuleExportName::Ident(identifier) => self.convert_identifier(identifier), + ModuleExportName::Str(string_literal) => self.convert_literal_string(string_literal), + } + } + + fn convert_import_specifier(&mut self, import_specifier: &ImportSpecifier) { + match import_specifier { + ImportSpecifier::Named(import_named_specifier) => { + self.convert_import_named_specifier(import_named_specifier) + } + ImportSpecifier::Default(import_default_specifier) => { + self.convert_import_default_specifier(import_default_specifier) + } + ImportSpecifier::Namespace(import_namespace_specifier) => { + self.convert_import_namespace_specifier(import_namespace_specifier) + } + } + } + + fn convert_object_pattern_property(&mut self, object_pattern_property: &ObjectPatProp) { + match object_pattern_property { + ObjectPatProp::Assign(assignment_pattern_property) => { + self.convert_assignment_pattern_property(assignment_pattern_property) + } + ObjectPatProp::KeyValue(key_value_pattern_property) => { + self.convert_key_value_pattern_property(key_value_pattern_property) + } + ObjectPatProp::Rest(rest_pattern) => self.convert_rest_pattern(rest_pattern), + } + } + + fn convert_class_member(&mut self, class_member: &ClassMember) { + match class_member { + ClassMember::ClassProp(class_property) => self.convert_class_property(class_property), + ClassMember::Constructor(constructor) => self.convert_constructor(constructor), + ClassMember::Method(method) => self.convert_method(method), + ClassMember::PrivateMethod(private_method) => self.convert_private_method(private_method), + ClassMember::PrivateProp(private_property) => self.convert_private_property(private_property), + ClassMember::StaticBlock(static_block) => self.convert_static_block(static_block), + ClassMember::TsIndexSignature(_) => { + unimplemented!("Cannot convert ClassMember::TsIndexSignature") + } + ClassMember::Empty(_) => unimplemented!("Cannot convert ClassMember::Empty"), + ClassMember::AutoAccessor(_) => unimplemented!("Cannot convert ClassMember::AutoAccessor"), + } + } + + fn convert_property_or_spread(&mut self, property_or_spread: &PropOrSpread) { + match property_or_spread { + PropOrSpread::Prop(property) => self.convert_property(&**property), + PropOrSpread::Spread(spread_element) => self.convert_spread_element(spread_element), + } + } + + fn convert_property(&mut self, property: &Prop) { + match property { + Prop::Getter(getter_property) => self.convert_getter_property(getter_property), + Prop::KeyValue(key_value_property) => self.convert_key_value_property(key_value_property), + Prop::Method(method_property) => self.convert_method_property(method_property), + Prop::Setter(setter_property) => self.convert_setter_property(setter_property), + Prop::Shorthand(identifier) => self.convert_shorthand_property(identifier), + Prop::Assign(_) => unimplemented!("Cannot convert Prop::Assign"), + } + } + + fn convert_pattern_or_expression(&mut self, pattern_or_expression: &PatOrExpr) { + match pattern_or_expression { + PatOrExpr::Pat(pattern) => { + self.convert_pattern(pattern); + } + PatOrExpr::Expr(expression) => { + self.convert_expression(expression); + } + } + } + + fn convert_parenthesized_expression( + &mut self, + parenthesized_expression: &ParenExpr, + ) -> (u32, u32) { + let start = self.index_converter.convert( + parenthesized_expression.span.lo.0 - 1, + match &*parenthesized_expression.expr { + Expr::Call(_) | Expr::New(_) | Expr::Paren(_) => true, + _ => false, + }, + ); + self.convert_expression(&parenthesized_expression.expr); + let end = self + .index_converter + .convert(parenthesized_expression.span.hi.0 - 1, false); + (start, end) + } + + fn convert_optional_chain_base(&mut self, optional_chain_base: &OptChainBase, is_optional: bool) { + match optional_chain_base { + OptChainBase::Member(member_expression) => { + self.convert_member_expression(&member_expression, is_optional, true) + } + OptChainBase::Call(optional_call) => { + self.convert_optional_call(optional_call, is_optional, true) + } + } + } + + fn convert_call_expression( + &mut self, + call_expression: &CallExpr, + is_optional: bool, + is_chained: bool, + ) { + match &call_expression.callee { + Callee::Import(_) => { + self.store_import_expression(&call_expression.span, &call_expression.args) + } + Callee::Expr(callee_expression) => self.store_call_expression( + &call_expression.span, + is_optional, + &StoredCallee::Expression(&callee_expression), + &call_expression.args, + is_chained, + ), + Callee::Super(callee_super) => self.store_call_expression( + &call_expression.span, + is_optional, + &StoredCallee::Super(&callee_super), + &call_expression.args, + is_chained, + ), + } + } + + fn convert_optional_call( + &mut self, + optional_call: &OptCall, + is_optional: bool, + is_chained: bool, + ) { + self.store_call_expression( + &optional_call.span, + is_optional, + &StoredCallee::Expression(&optional_call.callee), + &optional_call.args, + is_chained, + ); + } + + fn convert_export_declaration(&mut self, export_declaration: &ExportDecl) { + self.store_export_named_declaration( + &export_declaration.span, + &vec![], + None, + Some(&export_declaration.decl), + &None, + ); + } + + fn convert_export_named_declaration(&mut self, export_named_declaration: &NamedExport) { + match export_named_declaration.specifiers.first().unwrap() { + ExportSpecifier::Namespace(export_namespace_specifier) => self.store_export_all_declaration( + &export_named_declaration.span, + export_named_declaration.src.as_ref().unwrap(), + &export_named_declaration.with, + Some(&export_namespace_specifier.name), + ), + ExportSpecifier::Named(_) => self.store_export_named_declaration( + &export_named_declaration.span, + &export_named_declaration.specifiers, + export_named_declaration + .src + .as_ref() + .map(|source| &**source), + None, + &export_named_declaration.with, + ), + ExportSpecifier::Default(_) => panic!("Unexpected default export specifier"), + } + } + + fn convert_for_head(&mut self, for_head: &ForHead) { + match for_head { + ForHead::VarDecl(variable_declaration) => { + self.convert_variable_declaration(variable_declaration) + } + ForHead::Pat(pattern) => { + self.convert_pattern(pattern); + } + ForHead::UsingDecl(_) => unimplemented!("Cannot convert ForHead::UsingDecl"), + } + } + + fn convert_variable_declaration_or_expression( + &mut self, + variable_declaration_or_expression: &VarDeclOrExpr, + ) { + match variable_declaration_or_expression { + VarDeclOrExpr::VarDecl(variable_declaration) => { + self.convert_variable_declaration(variable_declaration); + } + VarDeclOrExpr::Expr(expression) => { + self.convert_expression(expression); + } + } + } + + fn convert_export_all(&mut self, export_all: &ExportAll) { + self.store_export_all_declaration(&export_all.span, &export_all.src, &export_all.with, None); + } + + fn convert_identifier(&mut self, identifier: &Ident) { + self.store_identifier( + identifier.span.lo.0 - 1, + identifier.span.hi.0 - 1, + &identifier.sym, + ); + } + + // === nodes + fn store_program(&mut self, body: ModuleItemsOrStatements) { + let end_position = self.add_type_and_explicit_start(&TYPE_PROGRAM, 0u32); + // reserve annotations + let reference_position = self.reserve_reference_positions(1); + // body + let mut keep_checking_directives = true; + match body { + ModuleItemsOrStatements::ModuleItems(module_items) => { + self.convert_item_list_with_state( + module_items, + &mut keep_checking_directives, + |ast_converter, module_item, can_be_directive| { + if *can_be_directive { + if let ModuleItem::Stmt(Stmt::Expr(expression)) = &*module_item { + if let Expr::Lit(Lit::Str(string)) = &*expression.expr { + ast_converter.convert_expression_statement(expression, Some(&string.value)); + return true; + } + }; + } + *can_be_directive = false; + ast_converter.convert_module_item(module_item); + true + }, + ); + } + ModuleItemsOrStatements::Statements(statements) => { + self.convert_item_list_with_state( + statements, + &mut keep_checking_directives, + |ast_converter, statement, can_be_directive| { + if *can_be_directive { + if let Stmt::Expr(expression) = &*statement { + if let Expr::Lit(Lit::Str(string)) = &*expression.expr { + ast_converter.convert_expression_statement(expression, Some(&string.value)); + return true; + } + }; + } + *can_be_directive = false; + ast_converter.convert_statement(statement); + true + }, + ); + } + } + // end + self.add_explicit_end(end_position, self.code.len() as u32); + // annotations + self.update_reference_position(reference_position); + self.index_converter.invalidate_collected_annotations(); + let invalid_annotations = self.index_converter.take_invalid_annotations(); + self.convert_item_list(&invalid_annotations, |ast_converter, annotation| { + ast_converter.convert_annotation(annotation); + true + }); + } + + fn convert_expression_statement( + &mut self, + expression_statement: &ExprStmt, + directive: Option<&JsWord>, + ) { + let end_position = + self.add_type_and_start(&TYPE_EXPRESSION_STATEMENT, &expression_statement.span); + // reserve directive + let reference_position = self.reserve_reference_positions(1); + // expression + self.convert_expression(&expression_statement.expr); + // directive + directive.map(|directive| { + self.update_reference_position(reference_position); + self.convert_string(directive); + }); + // end + self.add_end(end_position, &expression_statement.span); + } + + fn store_export_named_declaration( + &mut self, + span: &Span, + specifiers: &Vec, + src: Option<&Str>, + declaration: Option<&Decl>, + with: &Option>, + ) { + let end_position = self.add_type_and_start_and_handle_annotations( + &TYPE_EXPORT_NAMED_DECLARATION, + span, + match declaration { + Some(Decl::Fn(_)) => true, + Some(Decl::Var(variable_declaration)) => variable_declaration.kind == VarDeclKind::Const, + _ => false, + }, + ); + // reserve for declaration, src, attributes + let reference_position = self.reserve_reference_positions(3); + // specifiers + self.convert_item_list(specifiers, |ast_converter, specifier| { + ast_converter.convert_export_specifier(specifier); + true + }); + // declaration + declaration.map(|declaration| { + self.update_reference_position(reference_position); + self.convert_declaration(declaration) + }); + // src + src.map(|src| { + self.update_reference_position(reference_position + 4); + self.convert_literal_string(src) + }); + // attributes + self.update_reference_position(reference_position + 8); + self.store_import_attributes(with); + // end + self.add_end(end_position, span); + } + + fn convert_literal_number(&mut self, literal: &Number) { + self.add_type_and_positions(&TYPE_LITERAL_NUMBER, &literal.span); + // reserve for raw + let reference_position = self.reserve_reference_positions(1); + // value, needs to be little endian as we are reading via a DataView + self.buffer.extend_from_slice(&literal.value.to_le_bytes()); + // raw + literal.raw.as_ref().map(|raw| { + self.update_reference_position(reference_position); + self.convert_string(&*raw); + }); + } + + fn convert_literal_string(&mut self, literal: &Str) { + self.add_type_and_positions(&TYPE_LITERAL_STRING, &literal.span); + // reserve for raw + let reference_position = self.reserve_reference_positions(1); + // value + self.convert_string(&literal.value); + // raw + literal.raw.as_ref().map(|raw| { + self.update_reference_position(reference_position); + self.convert_string(&*raw); + }); + } + + fn convert_variable_declaration(&mut self, variable_declaration: &VarDecl) { + let end_position = self.add_type_and_start_and_handle_annotations( + &TYPE_VARIABLE_DECLARATION, + &variable_declaration.span, + match variable_declaration.kind { + VarDeclKind::Const => true, + _ => false, + }, + ); + self + .buffer + .extend_from_slice(match variable_declaration.kind { + VarDeclKind::Var => &STRING_VAR, + VarDeclKind::Let => &STRING_LET, + VarDeclKind::Const => &STRING_CONST, + }); + self.convert_item_list( + &variable_declaration.decls, + |ast_converter, variable_declarator| { + ast_converter.convert_variable_declarator(variable_declarator); + true + }, + ); + // end + self.add_end(end_position, &variable_declaration.span); + } + + fn convert_variable_declarator(&mut self, variable_declarator: &VarDeclarator) { + let end_position = + self.add_type_and_start(&TYPE_VARIABLE_DECLARATOR, &variable_declarator.span); + let forwarded_annotations = match &variable_declarator.init { + Some(expression) => match &**expression { + Expr::Arrow(_) => { + let annotations = self + .index_converter + .take_collected_annotations(AnnotationKind::NoSideEffects); + Some(annotations) + } + _ => None, + }, + None => None, + }; + // reserve for init + let reference_position = self.reserve_reference_positions(1); + // id + self.convert_pattern(&variable_declarator.name); + // init + forwarded_annotations.map(|annotations| { + self.index_converter.add_collected_annotations(annotations); + }); + variable_declarator.init.as_ref().map(|init| { + self.update_reference_position(reference_position); + self.convert_expression(&init); + }); + // end + self.add_end(end_position, &variable_declarator.span); + } + + fn store_identifier(&mut self, start: u32, end: u32, name: &str) { + let end_position = self.add_type_and_explicit_start(&TYPE_IDENTIFIER, start); + // name + self.convert_string(name); + // end + self.add_explicit_end(end_position, end); + } + + fn convert_export_named_specifier(&mut self, export_named_specifier: &ExportNamedSpecifier) { + let end_position = + self.add_type_and_start(&TYPE_EXPORT_SPECIFIER, &export_named_specifier.span); + // reserve for exported + let reference_position = self.reserve_reference_positions(1); + // local + self.convert_module_export_name(&export_named_specifier.orig); + // exported + export_named_specifier.exported.as_ref().map(|exported| { + self.update_reference_position(reference_position); + self.convert_module_export_name(&exported); + }); + // end + self.add_end(end_position, &export_named_specifier.span); + } + + fn convert_import_declaration(&mut self, import_declaration: &ImportDecl) { + let end_position = self.add_type_and_start(&TYPE_IMPORT_DECLARATION, &import_declaration.span); + // reserve for src, attributes + let reference_position = self.reserve_reference_positions(2); + // specifiers + self.convert_item_list( + &import_declaration.specifiers, + |ast_converter, import_specifier| { + ast_converter.convert_import_specifier(import_specifier); + true + }, + ); + // src + self.update_reference_position(reference_position); + self.convert_literal_string(&*import_declaration.src); + // attributes + self.update_reference_position(reference_position + 4); + self.store_import_attributes(&import_declaration.with); + // end + self.add_end(end_position, &import_declaration.span); + } + + fn store_import_attributes(&mut self, with: &Option>) { + match with { + Some(ref with) => { + self.convert_item_list(&with.props, |ast_converter, prop| match prop { + PropOrSpread::Prop(prop) => match &**prop { + Prop::KeyValue(key_value_property) => { + ast_converter.convert_import_attribute(key_value_property); + true + } + _ => panic!("Non key-value property in import declaration attributes"), + }, + PropOrSpread::Spread(_) => panic!("Spread in import declaration attributes"), + }); + } + None => self.buffer.resize(self.buffer.len() + 4, 0), + } + } + + fn store_import_expression(&mut self, span: &Span, arguments: &Vec) { + let end_position = self.add_type_and_start(&TYPE_IMPORT_EXPRESSION, span); + // reserve for options + let reference_position = self.reserve_reference_positions(1); + // source + self.convert_expression(&*arguments.first().unwrap().expr); + // options + arguments.get(1).map(|argument| { + self.update_reference_position(reference_position); + self.convert_expression_or_spread(argument); + }); + // end + self.add_end(end_position, span); + } + + fn store_call_expression( + &mut self, + span: &Span, + is_optional: bool, + callee: &StoredCallee, + arguments: &[ExprOrSpread], + is_chained: bool, + ) { + let end_position = self.add_type_and_start(&TYPE_CALL_EXPRESSION, span); + let annotations = self + .index_converter + .take_collected_annotations(AnnotationKind::Pure); + // optional + self.convert_boolean(is_optional); + // reserve for callee, arguments + let reference_position = self.reserve_reference_positions(2); + // annotations + self.convert_item_list(&annotations, |ast_converter, annotation| { + ast_converter.convert_annotation(annotation); + true + }); + // callee + self.update_reference_position(reference_position); + match callee { + StoredCallee::Expression(Expr::OptChain(optional_chain_expression)) => { + self.convert_optional_chain_expression(optional_chain_expression, is_chained); + } + StoredCallee::Expression(Expr::Call(call_expression)) => { + self.convert_call_expression(call_expression, false, is_chained); + } + StoredCallee::Expression(Expr::Member(member_expression)) => { + self.convert_member_expression(member_expression, false, is_chained); + } + StoredCallee::Expression(callee_expression) => { + self.convert_expression(callee_expression); + } + StoredCallee::Super(callee_super) => self.convert_super(callee_super), + } + // arguments + self.update_reference_position(reference_position + 4); + self.convert_item_list(arguments, |ast_converter, argument| { + ast_converter.convert_expression_or_spread(argument); + true + }); + // end + self.add_end(end_position, span); + } + + fn convert_import_named_specifier(&mut self, import_named_specifier: &ImportNamedSpecifier) { + let end_position = + self.add_type_and_start(&TYPE_IMPORT_SPECIFIER, &import_named_specifier.span); + // reserve for imported, local + let reference_position = self.reserve_reference_positions(2); + // imported + import_named_specifier.imported.as_ref().map(|imported| { + self.update_reference_position(reference_position); + self.convert_module_export_name(&imported); + }); + // local + self.update_reference_position(reference_position + 4); + self.convert_identifier(&import_named_specifier.local); + // end + self.add_end(end_position, &import_named_specifier.span); + } + + fn convert_arrow_expression(&mut self, arrow_expression: &ArrowExpr) { + let end_position = + self.add_type_and_start(&TYPE_ARROW_FUNCTION_EXPRESSION, &arrow_expression.span); + let annotations = self + .index_converter + .take_collected_annotations(AnnotationKind::NoSideEffects); + // async + self.convert_boolean(arrow_expression.is_async); + // generator + self.convert_boolean(arrow_expression.is_generator); + // expression + self.convert_boolean(match &*arrow_expression.body { + BlockStmtOrExpr::BlockStmt(_) => false, + BlockStmtOrExpr::Expr(_) => true, + }); + // reserve for params, body + let reference_position = self.reserve_reference_positions(2); + // annotations + self.convert_item_list(&annotations, |ast_converter, annotation| { + ast_converter.convert_annotation(annotation); + true + }); + // params + self.update_reference_position(reference_position); + self.convert_item_list(&arrow_expression.params, |ast_converter, param| { + ast_converter.convert_pattern(param); + true + }); + // body + self.update_reference_position(reference_position + 4); + match &*arrow_expression.body { + BlockStmtOrExpr::BlockStmt(block_statement) => { + self.convert_block_statement(block_statement, true) + } + BlockStmtOrExpr::Expr(expression) => { + self.convert_expression(expression); + } + } + // end + self.add_end(end_position, &arrow_expression.span); + } + + fn convert_block_statement(&mut self, block_statement: &BlockStmt, check_directive: bool) { + let end_position = self.add_type_and_start(&TYPE_BLOCK_STATEMENT, &block_statement.span); + // body + let mut keep_checking_directives = check_directive; + self.convert_item_list_with_state( + &block_statement.stmts, + &mut keep_checking_directives, + |ast_converter, statement, can_be_directive| { + if *can_be_directive { + if let Stmt::Expr(expression) = &*statement { + if let Expr::Lit(Lit::Str(string)) = &*expression.expr { + ast_converter.convert_expression_statement(expression, Some(&string.value)); + return true; + } + } + } + *can_be_directive = false; + ast_converter.convert_statement(statement); + true + }, + ); + // end + self.add_end(end_position, &block_statement.span); + } + + fn convert_expression_or_spread(&mut self, expression_or_spread: &ExprOrSpread) { + match expression_or_spread.spread { + Some(spread_span) => self.store_spread_element(&spread_span, &expression_or_spread.expr), + None => { + self.convert_expression(&expression_or_spread.expr); + } + } + } + + fn convert_spread_element(&mut self, spread_element: &SpreadElement) { + self.store_spread_element(&spread_element.dot3_token, &spread_element.expr); + } + + fn store_spread_element(&mut self, dot_span: &Span, argument: &Expr) { + let end_position = self.add_type_and_start(&TYPE_SPREAD_ELEMENT, dot_span); + // we need to set the end position to that of the expression + let argument_position = self.buffer.len(); + // argument + self.convert_expression(argument); + let expression_end: [u8; 4] = self.buffer[argument_position + 8..argument_position + 12] + .try_into() + .unwrap(); + self.buffer[end_position..end_position + 4].copy_from_slice(&expression_end); + } + + fn store_member_expression( + &mut self, + span: &Span, + is_optional: bool, + object: &ExpressionOrSuper, + property: MemberOrSuperProp, + is_chained: bool, + ) { + let end_position = self.add_type_and_start(&TYPE_MEMBER_EXPRESSION, span); + // optional + self.convert_boolean(is_optional); + // computed + self.convert_boolean(match property { + MemberOrSuperProp::Computed(_) => true, + _ => false, + }); + // reserve property + let reference_position = self.reserve_reference_positions(1); + // object + match object { + ExpressionOrSuper::Expression(Expr::OptChain(optional_chain_expression)) => { + self.convert_optional_chain_expression(optional_chain_expression, is_chained); + } + ExpressionOrSuper::Expression(Expr::Call(call_expression)) => { + self.convert_call_expression(call_expression, false, is_chained); + } + ExpressionOrSuper::Expression(Expr::Member(member_expression)) => { + self.convert_member_expression(member_expression, false, is_chained); + } + ExpressionOrSuper::Expression(expression) => { + self.convert_expression(expression); + } + ExpressionOrSuper::Super(super_token) => self.convert_super(&super_token), + } + // property + self.update_reference_position(reference_position); + match property { + MemberOrSuperProp::Identifier(ident) => self.convert_identifier(&ident), + MemberOrSuperProp::Computed(computed) => { + self.convert_expression(&computed.expr); + } + MemberOrSuperProp::PrivateName(private_name) => self.convert_private_name(&private_name), + } + // end + self.add_end(end_position, span); + } + + fn convert_member_expression( + &mut self, + member_expression: &MemberExpr, + is_optional: bool, + is_chained: bool, + ) { + self.store_member_expression( + &member_expression.span, + is_optional, + &ExpressionOrSuper::Expression(&member_expression.obj), + match &member_expression.prop { + MemberProp::Ident(identifier) => MemberOrSuperProp::Identifier(identifier), + MemberProp::PrivateName(private_name) => MemberOrSuperProp::PrivateName(private_name), + MemberProp::Computed(computed) => MemberOrSuperProp::Computed(computed), + }, + is_chained, + ); + } + + fn convert_private_name(&mut self, private_name: &PrivateName) { + self.add_type_and_positions(&TYPE_PRIVATE_IDENTIFIER, &private_name.span); + // id + self.convert_string(&private_name.id.sym); + } + + fn convert_import_default_specifier( + &mut self, + import_default_specifier: &ImportDefaultSpecifier, + ) { + let end_position = self.add_type_and_start( + &TYPE_IMPORT_DEFAULT_SPECIFIER, + &import_default_specifier.span, + ); + // local + self.convert_identifier(&import_default_specifier.local); + // end + self.add_end(end_position, &import_default_specifier.span); + } + + fn convert_literal_boolean(&mut self, literal: &Bool) { + self.add_type_and_positions(&TYPE_LITERAL_BOOLEAN, &literal.span); + // value + self.convert_boolean(literal.value); + } + + fn convert_export_default_expression(&mut self, export_default_expression: &ExportDefaultExpr) { + self.store_export_default_declaration( + &export_default_expression.span, + StoredDefaultExportExpression::Expression(&export_default_expression.expr), + ); + } + + fn convert_export_default_declaration(&mut self, export_default_declaration: &ExportDefaultDecl) { + self.store_export_default_declaration( + &export_default_declaration.span, + match &export_default_declaration.decl { + DefaultDecl::Class(class_expression) => { + StoredDefaultExportExpression::Class(&class_expression) + } + DefaultDecl::Fn(function_expression) => { + StoredDefaultExportExpression::Function(&function_expression) + } + DefaultDecl::TsInterfaceDecl(_) => { + unimplemented!("Cannot convert ExportDefaultDeclaration with TsInterfaceDecl") + } + }, + ); + } + + fn store_export_default_declaration( + &mut self, + span: &Span, + expression: StoredDefaultExportExpression, + ) { + let end_position = self.add_type_and_start_and_handle_annotations( + &TYPE_EXPORT_DEFAULT_DECLARATION, + span, + match expression { + StoredDefaultExportExpression::Expression(Expr::Fn(_) | Expr::Arrow(_)) + | StoredDefaultExportExpression::Function(_) => true, + _ => false, + }, + ); + // expression + match expression { + StoredDefaultExportExpression::Expression(expression) => { + self.convert_expression(&expression); + } + StoredDefaultExportExpression::Class(class_expression) => { + self.convert_class_expression(&class_expression, &TYPE_CLASS_DECLARATION) + } + StoredDefaultExportExpression::Function(function_expression) => self.convert_function( + &function_expression.function, + &TYPE_FUNCTION_DECLARATION, + function_expression.ident.as_ref(), + ), + } + // end + self.add_end(end_position, span); + } + + fn convert_literal_null(&mut self, literal: &Null) { + self.add_type_and_positions(&TYPE_LITERAL_NULL, &literal.span); + } + + fn convert_import_namespace_specifier( + &mut self, + import_namespace_specifier: &ImportStarAsSpecifier, + ) { + let end_position = self.add_type_and_start( + &TYPE_IMPORT_NAMESPACE_SPECIFIER, + &import_namespace_specifier.span, + ); + // local + self.convert_identifier(&import_namespace_specifier.local); + // end + self.add_end(end_position, &import_namespace_specifier.span); + } + + fn store_export_all_declaration( + &mut self, + span: &Span, + source: &Str, + attributes: &Option>, + exported: Option<&ModuleExportName>, + ) { + let end_position = self.add_type_and_start(&TYPE_EXPORT_ALL_DECLARATION, span); + // reserve exported, source, attributes + let reference_position = self.reserve_reference_positions(3); + // exported + exported.map(|exported| { + self.update_reference_position(reference_position); + self.convert_module_export_name(exported); + }); + // source + self.update_reference_position(reference_position + 4); + self.convert_literal_string(source); + // attributes + self.update_reference_position(reference_position + 8); + self.store_import_attributes(attributes); + // end + self.add_end(end_position, span); + } + + fn convert_binary_expression(&mut self, binary_expression: &BinExpr) { + let end_position = self.add_type_and_start( + match binary_expression.op { + BinaryOp::LogicalOr | BinaryOp::LogicalAnd | BinaryOp::NullishCoalescing => { + &TYPE_LOGICAL_EXPRESSION + } + _ => &TYPE_BINARY_EXPRESSION, + }, + &binary_expression.span, + ); + // operator + self.buffer.extend_from_slice(match binary_expression.op { + BinaryOp::EqEq => &STRING_EQEQ, + BinaryOp::NotEq => &STRING_NOTEQ, + BinaryOp::EqEqEq => &STRING_EQEQEQ, + BinaryOp::NotEqEq => &STRING_NOTEQEQ, + BinaryOp::Lt => &STRING_LT, + BinaryOp::LtEq => &STRING_LTEQ, + BinaryOp::Gt => &STRING_GT, + BinaryOp::GtEq => &STRING_GTEQ, + BinaryOp::LShift => &STRING_LSHIFT, + BinaryOp::RShift => &STRING_RSHIFT, + BinaryOp::ZeroFillRShift => &STRING_ZEROFILLRSHIFT, + BinaryOp::Add => &STRING_ADD, + BinaryOp::Sub => &STRING_SUB, + BinaryOp::Mul => &STRING_MUL, + BinaryOp::Div => &STRING_DIV, + BinaryOp::Mod => &STRING_MOD, + BinaryOp::BitOr => &STRING_BITOR, + BinaryOp::BitXor => &STRING_BITXOR, + BinaryOp::BitAnd => &STRING_BITAND, + BinaryOp::LogicalOr => &STRING_LOGICALOR, + BinaryOp::LogicalAnd => &STRING_LOGICALAND, + BinaryOp::In => &STRING_IN, + BinaryOp::InstanceOf => &STRING_INSTANCEOF, + BinaryOp::Exp => &STRING_EXP, + BinaryOp::NullishCoalescing => &STRING_NULLISHCOALESCING, + }); + // reserve right + let reference_position = self.reserve_reference_positions(1); + // left + self.convert_expression(&binary_expression.left); + // right + self.update_reference_position(reference_position); + self.convert_expression(&binary_expression.right); + // end + self.add_end(end_position, &binary_expression.span); + } + + fn convert_array_pattern(&mut self, array_pattern: &ArrayPat) { + let end_position = self.add_type_and_start(&TYPE_ARRAY_PATTERN, &array_pattern.span); + // elements + self.convert_item_list( + &array_pattern.elems, + |ast_converter, element| match element { + Some(element) => { + ast_converter.convert_pattern(element); + true + } + None => false, + }, + ); + // end + self.add_end(end_position, &array_pattern.span); + } + + fn convert_object_pattern(&mut self, object_pattern: &ObjectPat) { + let end_position = self.add_type_and_start(&TYPE_OBJECT_PATTERN, &object_pattern.span); + // properties + self.convert_item_list( + &object_pattern.props, + |ast_converter, object_pattern_property| { + ast_converter.convert_object_pattern_property(object_pattern_property); + true + }, + ); + // end + self.add_end(end_position, &object_pattern.span); + } + + fn convert_array_literal(&mut self, array_literal: &ArrayLit) { + let end_position = self.add_type_and_start(&TYPE_ARRAY_EXPRESSION, &array_literal.span); + // elements + self.convert_item_list( + &array_literal.elems, + |ast_converter, element| match element { + Some(element) => { + ast_converter.convert_expression_or_spread(element); + true + } + None => false, + }, + ); + // end + self.add_end(end_position, &array_literal.span); + } + + fn convert_conditional_expression(&mut self, conditional_expression: &CondExpr) { + let end_position = + self.add_type_and_start(&TYPE_CONDITIONAL_EXPRESSION, &conditional_expression.span); + // reserve consequent, alternate + let reference_position = self.reserve_reference_positions(2); + // test + self.convert_expression(&conditional_expression.test); + // consequent + self.update_reference_position(reference_position); + self.convert_expression(&conditional_expression.cons); + // alternate + self.update_reference_position(reference_position + 4); + self.convert_expression(&conditional_expression.alt); + // end + self.add_end(end_position, &conditional_expression.span); + } + + fn convert_function( + &mut self, + function: &Function, + node_type: &[u8; 4], + identifier: Option<&Ident>, + ) { + self.store_function_node( + node_type, + function.span.lo.0 - 1, + function.span.hi.0 - 1, + function.is_async, + function.is_generator, + identifier, + &function.params.iter().map(|param| ¶m.pat).collect(), + function.body.as_ref().unwrap(), + true, + ); + } + + fn convert_class_expression(&mut self, class_expression: &ClassExpr, node_type: &[u8; 4]) { + self.store_class_node( + node_type, + class_expression.ident.as_ref(), + &class_expression.class, + ); + } + + fn convert_class_declaration(&mut self, class_declaration: &ClassDecl) { + self.store_class_node( + &TYPE_CLASS_DECLARATION, + Some(&class_declaration.ident), + &class_declaration.class, + ); + } + + fn store_class_node(&mut self, node_type: &[u8; 4], identifier: Option<&Ident>, class: &Class) { + let end_position = self.add_type_and_start(node_type, &class.span); + // reserve id, super_class, body + let reference_position = self.reserve_reference_positions(3); + let mut body_start_search = class.span.lo.0 - 1; + // id + identifier.map(|identifier| { + self.update_reference_position(reference_position); + self.convert_identifier(identifier); + body_start_search = identifier.span.hi.0 - 1; + }); + // super_class + class.super_class.as_ref().map(|super_class| { + self.update_reference_position(reference_position + 4); + self.convert_expression(super_class); + body_start_search = self.get_expression_span(super_class).hi.0 - 1; + }); + // body + self.update_reference_position(reference_position + 8); + let class_body_start = + find_first_occurrence_outside_comment(self.code, b'{', body_start_search); + self.convert_class_body(&class.body, class_body_start, class.span.hi.0 - 1); + // end + self.add_end(end_position, &class.span); + } + + fn convert_class_body(&mut self, class_members: &Vec, start: u32, end: u32) { + let end_position = self.add_type_and_explicit_start(&TYPE_CLASS_BODY, start); + // body + self.convert_item_list(class_members, |ast_converter, class_member| { + ast_converter.convert_class_member(class_member); + true + }); + // end + self.add_explicit_end(end_position, end); + } + + fn convert_return_statement(&mut self, return_statement: &ReturnStmt) { + let end_position = self.add_type_and_start(&TYPE_RETURN_STATEMENT, &return_statement.span); + // reserve argument + let reference_position = self.reserve_reference_positions(1); + // argument + return_statement.arg.as_ref().map(|argument| { + self.update_reference_position(reference_position); + self.convert_expression(argument) + }); + // end + self.add_end(end_position, &return_statement.span); + } + + fn convert_import_attribute(&mut self, key_value_property: &KeyValueProp) { + // type + self.buffer.extend_from_slice(&TYPE_IMPORT_ATTRIBUTE); + // reserve start, end, value + let reference_position = self.reserve_reference_positions(3); + // key + let key_position = self.buffer.len(); + let key_boundaries = self.convert_property_name(&key_value_property.key); + let start_bytes: [u8; 4] = match key_boundaries { + Some((start, _)) => start.to_ne_bytes(), + None => { + let key_start: [u8; 4] = self.buffer[key_position + 4..key_position + 8] + .try_into() + .unwrap(); + key_start + } + }; + self.buffer[reference_position..reference_position + 4].copy_from_slice(&start_bytes); + // value + self.update_reference_position(reference_position + 8); + let value_position = self.buffer.len(); + let value_boundaries = self.convert_expression(&key_value_property.value); + let end_bytes: [u8; 4] = match value_boundaries { + Some((_, end)) => end.to_ne_bytes(), + None => { + let value_end: [u8; 4] = self.buffer[value_position + 8..value_position + 12] + .try_into() + .unwrap(); + value_end + } + }; + self.buffer[reference_position + 4..reference_position + 8].copy_from_slice(&end_bytes); + } + + fn convert_object_literal(&mut self, object_literal: &ObjectLit) { + let end_position = self.add_type_and_start(&TYPE_OBJECT_EXPRESSION, &object_literal.span); + // properties + self.convert_item_list( + &object_literal.props, + |ast_converter, property_or_spread| { + ast_converter.convert_property_or_spread(property_or_spread); + true + }, + ); + // end + self.add_end(end_position, &object_literal.span); + } + + fn convert_property_name(&mut self, property_name: &PropName) -> Option<(u32, u32)> { + match property_name { + PropName::Computed(computed_property_name) => { + self.convert_expression(computed_property_name.expr.as_ref()) + } + PropName::Ident(ident) => { + self.convert_identifier(ident); + None + } + PropName::Str(string) => { + self.convert_literal_string(&string); + None + } + PropName::Num(number) => { + self.convert_literal_number(&number); + None + } + PropName::BigInt(bigint) => { + self.convert_literal_bigint(&bigint); + None + } + } + } + + fn get_property_name_span(&self, property_name: &PropName) -> Span { + match property_name { + PropName::Computed(computed_property_name) => computed_property_name.span, + PropName::Ident(ident) => ident.span, + PropName::Str(string) => string.span, + PropName::Num(number) => number.span, + PropName::BigInt(bigint) => bigint.span, + } + } + + // TODO SWC property has many different formats that should be merged if possible + fn store_key_value_property(&mut self, property_name: &PropName, value: PatternOrExpression) { + let end_position = self.add_type_and_explicit_start( + &TYPE_PROPERTY, + self.get_property_name_span(property_name).lo.0 - 1, + ); + // kind + self.buffer.extend_from_slice(&STRING_INIT); + // method + self.convert_boolean(false); + // computed + self.convert_boolean(match property_name { + PropName::Computed(_) => true, + _ => false, + }); + // shorthand + self.convert_boolean(false); + // reserve key, value + let reference_position = self.reserve_reference_positions(2); + // key + self.update_reference_position(reference_position); + self.convert_property_name(property_name); + // value + self.update_reference_position(reference_position + 4); + let value_position = self.buffer.len(); + let value_boundaries = match value { + PatternOrExpression::Pattern(pattern) => self.convert_pattern(pattern), + PatternOrExpression::Expression(expression) => self.convert_expression(expression), + }; + // end + let end_bytes: [u8; 4] = match value_boundaries { + Some((_, end)) => end.to_ne_bytes(), + None => { + let value_end: [u8; 4] = self.buffer[value_position + 8..value_position + 12] + .try_into() + .unwrap(); + value_end + } + }; + // TODO SWC avoid copying positions around but use span getters instead + self.buffer[end_position..end_position + 4].copy_from_slice(&end_bytes); + } + + fn convert_key_value_property(&mut self, key_value_property: &KeyValueProp) { + self.store_key_value_property( + &key_value_property.key, + PatternOrExpression::Expression(&key_value_property.value), + ); + } + + fn convert_key_value_pattern_property(&mut self, key_value_pattern_property: &KeyValuePatProp) { + self.store_key_value_property( + &key_value_pattern_property.key, + PatternOrExpression::Pattern(&key_value_pattern_property.value), + ); + } + + // TODO SWC merge with method + fn store_getter_setter_property( + &mut self, + span: &Span, + kind: &[u8; 4], + key: &PropName, + body: &Option, + param: Option<&Pat>, + ) { + let end_position = self.add_type_and_start(&TYPE_PROPERTY, span); + // kind + self.buffer.extend_from_slice(kind); + // method + self.convert_boolean(false); + // computed + self.convert_boolean(match &key { + PropName::Computed(_) => true, + _ => false, + }); + // shorthand + self.convert_boolean(false); + // reserve key, value + let reference_position = self.reserve_reference_positions(2); + // key + self.update_reference_position(reference_position); + self.convert_property_name(key); + let key_end = self.get_property_name_span(&key).hi.0 - 1; + // value + let block_statement = body.as_ref().expect("Getter/setter property without body"); + self.update_reference_position(reference_position + 4); + let parameters = match param { + Some(pattern) => vec![pattern], + None => vec![], + }; + self.store_function_node( + &TYPE_FUNCTION_EXPRESSION, + find_first_occurrence_outside_comment(self.code, b'(', key_end), + block_statement.span.hi.0 - 1, + false, + false, + None, + ¶meters, + block_statement, + false, + ); + // end + self.add_end(end_position, span); + } + + fn convert_getter_property(&mut self, getter_property: &GetterProp) { + self.store_getter_setter_property( + &getter_property.span, + &STRING_GET, + &getter_property.key, + &getter_property.body, + None, + ); + } + + fn convert_setter_property(&mut self, setter_property: &SetterProp) { + self.store_getter_setter_property( + &setter_property.span, + &STRING_SET, + &setter_property.key, + &setter_property.body, + Some(&*setter_property.param), + ); + } + + fn convert_method_property(&mut self, method_property: &MethodProp) { + let end_position = self.add_type_and_start(&TYPE_PROPERTY, &method_property.function.span); + // kind + self.buffer.extend_from_slice(&STRING_INIT); + // method + self.convert_boolean(true); + // computed + self.convert_boolean(match &method_property.key { + PropName::Computed(_) => true, + _ => false, + }); + // shorthand + self.convert_boolean(false); + // reserve key, value + let reference_position = self.reserve_reference_positions(2); + // key + self.update_reference_position(reference_position); + self.convert_property_name(&method_property.key); + let key_end = self.get_property_name_span(&method_property.key).hi.0 - 1; + let function_start = find_first_occurrence_outside_comment(self.code, b'(', key_end); + // value + self.update_reference_position(reference_position + 4); + let function = &method_property.function; + self.store_function_node( + &TYPE_FUNCTION_EXPRESSION, + function_start, + function.span.hi.0 - 1, + function.is_async, + function.is_generator, + None, + &function.params.iter().map(|param| ¶m.pat).collect(), + function.body.as_ref().unwrap(), + false, + ); + // end + self.add_end(end_position, &method_property.function.span); + } + + fn store_shorthand_property( + &mut self, + span: &Span, + key: &Ident, + assignment_value: &Option>, + ) { + let end_position = self.add_type_and_start(&TYPE_PROPERTY, span); + // kind + self.buffer.extend_from_slice(&STRING_INIT); + // method + self.convert_boolean(false); + // computed + self.convert_boolean(false); + // shorthand + self.convert_boolean(true); + // reserve key, value + let reference_position = self.reserve_reference_positions(2); + // value + match assignment_value { + Some(value) => { + // value + self.update_reference_position(reference_position + 4); + let left_position = self.store_assignment_pattern_and_get_left_position( + span, + PatternOrIdentifier::Identifier(key), + value, + ); + // key, reuse identifier to avoid converting positions out of order + self.buffer[reference_position..reference_position + 4] + .copy_from_slice(&left_position.to_ne_bytes()); + } + None => { + // key + self.update_reference_position(reference_position); + self.convert_identifier(key); + } + } + // end + self.add_end(end_position, span); + } + + fn convert_shorthand_property(&mut self, identifier: &Ident) { + self.store_shorthand_property(&identifier.span, identifier, &None); + } + + fn convert_assignment_pattern_property(&mut self, assignment_pattern_property: &AssignPatProp) { + self.store_shorthand_property( + &assignment_pattern_property.span, + &assignment_pattern_property.key, + &assignment_pattern_property.value, + ); + } + + fn convert_assignment_expression(&mut self, assignment_expression: &AssignExpr) { + let end_position = + self.add_type_and_start(&TYPE_ASSIGNMENT_EXPRESSION, &assignment_expression.span); + // operator + self + .buffer + .extend_from_slice(match assignment_expression.op { + AssignOp::Assign => &STRING_ASSIGN, + AssignOp::AddAssign => &STRING_ADDASSIGN, + AssignOp::SubAssign => &STRING_SUBASSIGN, + AssignOp::MulAssign => &STRING_MULASSIGN, + AssignOp::DivAssign => &STRING_DIVASSIGN, + AssignOp::ModAssign => &STRING_MODASSIGN, + AssignOp::LShiftAssign => &STRING_LSHIFTASSIGN, + AssignOp::RShiftAssign => &STRING_RSHIFTASSIGN, + AssignOp::ZeroFillRShiftAssign => &STRING_ZEROFILLRSHIFTASSIGN, + AssignOp::BitOrAssign => &STRING_BITORASSIGN, + AssignOp::BitXorAssign => &STRING_BITXORASSIGN, + AssignOp::BitAndAssign => &STRING_BITANDASSIGN, + AssignOp::ExpAssign => &STRING_EXPASSIGN, + AssignOp::AndAssign => &STRING_ANDASSIGN, + AssignOp::OrAssign => &STRING_ORASSIGN, + AssignOp::NullishAssign => &STRING_NULLISHASSIGN, + }); + // reserve right + let reference_position = self.reserve_reference_positions(1); + // left + self.convert_pattern_or_expression(&assignment_expression.left); + // right + self.update_reference_position(reference_position); + self.convert_expression(&assignment_expression.right); + // end + self.add_end(end_position, &assignment_expression.span); + } + + fn convert_new_expression(&mut self, new_expression: &NewExpr) { + let end_position = self.add_type_and_start(&TYPE_NEW_EXPRESSION, &new_expression.span); + let annotations = self + .index_converter + .take_collected_annotations(AnnotationKind::Pure); + // reserve for callee, args + let reference_position = self.reserve_reference_positions(2); + // annotations + self.convert_item_list(&annotations, |ast_converter, annotation| { + ast_converter.convert_annotation(annotation); + true + }); + // callee + self.update_reference_position(reference_position); + self.convert_expression(&new_expression.callee); + // args + if let Some(expressions_or_spread) = &new_expression.args { + self.update_reference_position(reference_position + 4); + self.convert_item_list( + &expressions_or_spread, + |ast_converter, expression_or_spread| { + ast_converter.convert_expression_or_spread(expression_or_spread); + true + }, + ); + } + // end + self.add_end(end_position, &new_expression.span); + } + + fn store_function_node( + &mut self, + node_type: &[u8; 4], + start: u32, + end: u32, + is_async: bool, + is_generator: bool, + identifier: Option<&Ident>, + parameters: &Vec<&Pat>, + body: &BlockStmt, + observe_annotations: bool, + ) { + let end_position = self.add_type_and_explicit_start(node_type, start); + // async + self.convert_boolean(is_async); + // generator + self.convert_boolean(is_generator); + // reserve id, params, body + let reference_position = self.reserve_reference_positions(3); + // annotations + if observe_annotations { + let annotations = self + .index_converter + .take_collected_annotations(AnnotationKind::NoSideEffects); + self.convert_item_list(&annotations, |ast_converter, annotation| { + ast_converter.convert_annotation(annotation); + true + }); + } else { + self.buffer.extend_from_slice(&0u32.to_ne_bytes()); + } + // id + identifier.map(|ident| { + self.update_reference_position(reference_position); + self.convert_identifier(ident); + }); + // params + self.update_reference_position(reference_position + 4); + self.convert_item_list(parameters, |ast_converter, param| { + ast_converter.convert_pattern(¶m); + true + }); + // body + self.update_reference_position(reference_position + 8); + self.convert_block_statement(body, true); + // end + self.add_explicit_end(end_position, end); + } + + fn convert_throw_statement(&mut self, throw_statement: &ThrowStmt) { + let end_position = self.add_type_and_start(&TYPE_THROW_STATEMENT, &throw_statement.span); + // argument + self.convert_expression(&throw_statement.arg); + // end + self.add_end(end_position, &throw_statement.span); + } + + fn convert_assignment_pattern(&mut self, assignment_pattern: &AssignPat) { + self.store_assignment_pattern_and_get_left_position( + &assignment_pattern.span, + PatternOrIdentifier::Pattern(&assignment_pattern.left), + &assignment_pattern.right, + ); + } + + fn store_assignment_pattern_and_get_left_position( + &mut self, + span: &Span, + left: PatternOrIdentifier, + right: &Expr, + ) -> u32 { + let end_position = self.add_type_and_start(&TYPE_ASSIGNMENT_PATTERN, span); + // reserve right + let reference_position = self.reserve_reference_positions(1); + // left + let left_position = (self.buffer.len() >> 2) as u32; + match left { + PatternOrIdentifier::Pattern(pattern) => { + self.convert_pattern(&pattern); + } + PatternOrIdentifier::Identifier(identifier) => self.convert_identifier(&identifier), + } + // right + self.update_reference_position(reference_position); + self.convert_expression(right); + // end + self.add_end(end_position, span); + left_position + } + + fn convert_await_expression(&mut self, await_expression: &AwaitExpr) { + let end_position = self.add_type_and_start(&TYPE_AWAIT_EXPRESSION, &await_expression.span); + // argument + self.convert_expression(&await_expression.arg); + // end + self.add_end(end_position, &await_expression.span); + } + + fn convert_labeled_statement(&mut self, labeled_statement: &LabeledStmt) { + let end_position = self.add_type_and_start(&TYPE_LABELED_STATEMENT, &labeled_statement.span); + // reserve body + let reference_position = self.reserve_reference_positions(1); + // label + self.convert_identifier(&labeled_statement.label); + // body + self.update_reference_position(reference_position); + self.convert_statement(&labeled_statement.body); + // end + self.add_end(end_position, &labeled_statement.span); + } + + fn convert_break_statement(&mut self, break_statement: &BreakStmt) { + let end_position = self.add_type_and_start(&TYPE_BREAK_STATEMENT, &break_statement.span); + // reserve label + let reference_position = self.reserve_reference_positions(1); + // label + break_statement.label.as_ref().map(|label| { + self.update_reference_position(reference_position); + self.convert_identifier(label); + }); + // end + self.add_end(end_position, &break_statement.span); + } + + fn convert_try_statement(&mut self, try_statement: &TryStmt) { + let end_position = self.add_type_and_start(&TYPE_TRY_STATEMENT, &try_statement.span); + // reserve handler, finalizer + let reference_position = self.reserve_reference_positions(2); + // block + self.convert_block_statement(&try_statement.block, false); + // handler + try_statement.handler.as_ref().map(|catch_clause| { + self.update_reference_position(reference_position); + self.convert_catch_clause(catch_clause); + }); + // finalizer + try_statement.finalizer.as_ref().map(|block_statement| { + self.update_reference_position(reference_position + 4); + self.convert_block_statement(block_statement, false); + }); + // end + self.add_end(end_position, &try_statement.span); + } + + fn convert_catch_clause(&mut self, catch_clause: &CatchClause) { + let end_position = self.add_type_and_start(&TYPE_CATCH_CLAUSE, &catch_clause.span); + // reserve param, body + let reference_position = self.reserve_reference_positions(2); + // param + catch_clause.param.as_ref().map(|pattern| { + self.update_reference_position(reference_position); + self.convert_pattern(pattern); + }); + // body + self.update_reference_position(reference_position + 4); + self.convert_block_statement(&catch_clause.body, false); + // end + self.add_end(end_position, &catch_clause.span); + } + + fn convert_optional_chain_expression( + &mut self, + optional_chain_expression: &OptChainExpr, + is_chained: bool, + ) { + if is_chained { + self.convert_optional_chain_base( + &optional_chain_expression.base, + optional_chain_expression.optional, + ); + } else { + let end_position = + self.add_type_and_start(&TYPE_CHAIN_EXPRESSION, &optional_chain_expression.span); + // expression + self.convert_optional_chain_base( + &optional_chain_expression.base, + optional_chain_expression.optional, + ); + // end + self.add_end(end_position, &optional_chain_expression.span); + } + } + + fn convert_while_statement(&mut self, while_statement: &WhileStmt) { + let end_position = self.add_type_and_start(&TYPE_WHILE_STATEMENT, &while_statement.span); + // reserve body + let reference_position = self.reserve_reference_positions(1); + // test + self.convert_expression(&while_statement.test); + // body + self.update_reference_position(reference_position); + self.convert_statement(&while_statement.body); + // end + self.add_end(end_position, &while_statement.span); + } + + fn convert_continue_statement(&mut self, continue_statement: &ContinueStmt) { + let end_position = self.add_type_and_start(&TYPE_CONTINUE_STATEMENT, &continue_statement.span); + // reserve label + let reference_position = self.reserve_reference_positions(1); + // label + continue_statement.label.as_ref().map(|label| { + self.update_reference_position(reference_position); + self.convert_identifier(label); + }); + // end + self.add_end(end_position, &continue_statement.span); + } + + fn convert_do_while_statement(&mut self, do_while_statement: &DoWhileStmt) { + let end_position = self.add_type_and_start(&TYPE_DO_WHILE_STATEMENT, &do_while_statement.span); + // reserve test + let reference_position = self.reserve_reference_positions(1); + // body + self.convert_statement(&do_while_statement.body); + // test + self.update_reference_position(reference_position); + self.convert_expression(&do_while_statement.test); + // end + self.add_end(end_position, &do_while_statement.span); + } + + fn convert_debugger_statement(&mut self, debugger_statement: &DebuggerStmt) { + self.add_type_and_positions(&TYPE_DEBUGGER_STATEMENT, &debugger_statement.span); + } + + fn convert_empty_statement(&mut self, empty_statement: &EmptyStmt) { + self.add_type_and_positions(&TYPE_EMPTY_STATEMENT, &empty_statement.span); + } + + fn convert_for_in_statement(&mut self, for_in_statement: &ForInStmt) { + let end_position = self.add_type_and_start(&TYPE_FOR_IN_STATEMENT, &for_in_statement.span); + // reserve right, body + let reference_position = self.reserve_reference_positions(2); + // left + self.convert_for_head(&for_in_statement.left); + // right + self.update_reference_position(reference_position); + self.convert_expression(&for_in_statement.right); + // body + self.update_reference_position(reference_position + 4); + self.convert_statement(&for_in_statement.body); + // end + self.add_end(end_position, &for_in_statement.span); + } + + fn convert_for_of_statement(&mut self, for_of_statement: &ForOfStmt) { + let end_position = self.add_type_and_start(&TYPE_FOR_OF_STATEMENT, &for_of_statement.span); + // await + self.convert_boolean(for_of_statement.is_await); + // reserve right, body + let reference_position = self.reserve_reference_positions(2); + // left + self.convert_for_head(&for_of_statement.left); + // right + self.update_reference_position(reference_position); + self.convert_expression(&for_of_statement.right); + // body + self.update_reference_position(reference_position + 4); + self.convert_statement(&for_of_statement.body); + // end + self.add_end(end_position, &for_of_statement.span); + } + + fn convert_for_statement(&mut self, for_statement: &ForStmt) { + let end_position = self.add_type_and_start(&TYPE_FOR_STATEMENT, &for_statement.span); + // reserve init, test, update, body + let reference_position = self.reserve_reference_positions(4); + // init + for_statement.init.as_ref().map(|init| { + self.update_reference_position(reference_position); + self.convert_variable_declaration_or_expression(init); + }); + // test + for_statement.test.as_ref().map(|test| { + self.update_reference_position(reference_position + 4); + self.convert_expression(test); + }); + // update + for_statement.update.as_ref().map(|update| { + self.update_reference_position(reference_position + 8); + self.convert_expression(update); + }); + // body + self.update_reference_position(reference_position + 12); + self.convert_statement(&for_statement.body); + // end + self.add_end(end_position, &for_statement.span); + } + + fn convert_if_statement(&mut self, if_statement: &IfStmt) { + let end_position = self.add_type_and_start(&TYPE_IF_STATEMENT, &if_statement.span); + // reserve consequent, alternate + let reference_position = self.reserve_reference_positions(2); + // test + self.convert_expression(&if_statement.test); + // consequent + self.update_reference_position(reference_position); + self.convert_statement(&if_statement.cons); + // alternate + if_statement.alt.as_ref().map(|alt| { + self.update_reference_position(reference_position + 4); + self.convert_statement(alt); + }); + // end + self.add_end(end_position, &if_statement.span); + } + + fn convert_literal_regex(&mut self, regex: &Regex) { + self.add_type_and_positions(&TYPE_LITERAL_REGEXP, ®ex.span); + // reserve pattern + let reference_position = self.reserve_reference_positions(1); + // flags + self.convert_string(®ex.flags); + // pattern + self.update_reference_position(reference_position); + self.convert_string(®ex.exp); + } + + fn convert_literal_bigint(&mut self, bigint: &BigInt) { + self.add_type_and_positions(&TYPE_LITERAL_BIGINT, &bigint.span); + // reserve value + let reference_position = self.reserve_reference_positions(1); + // raw + self.convert_string(bigint.raw.as_ref().unwrap()); + // value + self.update_reference_position(reference_position); + self.convert_string(&bigint.value.to_str_radix(10)); + } + + fn convert_meta_property(&mut self, meta_property_expression: &MetaPropExpr) { + let end_position = self.add_type_and_start(&TYPE_META_PROPERTY, &meta_property_expression.span); + // reserve property + let reference_position = self.reserve_reference_positions(1); + match meta_property_expression.kind { + MetaPropKind::ImportMeta => { + // meta + self.store_identifier( + meta_property_expression.span.lo.0 - 1, + meta_property_expression.span.lo.0 + 5, + "import", + ); + // property + self.update_reference_position(reference_position); + self.store_identifier( + meta_property_expression.span.hi.0 - 5, + meta_property_expression.span.hi.0 - 1, + "meta", + ); + } + MetaPropKind::NewTarget => { + // meta + self.store_identifier( + meta_property_expression.span.lo.0 - 1, + meta_property_expression.span.lo.0 + 2, + "new", + ); + // property + self.update_reference_position(reference_position); + self.store_identifier( + meta_property_expression.span.hi.0 - 7, + meta_property_expression.span.hi.0 - 1, + "target", + ); + } + } + // end + self.add_end(end_position, &meta_property_expression.span); + } + + fn convert_constructor(&mut self, constructor: &Constructor) { + let end_position = self.add_type_and_start(&TYPE_METHOD_DEFINITION, &constructor.span); + // kind + self.buffer.extend_from_slice(&STRING_CONSTRUCTOR); + // computed + self.convert_boolean(false); + // static + self.convert_boolean(false); + // reserve value + let reference_position = self.reserve_reference_positions(1); + // key + self.convert_property_name(&constructor.key); + // value + match &constructor.body { + Some(block_statement) => { + self.update_reference_position(reference_position); + let key_end = self.get_property_name_span(&constructor.key).hi.0 - 1; + let function_start = find_first_occurrence_outside_comment(self.code, b'(', key_end); + self.store_function_node( + &TYPE_FUNCTION_EXPRESSION, + function_start, + block_statement.span.hi.0 - 1, + false, + false, + None, + &constructor + .params + .iter() + .map(|param| match param { + ParamOrTsParamProp::Param(param) => ¶m.pat, + ParamOrTsParamProp::TsParamProp(_) => panic!("TsParamProp in constructor"), + }) + .collect(), + block_statement, + false, + ); + } + None => { + panic!("Getter property without body"); + } + } + // end + self.add_end(end_position, &constructor.span); + } + + fn convert_method(&mut self, method: &ClassMethod) { + self.store_method_definition( + &method.span, + &method.kind, + method.is_static, + PropOrPrivateName::PropName(&method.key), + match method.key { + PropName::Computed(_) => true, + _ => false, + }, + &method.function, + ); + } + + fn convert_private_method(&mut self, private_method: &PrivateMethod) { + self.store_method_definition( + &private_method.span, + &private_method.kind, + private_method.is_static, + PropOrPrivateName::PrivateName(&private_method.key), + false, + &private_method.function, + ); + } + + fn store_method_definition( + &mut self, + span: &Span, + kind: &MethodKind, + is_static: bool, + key: PropOrPrivateName, + is_computed: bool, + function: &Function, + ) { + let end_position = self.add_type_and_start(&TYPE_METHOD_DEFINITION, span); + // kind + self.buffer.extend_from_slice(match kind { + MethodKind::Method => &STRING_METHOD, + MethodKind::Getter => &STRING_GET, + MethodKind::Setter => &STRING_SET, + }); + // computed + self.convert_boolean(is_computed); + // static + self.convert_boolean(is_static); + // reserve value + let reference_position = self.reserve_reference_positions(1); + // key + let key_end = match key { + PropOrPrivateName::PropName(prop_name) => { + self.convert_property_name(&prop_name); + self.get_property_name_span(&prop_name).hi.0 - 1 + } + PropOrPrivateName::PrivateName(private_name) => { + self.convert_private_name(&private_name); + private_name.id.span.hi.0 - 1 + } + }; + let function_start = find_first_occurrence_outside_comment(self.code, b'(', key_end); + // value + self.update_reference_position(reference_position); + self.store_function_node( + &TYPE_FUNCTION_EXPRESSION, + function_start, + function.span.hi.0 - 1, + function.is_async, + function.is_generator, + None, + &function.params.iter().map(|param| ¶m.pat).collect(), + function.body.as_ref().unwrap(), + false, + ); + // end + self.add_end(end_position, span); + } + + fn store_property_definition( + &mut self, + span: &Span, + is_computed: bool, + is_static: bool, + key: PropOrPrivateName, + value: &Option<&Expr>, + ) { + let end_position = self.add_type_and_start(&TYPE_PROPERTY_DEFINITION, span); + // computed + self.convert_boolean(is_computed); + // static + self.convert_boolean(is_static); + // reserve value + let reference_position = self.reserve_reference_positions(1); + // key + match key { + PropOrPrivateName::PropName(prop_name) => { + self.convert_property_name(&prop_name); + } + PropOrPrivateName::PrivateName(private_name) => self.convert_private_name(&private_name), + } + // value + value.map(|expression| { + self.update_reference_position(reference_position); + self.convert_expression(expression); + }); + // end + self.add_end(end_position, span); + } + + fn convert_class_property(&mut self, class_property: &ClassProp) { + self.store_property_definition( + &class_property.span, + match &class_property.key { + PropName::Computed(_) => true, + _ => false, + }, + class_property.is_static, + PropOrPrivateName::PropName(&class_property.key), + &class_property + .value + .as_ref() + .map(|expression| &**expression), + ); + } + + fn convert_private_property(&mut self, private_property: &PrivateProp) { + self.store_property_definition( + &private_property.span, + false, + private_property.is_static, + PropOrPrivateName::PrivateName(&private_property.key), + &private_property + .value + .as_ref() + .map(|expression| &**expression), + ); + } + + fn convert_this_expression(&mut self, this_expression: &ThisExpr) { + self.add_type_and_positions(&TYPE_THIS_EXPRESSION, &this_expression.span); + } + + fn convert_static_block(&mut self, static_block: &StaticBlock) { + let end_position = self.add_type_and_start(&TYPE_STATIC_BLOCK, &static_block.span); + // body + self.convert_item_list(&static_block.body.stmts, |ast_converter, statement| { + ast_converter.convert_statement(statement); + true + }); + // end + self.add_end(end_position, &static_block.span); + } + + fn convert_super_property(&mut self, super_property: &SuperPropExpr) { + self.store_member_expression( + &super_property.span, + false, + &ExpressionOrSuper::Super(&super_property.obj), + match &super_property.prop { + SuperProp::Ident(identifier) => MemberOrSuperProp::Identifier(&identifier), + SuperProp::Computed(computed_property_name) => { + MemberOrSuperProp::Computed(&computed_property_name) + } + }, + false, + ); + } + + fn convert_super(&mut self, super_token: &Super) { + self.add_type_and_positions(&TYPE_SUPER, &super_token.span); + } + + fn convert_rest_pattern(&mut self, rest_pattern: &RestPat) { + let end_position = + self.add_type_and_explicit_start(&TYPE_REST_ELEMENT, rest_pattern.dot3_token.lo.0 - 1); + // argument + self.convert_pattern(&rest_pattern.arg); + // end + self.add_explicit_end(end_position, rest_pattern.span.hi.0 - 1); + } + + fn convert_sequence_expression(&mut self, sequence_expression: &SeqExpr) { + let end_position = + self.add_type_and_start(&TYPE_SEQUENCE_EXPRESSION, &sequence_expression.span); + // expressions + self.convert_item_list(&sequence_expression.exprs, |ast_converter, expression| { + ast_converter.convert_expression(expression); + true + }); + // end + self.add_end(end_position, &sequence_expression.span); + } + + fn convert_switch_statement(&mut self, switch_statement: &SwitchStmt) { + let end_position = self.add_type_and_start(&TYPE_SWITCH_STATEMENT, &switch_statement.span); + // reserve cases + let reference_position = self.reserve_reference_positions(1); + // discriminant + self.convert_expression(&switch_statement.discriminant); + // cases + self.update_reference_position(reference_position); + self.convert_item_list(&switch_statement.cases, |ast_converter, switch_case| { + ast_converter.convert_switch_case(switch_case); + true + }); + // end + self.add_end(end_position, &switch_statement.span); + } + + fn convert_switch_case(&mut self, switch_case: &SwitchCase) { + let end_position = self.add_type_and_start(&TYPE_SWITCH_CASE, &switch_case.span); + // reserve test, consequent + let reference_position = self.reserve_reference_positions(2); + // test + switch_case.test.as_ref().map(|expression| { + self.update_reference_position(reference_position); + self.convert_expression(expression) + }); + // consequent + self.update_reference_position(reference_position + 4); + self.convert_item_list(&switch_case.cons, |ast_converter, statement| { + ast_converter.convert_statement(statement); + true + }); + // end + self.add_end(end_position, &switch_case.span); + } + + fn convert_tagged_template_expression(&mut self, tagged_template: &TaggedTpl) { + let end_position = + self.add_type_and_start(&TYPE_TAGGED_TEMPLATE_EXPRESSION, &tagged_template.span); + // reserve quasi + let reference_position = self.reserve_reference_positions(1); + // tag + self.convert_expression(&tagged_template.tag); + // quasi + self.update_reference_position(reference_position); + self.convert_template_literal(&tagged_template.tpl); + // end + self.add_end(end_position, &tagged_template.span); + } + + fn convert_template_literal(&mut self, template_literal: &Tpl) { + let end_position = self.add_type_and_start(&TYPE_TEMPLATE_LITERAL, &template_literal.span); + // reserve expressions + let reference_position = self.reserve_reference_positions(1); + // quasis, we manually do an item list here + self + .buffer + .extend_from_slice(&(template_literal.quasis.len() as u32).to_ne_bytes()); + let mut next_quasi_position = self.buffer.len(); + // make room for the positions of the quasis + self + .buffer + .resize(self.buffer.len() + template_literal.quasis.len() * 4, 0); + let mut quasis = template_literal.quasis.iter(); + // convert first quasi + let first_quasi = quasis.next().unwrap(); + let insert_position = (self.buffer.len() as u32) >> 2; + self.convert_template_element(first_quasi); + self.buffer[next_quasi_position..next_quasi_position + 4] + .copy_from_slice(&insert_position.to_ne_bytes()); + next_quasi_position += 4; + // now convert expressions, interleaved with quasis + self.update_reference_position(reference_position); + self + .buffer + .extend_from_slice(&(template_literal.exprs.len() as u32).to_ne_bytes()); + let mut next_expression_position = self.buffer.len(); + // make room for the positions of the expressions + self + .buffer + .resize(self.buffer.len() + template_literal.exprs.len() * 4, 0); + for expression in template_literal.exprs.as_slice() { + // convert expression + let insert_position = (self.buffer.len() as u32) >> 2; + self.convert_expression(&expression); + self.buffer[next_expression_position..next_expression_position + 4] + .copy_from_slice(&insert_position.to_ne_bytes()); + next_expression_position += 4; + // convert next quasi + let next_quasi = quasis.next().unwrap(); + let insert_position = (self.buffer.len() as u32) >> 2; + self.convert_template_element(next_quasi); + self.buffer[next_quasi_position..next_quasi_position + 4] + .copy_from_slice(&insert_position.to_ne_bytes()); + next_quasi_position += 4; + } + // end + self.add_end(end_position, &template_literal.span); + } + + fn convert_template_element(&mut self, template_element: &TplElement) { + self.add_type_and_positions(&TYPE_TEMPLATE_ELEMENT, &template_element.span); + // tail + self.convert_boolean(template_element.tail); + // reserve cooked + let reference_position = self.reserve_reference_positions(1); + // raw + self.convert_string(&template_element.raw); + // cooked + template_element.cooked.as_ref().map(|cooked| { + self.update_reference_position(reference_position); + self.convert_string(cooked) + }); + } + + fn convert_unary_expression(&mut self, unary_expression: &UnaryExpr) { + let end_position = self.add_type_and_start(&TYPE_UNARY_EXPRESSION, &unary_expression.span); + // operator + self.buffer.extend_from_slice(match unary_expression.op { + UnaryOp::Minus => &STRING_MINUS, + UnaryOp::Plus => &STRING_PLUS, + UnaryOp::Bang => &STRING_BANG, + UnaryOp::Tilde => &STRING_TILDE, + UnaryOp::TypeOf => &STRING_TYPEOF, + UnaryOp::Void => &STRING_VOID, + UnaryOp::Delete => &STRING_DELETE, + }); + // argument + self.convert_expression(&unary_expression.arg); + // end + self.add_end(end_position, &unary_expression.span); + } + + fn convert_update_expression(&mut self, update_expression: &UpdateExpr) { + let end_position = self.add_type_and_start(&TYPE_UPDATE_EXPRESSION, &update_expression.span); + // prefix + self.convert_boolean(update_expression.prefix); + // operator + self.buffer.extend_from_slice(match update_expression.op { + UpdateOp::PlusPlus => &STRING_PLUSPLUS, + UpdateOp::MinusMinus => &STRING_MINUSMINUS, + }); + // argument + self.convert_expression(&update_expression.arg); + // end + self.add_end(end_position, &update_expression.span); + } + + fn convert_yield_expression(&mut self, yield_expression: &YieldExpr) { + let end_position = self.add_type_and_start(&TYPE_YIELD_EXPRESSION, &yield_expression.span); + // delegate + self.convert_boolean(yield_expression.delegate); + // reserve argument + let reference_position = self.reserve_reference_positions(1); + // argument + yield_expression.arg.as_ref().map(|expression| { + self.update_reference_position(reference_position); + self.convert_expression(expression) + }); + // end + self.add_end(end_position, &yield_expression.span); + } + + fn convert_annotation(&mut self, annotation: &ConvertedAnnotation) { + // start + self + .buffer + .extend_from_slice(&annotation.start.to_ne_bytes()); + // end + self.buffer.extend_from_slice(&annotation.end.to_ne_bytes()); + // kind + self.buffer.extend_from_slice(match annotation.kind { + AnnotationKind::Pure => &STRING_PURE, + AnnotationKind::NoSideEffects => &STRING_NOSIDEEFFECTS, + AnnotationKind::SourceMappingUrl => &STRING_SOURCEMAP, + }); + } +} + +pub fn convert_string(buffer: &mut Vec, string: &str) { + let length = string.len(); + let additional_length = ((length + 3) & !3) - length; + buffer.extend_from_slice(&(length as u32).to_ne_bytes()); + buffer.extend_from_slice(string.as_bytes()); + buffer.resize(buffer.len() + additional_length, 0); +} + +enum StoredCallee<'a> { + Expression(&'a Expr), + Super(&'a Super), +} + +enum StoredDefaultExportExpression<'a> { + Expression(&'a Expr), + Class(&'a ClassExpr), + Function(&'a FnExpr), +} + +enum PropOrPrivateName<'a> { + PropName(&'a PropName), + PrivateName(&'a PrivateName), +} + +enum ExpressionOrSuper<'a> { + Expression(&'a Expr), + Super(&'a Super), +} + +enum MemberOrSuperProp<'a> { + Identifier(&'a Ident), + PrivateName(&'a PrivateName), + Computed(&'a ComputedPropName), +} + +enum PatternOrIdentifier<'a> { + Pattern(&'a Pat), + Identifier(&'a Ident), +} + +enum PatternOrExpression<'a> { + Pattern(&'a Pat), + Expression(&'a Expr), +} + +enum ModuleItemsOrStatements<'a> { + ModuleItems(&'a Vec), + Statements(&'a Vec), +} diff --git a/rust/parse_ast/src/convert_ast/converter/analyze_code.rs b/rust/parse_ast/src/convert_ast/converter/analyze_code.rs new file mode 100644 index 000000000..d2fb985df --- /dev/null +++ b/rust/parse_ast/src/convert_ast/converter/analyze_code.rs @@ -0,0 +1,40 @@ +pub fn find_first_occurrence_outside_comment(code: &[u8], search_byte: u8, start: u32) -> u32 { + let mut search_pos = start as usize; + let mut comment_type = CommentType::None; + loop { + match comment_type { + CommentType::SingleLine => { + if code[search_pos] == b'\n' { + comment_type = CommentType::None; + } + } + CommentType::MultiLine => { + if code[search_pos] == b'*' && code[search_pos + 1] == b'/' { + comment_type = CommentType::None; + search_pos += 1; + } + } + CommentType::None => { + if code[search_pos] == b'/' && code[search_pos + 1] == b'/' { + comment_type = CommentType::SingleLine; + search_pos += 1; + } else if code[search_pos] == b'/' && code[search_pos + 1] == b'*' { + comment_type = CommentType::MultiLine; + search_pos += 1; + } else if code[search_pos] == search_byte { + return search_pos as u32; + } + } + } + search_pos += 1; + if search_pos >= code.len() { + return code.len().try_into().unwrap(); + } + } +} + +enum CommentType { + SingleLine, + MultiLine, + None, +} diff --git a/rust/parse_ast/src/convert_ast/converter/node_types.rs b/rust/parse_ast/src/convert_ast/converter/node_types.rs new file mode 100644 index 000000000..0a26646ee --- /dev/null +++ b/rust/parse_ast/src/convert_ast/converter/node_types.rs @@ -0,0 +1,78 @@ +// These need to reflect the order in the JavaScript decoder +pub const TYPE_ARRAY_EXPRESSION: [u8; 4] = 0u32.to_ne_bytes(); +pub const TYPE_ARRAY_PATTERN: [u8; 4] = 1u32.to_ne_bytes(); +pub const TYPE_ARROW_FUNCTION_EXPRESSION: [u8; 4] = 2u32.to_ne_bytes(); +pub const TYPE_ASSIGNMENT_EXPRESSION: [u8; 4] = 3u32.to_ne_bytes(); +pub const TYPE_ASSIGNMENT_PATTERN: [u8; 4] = 4u32.to_ne_bytes(); +pub const TYPE_AWAIT_EXPRESSION: [u8; 4] = 5u32.to_ne_bytes(); +pub const TYPE_BINARY_EXPRESSION: [u8; 4] = 6u32.to_ne_bytes(); +pub const TYPE_BLOCK_STATEMENT: [u8; 4] = 7u32.to_ne_bytes(); +pub const TYPE_BREAK_STATEMENT: [u8; 4] = 8u32.to_ne_bytes(); +pub const TYPE_CALL_EXPRESSION: [u8; 4] = 9u32.to_ne_bytes(); +pub const TYPE_CATCH_CLAUSE: [u8; 4] = 10u32.to_ne_bytes(); +pub const TYPE_CHAIN_EXPRESSION: [u8; 4] = 11u32.to_ne_bytes(); +pub const TYPE_CLASS_BODY: [u8; 4] = 12u32.to_ne_bytes(); +pub const TYPE_CLASS_DECLARATION: [u8; 4] = 13u32.to_ne_bytes(); +pub const TYPE_CLASS_EXPRESSION: [u8; 4] = 14u32.to_ne_bytes(); +pub const TYPE_CONDITIONAL_EXPRESSION: [u8; 4] = 15u32.to_ne_bytes(); +pub const TYPE_CONTINUE_STATEMENT: [u8; 4] = 16u32.to_ne_bytes(); +pub const TYPE_DEBUGGER_STATEMENT: [u8; 4] = 17u32.to_ne_bytes(); +pub const TYPE_DO_WHILE_STATEMENT: [u8; 4] = 18u32.to_ne_bytes(); +pub const TYPE_EMPTY_STATEMENT: [u8; 4] = 19u32.to_ne_bytes(); +pub const TYPE_EXPORT_ALL_DECLARATION: [u8; 4] = 20u32.to_ne_bytes(); +pub const TYPE_EXPORT_DEFAULT_DECLARATION: [u8; 4] = 21u32.to_ne_bytes(); +pub const TYPE_EXPORT_NAMED_DECLARATION: [u8; 4] = 22u32.to_ne_bytes(); +pub const TYPE_EXPORT_SPECIFIER: [u8; 4] = 23u32.to_ne_bytes(); +pub const TYPE_EXPRESSION_STATEMENT: [u8; 4] = 24u32.to_ne_bytes(); +pub const TYPE_FOR_IN_STATEMENT: [u8; 4] = 25u32.to_ne_bytes(); +pub const TYPE_FOR_OF_STATEMENT: [u8; 4] = 26u32.to_ne_bytes(); +pub const TYPE_FOR_STATEMENT: [u8; 4] = 27u32.to_ne_bytes(); +pub const TYPE_FUNCTION_DECLARATION: [u8; 4] = 28u32.to_ne_bytes(); +pub const TYPE_FUNCTION_EXPRESSION: [u8; 4] = 29u32.to_ne_bytes(); +pub const TYPE_IDENTIFIER: [u8; 4] = 30u32.to_ne_bytes(); +pub const TYPE_IF_STATEMENT: [u8; 4] = 31u32.to_ne_bytes(); +pub const TYPE_IMPORT_ATTRIBUTE: [u8; 4] = 32u32.to_ne_bytes(); +pub const TYPE_IMPORT_DECLARATION: [u8; 4] = 33u32.to_ne_bytes(); +pub const TYPE_IMPORT_DEFAULT_SPECIFIER: [u8; 4] = 34u32.to_ne_bytes(); +pub const TYPE_IMPORT_EXPRESSION: [u8; 4] = 35u32.to_ne_bytes(); +pub const TYPE_IMPORT_NAMESPACE_SPECIFIER: [u8; 4] = 36u32.to_ne_bytes(); +pub const TYPE_IMPORT_SPECIFIER: [u8; 4] = 37u32.to_ne_bytes(); +pub const TYPE_LABELED_STATEMENT: [u8; 4] = 38u32.to_ne_bytes(); +pub const TYPE_LITERAL_STRING: [u8; 4] = 39u32.to_ne_bytes(); +pub const TYPE_LITERAL_BOOLEAN: [u8; 4] = 40u32.to_ne_bytes(); +pub const TYPE_LITERAL_NUMBER: [u8; 4] = 41u32.to_ne_bytes(); +pub const TYPE_LITERAL_NULL: [u8; 4] = 42u32.to_ne_bytes(); +pub const TYPE_LITERAL_REGEXP: [u8; 4] = 43u32.to_ne_bytes(); +pub const TYPE_LITERAL_BIGINT: [u8; 4] = 44u32.to_ne_bytes(); +pub const TYPE_LOGICAL_EXPRESSION: [u8; 4] = 45u32.to_ne_bytes(); +pub const TYPE_MEMBER_EXPRESSION: [u8; 4] = 46u32.to_ne_bytes(); +pub const TYPE_META_PROPERTY: [u8; 4] = 47u32.to_ne_bytes(); +pub const TYPE_METHOD_DEFINITION: [u8; 4] = 48u32.to_ne_bytes(); +pub const TYPE_NEW_EXPRESSION: [u8; 4] = 49u32.to_ne_bytes(); +pub const TYPE_OBJECT_EXPRESSION: [u8; 4] = 50u32.to_ne_bytes(); +pub const TYPE_OBJECT_PATTERN: [u8; 4] = 51u32.to_ne_bytes(); +pub const TYPE_PRIVATE_IDENTIFIER: [u8; 4] = 52u32.to_ne_bytes(); +pub const TYPE_PROGRAM: [u8; 4] = 53u32.to_ne_bytes(); +pub const TYPE_PROPERTY: [u8; 4] = 54u32.to_ne_bytes(); +pub const TYPE_PROPERTY_DEFINITION: [u8; 4] = 55u32.to_ne_bytes(); +pub const TYPE_REST_ELEMENT: [u8; 4] = 56u32.to_ne_bytes(); +pub const TYPE_RETURN_STATEMENT: [u8; 4] = 57u32.to_ne_bytes(); +pub const TYPE_SEQUENCE_EXPRESSION: [u8; 4] = 58u32.to_ne_bytes(); +pub const TYPE_SPREAD_ELEMENT: [u8; 4] = 59u32.to_ne_bytes(); +pub const TYPE_STATIC_BLOCK: [u8; 4] = 60u32.to_ne_bytes(); +pub const TYPE_SUPER: [u8; 4] = 61u32.to_ne_bytes(); +pub const TYPE_SWITCH_CASE: [u8; 4] = 62u32.to_ne_bytes(); +pub const TYPE_SWITCH_STATEMENT: [u8; 4] = 63u32.to_ne_bytes(); +pub const TYPE_TAGGED_TEMPLATE_EXPRESSION: [u8; 4] = 64u32.to_ne_bytes(); +pub const TYPE_TEMPLATE_ELEMENT: [u8; 4] = 65u32.to_ne_bytes(); +pub const TYPE_TEMPLATE_LITERAL: [u8; 4] = 66u32.to_ne_bytes(); +pub const TYPE_THIS_EXPRESSION: [u8; 4] = 67u32.to_ne_bytes(); +pub const TYPE_THROW_STATEMENT: [u8; 4] = 68u32.to_ne_bytes(); +pub const TYPE_TRY_STATEMENT: [u8; 4] = 69u32.to_ne_bytes(); +pub const TYPE_UNARY_EXPRESSION: [u8; 4] = 70u32.to_ne_bytes(); +pub const TYPE_UPDATE_EXPRESSION: [u8; 4] = 71u32.to_ne_bytes(); +pub const TYPE_VARIABLE_DECLARATION: [u8; 4] = 72u32.to_ne_bytes(); +pub const TYPE_VARIABLE_DECLARATOR: [u8; 4] = 73u32.to_ne_bytes(); +pub const TYPE_WHILE_STATEMENT: [u8; 4] = 74u32.to_ne_bytes(); +pub const TYPE_YIELD_EXPRESSION: [u8; 4] = 75u32.to_ne_bytes(); +pub const TYPE_PARSE_ERROR: [u8; 4] = 76u32.to_ne_bytes(); diff --git a/rust/parse_ast/src/convert_ast/converter/string_constants.rs b/rust/parse_ast/src/convert_ast/converter/string_constants.rs new file mode 100644 index 000000000..5163c0242 --- /dev/null +++ b/rust/parse_ast/src/convert_ast/converter/string_constants.rs @@ -0,0 +1,62 @@ +// These need to correspond to the positions in convert-ast-strings.ts +pub const STRING_VAR: [u8; 4] = 0u32.to_ne_bytes(); // var +pub const STRING_LET: [u8; 4] = 1u32.to_ne_bytes(); // let +pub const STRING_CONST: [u8; 4] = 2u32.to_ne_bytes(); // const +pub const STRING_INIT: [u8; 4] = 3u32.to_ne_bytes(); // init +pub const STRING_GET: [u8; 4] = 4u32.to_ne_bytes(); // get +pub const STRING_SET: [u8; 4] = 5u32.to_ne_bytes(); // set +pub const STRING_CONSTRUCTOR: [u8; 4] = 6u32.to_ne_bytes(); // constructor +pub const STRING_METHOD: [u8; 4] = 7u32.to_ne_bytes(); // method +pub const STRING_MINUS: [u8; 4] = 8u32.to_ne_bytes(); // - +pub const STRING_PLUS: [u8; 4] = 9u32.to_ne_bytes(); // + +pub const STRING_BANG: [u8; 4] = 10u32.to_ne_bytes(); // ! +pub const STRING_TILDE: [u8; 4] = 11u32.to_ne_bytes(); // ~ +pub const STRING_TYPEOF: [u8; 4] = 12u32.to_ne_bytes(); // typeof +pub const STRING_VOID: [u8; 4] = 13u32.to_ne_bytes(); // void +pub const STRING_DELETE: [u8; 4] = 14u32.to_ne_bytes(); // delete +pub const STRING_PLUSPLUS: [u8; 4] = 15u32.to_ne_bytes(); // ++ +pub const STRING_MINUSMINUS: [u8; 4] = 16u32.to_ne_bytes(); // -- +pub const STRING_EQEQ: [u8; 4] = 17u32.to_ne_bytes(); // == +pub const STRING_NOTEQ: [u8; 4] = 18u32.to_ne_bytes(); // != +pub const STRING_EQEQEQ: [u8; 4] = 19u32.to_ne_bytes(); // === +pub const STRING_NOTEQEQ: [u8; 4] = 20u32.to_ne_bytes(); // !== +pub const STRING_LT: [u8; 4] = 21u32.to_ne_bytes(); // < +pub const STRING_LTEQ: [u8; 4] = 22u32.to_ne_bytes(); // <= +pub const STRING_GT: [u8; 4] = 23u32.to_ne_bytes(); // > +pub const STRING_GTEQ: [u8; 4] = 24u32.to_ne_bytes(); // >= +pub const STRING_LSHIFT: [u8; 4] = 25u32.to_ne_bytes(); // << +pub const STRING_RSHIFT: [u8; 4] = 26u32.to_ne_bytes(); // >> +pub const STRING_ZEROFILLRSHIFT: [u8; 4] = 27u32.to_ne_bytes(); // >>> +pub const STRING_ADD: [u8; 4] = 28u32.to_ne_bytes(); // + +pub const STRING_SUB: [u8; 4] = 29u32.to_ne_bytes(); // - +pub const STRING_MUL: [u8; 4] = 30u32.to_ne_bytes(); // * +pub const STRING_DIV: [u8; 4] = 31u32.to_ne_bytes(); // / +pub const STRING_MOD: [u8; 4] = 32u32.to_ne_bytes(); // % +pub const STRING_BITOR: [u8; 4] = 33u32.to_ne_bytes(); // | +pub const STRING_BITXOR: [u8; 4] = 34u32.to_ne_bytes(); // ^ +pub const STRING_BITAND: [u8; 4] = 35u32.to_ne_bytes(); // & +pub const STRING_LOGICALOR: [u8; 4] = 36u32.to_ne_bytes(); // || +pub const STRING_LOGICALAND: [u8; 4] = 37u32.to_ne_bytes(); // && +pub const STRING_IN: [u8; 4] = 38u32.to_ne_bytes(); // in +pub const STRING_INSTANCEOF: [u8; 4] = 39u32.to_ne_bytes(); // instanceof +pub const STRING_EXP: [u8; 4] = 40u32.to_ne_bytes(); // ** +pub const STRING_NULLISHCOALESCING: [u8; 4] = 41u32.to_ne_bytes(); // ?? +pub const STRING_ASSIGN: [u8; 4] = 42u32.to_ne_bytes(); // = +pub const STRING_ADDASSIGN: [u8; 4] = 43u32.to_ne_bytes(); // += +pub const STRING_SUBASSIGN: [u8; 4] = 44u32.to_ne_bytes(); // -= +pub const STRING_MULASSIGN: [u8; 4] = 45u32.to_ne_bytes(); // *= +pub const STRING_DIVASSIGN: [u8; 4] = 46u32.to_ne_bytes(); // /= +pub const STRING_MODASSIGN: [u8; 4] = 47u32.to_ne_bytes(); // %= +pub const STRING_LSHIFTASSIGN: [u8; 4] = 48u32.to_ne_bytes(); // <<= +pub const STRING_RSHIFTASSIGN: [u8; 4] = 49u32.to_ne_bytes(); // >>= +pub const STRING_ZEROFILLRSHIFTASSIGN: [u8; 4] = 50u32.to_ne_bytes(); // ">>>= +pub const STRING_BITORASSIGN: [u8; 4] = 51u32.to_ne_bytes(); // |= +pub const STRING_BITXORASSIGN: [u8; 4] = 52u32.to_ne_bytes(); // ^= +pub const STRING_BITANDASSIGN: [u8; 4] = 53u32.to_ne_bytes(); // &= +pub const STRING_EXPASSIGN: [u8; 4] = 54u32.to_ne_bytes(); // **= +pub const STRING_ANDASSIGN: [u8; 4] = 55u32.to_ne_bytes(); // &&= +pub const STRING_ORASSIGN: [u8; 4] = 56u32.to_ne_bytes(); // ||= +pub const STRING_NULLISHASSIGN: [u8; 4] = 57u32.to_ne_bytes(); // ??= +pub const STRING_PURE: [u8; 4] = 58u32.to_ne_bytes(); // pure +pub const STRING_NOSIDEEFFECTS: [u8; 4] = 59u32.to_ne_bytes(); // noSideEffects +pub const STRING_SOURCEMAP: [u8; 4] = 60u32.to_ne_bytes(); // sourcemap diff --git a/rust/parse_ast/src/convert_ast/converter/utf16_positions.rs b/rust/parse_ast/src/convert_ast/converter/utf16_positions.rs new file mode 100644 index 000000000..73a930066 --- /dev/null +++ b/rust/parse_ast/src/convert_ast/converter/utf16_positions.rs @@ -0,0 +1,142 @@ +use std::mem; +use std::slice::Iter; +use std::str::Chars; + +use crate::convert_ast::annotations::{AnnotationKind, AnnotationWithType}; + +pub struct Utf8ToUtf16ByteIndexConverterAndAnnotationHandler<'a> { + current_utf8_index: u32, + current_utf16_index: u32, + character_iterator: Chars<'a>, + next_annotation: Option<&'a AnnotationWithType>, + next_annotation_start: u32, + annotation_iterator: Iter<'a, AnnotationWithType>, + collected_annotations: Vec, + invalid_annotations: Vec, + keep_annotations: bool, +} + +#[derive(Debug)] +pub struct ConvertedAnnotation { + pub start: u32, + pub end: u32, + pub kind: AnnotationKind, +} + +impl<'a> Utf8ToUtf16ByteIndexConverterAndAnnotationHandler<'a> { + pub fn new(code: &'a str, annotations: &'a Vec) -> Self { + let mut annotation_iterator = annotations.iter(); + let current_annotation = annotation_iterator.next(); + Self { + current_utf8_index: 0, + current_utf16_index: 0, + character_iterator: code.chars(), + next_annotation: current_annotation, + next_annotation_start: get_annotation_start(current_annotation), + annotation_iterator, + collected_annotations: Vec::new(), + invalid_annotations: Vec::with_capacity(annotations.len()), + keep_annotations: false, + } + } + + /// Converts the given UTF-8 byte index to a UTF-16 byte index. + /// + /// To be performant, this method assumes that the given index is not smaller + /// than the previous index. Additionally, it handles "annotations" like + /// `@__PURE__` comments in the process. + /// + /// The logic for those comments is as follows: + /// - If the current index is at the start of an annotation, the annotation + /// is collected and the index is advanced to the end of the annotation. + /// - Otherwise, we check if the next character is a white-space character. + /// If not, we invalidate all collected annotations. + /// This is to ensure that we only collect annotations that directly precede + /// an expression and are not e.g. separated by a comma. + /// - If annotations are relevant for an expression, it can "take" the + /// collected annotations by calling `take_collected_annotations`. This + /// clears the internal buffer and returns the collected annotations. + /// - Invalidated annotations are attached to the Program node so that they + /// can all be removed from the source code later. + /// - If an annotation can influence a child that is separated by some + /// non-whitespace from the annotation, `keep_annotations_for_next` will + /// prevent annotations from being invalidated when the next position is + /// converted. + pub fn convert(&mut self, utf8_index: u32, keep_annotations_for_next: bool) -> u32 { + if self.current_utf8_index > utf8_index { + panic!( + "Cannot convert positions backwards: {} < {}", + utf8_index, self.current_utf8_index + ); + } + while self.current_utf8_index < utf8_index { + if self.current_utf8_index == self.next_annotation_start { + let start = self.current_utf16_index; + let (next_annotation_end, next_annotation_kind) = self + .next_annotation + .map(|a| (a.comment.span.hi.0 - 1, a.kind.clone())) + .unwrap(); + while self.current_utf8_index < next_annotation_end { + let character = self.character_iterator.next().unwrap(); + self.current_utf8_index += character.len_utf8() as u32; + self.current_utf16_index += character.len_utf16() as u32; + } + self.collected_annotations.push(ConvertedAnnotation { + start, + end: self.current_utf16_index, + kind: next_annotation_kind, + }); + self.next_annotation = self.annotation_iterator.next(); + self.next_annotation_start = get_annotation_start(self.next_annotation); + } else { + let character = self.character_iterator.next().unwrap(); + if !(self.keep_annotations || self.collected_annotations.is_empty()) { + match character { + ' ' | '\t' | '\r' | '\n' => {} + _ => { + self.invalidate_collected_annotations(); + } + } + } + self.current_utf8_index += character.len_utf8() as u32; + self.current_utf16_index += character.len_utf16() as u32; + } + } + self.keep_annotations = keep_annotations_for_next; + self.current_utf16_index + } + + pub fn take_collected_annotations(&mut self, kind: AnnotationKind) -> Vec { + let mut relevant_annotations = Vec::new(); + for annotation in self.collected_annotations.drain(..) { + if annotation.kind == kind { + relevant_annotations.push(annotation); + } else { + self.invalid_annotations.push(annotation); + } + } + relevant_annotations + } + + pub fn add_collected_annotations(&mut self, annotations: Vec) { + self.collected_annotations.extend(annotations); + self.keep_annotations = true; + } + + pub fn invalidate_collected_annotations(&mut self) { + self + .invalid_annotations + .extend(self.collected_annotations.drain(..)); + } + + pub fn take_invalid_annotations(&mut self) -> Vec { + let invalid_annotations = mem::replace(&mut self.invalid_annotations, Vec::new()); + invalid_annotations + } +} + +fn get_annotation_start(annotation: Option<&AnnotationWithType>) -> u32 { + annotation + .map(|a| a.comment.span.lo.0 - 1) + .unwrap_or(u32::MAX) +} diff --git a/rust/parse_ast/src/error_emit.rs b/rust/parse_ast/src/error_emit.rs new file mode 100644 index 000000000..f444ca859 --- /dev/null +++ b/rust/parse_ast/src/error_emit.rs @@ -0,0 +1,129 @@ +use std::{io::Write, mem::take, sync::Arc}; + +use anyhow::Error; +use parking_lot::Mutex; +use swc_common::{ + errors::{DiagnosticBuilder, Emitter, Handler, Level, HANDLER}, + Mark, SourceMap, SyntaxContext, +}; +use swc_ecma_ast::{EsVersion, Program}; +use swc_ecma_lints::{rule::Rule, rules, rules::LintParams}; +use swc_ecma_transforms_base::resolver; +use swc_ecma_visit::VisitMutWith; + +use crate::convert_ast::converter::{convert_string, node_types::TYPE_PARSE_ERROR}; + +#[derive(Clone, Default)] +struct Writer(Arc>>); + +impl Write for Writer { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + let mut lock = self.0.lock(); + + lock.extend_from_slice(buf); + + Ok(buf.len()) + } + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +pub struct ErrorEmitter { + wr: Box, +} + +impl Emitter for ErrorEmitter { + fn emit(&mut self, db: &DiagnosticBuilder<'_>) { + if db.level == Level::Error { + let mut buffer = Vec::new(); + let mut pos: u32 = 0; + if let Some(span) = db.span.primary_span() { + pos = span.lo.0 - 1; + }; + let message = &db.message[0].0; + buffer.extend_from_slice(&(pos as u32).to_ne_bytes()); + convert_string(&mut buffer, message); + let _ = self.wr.write(&buffer); + } + } +} + +pub fn try_with_handler( + code: &str, + cm: &Arc, + es_version: EsVersion, + op: F, +) -> Result> +where + F: FnOnce(&Handler) -> Result, +{ + let wr = Box::::default(); + + let emitter = ErrorEmitter { wr: wr.clone() }; + + let handler = Handler::with_emitter(true, false, Box::new(emitter)); + + let result = HANDLER.set(&handler, || op(&handler)); + + match result { + Ok(mut program) => { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + let unresolved_ctxt = SyntaxContext::empty().apply_mark(unresolved_mark); + let top_level_ctxt = SyntaxContext::empty().apply_mark(top_level_mark); + + program.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, false)); + + let mut rules = rules::all(LintParams { + program: &program, + lint_config: &Default::default(), + unresolved_ctxt, + top_level_ctxt, + es_version, + source_map: cm.clone(), + }); + + HANDLER.set(&handler, || match &program { + Program::Module(m) => { + rules.lint_module(m); + } + Program::Script(s) => { + rules.lint_script(s); + } + }); + + if handler.has_errors() { + let buffer = create_error_buffer(&wr, code); + Err(buffer) + } else { + Ok(program) + } + } + Err(_) => { + if handler.has_errors() { + let buffer = create_error_buffer(&wr, code); + Err(buffer) + } else { + panic!("Unexpected error in parse") + } + } + } +} + +fn create_error_buffer(wr: &Box, code: &str) -> Vec { + let mut buffer = TYPE_PARSE_ERROR.to_vec(); + let mut lock = wr.0.lock(); + let mut error_buffer = take(&mut *lock); + let pos = u32::from_ne_bytes(error_buffer[0..4].try_into().unwrap()); + let mut utf_16_pos: u32 = 0; + for (utf_8_pos, char) in code.char_indices() { + if (utf_8_pos as u32) == pos { + break; + } + utf_16_pos += char.len_utf16() as u32; + } + error_buffer[0..4].copy_from_slice(&utf_16_pos.to_ne_bytes()); + buffer.extend_from_slice(&error_buffer); + buffer +} diff --git a/rust/parse_ast/src/lib.rs b/rust/parse_ast/src/lib.rs new file mode 100644 index 000000000..2138546b3 --- /dev/null +++ b/rust/parse_ast/src/lib.rs @@ -0,0 +1,69 @@ +#![feature(ptr_internals)] +use std::sync::Arc; + +use swc::config::IsModule::Unknown; +use swc::{config::ParseOptions, Compiler}; +use swc_common::sync::Lrc; +use swc_common::{FileName, FilePathMapping, Globals, SourceMap, GLOBALS}; +use swc_ecma_ast::EsVersion; +use swc_ecma_parser::{EsConfig, Syntax}; + +use convert_ast::converter::AstConverter; + +use crate::convert_ast::annotations::SequentialComments; + +mod convert_ast; + +use error_emit::try_with_handler; + +mod error_emit; + +fn get_compiler() -> Arc { + let cm = Arc::new(SourceMap::new(FilePathMapping::empty())); + Arc::new(Compiler::new(cm)) +} + +pub fn parse_ast(code: String) -> Vec { + let compiler = get_compiler(); + let compiler_options = ParseOptions { + syntax: Syntax::Es(EsConfig { + import_attributes: true, + ..Default::default() + }), + target: EsVersion::EsNext, + is_module: Unknown, + comments: false, + }; + let filename = FileName::Anon; + let file = compiler.cm.new_source_file(filename, code); + let code_reference = Lrc::clone(&file.src); + let comments = SequentialComments::default(); + GLOBALS.set(&Globals::default(), || { + compiler.run(|| { + let result = try_with_handler( + &code_reference, + &compiler.cm, + compiler_options.target, + |handler| { + compiler.parse_js( + file, + handler, + compiler_options.target, + compiler_options.syntax, + compiler_options.is_module, + Some(&comments), + ) + }, + ); + match result { + Err(buffer) => buffer, + Ok(program) => { + let annotations = comments.take_annotations(); + let converter = AstConverter::new(&code_reference, &annotations); + let buffer = converter.convert_ast_to_buffer(&program); + buffer + } + } + }) + }) +} diff --git a/rust/rustfmt.toml b/rust/rustfmt.toml new file mode 100644 index 000000000..cab5731ed --- /dev/null +++ b/rust/rustfmt.toml @@ -0,0 +1,2 @@ +tab_spaces = 2 +edition = "2021" diff --git a/scripts/check-release.js b/scripts/check-release.js index 165633c6f..ba767b9f6 100755 --- a/scripts/check-release.js +++ b/scripts/check-release.js @@ -3,5 +3,6 @@ import { env, exit } from 'node:process'; if (env.ROLLUP_RELEASE !== 'releasing') { + console.error('This script should only be run as part of the release process.'); exit(1); } diff --git a/scripts/colors.js b/scripts/colors.js index 6713d2ff9..e584ecefc 100644 --- a/scripts/colors.js +++ b/scripts/colors.js @@ -3,6 +3,6 @@ import { createColors } from 'colorette'; // @see https://no-color.org // @see https://www.npmjs.com/package/chalk -export const { bold, cyan, green, red } = createColors({ +export const { bold, cyan, green, red, yellow, blue, magenta } = createColors({ useColor: env.FORCE_COLOR !== '0' && !env.NO_COLOR }); diff --git a/scripts/helpers.js b/scripts/helpers.js index 94773a83d..df55a90a3 100644 --- a/scripts/helpers.js +++ b/scripts/helpers.js @@ -1,27 +1,35 @@ import { spawn } from 'node:child_process'; -import { bold, cyan, green } from './colors.js'; +import { readFile } from 'node:fs/promises'; +import { blue, bold, cyan, green, magenta, red, yellow } from './colors.js'; + +const colors = [cyan, yellow, blue, red, green, magenta]; +let nextColorIndex = 0; export function runWithEcho(command, parameters, options) { + const color = colors[nextColorIndex]; + nextColorIndex = (nextColorIndex + 1) % colors.length; return new Promise((resolve, reject) => { const cmdString = formatCommand(command, parameters); - console.error(bold(`\n${cyan`Run>`} ${cmdString}`)); - - const childProcess = spawn(command, parameters, options); + console.error(bold(`\n${color`Run>`} ${cmdString}`)); - childProcess.stdout.pipe(process.stdout); - childProcess.stderr.pipe(process.stderr); + const childProcess = spawn(command, parameters, { stdio: 'inherit', ...options }); childProcess.on('close', code => { if (code) { reject(new Error(`"${cmdString}" exited with code ${code}.`)); } else { - console.error(bold(`${green`Finished>`} ${cmdString}\n`)); + console.error(bold(`${color`Finished>`} ${cmdString}\n`)); resolve(); } }); }); } +/** + * @param {string} command + * @param {string[]} parameters + * @return {Promise} + */ export function runAndGetStdout(command, parameters) { return new Promise((resolve, reject) => { const childProcess = spawn(command, parameters); @@ -43,3 +51,12 @@ export function runAndGetStdout(command, parameters) { function formatCommand(command, parameters) { return [command, ...parameters].join(' '); } + +/** + * @param {string} file + * @returns {Promise>} + */ +export async function readJson(file) { + const content = await readFile(file, 'utf8'); + return JSON.parse(content); +} diff --git a/scripts/postpublish.js b/scripts/postpublish.js new file mode 100644 index 000000000..aab24b9a9 --- /dev/null +++ b/scripts/postpublish.js @@ -0,0 +1,91 @@ +import { readFile } from 'node:fs/promises'; +import { env } from 'node:process'; +import GitHub from 'github-api'; +import semverPreRelease from 'semver/functions/prerelease.js'; +import { cyan } from './colors.js'; +import { CHANGELOG } from './release-constants.js'; +import { + getCurrentCommitMessage, + getFirstChangelogEntry, + getGitTag, + getIncludedPRs +} from './release-helpers.js'; + +console.log( + `------------------------------------------------------------------------------- +This script will create the release in GitHub and post comments to all released +PRs and resolved issues. It is only run from CI. +-------------------------------------------------------------------------------` +); + +if (!(env.CI && env.ROLLUP_RELEASE && env.GITHUB_TOKEN)) { + throw new Error('This script is only intended to be run from CI.'); +} + +const gh = new GitHub({ token: env.GITHUB_TOKEN }); +const [newVersion, changelog, repo, issues] = await Promise.all([ + getCurrentCommitMessage(), + readFile(CHANGELOG, 'utf8'), + gh.getRepo('rollup', 'rollup'), + gh.getIssues('rollup', 'rollup') +]); + +const matched = /^\d+\.\d+\.\d+(-\d+)?$/.exec(newVersion); +if (!matched) { + throw new Error(`The last commit message "${newVersion}" does not contain a version.`); +} + +const isPreRelease = !!matched[1]; + +const firstEntry = getFirstChangelogEntry(changelog); +const [previousVersion, changelogEntry] = + firstEntry.currentVersion === newVersion + ? [firstEntry.previousVersion, firstEntry.text] + : [firstEntry.currentVersion, null]; +const includedPRs = await getIncludedPRs( + `v${previousVersion}`, + `v${newVersion}`, + repo, + null, + isPreRelease +); + +if (changelogEntry) { + await createReleaseNotes(changelogEntry, getGitTag(newVersion)); +} +await postReleaseComments(includedPRs, issues, newVersion); + +function createReleaseNotes(changelog, tag) { + return repo.createRelease({ + body: changelog, + name: tag, + tag_name: tag + }); +} + +function postReleaseComments(includedPRs, issues, version) { + const isPreRelease = semverPreRelease(version); + const installNote = isPreRelease + ? `Note that this is a pre-release, so to test it, you need to install Rollup via \`npm install rollup@${version}\` or \`npm install rollup@beta\`. It will likely become part of a regular release later.` + : 'You can test it via `npm install rollup`.'; + return Promise.all( + includedPRs.map(({ pr, closed }) => + Promise.all([ + issues + .createIssueComment( + pr, + `This PR has been released as part of rollup@${version}. ${installNote}` + ) + .then(() => console.log(cyan(`Added release comment to #${pr}.`))), + ...closed.map(closedPr => + issues + .createIssueComment( + closedPr, + `This issue has been resolved via #${pr} as part of rollup@${version}. ${installNote}` + ) + .then(() => console.log(cyan(`Added fix comment to #${closedPr} via #${pr}.`))) + ) + ]) + ) + ); +} diff --git a/scripts/release.js b/scripts/prepare-release.js similarity index 53% rename from scripts/release.js rename to scripts/prepare-release.js index c34b96710..eebfaee32 100755 --- a/scripts/release.js +++ b/scripts/prepare-release.js @@ -3,88 +3,80 @@ import { readFile, writeFile } from 'node:fs/promises'; import { chdir, exit } from 'node:process'; import { fileURLToPath } from 'node:url'; -import GitHub from 'github-api'; import inquirer from 'inquirer'; import semverInc from 'semver/functions/inc.js'; import semverParse from 'semver/functions/parse.js'; import semverPreRelease from 'semver/functions/prerelease.js'; import { cyan } from './colors.js'; -import { runAndGetStdout, runWithEcho } from './helpers.js'; +import { readJson, runAndGetStdout, runWithEcho } from './helpers.js'; +import { + BROWSER_PACKAGE, + CHANGELOG, + DOCUMENTATION_BRANCH, + MAIN_BRANCH, + MAIN_LOCKFILE, + MAIN_PACKAGE +} from './release-constants.js'; +import { + getFirstChangelogEntry, + getGithubApi, + getGitTag, + getIncludedPRs +} from './release-helpers.js'; + +console.log( + `----------------------------------------------------------------------------- +This script will create a release tag for you and guide you through writing a +CHANGELOG entry for non-beta releases. The actual release will be performed +by GitHub Actions once this script completes successfully. +-----------------------------------------------------------------------------` +); // We execute everything from the main directory chdir(fileURLToPath(new URL('..', import.meta.url))); -const MAIN_BRANCH = 'master'; -const MAIN_PACKAGE = 'package.json'; -const MAIN_LOCKFILE = 'package-lock.json'; -const BROWSER_PACKAGE = 'browser/package.json'; -const CHANGELOG = 'CHANGELOG.md'; -const DOCUMENTATION_BRANCH = 'documentation-published'; - const [gh, currentBranch] = await Promise.all([ getGithubApi(), runAndGetStdout('git', ['branch', '--show-current']), runWithEcho('git', ['pull', '--ff-only']) ]); -const [mainPackage, mainLockFile, browserPackage, repo, issues, changelog] = await Promise.all([ +const [mainPackage, mainLockFile, browserPackage, repo, changelog] = await Promise.all([ readJson(MAIN_PACKAGE), readJson(MAIN_LOCKFILE), readJson(BROWSER_PACKAGE), gh.getRepo('rollup', 'rollup'), - gh.getIssues('rollup', 'rollup'), readFile(CHANGELOG, 'utf8') ]); const isMainBranch = currentBranch === MAIN_BRANCH; const [newVersion, includedPRs] = await Promise.all([ getNewVersion(mainPackage, isMainBranch), - getIncludedPRs(changelog, repo, currentBranch, isMainBranch) + getIncludedPRs( + `v${getFirstChangelogEntry(changelog).currentVersion}`, + 'HEAD', + repo, + currentBranch, + !isMainBranch + ) ]); -let changelogEntry, gitTag; +const gitTag = getGitTag(newVersion); try { if (isMainBranch) { await addStubChangelogEntry(newVersion, repo, changelog, includedPRs); } await updatePackages(mainPackage, mainLockFile, browserPackage, newVersion); - await installDependenciesBuildAndTest(); - changelogEntry = isMainBranch ? await waitForChangelogUpdate(newVersion) : ''; - gitTag = `v${newVersion}`; + await installDependenciesAndLint(); + if (isMainBranch) { + await waitForChangelogUpdate(newVersion); + } await commitChanges(newVersion, gitTag, isMainBranch); } catch (error) { console.error(`Error during release, rolling back changes: ${error.message}`); - await runWithEcho('git', ['reset', '--hard']); + console.error('Run `git reset --hard` to roll back changes.'); throw error; } -await releasePackages(newVersion); await pushChanges(gitTag); -if (changelogEntry) { - await createReleaseNotes(changelogEntry, gitTag); -} -await postReleaseComments(includedPRs, issues, newVersion); - -async function getGithubApi() { - const GITHUB_TOKEN = '.github_token'; - try { - const token = (await readFile(GITHUB_TOKEN, 'utf8')).trim(); - return new GitHub({ token }); - } catch (error) { - if (error.code === 'ENOENT') { - console.error( - `Could not find GitHub token file. Please create "${GITHUB_TOKEN}" containing a token with the following permissions: -- public_repo` - ); - exit(1); - } else { - throw error; - } - } -} - -async function readJson(file) { - const content = await readFile(file, 'utf8'); - return JSON.parse(content); -} async function getNewVersion(mainPackage, isMainBranch) { const { version } = mainPackage; @@ -136,64 +128,6 @@ breaking changes in the release while the tests are running.`) ); } -function getFirstChangelogEntry(changelog) { - const match = changelog.match( - /(?## (?\d+\.\d+\.\d+)[\S\s]*?)\n+## (?\d+\.\d+\.\d+)/ - ); - if (!match) { - throw new Error('Could not detect any changelog entry.'); - } - const { - groups: { text, currentVersion, previousVersion }, - index - } = match; - return { currentVersion, index, previousVersion, text }; -} - -async function getIncludedPRs(changelog, repo, currentBranch, isMainBranch) { - const { currentVersion } = getFirstChangelogEntry(changelog); - const commits = await runAndGetStdout('git', [ - '--no-pager', - 'log', - `v${currentVersion}..HEAD`, - '--pretty=tformat:%s' - ]); - const getPrRegExp = /^(.+)\s\(#(\d+)\)$/gm; - const prs = []; - let match; - while ((match = getPrRegExp.exec(commits))) { - prs.push({ pr: match[2], text: match[1].split('\n')[0] }); - } - - if (!isMainBranch) { - const { data: basePrs } = await repo.listPullRequests({ - head: `rollup:${currentBranch}`, - state: 'open' - }); - for (const { number, title } of basePrs) { - prs.push({ pr: number, text: title }); - } - } - prs.sort((a, b) => (a.pr > b.pr ? 1 : -1)); - return Promise.all( - prs.map(async ({ pr, text }) => { - const { data } = await repo.getPullRequest(pr); - const bodyWithoutComments = data.body.replace(//g, ''); - const closedIssuesRegexp = /([Ff]ix(es|ed)?|([Cc]lose|[Rr]esolve)[ds]?) #(\d+)/g; - const closed = []; - while ((match = closedIssuesRegexp.exec(bodyWithoutComments))) { - closed.push(match[4]); - } - return { - author: data.user.login, - closed, - pr, - text - }; - }) - ); -} - function getNewLogEntry(version, prs) { if (prs.length === 0) { throw new Error(`Release does not contain any PRs`); @@ -230,13 +164,12 @@ function getDummyLogSection(headline, pr) { `; } -async function installDependenciesBuildAndTest() { - await Promise.all([runWithEcho('npm', ['ci']), runWithEcho('npm', ['audit'])]); +async function installDependenciesAndLint() { await Promise.all([ - runWithEcho('npm', ['run', 'ci:lint']), - runWithEcho('npm', ['run', 'build:bootstrap']) + runWithEcho('npm', ['ci', '--ignore-scripts']), + runWithEcho('npm', ['audit']) ]); - await runWithEcho('npm', ['run', 'test:all']); + await runWithEcho('npm', ['run', 'ci:lint']); } async function waitForChangelogUpdate(version) { @@ -260,8 +193,6 @@ async function waitForChangelogUpdate(version) { } ]); } - - return changelogEntry; } function updatePackages(mainPackage, mainLockFile, browserPackage, newVersion) { @@ -296,22 +227,6 @@ async function commitChanges(newVersion, gitTag, isMainBranch) { isMainBranch && (await runWithEcho('git', ['branch', DOCUMENTATION_BRANCH, '--force', gitTag])); } -function releasePackages(newVersion) { - const releaseEnvironment = { ...process.env, ROLLUP_RELEASE: 'releasing' }; - const releaseTag = semverPreRelease(newVersion) ? ['--tag', 'beta'] : []; - const parameters = ['publish', '--access', 'public', ...releaseTag]; - return Promise.all([ - runWithEcho('npm', parameters, { - cwd: new URL('..', import.meta.url), - env: releaseEnvironment - }), - runWithEcho('npm', parameters, { - cwd: new URL('../browser', import.meta.url), - env: releaseEnvironment - }) - ]); -} - function pushChanges(gitTag) { return Promise.all([ runWithEcho('git', ['push', 'origin', 'HEAD']), @@ -319,38 +234,3 @@ function pushChanges(gitTag) { isMainBranch && runWithEcho('git', ['push', '--force', 'origin', DOCUMENTATION_BRANCH]) ]); } - -function createReleaseNotes(changelog, tag) { - return repo.createRelease({ - body: changelog, - name: tag, - tag_name: tag - }); -} - -function postReleaseComments(includedPRs, issues, version) { - const isPreRelease = semverPreRelease(newVersion); - const installNote = isPreRelease - ? `Note that this is a pre-release, so to test it, you need to install Rollup via \`npm install rollup@${newVersion}\` or \`npm install rollup@beta\`. It will likely become part of a regular release later.` - : 'You can test it via `npm install rollup`.'; - return Promise.all( - includedPRs.map(({ pr, closed }) => - Promise.all([ - issues - .createIssueComment( - pr, - `This PR has been released as part of rollup@${version}. ${installNote}` - ) - .then(() => console.log(cyan(`Added release comment to #${pr}.`))), - ...closed.map(closedPr => - issues - .createIssueComment( - closedPr, - `This issue has been resolved via #${pr} as part of rollup@${version}. ${installNote}` - ) - .then(() => console.log(cyan(`Added fix comment to #${closedPr} via #${pr}.`))) - ) - ]) - ) - ); -} diff --git a/scripts/prepublish.js b/scripts/prepublish.js new file mode 100755 index 000000000..d43a85977 --- /dev/null +++ b/scripts/prepublish.js @@ -0,0 +1,65 @@ +#!/usr/bin/env node + +import { readFile, writeFile } from 'node:fs/promises'; +import { resolve } from 'node:path'; +import { chdir } from 'node:process'; +import { fileURLToPath } from 'node:url'; +import { readJson, runWithEcho } from './helpers.js'; +import publishWasmNodePackage from './publish-wasm-node-package.js'; +import { CHANGELOG, MAIN_PACKAGE } from './release-constants.js'; +import { getCurrentCommitMessage, getFirstChangelogEntry } from './release-helpers.js'; + +// We execute everything from the main directory +chdir(fileURLToPath(new URL('..', import.meta.url))); + +const version = await getCurrentCommitMessage(); +const matched = /^\d+\.\d+\.\d+(-\d+)?$/.exec(version); + +if (!matched) { + throw new Error( + `The commit message "${version}" does not satisfy the patterns 0.0.0 or 0.0.0-0.` + ); +} +const isPreRelease = !!matched[1]; +await verifyChangelog(isPreRelease); + +await runWithEcho('npm', ['publish'], { cwd: resolve('browser') }); +await publishWasmNodePackage(); + +const { optionalDependencies } = await readJson(MAIN_PACKAGE); +await runWithEcho('npm', ['run', 'prepublish:napi']); +const mainPackage = await readJson(MAIN_PACKAGE); +await writeFile( + MAIN_PACKAGE, + JSON.stringify( + { + ...mainPackage, + optionalDependencies: { ...optionalDependencies, ...mainPackage.optionalDependencies } + }, + null, + 2 + ) +); + +/** + * @param {boolean} isPreRelease + * @return {Promise} + */ +async function verifyChangelog(isPreRelease) { + const changelog = await readFile(CHANGELOG, 'utf8'); + const { currentVersion, text } = getFirstChangelogEntry(changelog); + if (currentVersion !== version) { + if (isPreRelease) { + console.log( + `There is no changelog entry for version "${version}", the last entry is for version "${currentVersion}". This is OK for a pre-release.` + ); + return; + } + throw new Error( + `There is no changelog entry for version "${version}", the last entry is for version "${currentVersion}".` + ); + } + if (text.includes('[replace me]')) { + throw new Error(`The changelog entry must not contain placeholders. The text was:\n${text}`); + } +} diff --git a/scripts/publish-wasm-node-package.js b/scripts/publish-wasm-node-package.js new file mode 100644 index 000000000..45426fa88 --- /dev/null +++ b/scripts/publish-wasm-node-package.js @@ -0,0 +1,54 @@ +import fs from 'node:fs/promises'; +import { resolve } from 'node:path'; + +import { readJson, runWithEcho } from './helpers.js'; +import { MAIN_PACKAGE } from './release-constants.js'; + +const WASM_NODE_PACKAGE_INFO = { + description: 'Next-generation ES module bundler with Node wasm', + name: '@rollup/wasm-node' +}; +const COPIED_FILES_OR_DIRS = ['LICENSE.md', 'dist']; +const PACKAGE_DIR = 'wasm-node-package'; +const NATIVE_JS_CONTENT = ` +const { parse } = require('./wasm-node/bindings_wasm.js'); + +exports.parse = parse +`; + +function getPath(...arguments_) { + return resolve(PACKAGE_DIR, ...arguments_); +} + +export default async function publishWasmNodePackage() { + await fs.mkdir(PACKAGE_DIR); + + const mainPackage = await readJson(MAIN_PACKAGE); + mainPackage.files.unshift('dist/wasm-node/*.wasm'); + delete mainPackage.napi; + delete mainPackage.scripts; + + await Promise.all([ + ...COPIED_FILES_OR_DIRS.map(file => fs.cp(file, getPath(file), { recursive: true })), + fs.writeFile( + getPath('package.json'), + JSON.stringify( + { + ...mainPackage, + ...WASM_NODE_PACKAGE_INFO + }, + undefined, + 2 + ) + ) + ]); + + await Promise.all([ + fs.writeFile(getPath('dist', 'native.js'), NATIVE_JS_CONTENT.trimStart()), + fs.cp('artifacts/bindings-wasm-node/wasm-node', getPath('dist', 'wasm-node'), { + recursive: true + }) + ]); + + await runWithEcho('npm', ['publish'], { cwd: resolve(PACKAGE_DIR) }); +} diff --git a/scripts/release-constants.js b/scripts/release-constants.js new file mode 100644 index 000000000..869fbf965 --- /dev/null +++ b/scripts/release-constants.js @@ -0,0 +1,6 @@ +export const MAIN_BRANCH = 'master'; +export const MAIN_PACKAGE = 'package.json'; +export const MAIN_LOCKFILE = 'package-lock.json'; +export const BROWSER_PACKAGE = 'browser/package.json'; +export const CHANGELOG = 'CHANGELOG.md'; +export const DOCUMENTATION_BRANCH = 'documentation-published'; diff --git a/scripts/release-helpers.js b/scripts/release-helpers.js new file mode 100644 index 000000000..925eaed66 --- /dev/null +++ b/scripts/release-helpers.js @@ -0,0 +1,111 @@ +import { readFile } from 'node:fs/promises'; +import { exit } from 'node:process'; +import GitHub from 'github-api'; +import { runAndGetStdout } from './helpers.js'; + +/** + * @param {string} changelog + * @returns {{ currentVersion: string, index: number, previousVersion: string, text: string }} + */ +export function getFirstChangelogEntry(changelog) { + const match = changelog.match( + /(?## (?\d+\.\d+\.\d+(-\d+)?)[\S\s]*?)\n+## (?\d+\.\d+\.\d+)/ + ); + if (!match) { + throw new Error('Could not detect any changelog entry.'); + } + const { + groups: { text, currentVersion, previousVersion }, + index + } = match; + return { currentVersion, index, previousVersion, text }; +} + +/** + * @param {string} fromVersion + * @param {string} toVersion + * @param repo + * @param {string|null} currentBranch We only have a branch when locally prepare a release, otherwise we use the sha to find the PR + * @param {boolean} isPreRelease + * @returns {Promise<{ author: string, closed: string[], pr: string, text: string }[]>} + */ +export async function getIncludedPRs(fromVersion, toVersion, repo, currentBranch, isPreRelease) { + const [commits, commitSha] = await Promise.all([ + runAndGetStdout('git', [ + '--no-pager', + 'log', + `${fromVersion}..${toVersion}`, + '--pretty=tformat:%s' + ]), + runAndGetStdout('git', ['rev-parse', toVersion]) + ]); + const getPrRegExp = /^(.+)\s\(#(\d+)\)$/gm; + const prs = []; + let match; + while ((match = getPrRegExp.exec(commits))) { + prs.push({ pr: Number(match[2]), text: match[1].split('\n')[0] }); + } + + if (isPreRelease) { + const { data: basePrs } = await repo.listPullRequests({ + state: 'open', + ...(currentBranch ? { head: `rollup:${currentBranch}` } : {}) + }); + for (const { + number, + title, + head: { sha } + } of basePrs) { + if (currentBranch || sha === commitSha) { + prs.push({ pr: number, text: title }); + } + } + } + prs.sort((a, b) => (a.pr > b.pr ? 1 : -1)); + return Promise.all( + prs.map(async ({ pr, text }) => { + const { data } = await repo.getPullRequest(pr); + const bodyWithoutComments = data.body.replace(//g, ''); + const closedIssuesRegexp = /([Ff]ix(es|ed)?|([Cc]lose|[Rr]esolve)[ds]?) #(\d+)/g; + const closed = []; + while ((match = closedIssuesRegexp.exec(bodyWithoutComments))) { + closed.push(match[4]); + } + return { + author: data.user.login, + closed, + pr, + text + }; + }) + ); +} + +export async function getGithubApi() { + const GITHUB_TOKEN = '.github_token'; + try { + const token = (await readFile(GITHUB_TOKEN, 'utf8')).trim(); + return new GitHub({ token }); + } catch (error) { + if (error.code === 'ENOENT') { + console.error( + `Could not find GitHub token file. Please create "${GITHUB_TOKEN}" containing a token with the following permissions: +- public_repo` + ); + exit(1); + } else { + throw error; + } + } +} + +export function getGitTag(version) { + return `v${version}`; +} + +/** + * @return {Promise} + */ +export function getCurrentCommitMessage() { + return runAndGetStdout('git', ['--no-pager', 'log', '-1', '--pretty=%B']); +} diff --git a/scripts/test-options.js b/scripts/test-options.js index 907c55a72..4ece8ce95 100644 --- a/scripts/test-options.js +++ b/scripts/test-options.js @@ -1,4 +1,5 @@ import { readFile } from 'node:fs/promises'; +import { exit } from 'node:process'; const [optionsText, helpText, commandReferenceText] = await Promise.all([ readFile(new URL('../docs/configuration-options/index.md', import.meta.url), 'utf8'), @@ -48,7 +49,7 @@ for (const { long, short } of allCliOptions) { } if (failed) { - process.exit(1); + exit(1); } let current = null; @@ -58,7 +59,7 @@ for (const [long, short] of cliOptionsInHelp) { console.error( `Options in help.md are not sorted properly. "${long}" should occur before "${current}".` ); - process.exit(1); + exit(1); } current = long; } @@ -68,7 +69,7 @@ const splitHelpText = helpText.split('\n'); for (const line of splitHelpText) { if (line.length > 80) { console.error(`The following line in help.md exceeds the limit of 80 characters:\n${line}`); - process.exit(1); + exit(1); } } @@ -88,6 +89,6 @@ for (const [index, line] of helpOptionLines.entries()) { console.error( `The command lines in command-line-interface/index.md do not match help.md. Expected line:\n${line}\n\nReceived line:\n${optionListLine}` ); - process.exit(1); + exit(1); } } diff --git a/src/Bundle.ts b/src/Bundle.ts index ca721d3d7..883af627b 100644 --- a/src/Bundle.ts +++ b/src/Bundle.ts @@ -150,9 +150,7 @@ export default class Bundle { for (const file of Object.values(bundle)) { if ('code' in file) { try { - this.graph.contextParse(file.code, { - ecmaVersion: 'latest' - }); + this.graph.contextParse(file.code); } catch (error_: any) { this.inputOptions.onLog(LOGLEVEL_WARN, logChunkInvalid(file, error_)); } diff --git a/src/Chunk.ts b/src/Chunk.ts index df3c26a09..dd9327397 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -95,7 +95,7 @@ export type ResolvedDynamicImport = ( ) & { node: ImportExpression }; export interface ChunkDependency { - assertions: string | null; + attributes: string | null; defaultVariableName: string | undefined; globalName: string | false | undefined; importPath: string; @@ -947,17 +947,17 @@ export default class Chunk { ); } - private getDynamicImportStringAndAssertions( + private getDynamicImportStringAndAttributes( resolution: ExternalModule | string | null, fileName: string - ): [importPath: string, assertions: string | null | true] { + ): [importPath: string, attributes: string | null | true] { if (resolution instanceof ExternalModule) { const chunk = this.externalChunkByModule.get(resolution)!; - return [`'${chunk.getImportPath(fileName)}'`, chunk.getImportAssertions(this.snippets)]; + return [`'${chunk.getImportPath(fileName)}'`, chunk.getImportAttributes(this.snippets)]; } return [ resolution || '', - (this.outputOptions.format === 'es' && this.outputOptions.externalImportAssertions) || null + (this.outputOptions.format === 'es' && this.outputOptions.externalImportAttributes) || null ]; } @@ -1140,7 +1140,7 @@ export default class Chunk { const importPath = dep.getImportPath(fileName); renderedDependencies.set(dep, { - assertions: dep instanceof ExternalChunk ? dep.getImportAssertions(this.snippets) : null, + attributes: dep instanceof ExternalChunk ? dep.getImportAttributes(this.snippets) : null, defaultVariableName: dep.defaultVariableName, globalName: dep instanceof ExternalChunk && @@ -1299,7 +1299,7 @@ export default class Chunk { } } else { const { node, resolution } = resolvedDynamicImport; - const [resolutionString, assertions] = this.getDynamicImportStringAndAssertions( + const [resolutionString, attributes] = this.getDynamicImportStringAndAttributes( resolution, fileName ); @@ -1312,7 +1312,7 @@ export default class Chunk { accessedGlobalsByScope, resolutionString, false, - assertions + attributes ); } } diff --git a/src/ExternalChunk.ts b/src/ExternalChunk.ts index 231b797f7..41d442629 100644 --- a/src/ExternalChunk.ts +++ b/src/ExternalChunk.ts @@ -13,7 +13,7 @@ export default class ExternalChunk { variableName = ''; private fileName: string | null = null; - private importAssertions: string | null = null; + private importAttributes: string | null = null; private moduleInfo: ModuleInfo; private renormalizeRenderPath: boolean; @@ -38,11 +38,11 @@ export default class ExternalChunk { (this.renormalizeRenderPath ? normalize(relative(this.inputBase, this.id)) : this.id)); } - getImportAssertions(snippets: GenerateCodeSnippets): string | null { - return (this.importAssertions ||= formatAssertions( + getImportAttributes(snippets: GenerateCodeSnippets): string | null { + return (this.importAttributes ||= formatAttributes( this.options.format === 'es' && - this.options.externalImportAssertions && - this.moduleInfo.assertions, + this.options.externalImportAttributes && + this.moduleInfo.attributes, snippets )); } @@ -56,14 +56,14 @@ export default class ExternalChunk { } } -function formatAssertions( - assertions: Record | null | void | false, +function formatAttributes( + attributes: Record | null | void | false, { getObject }: GenerateCodeSnippets ): string | null { - if (!assertions) { + if (!attributes) { return null; } - const assertionEntries: [key: string, value: string][] = Object.entries(assertions).map( + const assertionEntries: [key: string, value: string][] = Object.entries(attributes).map( ([key, value]) => [key, `'${value}'`] ); if (assertionEntries.length > 0) { diff --git a/src/ExternalModule.ts b/src/ExternalModule.ts index 4a76b4c20..33b1a7c1f 100644 --- a/src/ExternalModule.ts +++ b/src/ExternalModule.ts @@ -26,14 +26,14 @@ export default class ExternalModule { moduleSideEffects: boolean | 'no-treeshake', meta: CustomPluginOptions, public readonly renormalizeRenderPath: boolean, - assertions: Record + attributes: Record ) { this.suggestedVariableName = makeLegal(id.split(/[/\\]/).pop()!); const { importers, dynamicImporters } = this; const info: ModuleInfo = (this.info = { - assertions, ast: null, + attributes, code: null, dynamicallyImportedIdResolutions: EMPTY_ARRAY, dynamicallyImportedIds: EMPTY_ARRAY, diff --git a/src/Graph.ts b/src/Graph.ts index 9932970fd..80bf42a46 100644 --- a/src/Graph.ts +++ b/src/Graph.ts @@ -1,11 +1,12 @@ -import * as acorn from 'acorn'; import flru from 'flru'; +import native from '../native'; import type ExternalModule from './ExternalModule'; import Module from './Module'; import { ModuleLoader, type UnresolvedModule } from './ModuleLoader'; import GlobalScope from './ast/scopes/GlobalScope'; import { PathTracker } from './ast/utils/PathTracker'; import type { + AstNode, ModuleInfo, ModuleJSON, NormalizedInputOptions, @@ -17,8 +18,9 @@ import type { import { PluginDriver } from './utils/PluginDriver'; import Queue from './utils/Queue'; import { BuildPhase } from './utils/buildPhase'; -import { addAnnotations } from './utils/commentAnnotations'; +import { convertProgram } from './utils/convert-ast'; import { analyseModuleExecution } from './utils/executionOrder'; +import getReadStringFunction from './utils/getReadStringFunction'; import { LOGLEVEL_WARN } from './utils/logging'; import { error, @@ -53,8 +55,7 @@ function normalizeEntryModules( } export default class Graph { - readonly acornParser: typeof acorn.Parser; - readonly astLru = flru(5); + readonly astLru = flru(5); readonly cachedModules = new Map(); readonly deoptimizationTracker = new PathTracker(); entryModules: Module[] = []; @@ -100,7 +101,6 @@ export default class Graph { watcher.onCurrentRun('close', handleClose); } this.pluginDriver = new PluginDriver(this, options, options.plugins, this.pluginCache); - this.acornParser = acorn.Parser.extend(...(options.acornInjectPlugins as any[])); this.moduleLoader = new ModuleLoader(this, this.modulesById, this.options, this.pluginDriver); this.fileOperationQueue = new Queue(options.maxParallelFileOps); this.pureFunctions = getPureFunctions(options); @@ -123,32 +123,10 @@ export default class Graph { this.phase = BuildPhase.GENERATE; } - contextParse(code: string, options: Partial = {}): acorn.Node { - const onCommentOrig = options.onComment; - const comments: acorn.Comment[] = []; - - options.onComment = - onCommentOrig && typeof onCommentOrig == 'function' - ? (block, text, start, end, ...parameters) => { - comments.push({ end, start, type: block ? 'Block' : 'Line', value: text }); - return onCommentOrig.call(options, block, text, start, end, ...parameters); - } - : comments; - - const ast = this.acornParser.parse(code, { - ...(this.options.acorn as unknown as acorn.Options), - ...options - }); - - if (typeof onCommentOrig == 'object') { - onCommentOrig.push(...comments); - } - - options.onComment = onCommentOrig; - - addAnnotations(comments, ast, code); - - return ast; + contextParse(code: string): AstNode { + const astBuffer = native.parse(code); + const readString = getReadStringFunction(astBuffer); + return convertProgram(astBuffer.buffer, readString); } getCache(): RollupCache { diff --git a/src/Module.ts b/src/Module.ts index 9b0ae660f..224345c29 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -1,5 +1,4 @@ import { extractAssignedNames } from '@rollup/pluginutils'; -import type * as acorn from 'acorn'; import { locate } from 'locate-character'; import MagicString from 'magic-string'; import ExternalModule from './ExternalModule'; @@ -29,6 +28,7 @@ import NamespaceVariable from './ast/variables/NamespaceVariable'; import SyntheticNamedExportVariable from './ast/variables/SyntheticNamedExportVariable'; import type Variable from './ast/variables/Variable'; import type { + AstNode, CustomPluginOptions, DecodedSourceMapOrMissing, EmittedFile, @@ -59,7 +59,7 @@ import { error, logAmbiguousExternalNamespaces, logCircularReexport, - logInconsistentImportAssertions, + logInconsistentImportAttributes, logInvalidFormatForTopLevelAwait, logInvalidSourcemapForError, logMissingExport, @@ -70,9 +70,9 @@ import { warnDeprecation } from './utils/logs'; import { - doAssertionsDiffer, - getAssertionsFromImportExportDeclaration -} from './utils/parseAssertions'; + doAttributesDiffer, + getAttributesFromImportExportDeclaration +} from './utils/parseImportAttributes'; import { basename, extname } from './utils/path'; import type { PureFunctions } from './utils/pureFunctions'; import type { RenderOptions } from './utils/renderHelpers'; @@ -235,7 +235,7 @@ export default class Module { declare scope: ModuleScope; readonly sideEffectDependenciesByVariable = new Map>(); declare sourcemapChain: DecodedSourceMapOrMissing[]; - readonly sourcesWithAssertions = new Map>(); + readonly sourcesWithAttributes = new Map>(); declare transformFiles?: EmittedFile[]; private allExportNames: Set | null = null; @@ -267,7 +267,7 @@ export default class Module { moduleSideEffects: boolean | 'no-treeshake', syntheticNamedExports: boolean | string, meta: CustomPluginOptions, - assertions: Record + attributes: Record ) { this.excludeFromSourcemap = /\0/.test(id); this.context = options.moduleContext(id); @@ -284,12 +284,12 @@ export default class Module { implicitlyLoadedBefore, importers, reexportDescriptions, - sourcesWithAssertions + sourcesWithAttributes } = this; this.info = { - assertions, ast: null, + attributes, code: null, get dynamicallyImportedIdResolutions() { return dynamicImports @@ -352,7 +352,7 @@ export default class Module { get importedIdResolutions() { // eslint-disable-next-line unicorn/prefer-spread return Array.from( - sourcesWithAssertions.keys(), + sourcesWithAttributes.keys(), source => module.resolvedIds[source] ).filter(Boolean); }, @@ -361,7 +361,7 @@ export default class Module { // dependencies are populated // eslint-disable-next-line unicorn/prefer-spread return Array.from( - sourcesWithAssertions.keys(), + sourcesWithAttributes.keys(), source => module.resolvedIds[source]?.id ).filter(Boolean); }, @@ -910,8 +910,8 @@ export default class Module { toJSON(): ModuleJSON { return { - assertions: this.info.assertions, ast: this.info.ast!, + attributes: this.info.attributes, code: this.info.code!, customTransformCache: this.customTransformCache, // eslint-disable-next-line unicorn/prefer-spread @@ -1166,18 +1166,18 @@ export default class Module { source: string, declaration: ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration ) { - const parsedAssertions = getAssertionsFromImportExportDeclaration(declaration.assertions); - const existingAssertions = this.sourcesWithAssertions.get(source); - if (existingAssertions) { - if (doAssertionsDiffer(existingAssertions, parsedAssertions)) { + const parsedAttributes = getAttributesFromImportExportDeclaration(declaration.attributes); + const existingAttributes = this.sourcesWithAttributes.get(source); + if (existingAttributes) { + if (doAttributesDiffer(existingAttributes, parsedAttributes)) { this.log( LOGLEVEL_WARN, - logInconsistentImportAssertions(existingAssertions, parsedAssertions, source, this.id), + logInconsistentImportAttributes(existingAttributes, parsedAttributes, source, this.id), declaration.start ); } } else { - this.sourcesWithAssertions.set(source, parsedAssertions); + this.sourcesWithAttributes.set(source, parsedAttributes); } } @@ -1332,7 +1332,7 @@ export default class Module { this.exports.set(name, MISSING_EXPORT_SHIM_DESCRIPTION); } - private tryParse(): acorn.Node { + private tryParse(): AstNode { try { return this.graph.contextParse(this.info.code!); } catch (error_: any) { diff --git a/src/ModuleLoader.ts b/src/ModuleLoader.ts index 402e05ff3..2c8a5442b 100644 --- a/src/ModuleLoader.ts +++ b/src/ModuleLoader.ts @@ -1,8 +1,8 @@ -import type * as acorn from 'acorn'; import ExternalModule from './ExternalModule'; import type Graph from './Graph'; import Module, { type DynamicImport } from './Module'; import type { + AstNode, CustomPluginOptions, EmittedChunk, HasModuleSideEffects, @@ -27,14 +27,17 @@ import { logExternalModulesCannotBeTransformedToModules, logExternalSyntheticExports, logImplicitDependantCannotBeExternal, - logInconsistentImportAssertions, + logInconsistentImportAttributes, logInternalIdCannotBeExternal, logUnresolvedEntry, logUnresolvedImplicitDependant, logUnresolvedImport, logUnresolvedImportTreatedAsExternal } from './utils/logs'; -import { doAssertionsDiffer, getAssertionsFromImportExpression } from './utils/parseAssertions'; +import { + doAttributesDiffer, + getAttributesFromImportExpression +} from './utils/parseImportAttributes'; import { isAbsolute, isRelative, resolve } from './utils/path'; import relativeId from './utils/relativeId'; import { resolveId } from './utils/resolveId'; @@ -52,7 +55,7 @@ export type ModuleLoaderResolveId = ( importer: string | undefined, customOptions: CustomPluginOptions | undefined, isEntry: boolean | undefined, - assertions: Record, + attributes: Record, skip?: readonly { importer: string | undefined; plugin: Plugin; source: string }[] | null ) => Promise; @@ -208,7 +211,7 @@ export class ModuleLoader { importer, customOptions, isEntry, - assertions, + attributes, skip = null ) => this.getResolvedIdWithDefaults( @@ -224,12 +227,12 @@ export class ModuleLoader { skip, customOptions, typeof isEntry === 'boolean' ? isEntry : !importer, - assertions + attributes ), importer, source ), - assertions + attributes ); private addEntryWithImplicitDependants( @@ -368,17 +371,17 @@ export class ModuleLoader { // its dependencies to be loaded. // Otherwise, it returns immediately. private async fetchModule( - { assertions, id, meta, moduleSideEffects, syntheticNamedExports }: ResolvedId, + { attributes, id, meta, moduleSideEffects, syntheticNamedExports }: ResolvedId, importer: string | undefined, isEntry: boolean, isPreload: PreloadType ): Promise { const existingModule = this.modulesById.get(id); if (existingModule instanceof Module) { - if (importer && doAssertionsDiffer(assertions, existingModule.info.assertions)) { + if (importer && doAttributesDiffer(attributes, existingModule.info.attributes)) { this.options.onLog( LOGLEVEL_WARN, - logInconsistentImportAssertions(existingModule.info.assertions, assertions, id, importer) + logInconsistentImportAttributes(existingModule.info.attributes, attributes, id, importer) ); } await this.handleExistingModule(existingModule, isEntry, isPreload); @@ -397,7 +400,7 @@ export class ModuleLoader { moduleSideEffects, syntheticNamedExports, meta, - assertions + attributes ); this.modulesById.set(id, module); this.graph.watchFiles[id] = true; @@ -447,7 +450,7 @@ export class ModuleLoader { resolvedId: ResolvedId ): Promise { if (resolvedId.external) { - const { assertions, external, id, moduleSideEffects, meta } = resolvedId; + const { attributes, external, id, moduleSideEffects, meta } = resolvedId; let externalModule = this.modulesById.get(id); if (!externalModule) { externalModule = new ExternalModule( @@ -456,17 +459,17 @@ export class ModuleLoader { moduleSideEffects, meta, external !== 'absolute' && isAbsolute(id), - assertions + attributes ); this.modulesById.set(id, externalModule); } else if (!(externalModule instanceof ExternalModule)) { return error(logInternalIdCannotBeExternal(source, importer)); - } else if (doAssertionsDiffer(externalModule.info.assertions, assertions)) { + } else if (doAttributesDiffer(externalModule.info.attributes, attributes)) { this.options.onLog( LOGLEVEL_WARN, - logInconsistentImportAssertions( - externalModule.info.assertions, - assertions, + logInconsistentImportAttributes( + externalModule.info.attributes, + attributes, source, importer ) @@ -555,7 +558,7 @@ export class ModuleLoader { ? dynamicImport.argument : dynamicImport.argument.esTreeNode!, module.id, - getAssertionsFromImportExpression(dynamicImport.node) + getAttributesFromImportExpression(dynamicImport.node) ); if (resolvedId && typeof resolvedId === 'object') { dynamicImport.id = resolvedId.id; @@ -567,17 +570,17 @@ export class ModuleLoader { private getResolveStaticDependencyPromises(module: Module): ResolveStaticDependencyPromise[] { // eslint-disable-next-line unicorn/prefer-spread return Array.from( - module.sourcesWithAssertions, - async ([source, assertions]) => + module.sourcesWithAttributes, + async ([source, attributes]) => [ source, (module.resolvedIds[source] = module.resolvedIds[source] || this.handleInvalidResolvedId( - await this.resolveId(source, module.id, EMPTY_OBJECT, false, assertions), + await this.resolveId(source, module.id, EMPTY_OBJECT, false, attributes), source, module.id, - assertions + attributes )) ] as const ); @@ -585,14 +588,14 @@ export class ModuleLoader { private getResolvedIdWithDefaults( resolvedId: NormalizedResolveIdWithoutDefaults | null, - assertions: Record + attributes: Record ): ResolvedId | null { if (!resolvedId) { return null; } const external = resolvedId.external || false; return { - assertions: resolvedId.assertions || assertions, + attributes: resolvedId.attributes || attributes, external, id: resolvedId.id, meta: resolvedId.meta || {}, @@ -625,7 +628,7 @@ export class ModuleLoader { resolvedId: ResolvedId | null, source: string, importer: string, - assertions: Record + attributes: Record ): ResolvedId { if (resolvedId === null) { if (isRelative(source)) { @@ -633,7 +636,7 @@ export class ModuleLoader { } this.options.onLog(LOGLEVEL_WARN, logUnresolvedImportTreatedAsExternal(source, importer)); return { - assertions, + attributes, external: true, id: source, meta: {}, @@ -697,14 +700,14 @@ export class ModuleLoader { private async resolveDynamicImport( module: Module, - specifier: string | acorn.Node, + specifier: string | AstNode, importer: string, - assertions: Record + attributes: Record ): Promise { const resolution = await this.pluginDriver.hookFirst('resolveDynamicImport', [ specifier, importer, - { assertions } + { attributes } ]); if (typeof specifier !== 'string') { if (typeof resolution === 'string') { @@ -715,18 +718,18 @@ export class ModuleLoader { } return this.getResolvedIdWithDefaults( resolution as NormalizedResolveIdWithoutDefaults, - assertions + attributes ); } if (resolution == null) { const existingResolution = module.resolvedIds[specifier]; if (existingResolution) { - if (doAssertionsDiffer(existingResolution.assertions, assertions)) { + if (doAttributesDiffer(existingResolution.attributes, attributes)) { this.options.onLog( LOGLEVEL_WARN, - logInconsistentImportAssertions( - existingResolution.assertions, - assertions, + logInconsistentImportAttributes( + existingResolution.attributes, + attributes, specifier, importer ) @@ -735,20 +738,20 @@ export class ModuleLoader { return existingResolution; } return (module.resolvedIds[specifier] = this.handleInvalidResolvedId( - await this.resolveId(specifier, module.id, EMPTY_OBJECT, false, assertions), + await this.resolveId(specifier, module.id, EMPTY_OBJECT, false, attributes), specifier, module.id, - assertions + attributes )); } return this.handleInvalidResolvedId( this.getResolvedIdWithDefaults( this.getNormalizedResolvedIdWithoutDefaults(resolution, importer, specifier), - assertions + attributes ), specifier, importer, - assertions + attributes ); } } diff --git a/src/ast/keys.ts b/src/ast/keys.ts index 32764a3aa..e9f9d4379 100644 --- a/src/ast/keys.ts +++ b/src/ast/keys.ts @@ -3,9 +3,6 @@ import type { GenericEsTreeNode } from './nodes/shared/Node'; export const keys: { [name: string]: string[]; } = { - // TODO this should be removed once ImportExpression follows official ESTree - // specs with "null" as default - ImportExpression: ['arguments'], Literal: [], Program: ['body'] }; diff --git a/src/ast/nodes/BinaryExpression.ts b/src/ast/nodes/BinaryExpression.ts index 4d5e1924b..f11538690 100644 --- a/src/ast/nodes/BinaryExpression.ts +++ b/src/ast/nodes/BinaryExpression.ts @@ -112,6 +112,10 @@ export default class BinaryExpression extends NodeBase implements DeoptimizableE return type !== INTERACTION_ACCESSED || path.length > 1; } + removeAnnotations(code: MagicString) { + this.left.removeAnnotations(code); + } + render( code: MagicString, options: RenderOptions, diff --git a/src/ast/nodes/ChainExpression.ts b/src/ast/nodes/ChainExpression.ts index e2aa0a610..2dd05a259 100644 --- a/src/ast/nodes/ChainExpression.ts +++ b/src/ast/nodes/ChainExpression.ts @@ -1,3 +1,4 @@ +import type MagicString from 'magic-string'; import type { DeoptimizableEntity } from '../DeoptimizableEntity'; import type { HasEffectsContext } from '../ExecutionContext'; import type { ObjectPath, PathTracker } from '../utils/PathTracker'; @@ -27,4 +28,8 @@ export default class ChainExpression extends NodeBase implements DeoptimizableEn if (this.expression.isSkippedAsOptional(this)) return false; return this.expression.hasEffects(context); } + + removeAnnotations(code: MagicString) { + this.expression.removeAnnotations(code); + } } diff --git a/src/ast/nodes/ConditionalExpression.ts b/src/ast/nodes/ConditionalExpression.ts index c8969d5f9..94800c20e 100644 --- a/src/ast/nodes/ConditionalExpression.ts +++ b/src/ast/nodes/ConditionalExpression.ts @@ -6,7 +6,6 @@ import { findNonWhiteSpace, removeLineBreaks } from '../../utils/renderHelpers'; -import { removeAnnotations } from '../../utils/treeshakeNode'; import type { DeoptimizableEntity } from '../DeoptimizableEntity'; import type { HasEffectsContext, InclusionContext } from '../ExecutionContext'; import type { NodeInteraction, NodeInteractionCalled } from '../NodeInteractions'; @@ -156,6 +155,10 @@ export default class ConditionalExpression extends NodeBase implements Deoptimiz } } + removeAnnotations(code: MagicString) { + this.test.removeAnnotations(code); + } + render( code: MagicString, options: RenderOptions, @@ -186,7 +189,7 @@ export default class ConditionalExpression extends NodeBase implements Deoptimiz if (this.consequent.included) { code.remove(colonPos, this.end); } - removeAnnotations(this, code); + this.test.removeAnnotations(code); usedBranch!.render(code, options, { isCalleeOfRenderedParent, preventASI: true, diff --git a/src/ast/nodes/ExportAllDeclaration.ts b/src/ast/nodes/ExportAllDeclaration.ts index bd01cf451..271e36d7a 100644 --- a/src/ast/nodes/ExportAllDeclaration.ts +++ b/src/ast/nodes/ExportAllDeclaration.ts @@ -7,7 +7,7 @@ import type * as NodeType from './NodeType'; import { NodeBase } from './shared/Node'; export default class ExportAllDeclaration extends NodeBase { - declare assertions: ImportAttribute[]; + declare attributes: ImportAttribute[]; declare exported: Identifier | null; declare needsBoundaries: true; declare source: Literal; diff --git a/src/ast/nodes/ExportDefaultDeclaration.ts b/src/ast/nodes/ExportDefaultDeclaration.ts index 7a6266676..b6bf1d32b 100644 --- a/src/ast/nodes/ExportDefaultDeclaration.ts +++ b/src/ast/nodes/ExportDefaultDeclaration.ts @@ -60,6 +60,10 @@ export default class ExportDefaultDeclaration extends NodeBase { this.context.addExport(this); } + removeAnnotations(code: MagicString) { + this.declaration.removeAnnotations(code); + } + render(code: MagicString, options: RenderOptions, nodeRenderOptions?: NodeRenderOptions): void { const { start, end } = nodeRenderOptions as { end: number; start: number }; const declarationStart = getDeclarationStart(code.original, this.start); diff --git a/src/ast/nodes/ExportNamedDeclaration.ts b/src/ast/nodes/ExportNamedDeclaration.ts index 55c0f1f29..a63ea59e2 100644 --- a/src/ast/nodes/ExportNamedDeclaration.ts +++ b/src/ast/nodes/ExportNamedDeclaration.ts @@ -11,7 +11,7 @@ import type VariableDeclaration from './VariableDeclaration'; import { type Node, NodeBase } from './shared/Node'; export default class ExportNamedDeclaration extends NodeBase { - declare assertions: ImportAttribute[]; + declare attributes: ImportAttribute[]; declare declaration: FunctionDeclaration | ClassDeclaration | VariableDeclaration | null; declare needsBoundaries: true; declare source: Literal | null; @@ -31,6 +31,10 @@ export default class ExportNamedDeclaration extends NodeBase { this.context.addExport(this); } + removeAnnotations(code: MagicString) { + this.declaration?.removeAnnotations(code); + } + render(code: MagicString, options: RenderOptions, nodeRenderOptions?: NodeRenderOptions): void { const { start, end } = nodeRenderOptions as { end: number; start: number }; if (this.declaration === null) { diff --git a/src/ast/nodes/ExpressionStatement.ts b/src/ast/nodes/ExpressionStatement.ts index 67e545195..e1bb6847e 100644 --- a/src/ast/nodes/ExpressionStatement.ts +++ b/src/ast/nodes/ExpressionStatement.ts @@ -25,9 +25,15 @@ export default class ExpressionStatement extends StatementBase { } } + removeAnnotations(code: MagicString) { + this.expression.removeAnnotations(code); + } + render(code: MagicString, options: RenderOptions): void { super.render(code, options); - if (this.included) this.insertSemicolon(code); + if (code.original[this.end - 1] !== ';') { + code.appendLeft(this.end, ';'); + } } shouldBeIncluded(context: InclusionContext): boolean { diff --git a/src/ast/nodes/Identifier.ts b/src/ast/nodes/Identifier.ts index fdecf19a1..0ab953826 100644 --- a/src/ast/nodes/Identifier.ts +++ b/src/ast/nodes/Identifier.ts @@ -2,7 +2,6 @@ import isReference, { type NodeWithFieldDefinition } from 'is-reference'; import type MagicString from 'magic-string'; import type { NormalizedTreeshakingOptions } from '../../rollup/types'; import { BLANK } from '../../utils/blank'; -import { logIllegalImportReassignment } from '../../utils/logs'; import { PureFunctionKey } from '../../utils/pureFunctions'; import type { NodeRenderOptions, RenderOptions } from '../../utils/renderHelpers'; import type { DeoptimizableEntity } from '../DeoptimizableEntity'; @@ -107,9 +106,6 @@ export default class Identifier extends NodeBase implements PatternNode { } deoptimizePath(path: ObjectPath): void { - if (path.length === 0 && !this.scope.contains(this.name)) { - this.disallowImportReassignment(); - } // We keep conditional chaining because an unknown Node could have an // Identifier as property that might be deoptimized by default this.variable?.deoptimizePath(path); @@ -279,13 +275,6 @@ export default class Identifier extends NodeBase implements PatternNode { } } - private disallowImportReassignment(): never { - return this.context.error( - logIllegalImportReassignment(this.name, this.context.module.id), - this.start - ); - } - private getVariableRespectingTDZ(): ExpressionEntity | null { if (this.isPossibleTDZ()) { return UNKNOWN_EXPRESSION; diff --git a/src/ast/nodes/ImportDeclaration.ts b/src/ast/nodes/ImportDeclaration.ts index acf317b40..41fc90fc5 100644 --- a/src/ast/nodes/ImportDeclaration.ts +++ b/src/ast/nodes/ImportDeclaration.ts @@ -9,13 +9,13 @@ import type * as NodeType from './NodeType'; import { NodeBase } from './shared/Node'; export default class ImportDeclaration extends NodeBase { - declare assertions?: ImportAttribute[]; + declare attributes: ImportAttribute[]; declare needsBoundaries: true; declare source: Literal; declare specifiers: (ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier)[]; declare type: NodeType.tImportDeclaration; - // Do not bind specifiers or assertions + // Do not bind specifiers or attributes bind(): void {} hasEffects(): boolean { diff --git a/src/ast/nodes/ImportExpression.ts b/src/ast/nodes/ImportExpression.ts index c37976a78..386ca5042 100644 --- a/src/ast/nodes/ImportExpression.ts +++ b/src/ast/nodes/ImportExpression.ts @@ -21,7 +21,6 @@ import FunctionExpression from './FunctionExpression'; import Identifier from './Identifier'; import MemberExpression from './MemberExpression'; import type * as NodeType from './NodeType'; -import type ObjectExpression from './ObjectExpression'; import ObjectPattern from './ObjectPattern'; import VariableDeclarator from './VariableDeclarator'; import { @@ -36,21 +35,19 @@ interface DynamicImportMechanism { right: string; } -// TODO once ImportExpression follows official ESTree specs with "null" as -// default, keys.ts should be updated export default class ImportExpression extends NodeBase { - declare arguments: ObjectExpression[] | undefined; + declare options: ExpressionNode | null; inlineNamespace: NamespaceVariable | null = null; declare source: ExpressionNode; declare type: NodeType.tImportExpression; - private assertions: string | null | true = null; + private attributes: string | null | true = null; private mechanism: DynamicImportMechanism | null = null; private namespaceExportName: string | false | undefined = undefined; private resolution: Module | ExternalModule | string | null = null; private resolutionString: string | null = null; - // Do not bind assertions + // Do not bind attributes bind(): void { this.source.bind(); } @@ -209,14 +206,14 @@ export default class ImportExpression extends NodeBase { } else { this.source.render(code, options); } - if (this.assertions !== true) { - if (this.arguments) { + if (this.attributes !== true) { + if (this.options) { code.overwrite(this.source.end, this.end - 1, '', { contentOnly: true }); } - if (this.assertions) { + if (this.attributes) { code.appendLeft( this.end - 1, - `,${_}${getObject([['assert', this.assertions]], { + `,${_}${getObject([['assert', this.attributes]], { lineBreakIndent: null })}` ); @@ -233,14 +230,14 @@ export default class ImportExpression extends NodeBase { accessedGlobalsByScope: Map>, resolutionString: string, namespaceExportName: string | false | undefined, - assertions: string | null | true + attributes: string | null | true ): void { const { format } = options; this.inlineNamespace = null; this.resolution = resolution; this.resolutionString = resolutionString; this.namespaceExportName = namespaceExportName; - this.assertions = assertions; + this.attributes = attributes; const accessedGlobals = [...(accessedImportGlobals[format] || [])]; let helper: string | null; ({ helper, mechanism: this.mechanism } = this.getDynamicImportMechanismAndHelper( diff --git a/src/ast/nodes/LogicalExpression.ts b/src/ast/nodes/LogicalExpression.ts index 757d8286f..25c5fa7ea 100644 --- a/src/ast/nodes/LogicalExpression.ts +++ b/src/ast/nodes/LogicalExpression.ts @@ -7,7 +7,6 @@ import { removeLineBreaks, type RenderOptions } from '../../utils/renderHelpers'; -import { removeAnnotations } from '../../utils/treeshakeNode'; import type { DeoptimizableEntity } from '../DeoptimizableEntity'; import type { HasEffectsContext, InclusionContext } from '../ExecutionContext'; import type { NodeInteraction, NodeInteractionCalled } from '../NodeInteractions'; @@ -160,6 +159,10 @@ export default class LogicalExpression extends NodeBase implements Deoptimizable } } + removeAnnotations(code: MagicString) { + this.left.removeAnnotations(code); + } + render( code: MagicString, options: RenderOptions, @@ -182,10 +185,10 @@ export default class LogicalExpression extends NodeBase implements Deoptimizable if (preventASI) { removeLineBreaks(code, removePos, this.right.start); } + this.left.removeAnnotations(code); } else { code.remove(operatorPos, this.end); } - removeAnnotations(this, code); this.getUsedBranch()!.render(code, options, { isCalleeOfRenderedParent, preventASI, diff --git a/src/ast/nodes/SequenceExpression.ts b/src/ast/nodes/SequenceExpression.ts index af12d2729..8ca3f731d 100644 --- a/src/ast/nodes/SequenceExpression.ts +++ b/src/ast/nodes/SequenceExpression.ts @@ -80,6 +80,10 @@ export default class SequenceExpression extends NodeBase { } } + removeAnnotations(code: MagicString) { + this.expressions[0].removeAnnotations(code); + } + render( code: MagicString, options: RenderOptions, diff --git a/src/ast/nodes/VariableDeclaration.ts b/src/ast/nodes/VariableDeclaration.ts index 0265bae99..f6846527d 100644 --- a/src/ast/nodes/VariableDeclaration.ts +++ b/src/ast/nodes/VariableDeclaration.ts @@ -85,6 +85,10 @@ export default class VariableDeclaration extends NodeBase { } } + removeAnnotations(code: MagicString) { + this.declarations[0].removeAnnotations(code); + } + render( code: MagicString, options: RenderOptions, diff --git a/src/ast/nodes/VariableDeclarator.ts b/src/ast/nodes/VariableDeclarator.ts index 2308c248f..33b22a0ca 100644 --- a/src/ast/nodes/VariableDeclarator.ts +++ b/src/ast/nodes/VariableDeclarator.ts @@ -46,6 +46,10 @@ export default class VariableDeclarator extends NodeBase { } } + removeAnnotations(code: MagicString) { + this.init?.removeAnnotations(code); + } + render(code: MagicString, options: RenderOptions): void { const { exportNamesByVariable, diff --git a/src/ast/nodes/shared/Node.ts b/src/ast/nodes/shared/Node.ts index 8a3827dcd..47ca814dc 100644 --- a/src/ast/nodes/shared/Node.ts +++ b/src/ast/nodes/shared/Node.ts @@ -1,10 +1,9 @@ -import type * as acorn from 'acorn'; import { locate, type Location } from 'locate-character'; import type MagicString from 'magic-string'; import type { AstContext } from '../../../Module'; -import type { NormalizedTreeshakingOptions } from '../../../rollup/types'; -import type { RollupAnnotation } from '../../../utils/commentAnnotations'; -import { ANNOTATION_KEY, INVALID_COMMENT_KEY } from '../../../utils/commentAnnotations'; +import type { AstNode, NormalizedTreeshakingOptions } from '../../../rollup/types'; +import type { RollupAnnotation } from '../../../utils/convert-ast'; +import { ANNOTATION_KEY, INVALID_ANNOTATION_KEY } from '../../../utils/convert-ast'; import type { NodeRenderOptions, RenderOptions } from '../../../utils/renderHelpers'; import type { DeoptimizableEntity } from '../../DeoptimizableEntity'; import type { Entity } from '../../Entity'; @@ -23,7 +22,7 @@ import type * as NodeType from '../NodeType'; import type { InclusionOptions } from './Expression'; import { ExpressionEntity } from './Expression'; -export interface GenericEsTreeNode extends acorn.Node { +export interface GenericEsTreeNode extends AstNode { [key: string]: any; } @@ -31,7 +30,7 @@ export const INCLUDE_PARAMETERS = 'variables' as const; export type IncludeChildren = boolean | typeof INCLUDE_PARAMETERS; export interface Node extends Entity { - annotations?: acorn.Comment[]; + annotations?: RollupAnnotation[]; context: AstContext; end: number; esTreeNode: GenericEsTreeNode | null; @@ -95,6 +94,8 @@ export interface Node extends Entity { deoptimizeAccess: boolean ): void; + removeAnnotations(code: MagicString): void; + render(code: MagicString, options: RenderOptions, nodeRenderOptions?: NodeRenderOptions): void; /** @@ -134,7 +135,7 @@ export class NodeBase extends ExpressionEntity implements ExpressionNode { context: AstContext; declare end: number; - esTreeNode: acorn.Node | null; + esTreeNode: AstNode | null; keys: string[]; parent: Node | { context: AstContext; type: string }; declare scope: ChildScope; @@ -257,12 +258,6 @@ export class NodeBase extends ExpressionEntity implements ExpressionNode { */ initialise(): void {} - insertSemicolon(code: MagicString): void { - if (code.original[this.end - 1] !== ';') { - code.appendLeft(this.end, ';'); - } - } - parseNode(esTreeNode: GenericEsTreeNode, keepEsTreeNodeKeys?: string[]): void { for (const [key, value] of Object.entries(esTreeNode)) { // That way, we can override this function to add custom initialisation and then call super.parseNode @@ -273,12 +268,12 @@ export class NodeBase extends ExpressionEntity implements ExpressionNode { this.annotations = annotations; if ((this.context.options.treeshake as NormalizedTreeshakingOptions).annotations) { this.annotationNoSideEffects = annotations.some( - comment => comment.annotationType === 'noSideEffects' + comment => comment.type === 'noSideEffects' ); - this.annotationPure = annotations.some(comment => comment.annotationType === 'pure'); + this.annotationPure = annotations.some(comment => comment.type === 'pure'); } - } else if (key === INVALID_COMMENT_KEY) { - for (const { start, end } of value as acorn.Comment[]) + } else if (key === INVALID_ANNOTATION_KEY) { + for (const { start, end } of value as RollupAnnotation[]) this.context.magicString.remove(start, end); } } else if (typeof value !== 'object' || value === null) { @@ -308,6 +303,14 @@ export class NodeBase extends ExpressionEntity implements ExpressionNode { } } + removeAnnotations(code: MagicString): void { + if (this.annotations) { + for (const annotation of this.annotations) { + code.remove(annotation.start, annotation.end); + } + } + } + render(code: MagicString, options: RenderOptions): void { for (const key of this.keys) { const value = (this as GenericEsTreeNode)[key]; diff --git a/src/finalisers/es.ts b/src/finalisers/es.ts index ac49a9113..372109e4c 100644 --- a/src/finalisers/es.ts +++ b/src/finalisers/es.ts @@ -37,8 +37,8 @@ function getImportBlock( { _ }: GenerateCodeSnippets ): string[] { const importBlock: string[] = []; - for (const { importPath, reexports, imports, name, assertions } of dependencies) { - const assertion = assertions ? `${_}assert${_}${assertions}` : ''; + for (const { importPath, reexports, imports, name, attributes } of dependencies) { + const assertion = attributes ? `${_}assert${_}${attributes}` : ''; const pathWithAssertion = `'${importPath}'${assertion};`; if (!reexports && !imports) { importBlock.push(`import${_}${pathWithAssertion}`); diff --git a/src/rollup/rollup.ts b/src/rollup/rollup.ts index 2abf6c0e9..e642f92c6 100644 --- a/src/rollup/rollup.ts +++ b/src/rollup/rollup.ts @@ -5,6 +5,7 @@ import type { PluginDriver } from '../utils/PluginDriver'; import { getSortedValidatedPlugins } from '../utils/PluginDriver'; import { mkdir, writeFile } from '../utils/fs'; import { catchUnfinishedHookActions } from '../utils/hookActions'; +import initWasm from '../utils/initWasm'; import { getLogHandler } from '../utils/logHandler'; import { getLogger } from '../utils/logger'; import { LOGLEVEL_DEBUG, LOGLEVEL_INFO, LOGLEVEL_WARN } from '../utils/logging'; @@ -51,6 +52,8 @@ export async function rollupInternal( ); initialiseTimers(inputOptions); + await initWasm(); + const graph = new Graph(inputOptions, watcher); // remove the cache object from the memory after graph creation (cache is not used anymore) diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 2f2ceb5d4..1a446a9d2 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -93,20 +93,20 @@ export interface SourceMap { export type SourceMapInput = ExistingRawSourceMap | string | null | { mappings: '' }; interface ModuleOptions { - assertions: Record; + attributes: Record; meta: CustomPluginOptions; moduleSideEffects: boolean | 'no-treeshake'; syntheticNamedExports: boolean | string; } export interface SourceDescription extends Partial> { - ast?: AcornNode; + ast?: AstNode; code: string; map?: SourceMapInput; } export interface TransformModuleJSON { - ast?: AcornNode; + ast?: AstNode; code: string; // note if plugins use new this.cache to opt-out auto transform cache customTransformCache: boolean; @@ -117,7 +117,7 @@ export interface TransformModuleJSON { } export interface ModuleJSON extends TransformModuleJSON, ModuleOptions { - ast: AcornNode; + ast: AstNode; dependencies: string[]; id: string; resolvedIds: ResolvedIdMap; @@ -173,7 +173,7 @@ export type EmittedFile = EmittedAsset | EmittedChunk | EmittedPrebuiltChunk; export type EmitFile = (emittedFile: EmittedFile) => string; interface ModuleInfo extends ModuleOptions { - ast: AcornNode | null; + ast: AstNode | null; code: string | null; dynamicImporters: readonly string[]; dynamicallyImportedIdResolutions: readonly ResolvedId[]; @@ -221,12 +221,12 @@ export interface PluginContext extends MinimalPluginContext { ) => Promise; /** @deprecated Use `this.getModuleIds` instead */ moduleIds: IterableIterator; - parse: (input: string, options?: any) => AcornNode; + parse: (input: string) => AstNode; resolve: ( source: string, importer?: string, options?: { - assertions?: Record; + attributes?: Record; custom?: CustomPluginOptions; isEntry?: boolean; skipSelf?: boolean; @@ -265,13 +265,13 @@ export type ResolveIdHook = ( this: PluginContext, source: string, importer: string | undefined, - options: { assertions: Record; custom?: CustomPluginOptions; isEntry: boolean } + options: { attributes: Record; custom?: CustomPluginOptions; isEntry: boolean } ) => ResolveIdResult; export type ShouldTransformCachedModuleHook = ( this: PluginContext, options: { - ast: AcornNode; + ast: AstNode; code: string; id: string; meta: CustomPluginOptions; @@ -323,9 +323,9 @@ export type RenderChunkHook = ( export type ResolveDynamicImportHook = ( this: PluginContext, - specifier: string | AcornNode, + specifier: string | AstNode, importer: string, - options: { assertions: Record } + options: { attributes: Record } ) => ResolveIdResult; export type ResolveImportMetaHook = ( @@ -566,8 +566,6 @@ export type SourcemapIgnoreListOption = ( export type InputPluginOption = MaybePromise; export interface InputOptions { - acorn?: Record; - acornInjectPlugins?: ((...arguments_: any[]) => unknown)[] | ((...arguments_: any[]) => unknown); cache?: boolean | RollupCache; context?: string; experimentalCacheExpiry?: number; @@ -603,8 +601,6 @@ export interface InputOptionsWithPlugins extends InputOptions { } export interface NormalizedInputOptions { - acorn: Record; - acornInjectPlugins: (() => unknown)[]; cache: false | undefined | RollupCache; context: string; experimentalCacheExpiry: number; @@ -713,7 +709,9 @@ export interface OutputOptions { experimentalMinChunkSize?: number; exports?: 'default' | 'named' | 'none' | 'auto'; extend?: boolean; + /** @deprecated Use "externalImportAttributes" instead. */ externalImportAssertions?: boolean; + externalImportAttributes?: boolean; externalLiveBindings?: boolean; // only required for bundle.write file?: string; @@ -770,7 +768,9 @@ export interface NormalizedOutputOptions { experimentalMinChunkSize: number; exports: 'default' | 'named' | 'none' | 'auto'; extend: boolean; + /** @deprecated Use "externalImportAttributes" instead. */ externalImportAssertions: boolean; + externalImportAttributes: boolean; externalLiveBindings: boolean; file: string | undefined; footer: AddonFunction; @@ -997,7 +997,7 @@ export type RollupWatcher = AwaitingEventEmitter<{ export function watch(config: RollupWatchOptions | RollupWatchOptions[]): RollupWatcher; -interface AcornNode { +interface AstNode { end: number; start: number; type: string; diff --git a/src/utils/PluginContext.ts b/src/utils/PluginContext.ts index a00c262cb..4bde06fd8 100644 --- a/src/utils/PluginContext.ts +++ b/src/utils/PluginContext.ts @@ -99,13 +99,13 @@ export function getPluginContext( return wrappedModuleIds(); }, parse: graph.contextParse.bind(graph), - resolve(source, importer, { assertions, custom, isEntry, skipSelf } = BLANK) { + resolve(source, importer, { attributes, custom, isEntry, skipSelf } = BLANK) { return graph.moduleLoader.resolveId( source, importer, custom, isEntry, - assertions || EMPTY_OBJECT, + attributes || EMPTY_OBJECT, skipSelf ? [{ importer, plugin, source }] : null ); }, diff --git a/src/utils/commentAnnotations.ts b/src/utils/commentAnnotations.ts deleted file mode 100644 index ad77451b4..000000000 --- a/src/utils/commentAnnotations.ts +++ /dev/null @@ -1,212 +0,0 @@ -import type * as acorn from 'acorn'; -import { base as basicWalker } from 'acorn-walk'; -import { - ArrowFunctionExpression, - BinaryExpression, - CallExpression, - ChainExpression, - ConditionalExpression, - ExportDefaultDeclaration, - ExportNamedDeclaration, - ExpressionStatement, - FunctionDeclaration, - LogicalExpression, - NewExpression, - SequenceExpression, - VariableDeclaration, - VariableDeclarator -} from '../ast/nodes/NodeType'; -import { SOURCEMAPPING_URL_RE } from './sourceMappingURL'; - -export type AnnotationType = 'noSideEffects' | 'pure'; - -export interface RollupAnnotation extends acorn.Comment { - annotationType: AnnotationType; -} - -interface CommentState { - annotationIndex: number; - annotations: RollupAnnotation[]; - code: string; -} - -export const ANNOTATION_KEY = '_rollupAnnotations'; -export const INVALID_COMMENT_KEY = '_rollupRemoved'; - -interface NodeWithComments extends acorn.Node { - [ANNOTATION_KEY]?: acorn.Comment[]; - [INVALID_COMMENT_KEY]?: acorn.Comment[]; -} - -function handlePureAnnotationsOfNode( - node: acorn.Node, - state: CommentState, - type = node.type -): void { - const { annotations, code } = state; - // eslint-disable-next-line unicorn/consistent-destructuring - let comment = annotations[state.annotationIndex]; - while (comment && node.start >= comment.end) { - markPureNode(node, comment, code); - comment = annotations[++state.annotationIndex]; - } - if (comment && comment.end <= node.end) { - basicWalker[type](node, state, handlePureAnnotationsOfNode); - // eslint-disable-next-line unicorn/consistent-destructuring - while ((comment = annotations[state.annotationIndex]) && comment.end <= node.end) { - ++state.annotationIndex; - annotateNode(node, comment, false); - } - } -} - -const neitherWithespaceNorBrackets = /[^\s(]/g; -const noWhitespace = /\S/g; - -function markPureNode(node: NodeWithComments, comment: acorn.Comment, code: string): void { - const annotatedNodes: NodeWithComments[] = []; - let invalidAnnotation: boolean | undefined; - const codeInBetween = code.slice(comment.end, node.start); - if (doesNotMatchOutsideComment(codeInBetween, neitherWithespaceNorBrackets)) { - const parentStart = node.start; - while (true) { - annotatedNodes.push(node); - switch (node.type) { - case ExpressionStatement: - case ChainExpression: { - node = (node as any).expression; - continue; - } - case SequenceExpression: { - // if there are parentheses, the annotation would apply to the entire expression - if (doesNotMatchOutsideComment(code.slice(parentStart, node.start), noWhitespace)) { - node = (node as any).expressions[0]; - continue; - } - invalidAnnotation = true; - break; - } - case ConditionalExpression: { - // if there are parentheses, the annotation would apply to the entire expression - if (doesNotMatchOutsideComment(code.slice(parentStart, node.start), noWhitespace)) { - node = (node as any).test; - continue; - } - invalidAnnotation = true; - break; - } - case LogicalExpression: - case BinaryExpression: { - // if there are parentheses, the annotation would apply to the entire expression - if (doesNotMatchOutsideComment(code.slice(parentStart, node.start), noWhitespace)) { - node = (node as any).left; - continue; - } - invalidAnnotation = true; - break; - } - case ExportNamedDeclaration: - case ExportDefaultDeclaration: { - node = (node as any).declaration; - continue; - } - case VariableDeclaration: { - // case: /*#__PURE__*/ const foo = () => {} - const declaration = node as any; - if (declaration.kind === 'const') { - // jsdoc only applies to the first declaration - node = declaration.declarations[0].init; - continue; - } - invalidAnnotation = true; - break; - } - case VariableDeclarator: { - node = (node as any).init; - continue; - } - case FunctionDeclaration: - case ArrowFunctionExpression: - case CallExpression: - case NewExpression: { - break; - } - default: { - invalidAnnotation = true; - } - } - break; - } - } else { - invalidAnnotation = true; - } - if (invalidAnnotation) { - annotateNode(node, comment, false); - } else { - for (const node of annotatedNodes) { - annotateNode(node, comment, true); - } - } -} - -function doesNotMatchOutsideComment(code: string, forbiddenChars: RegExp): boolean { - let nextMatch: RegExpExecArray | null; - while ((nextMatch = forbiddenChars.exec(code)) !== null) { - if (nextMatch[0] === '/') { - const charCodeAfterSlash = code.charCodeAt(forbiddenChars.lastIndex); - if (charCodeAfterSlash === 42 /*"*"*/) { - forbiddenChars.lastIndex = code.indexOf('*/', forbiddenChars.lastIndex + 1) + 2; - continue; - } else if (charCodeAfterSlash === 47 /*"/"*/) { - forbiddenChars.lastIndex = code.indexOf('\n', forbiddenChars.lastIndex + 1) + 1; - continue; - } - } - forbiddenChars.lastIndex = 0; - return false; - } - return true; -} - -const annotationsRegexes: [AnnotationType, RegExp][] = [ - ['pure', /[#@]__PURE__/], - ['noSideEffects', /[#@]__NO_SIDE_EFFECTS__/] -]; - -export function addAnnotations( - comments: readonly acorn.Comment[], - esTreeAst: acorn.Node, - code: string -): void { - const annotations: RollupAnnotation[] = []; - const sourceMappingComments: acorn.Comment[] = []; - for (const comment of comments) { - for (const [annotationType, regex] of annotationsRegexes) { - if (regex.test(comment.value)) { - annotations.push({ ...comment, annotationType }); - } - } - if (SOURCEMAPPING_URL_RE.test(comment.value)) { - sourceMappingComments.push(comment); - } - } - for (const comment of sourceMappingComments) { - annotateNode(esTreeAst, comment, false); - } - - handlePureAnnotationsOfNode(esTreeAst, { - annotationIndex: 0, - annotations, - code - }); -} - -function annotateNode(node: NodeWithComments, comment: acorn.Comment, valid: boolean): void { - const key = valid ? ANNOTATION_KEY : INVALID_COMMENT_KEY; - const property = node[key]; - if (property) { - property.push(comment); - } else { - node[key] = [comment]; - } -} diff --git a/src/utils/convert-ast-strings.ts b/src/utils/convert-ast-strings.ts new file mode 100644 index 000000000..381bb3743 --- /dev/null +++ b/src/utils/convert-ast-strings.ts @@ -0,0 +1,62 @@ +export const FIXED_STRINGS = [ + 'var', + 'let', + 'const', + 'init', + 'get', + 'set', + 'constructor', + 'method', + '-', + '+', + '!', + '~', + 'typeof', + 'void', + 'delete', + '++', + '--', + '==', + '!=', + '===', + '!==', + '<', + '<=', + '>', + '>=', + '<<', + '>>', + '>>>', + '+', + '-', + '*', + '/', + '%', + '|', + '^', + '&', + '||', + '&&', + 'in', + 'instanceof', + '**', + '??', + '=', + '+=', + '-=', + '*=', + '/=', + '%=', + '<<=', + '>>=', + '>>>=', + '|=', + '^=', + '&=', + '**=', + '&&=', + '||=', + '??=', + 'pure', + 'noSideEffects' +]; diff --git a/src/utils/convert-ast.ts b/src/utils/convert-ast.ts new file mode 100644 index 000000000..608fb518f --- /dev/null +++ b/src/utils/convert-ast.ts @@ -0,0 +1,1235 @@ +import type * as estree from 'estree'; +import type { AstNode } from '../rollup/types'; +import { FIXED_STRINGS } from './convert-ast-strings'; +import { error } from './logs'; + +type ReadString = (start: number, length: number) => string; + +export const convertProgram = (buffer: ArrayBuffer, readString: ReadString): any => + convertNode(0, new Uint32Array(buffer), readString); + +const convertNode = (position: number, buffer: Uint32Array, readString: ReadString): any => { + const nodeType = buffer[position]; + const converter = nodeConverters[nodeType]; + /* istanbul ignore if: This should never be executed but is a safeguard against faulty buffers */ + if (!converter) { + console.trace(); + throw new Error(`Unknown node type: ${nodeType}`); + } + return converter(position + 1, buffer, readString); +}; + +/* eslint-disable sort-keys */ +const nodeConverters: ((position: number, buffer: Uint32Array, readString: ReadString) => any)[] = [ + // index:0; ArrayExpression + (position, buffer, readString): estree.ArrayExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const elements = convertNodeList(position, buffer, readString); + return { + type: 'ArrayExpression', + start, + end, + elements + }; + }, + // index:1; ArrayPattern + (position, buffer, readString): estree.ArrayPattern & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const elements = convertNodeList(position, buffer, readString); + return { + type: 'ArrayPattern', + start, + end, + elements + }; + }, + // index:2; ArrowFunctionExpression + (position, buffer, readString): ArrowFunctionExpression & AstNode & { id: null } => { + const start = buffer[position++]; + const end = buffer[position++]; + const async = !!buffer[position++]; + const generator = !!buffer[position++]; + const expression = !!buffer[position++]; + const parameters = convertNodeList(buffer[position++], buffer, readString); + const body = convertNode(buffer[position++], buffer, readString); + const annotations = convertAnnotationList(position, buffer); + return { + type: 'ArrowFunctionExpression', + start, + end, + async, + body, + expression, + generator, + id: null, + params: parameters, + _rollupAnnotations: annotations + }; + }, + // index:3; AssignmentExpression + (position, buffer, readString): estree.AssignmentExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const operator = FIXED_STRINGS[buffer[position++]] as estree.AssignmentOperator; + const right = convertNode(buffer[position++], buffer, readString); + const left = convertNode(position, buffer, readString); + return { + type: 'AssignmentExpression', + start, + end, + left, + operator, + right + }; + }, + // index:4; AssignmentPattern + (position, buffer, readString): estree.AssignmentPattern & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const right = convertNode(buffer[position++], buffer, readString); + const left = convertNode(position, buffer, readString); + return { + type: 'AssignmentPattern', + start, + end, + left, + right + }; + }, + // index:5; AwaitExpression + (position, buffer, readString): estree.AwaitExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const argument = convertNode(position, buffer, readString); + return { + type: 'AwaitExpression', + start, + argument, + end + }; + }, + // index:6; BinaryExpression + (position, buffer, readString): estree.BinaryExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const operator = FIXED_STRINGS[buffer[position++]] as estree.BinaryOperator; + const right = convertNode(buffer[position++], buffer, readString); + const left = convertNode(position, buffer, readString); + return { + type: 'BinaryExpression', + start, + end, + left, + operator, + right + }; + }, + // index:7; BlockStatement + (position, buffer, readString): estree.BlockStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const body = convertNodeList(position, buffer, readString); + return { + type: 'BlockStatement', + start, + body, + end + }; + }, + // index:8; BreakStatement + (position, buffer, readString): estree.BreakStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const labelPosition = buffer[position++]; + return { + type: 'BreakStatement', + start, + end, + label: labelPosition ? convertNode(labelPosition, buffer, readString) : null + }; + }, + // index:9; CallExpression + (position, buffer, readString): CallExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const optional = !!buffer[position++]; + const callee = convertNode(buffer[position++], buffer, readString); + const argumentsList = convertNodeList(buffer[position++], buffer, readString); + const annotations = convertAnnotationList(position, buffer); + return { + type: 'CallExpression', + start, + end, + arguments: argumentsList, + callee, + optional, + ...(annotations.length > 0 ? { _rollupAnnotations: annotations } : {}) + }; + }, + // index:10; CatchClause + (position, buffer, readString): estree.CatchClause & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const parameterPosition = buffer[position++]; + const body = convertNode(buffer[position], buffer, readString); + return { + type: 'CatchClause', + start, + end, + body, + param: parameterPosition ? convertNode(parameterPosition, buffer, readString) : null + }; + }, + // index:11; ChainExpression + (position, buffer, readString): estree.ChainExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const expression = convertNode(position, buffer, readString); + return { + type: 'ChainExpression', + start, + end, + expression + }; + }, + // index:12; ClassBody + (position, buffer, readString): estree.ClassBody & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const body = convertNodeList(position, buffer, readString); + return { + type: 'ClassBody', + start, + end, + body + }; + }, + // index:13; ClassDeclaration + (position, buffer, readString): estree.ClassDeclaration & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const idPosition = buffer[position++]; + const superClassPosition = buffer[position++]; + const body = convertNode(buffer[position], buffer, readString); + return { + type: 'ClassDeclaration', + start, + end, + body, + id: idPosition ? convertNode(idPosition, buffer, readString) : null, + superClass: superClassPosition ? convertNode(superClassPosition, buffer, readString) : null + }; + }, + // index:14; ClassExpression + (position, buffer, readString): estree.ClassExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const idPosition = buffer[position++]; + const superClassPosition = buffer[position++]; + const body = convertNode(buffer[position], buffer, readString); + return { + type: 'ClassExpression', + start, + end, + body, + id: idPosition ? convertNode(idPosition, buffer, readString) : null, + superClass: superClassPosition ? convertNode(superClassPosition, buffer, readString) : null + }; + }, + // index:15; ConditionalExpression + (position, buffer, readString): estree.ConditionalExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const consequent = convertNode(buffer[position++], buffer, readString); + const alternate = convertNode(buffer[position++], buffer, readString); + const test = convertNode(position, buffer, readString); + return { + type: 'ConditionalExpression', + start, + end, + alternate, + consequent, + test + }; + }, + // index:16; ContinueStatement + (position, buffer, readString): estree.ContinueStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const labelPosition = buffer[position]; + return { + type: 'ContinueStatement', + start, + end, + label: labelPosition ? convertNode(labelPosition, buffer, readString) : null + }; + }, + // index:17; DebuggerStatement + (position, buffer): estree.DebuggerStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + return { + type: 'DebuggerStatement', + start, + end + }; + }, + // index:18; DoWhileStatement + (position, buffer, readString): estree.DoWhileStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const test = convertNode(buffer[position++], buffer, readString); + const body = convertNode(position, buffer, readString); + return { + type: 'DoWhileStatement', + start, + end, + body, + test + }; + }, + // index:19; EmptyStatement + (position, buffer): estree.EmptyStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + return { + type: 'EmptyStatement', + start, + end + }; + }, + // index:20; ExportAllDeclaration + (position, buffer, readString): ExportAllDeclaration & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const exportedPosition = buffer[position++]; + const source = convertNode(buffer[position++], buffer, readString); + const attributes = convertNodeList(buffer[position], buffer, readString); + return { + type: 'ExportAllDeclaration', + start, + end, + exported: exportedPosition ? convertNode(exportedPosition, buffer, readString) : null, + source, + attributes + }; + }, + // index:21; ExportDefaultDeclaration + (position, buffer, readString): estree.ExportDefaultDeclaration & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const declaration = convertNode(position, buffer, readString); + return { + type: 'ExportDefaultDeclaration', + start, + end, + declaration + }; + }, + // index:22; ExportNamedDeclaration + (position, buffer, readString): ExportNamedDeclaration & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const declarationPosition = buffer[position++]; + const sourcePosition = buffer[position++]; + const attributes = convertNodeList(buffer[position++], buffer, readString); + const specifiers = convertNodeList(position, buffer, readString); + return { + type: 'ExportNamedDeclaration', + start, + end, + declaration: declarationPosition + ? convertNode(declarationPosition, buffer, readString) + : null, + source: sourcePosition ? convertNode(sourcePosition, buffer, readString) : null, + specifiers, + attributes + }; + }, + // index:23; ExportSpecifier + (position, buffer, readString): estree.ExportSpecifier & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const exportedPosition = buffer[position++]; + const local = convertNode(position, buffer, readString); + const exported = exportedPosition ? convertNode(exportedPosition, buffer, readString) : local; + return { + type: 'ExportSpecifier', + start, + end, + exported, + local + }; + }, + // index:24; ExpressionStatement + (position, buffer, readString): estree.ExpressionStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const directivePosition = buffer[position++]; + const expression = convertNode(position, buffer, readString); + return { + type: 'ExpressionStatement', + start, + end, + expression, + ...(directivePosition + ? { directive: convertString(directivePosition, buffer, readString) } + : {}) + }; + }, + // index:25; ForInStatement + (position, buffer, readString): estree.ForInStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const right = convertNode(buffer[position++], buffer, readString); + const body = convertNode(buffer[position++], buffer, readString); + const left = convertNode(position, buffer, readString); + return { + type: 'ForInStatement', + start, + end, + body, + left, + right + }; + }, + // index:26; ForOfStatement + (position, buffer, readString): estree.ForOfStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const awaited = !!buffer[position++]; + const right = convertNode(buffer[position++], buffer, readString); + const body = convertNode(buffer[position++], buffer, readString); + const left = convertNode(position, buffer, readString); + return { + type: 'ForOfStatement', + start, + end, + await: awaited, + body, + left, + right + }; + }, + // index:27; ForStatement + (position, buffer, readString): estree.ForStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const initPosition = buffer[position++]; + const testPosition = buffer[position++]; + const updatePosition = buffer[position++]; + const body = convertNode(buffer[position], buffer, readString); + return { + type: 'ForStatement', + start, + end, + body, + init: initPosition ? convertNode(initPosition, buffer, readString) : null, + test: testPosition ? convertNode(testPosition, buffer, readString) : null, + update: updatePosition ? convertNode(updatePosition, buffer, readString) : null + }; + }, + // index:28; FunctionDeclaration + (position, buffer, readString): FunctionDeclaration & AstNode & { expression: false } => { + const start = buffer[position++]; + const end = buffer[position++]; + const async = !!buffer[position++]; + const generator = !!buffer[position++]; + const idPosition = buffer[position++]; + const parameters = convertNodeList(buffer[position++], buffer, readString); + const body = convertNode(buffer[position++], buffer, readString); + const annotations = convertAnnotationList(position, buffer); + return { + type: 'FunctionDeclaration', + start, + end, + async, + body, + expression: false, + generator, + id: idPosition ? convertNode(idPosition, buffer, readString) : null, + params: parameters, + _rollupAnnotations: annotations + }; + }, + // index:29; FunctionExpression + (position, buffer, readString): FunctionExpression & AstNode & { expression: false } => { + const start = buffer[position++]; + const end = buffer[position++]; + const async = !!buffer[position++]; + const generator = !!buffer[position++]; + const idPosition = buffer[position++]; + const parameters = convertNodeList(buffer[position++], buffer, readString); + const body = convertNode(buffer[position++], buffer, readString); + const annotations = convertAnnotationList(position, buffer); + return { + type: 'FunctionExpression', + start, + end, + async, + body, + expression: false, + generator, + id: idPosition ? convertNode(idPosition, buffer, readString) : null, + params: parameters, + _rollupAnnotations: annotations + }; + }, + // index:30; Identifier + (position, buffer, readString): estree.Identifier & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const name = convertString(position, buffer, readString); + return { + type: 'Identifier', + start, + end, + name + }; + }, + // index:31; IfStatement + (position, buffer, readString): estree.IfStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const consequent = convertNode(buffer[position++], buffer, readString); + const alternatePosition = buffer[position++]; + const test = convertNode(position, buffer, readString); + return { + type: 'IfStatement', + start, + end, + alternate: alternatePosition ? convertNode(alternatePosition, buffer, readString) : null, + consequent, + test + }; + }, + // index:32; ImportAttribute + (position, buffer, readString): ImportAttribute & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const value = convertNode(buffer[position++], buffer, readString); + const key = convertNode(position, buffer, readString); + return { + type: 'ImportAttribute', + start, + end, + key, + value + }; + }, + // index:33; ImportDeclaration + (position, buffer, readString): ImportDeclaration & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const source = convertNode(buffer[position++], buffer, readString); + const attributes = convertNodeList(buffer[position++], buffer, readString); + const specifiers = convertNodeList(position, buffer, readString); + return { + type: 'ImportDeclaration', + start, + end, + source, + specifiers, + attributes + }; + }, + // index:34; ImportDefaultSpecifier + (position, buffer, readString): estree.ImportDefaultSpecifier & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const local = convertNode(position, buffer, readString); + return { + type: 'ImportDefaultSpecifier', + start, + end, + local + }; + }, + // index:35; ImportExpression + (position, buffer, readString): ImportExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const optionsPosition = buffer[position++]; + const source = convertNode(position, buffer, readString); + return { + type: 'ImportExpression', + start, + end, + source, + options: optionsPosition ? convertNode(optionsPosition, buffer, readString) : null + }; + }, + // index:36; ImportNamespaceSpecifier + (position, buffer, readString): estree.ImportNamespaceSpecifier & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const local = convertNode(position, buffer, readString); + return { + type: 'ImportNamespaceSpecifier', + start, + end, + local + }; + }, + // index:37; ImportSpecifier + (position, buffer, readString): estree.ImportSpecifier & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const importedPosition = buffer[position++]; + const local = convertNode(buffer[position], buffer, readString); + const imported = importedPosition ? convertNode(importedPosition, buffer, readString) : local; + return { + type: 'ImportSpecifier', + start, + end, + imported, + local + }; + }, + // index:38; LabeledStatement + (position, buffer, readString): estree.LabeledStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const body = convertNode(buffer[position++], buffer, readString); + const label = convertNode(position, buffer, readString); + return { + type: 'LabeledStatement', + start, + end, + body, + label + }; + }, + // index:39; Literal + (position, buffer, readString): estree.SimpleLiteral & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const rawPosition = buffer[position++]; + const raw = rawPosition ? convertString(rawPosition, buffer, readString) : undefined; + const value = convertString(position, buffer, readString); + return { + type: 'Literal', + start, + end, + raw, + value + }; + }, + // index:40; Literal + (position, buffer): estree.SimpleLiteral & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const value = !!buffer[position++]; + return { + type: 'Literal', + start, + end, + raw: value ? 'true' : 'false', + value + }; + }, + // index:41; Literal + (position, buffer, readString): estree.SimpleLiteral & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const rawPosition = buffer[position++]; + const raw = rawPosition ? convertString(rawPosition, buffer, readString) : undefined; + const value = new DataView(buffer.buffer).getFloat64(position << 2, true); + return { + type: 'Literal', + start, + end, + raw, + value + }; + }, + // index:42; Literal + (position, buffer): estree.SimpleLiteral & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + return { + type: 'Literal', + start, + end, + raw: 'null', + value: null + }; + }, + // index:43; Literal + (position, buffer, readString): estree.RegExpLiteral & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const pattern = convertString(buffer[position++], buffer, readString); + const flags = convertString(position, buffer, readString); + return { + type: 'Literal', + start, + end, + raw: `/${pattern}/${flags}`, + regex: { + flags, + pattern + }, + value: new RegExp(pattern, flags) + }; + }, + // index:44; Literal + (position, buffer, readString): estree.BigIntLiteral & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const bigint = convertString(buffer[position++], buffer, readString); + const raw = convertString(position, buffer, readString); + return { + type: 'Literal', + start, + end, + bigint, + raw, + value: BigInt(bigint) + }; + }, + // index:45; LogicalExpression + (position, buffer, readString): estree.LogicalExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const operator = FIXED_STRINGS[buffer[position++]] as estree.LogicalOperator; + const right = convertNode(buffer[position++], buffer, readString); + const left = convertNode(position, buffer, readString); + return { + type: 'LogicalExpression', + start, + end, + left, + operator, + right + }; + }, + // index:46; MemberExpression + (position, buffer, readString): estree.MemberExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const optional = !!buffer[position++]; + const computed = !!buffer[position++]; + const property = convertNode(buffer[position++], buffer, readString); + const object = convertNode(position, buffer, readString); + return { + type: 'MemberExpression', + start, + end, + computed, + object, + optional, + property + }; + }, + // index:47; MetaProperty + (position, buffer, readString): estree.MetaProperty & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const property = convertNode(buffer[position++], buffer, readString); + const meta = convertNode(position, buffer, readString); + return { + type: 'MetaProperty', + start, + end, + meta, + property + }; + }, + // index:48; MethodDefinition + (position, buffer, readString): estree.MethodDefinition & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const kind = FIXED_STRINGS[buffer[position++]] as estree.MethodDefinition['kind']; + const computed = !!buffer[position++]; + const isStatic = !!buffer[position++]; + const value = convertNode(buffer[position++], buffer, readString); + const key = convertNode(position, buffer, readString); + return { + type: 'MethodDefinition', + start, + end, + computed, + key, + kind, + static: isStatic, + value + }; + }, + // index:49; NewExpression + (position, buffer, readString): NewExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const callee = convertNode(buffer[position++], buffer, readString); + const argumentsPosition = buffer[position++]; + const annotations = convertAnnotationList(position, buffer); + return { + type: 'NewExpression', + start, + end, + arguments: argumentsPosition ? convertNodeList(argumentsPosition, buffer, readString) : [], + callee, + ...(annotations.length > 0 ? { _rollupAnnotations: annotations } : {}) + }; + }, + // index:50; ObjectExpression + (position, buffer, readString): estree.ObjectExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const properties = convertNodeList(position, buffer, readString); + return { + type: 'ObjectExpression', + start, + end, + properties + }; + }, + // index:51; ObjectPattern + (position, buffer, readString): estree.ObjectPattern & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const properties = convertNodeList(position, buffer, readString); + return { + type: 'ObjectPattern', + start, + end, + properties + }; + }, + // index:52; PrivateIdentifier + (position, buffer, readString): estree.PrivateIdentifier & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const name = convertString(position, buffer, readString); + return { + type: 'PrivateIdentifier', + start, + end, + name + }; + }, + // index:53; Program + (position, buffer, readString): Program & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const annotations = convertAnnotationList(buffer[position++], buffer); + const body = convertNodeList(position, buffer, readString); + return { + type: 'Program', + start, + end, + body, + sourceType: 'module', + ...(annotations.length > 0 ? { _rollupRemoved: annotations } : {}) + }; + }, + // index:54; Property + (position, buffer, readString): estree.Property & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const kind = FIXED_STRINGS[buffer[position++]] as estree.Property['kind']; + const method = !!buffer[position++]; + const computed = !!buffer[position++]; + const shorthand = !!buffer[position++]; + const key = convertNode(buffer[position++], buffer, readString); + const valuePosition = buffer[position]; + return { + type: 'Property', + start, + end, + computed, + key, + kind, + method, + shorthand, + value: valuePosition ? convertNode(valuePosition, buffer, readString) : key + }; + }, + // index:55; PropertyDefinition + (position, buffer, readString): estree.PropertyDefinition & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const computed = !!buffer[position++]; + const isStatic = !!buffer[position++]; + const valuePosition = buffer[position++]; + const key = convertNode(position, buffer, readString); + return { + type: 'PropertyDefinition', + start, + end, + computed, + key, + static: isStatic, + value: valuePosition ? convertNode(valuePosition, buffer, readString) : null + }; + }, + // index:56; RestElement + (position, buffer, readString): estree.RestElement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const argument = convertNode(position, buffer, readString); + return { + type: 'RestElement', + start, + end, + argument + }; + }, + // index:57; ReturnStatement + (position, buffer, readString): estree.ReturnStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const argumentPosition = buffer[position]; + return { + type: 'ReturnStatement', + start, + end, + argument: argumentPosition ? convertNode(argumentPosition, buffer, readString) : null + }; + }, + // index:58; SequenceExpression + (position, buffer, readString): estree.SequenceExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const expressions = convertNodeList(position, buffer, readString); + return { + type: 'SequenceExpression', + start, + end, + expressions + }; + }, + // index:59; SpreadElement + (position, buffer, readString): estree.SpreadElement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const argument = convertNode(position, buffer, readString); + return { + type: 'SpreadElement', + start, + end, + argument + }; + }, + // index:60; StaticBlock + (position, buffer, readString): estree.StaticBlock & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const body = convertNodeList(position, buffer, readString); + return { + type: 'StaticBlock', + start, + end, + body + }; + }, + // index:61; Super + (position, buffer): estree.Super & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + return { + type: 'Super', + start, + end + }; + }, + // index:62; SwitchCase + (position, buffer, readString): estree.SwitchCase & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const testPosition = buffer[position++]; + const consequent = convertNodeList(buffer[position], buffer, readString); + return { + type: 'SwitchCase', + start, + end, + consequent, + test: testPosition ? convertNode(testPosition, buffer, readString) : null + }; + }, + // index:63; SwitchStatement + (position, buffer, readString): estree.SwitchStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const cases = convertNodeList(buffer[position++], buffer, readString); + const discriminant = convertNode(position, buffer, readString); + return { + type: 'SwitchStatement', + start, + end, + cases, + discriminant + }; + }, + // index:64; TaggedTemplateExpression + (position, buffer, readString): estree.TaggedTemplateExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const quasi = convertNode(buffer[position++], buffer, readString); + const tag = convertNode(position, buffer, readString); + return { + type: 'TaggedTemplateExpression', + start, + end, + quasi, + tag + }; + }, + // index:65; TemplateElement + (position, buffer, readString): estree.TemplateElement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const tail = !!buffer[position++]; + const cookedPosition = buffer[position++]; + const raw = convertString(position, buffer, readString); + return { + type: 'TemplateElement', + start, + end, + tail, + value: { + cooked: cookedPosition ? convertString(cookedPosition, buffer, readString) : null, + raw + } + }; + }, + // index:66; TemplateLiteral + (position, buffer, readString): estree.TemplateLiteral & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const expressions = convertNodeList(buffer[position++], buffer, readString); + const quasis = convertNodeList(position, buffer, readString); + return { + type: 'TemplateLiteral', + start, + end, + expressions, + quasis + }; + }, + // index:67; ThisExpression + (position, buffer): estree.ThisExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + return { + type: 'ThisExpression', + start, + end + }; + }, + // index:68; ThrowStatement + (position, buffer, readString): estree.ThrowStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const argument = convertNode(position, buffer, readString); + return { + type: 'ThrowStatement', + start, + end, + argument + }; + }, + // index:69; TryStatement + (position, buffer, readString): estree.TryStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const handlerPosition = buffer[position++]; + const finalizerPosition = buffer[position++]; + const block = convertNode(position, buffer, readString); + return { + type: 'TryStatement', + start, + end, + block, + finalizer: finalizerPosition ? convertNode(finalizerPosition, buffer, readString) : null, + handler: handlerPosition ? convertNode(handlerPosition, buffer, readString) : null + }; + }, + // index:70; UnaryExpression + (position, buffer, readString): estree.UnaryExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const operator = FIXED_STRINGS[buffer[position++]] as estree.UnaryOperator; + const argument = convertNode(position, buffer, readString); + return { + type: 'UnaryExpression', + start, + end, + argument, + operator, + prefix: true + }; + }, + // index:71; UpdateExpression + (position, buffer, readString): estree.UpdateExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const prefix = !!buffer[position++]; + const operator = FIXED_STRINGS[buffer[position++]] as estree.UpdateOperator; + const argument = convertNode(position, buffer, readString); + return { + type: 'UpdateExpression', + start, + end, + argument, + operator, + prefix + }; + }, + // index:72; VariableDeclaration + (position, buffer, readString): estree.VariableDeclaration & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const kind = FIXED_STRINGS[buffer[position++]] as estree.VariableDeclaration['kind']; + const declarations = convertNodeList(position, buffer, readString); + return { + type: 'VariableDeclaration', + start, + end, + declarations, + kind + }; + }, + // index:73; VariableDeclarator + (position, buffer, readString): estree.VariableDeclarator & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const init_position = buffer[position++]; + const id = convertNode(position, buffer, readString); + return { + type: 'VariableDeclarator', + start, + end, + id, + init: init_position ? convertNode(init_position, buffer, readString) : null + }; + }, + // index:74; WhileStatement + (position, buffer, readString): estree.WhileStatement & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const body = convertNode(buffer[position++], buffer, readString); + const test = convertNode(position, buffer, readString); + return { + type: 'WhileStatement', + start, + end, + body, + test + }; + }, + // index:75; YieldExpression + (position, buffer, readString): estree.YieldExpression & AstNode => { + const start = buffer[position++]; + const end = buffer[position++]; + const delegate = !!buffer[position++]; + const argumentPosition = buffer[position]; + return { + type: 'YieldExpression', + start, + end, + argument: argumentPosition ? convertNode(argumentPosition, buffer, readString) : null, + delegate + }; + }, + // index:76; Syntax Error + (position, buffer, readString): never => { + const pos = buffer[position++]; + const message = convertString(position, buffer, readString); + error({ + pos, + message + }); + } +]; + +const convertNodeList = (position: number, buffer: Uint32Array, readString: ReadString): any[] => { + const length = buffer[position++]; + const list: any[] = []; + for (let index = 0; index < length; index++) { + const nodePosition = buffer[position++]; + list.push(nodePosition ? convertNode(nodePosition, buffer, readString) : null); + } + return list; +}; + +const convertAnnotationList = (position: number, buffer: Uint32Array): RollupAnnotation[] => { + const length = buffer[position++]; + const list: any[] = []; + for (let index = 0; index < length; index++) { + list.push(convertAnnotation(buffer[position++], buffer)); + } + return list; +}; + +const convertAnnotation = (position: number, buffer: Uint32Array): RollupAnnotation => { + const start = buffer[position++]; + const end = buffer[position++]; + const type = FIXED_STRINGS[buffer[position]] as AnnotationType; + return { end, start, type }; +}; + +const convertString = (position: number, buffer: Uint32Array, readString: ReadString): string => { + const length = buffer[position++]; + const bytePosition = position << 2; + return readString(bytePosition, length); +}; + +interface ImportAttribute { + key: estree.Identifier | estree.Literal; + type: 'ImportAttribute'; + value: estree.Literal; +} + +interface ImportDeclaration extends estree.ImportDeclaration { + attributes: ImportAttribute[]; +} + +interface ExportNamedDeclaration extends estree.ExportNamedDeclaration { + attributes: ImportAttribute[]; +} + +interface ExportAllDeclaration extends estree.ExportAllDeclaration { + attributes: ImportAttribute[]; +} + +interface ImportExpression extends estree.ImportExpression { + options: estree.Expression | null; +} + +export const ANNOTATION_KEY = '_rollupAnnotations'; +export const INVALID_ANNOTATION_KEY = '_rollupRemoved'; + +type AnnotationType = 'pure' | 'noSideEffects'; + +export interface RollupAnnotation { + start: number; + end: number; + type: AnnotationType; +} + +interface CallExpression extends estree.SimpleCallExpression { + [ANNOTATION_KEY]?: RollupAnnotation[]; +} + +interface NewExpression extends estree.NewExpression { + [ANNOTATION_KEY]?: RollupAnnotation[]; +} + +interface FunctionExpression extends estree.FunctionExpression { + [ANNOTATION_KEY]?: RollupAnnotation[]; +} + +interface FunctionDeclaration extends estree.FunctionDeclaration { + [ANNOTATION_KEY]?: RollupAnnotation[]; +} + +interface ArrowFunctionExpression extends estree.ArrowFunctionExpression { + [ANNOTATION_KEY]?: RollupAnnotation[]; +} + +interface Program extends estree.Program { + [INVALID_ANNOTATION_KEY]?: RollupAnnotation[]; +} diff --git a/src/utils/getReadStringFunction.ts b/src/utils/getReadStringFunction.ts new file mode 100644 index 000000000..ee63518cb --- /dev/null +++ b/src/utils/getReadStringFunction.ts @@ -0,0 +1,14 @@ +export default function getReadStringFunction( + astBuffer: Buffer | Uint8Array +): (start: number, length: number) => string { + if (typeof Buffer !== 'undefined' && astBuffer instanceof Buffer) { + return function readString(start, length) { + return astBuffer.toString('utf8', start, start + length); + }; + } else { + const textDecoder = new TextDecoder(); + return function readString(start, length) { + return textDecoder.decode(astBuffer.subarray(start, start + length)); + }; + } +} diff --git a/src/utils/initWasm.ts b/src/utils/initWasm.ts new file mode 100644 index 000000000..9cd42c723 --- /dev/null +++ b/src/utils/initWasm.ts @@ -0,0 +1 @@ +export default async function initWasm() {} diff --git a/src/utils/logs.ts b/src/utils/logs.ts index 0d874b886..57922cf54 100644 --- a/src/utils/logs.ts +++ b/src/utils/logs.ts @@ -48,7 +48,11 @@ export function augmentCodeLocation( properties.loc = { column, file: id, line }; } else { properties.pos = pos; - const { line, column } = locate(source, pos, { offsetLine: 1 })!; + const location = locate(source, pos, { offsetLine: 1 }); + if (!location) { + return; + } + const { line, column } = location; properties.loc = { column, file: id, line }; } @@ -92,12 +96,13 @@ const ADDON_ERROR = 'ADDON_ERROR', FIRST_SIDE_EFFECT = 'FIRST_SIDE_EFFECT', ILLEGAL_IDENTIFIER_AS_NAME = 'ILLEGAL_IDENTIFIER_AS_NAME', ILLEGAL_REASSIGNMENT = 'ILLEGAL_REASSIGNMENT', - INCONSISTENT_IMPORT_ASSERTIONS = 'INCONSISTENT_IMPORT_ASSERTIONS', + INCONSISTENT_IMPORT_ATTRIBUTES = 'INCONSISTENT_IMPORT_ATTRIBUTES', INPUT_HOOK_IN_OUTPUT_PLUGIN = 'INPUT_HOOK_IN_OUTPUT_PLUGIN', INVALID_CHUNK = 'INVALID_CHUNK', INVALID_CONFIG_MODULE_FORMAT = 'INVALID_CONFIG_MODULE_FORMAT', INVALID_EXPORT_OPTION = 'INVALID_EXPORT_OPTION', INVALID_EXTERNAL_ID = 'INVALID_EXTERNAL_ID', + INVALID_IMPORT_ATTRIBUTE = 'INVALID_IMPORT_ATTRIBUTE', INVALID_LOG_POSITION = 'INVALID_LOG_POSITION', INVALID_OPTION = 'INVALID_OPTION', INVALID_PLUGIN_HOOK = 'INVALID_PLUGIN_HOOK', @@ -235,13 +240,13 @@ export function logChunkNotGeneratedForFileName(name: string): RollupLog { export function logChunkInvalid( { fileName, code }: { code: string; fileName: string }, - exception: { loc: { column: number; line: number }; message: string } + { pos, message }: { pos: number; message: string } ): RollupLog { const errorProperties = { code: CHUNK_INVALID, - message: `Chunk "${fileName}" is not valid JavaScript: ${exception.message}.` + message: `Chunk "${fileName}" is not valid JavaScript: ${message}.` }; - augmentCodeLocation(errorProperties, exception.loc, code, fileName); + augmentCodeLocation(errorProperties, pos, code, fileName); return errorProperties; } @@ -394,26 +399,26 @@ export function logIllegalImportReassignment(name: string, importingId: string): }; } -export function logInconsistentImportAssertions( - existingAssertions: Record, - newAssertions: Record, +export function logInconsistentImportAttributes( + existingAttributes: Record, + newAttributes: Record, source: string, importer: string ): RollupLog { return { - code: INCONSISTENT_IMPORT_ASSERTIONS, + code: INCONSISTENT_IMPORT_ATTRIBUTES, message: `Module "${relativeId(importer)}" tried to import "${relativeId( source - )}" with ${formatAssertions( - newAssertions - )} assertions, but it was already imported elsewhere with ${formatAssertions( - existingAssertions - )} assertions. Please ensure that import assertions for the same module are always consistent.` + )}" with ${formatAttributes( + newAttributes + )} attributes, but it was already imported elsewhere with ${formatAttributes( + existingAttributes + )} attributes. Please ensure that import attributes for the same module are always consistent.` }; } -const formatAssertions = (assertions: Record): string => { - const entries = Object.entries(assertions); +const formatAttributes = (attributes: Record): string => { + const entries = Object.entries(attributes); if (entries.length === 0) return 'no'; return entries.map(([key, value]) => `"${key}": "${value}"`).join(', '); }; @@ -499,6 +504,24 @@ export function logInternalIdCannotBeExternal(source: string, importer: string): }; } +export function logImportOptionsAreInvalid(importer: string): RollupLog { + return { + code: INVALID_IMPORT_ATTRIBUTE, + message: `Rollup could not statically analyze the options argument of a dynamic import in "${relativeId( + importer + )}". Dynamic import options need to be an object with a nested attributes object.` + }; +} + +export function logImportAttributeIsInvalid(importer: string): RollupLog { + return { + code: INVALID_IMPORT_ATTRIBUTE, + message: `Rollup could not statically analyze an import attribute of a dynamic import in "${relativeId( + importer + )}". Import attributes need to have string keys and values. The attribute will be removed.` + }; +} + export function logInvalidLogPosition(plugin: string): RollupLog { return { code: INVALID_LOG_POSITION, diff --git a/src/utils/options/mergeOptions.ts b/src/utils/options/mergeOptions.ts index 4d7217a2a..9080ddb26 100644 --- a/src/utils/options/mergeOptions.ts +++ b/src/utils/options/mergeOptions.ts @@ -127,11 +127,6 @@ function mergeInputOptions( ): InputOptions { const getOption = (name: keyof InputOptions): any => overrides[name] ?? config[name]; const inputOptions: CompleteInputOptions = { - acorn: getOption('acorn'), - acornInjectPlugins: config.acornInjectPlugins as - | (() => unknown)[] - | (() => unknown) - | undefined, cache: config.cache as false | RollupCache | undefined, context: getOption('context'), experimentalCacheExpiry: getOption('experimentalCacheExpiry'), @@ -244,6 +239,7 @@ async function mergeOutputOptions( exports: getOption('exports'), extend: getOption('extend'), externalImportAssertions: getOption('externalImportAssertions'), + externalImportAttributes: getOption('externalImportAttributes'), externalLiveBindings: getOption('externalLiveBindings'), file: getOption('file'), footer: getOption('footer'), diff --git a/src/utils/options/normalizeInputOptions.ts b/src/utils/options/normalizeInputOptions.ts index 6083bcec7..ed938e5ee 100644 --- a/src/utils/options/normalizeInputOptions.ts +++ b/src/utils/options/normalizeInputOptions.ts @@ -1,5 +1,3 @@ -import type * as acorn from 'acorn'; -import { importAssertions } from 'acorn-import-assertions'; import type { HasModuleSideEffects, InputOptions, @@ -54,8 +52,6 @@ export async function normalizeInputOptions( const strictDeprecations = config.strictDeprecations || false; const maxParallelFileOps = getMaxParallelFileOps(config, onLog, strictDeprecations); const options: NormalizedInputOptions & InputOptions = { - acorn: getAcorn(config) as unknown as NormalizedInputOptions['acorn'], - acornInjectPlugins: getAcornInjectPlugins(config), cache: getCache(config), context, experimentalCacheExpiry: config.experimentalCacheExpiry ?? 10, @@ -91,19 +87,6 @@ export async function normalizeInputOptions( return { options, unsetOptions }; } -const getAcorn = (config: InputOptions): acorn.Options => ({ - ecmaVersion: 'latest', - sourceType: 'module', - ...config.acorn -}); - -const getAcornInjectPlugins = ( - config: InputOptions -): NormalizedInputOptions['acornInjectPlugins'] => [ - importAssertions, - ...ensureArray(config.acornInjectPlugins) -]; - const getCache = (config: InputOptions): NormalizedInputOptions['cache'] => config.cache === true // `true` is the default ? undefined diff --git a/src/utils/options/normalizeOutputOptions.ts b/src/utils/options/normalizeOutputOptions.ts index 5827e4115..231f50986 100644 --- a/src/utils/options/normalizeOutputOptions.ts +++ b/src/utils/options/normalizeOutputOptions.ts @@ -17,6 +17,7 @@ import { URL_OUTPUT_DIR, URL_OUTPUT_DYNAMICIMPORTFUNCTION, URL_OUTPUT_EXPERIMENTALDEEPCHUNKOPTIMIZATION, + URL_OUTPUT_EXTERNALIMPORTATTRIBUTES, URL_OUTPUT_FORMAT, URL_OUTPUT_GENERATEDCODE, URL_OUTPUT_GENERATEDCODE_CONSTBINDINGS, @@ -51,6 +52,7 @@ export async function normalizeOutputOptions( const file = getFile(config, preserveModules, inputOptions); const preferConst = getPreferConst(config, inputOptions); const generatedCode = getGeneratedCode(config, preferConst); + const externalImportAttributes = getExternalImportAttributes(config, inputOptions); const outputOptions: NormalizedOutputOptions & OutputOptions = { amd: getAmd(config), @@ -70,7 +72,8 @@ export async function normalizeOutputOptions( experimentalMinChunkSize: config.experimentalMinChunkSize ?? 1, exports: getExports(config, unsetOptions), extend: config.extend || false, - externalImportAssertions: config.externalImportAssertions ?? true, + externalImportAssertions: externalImportAttributes, + externalImportAttributes, externalLiveBindings: config.externalLiveBindings ?? true, file, footer: getAddon(config, 'footer'), @@ -406,6 +409,21 @@ function getExports( return configExports || 'auto'; } +const getExternalImportAttributes = ( + config: OutputOptions, + inputOptions: NormalizedInputOptions +): NormalizedOutputOptions['externalImportAttributes'] => { + if (config.externalImportAssertions != undefined) { + warnDeprecation( + `The "output.externalImportAssertions" option is deprecated. Use the "output.externalImportAttributes" option instead.`, + URL_OUTPUT_EXTERNALIMPORTATTRIBUTES, + true, + inputOptions + ); + } + return config.externalImportAttributes ?? config.externalImportAssertions ?? true; +}; + const getGeneratedCode = ( config: OutputOptions, preferConst: boolean diff --git a/src/utils/parseAssertions.ts b/src/utils/parseImportAttributes.ts similarity index 51% rename from src/utils/parseAssertions.ts rename to src/utils/parseImportAttributes.ts index 3fbf385fa..f2c094062 100644 --- a/src/utils/parseAssertions.ts +++ b/src/utils/parseImportAttributes.ts @@ -1,20 +1,34 @@ import type Identifier from '../ast/nodes/Identifier'; import type ImportAttribute from '../ast/nodes/ImportAttribute'; import type ImportExpression from '../ast/nodes/ImportExpression'; -import type { LiteralValue } from '../ast/nodes/Literal'; -import type Literal from '../ast/nodes/Literal'; -import type ObjectExpression from '../ast/nodes/ObjectExpression'; +import type { default as Literal, LiteralValue } from '../ast/nodes/Literal'; +import ObjectExpression from '../ast/nodes/ObjectExpression'; import type Property from '../ast/nodes/Property'; import type SpreadElement from '../ast/nodes/SpreadElement'; import { EMPTY_OBJECT } from './blank'; +import { LOGLEVEL_WARN } from './logging'; +import { logImportAttributeIsInvalid, logImportOptionsAreInvalid } from './logs'; -export function getAssertionsFromImportExpression(node: ImportExpression): Record { - const assertProperty = node.arguments?.[0]?.properties.find( - (property): property is Property => getPropertyKey(property) === 'assert' +const ATTRIBUTE_KEYWORDS = new Set(['assert', 'with']); + +export function getAttributesFromImportExpression(node: ImportExpression): Record { + const { context, options, start } = node; + if (!(options instanceof ObjectExpression)) { + if (options) { + context.module.log(LOGLEVEL_WARN, logImportAttributeIsInvalid(context.module.id), start); + } + return EMPTY_OBJECT; + } + const assertProperty = options.properties.find((property): property is Property => + ATTRIBUTE_KEYWORDS.has(getPropertyKey(property) as string) )?.value; if (!assertProperty) { return EMPTY_OBJECT; } + if (!(assertProperty instanceof ObjectExpression)) { + context.module.log(LOGLEVEL_WARN, logImportOptionsAreInvalid(context.module.id), start); + return EMPTY_OBJECT; + } const assertFields = (assertProperty as ObjectExpression).properties .map(property => { const key = getPropertyKey(property); @@ -24,6 +38,11 @@ export function getAssertionsFromImportExpression(node: ImportExpression): Recor ) { return [key, ((property as Property).value as Literal).value] as [string, string]; } + context.module.log( + LOGLEVEL_WARN, + logImportAttributeIsInvalid(context.module.id), + property.start + ); return null; }) .filter((property): property is [string, string] => !!property); @@ -37,20 +56,20 @@ const getPropertyKey = ( property: Property | SpreadElement | ImportAttribute ): LiteralValue | undefined => { const key = (property as Property | ImportAttribute).key; - return key && ((key as Identifier).name || (key as Literal).value); + return ( + key && !(property as Property).computed && ((key as Identifier).name || (key as Literal).value) + ); }; -export function getAssertionsFromImportExportDeclaration( - assertions: ImportAttribute[] | undefined -) { - return assertions?.length +export function getAttributesFromImportExportDeclaration(attributes: ImportAttribute[]) { + return attributes?.length ? Object.fromEntries( - assertions.map(assertion => [getPropertyKey(assertion), assertion.value.value]) + attributes.map(assertion => [getPropertyKey(assertion), assertion.value.value]) ) : EMPTY_OBJECT; } -export function doAssertionsDiffer( +export function doAttributesDiffer( assertionA: Record, assertionB: Record ): boolean { diff --git a/src/utils/resolveId.ts b/src/utils/resolveId.ts index eddacaff4..812f2e901 100644 --- a/src/utils/resolveId.ts +++ b/src/utils/resolveId.ts @@ -14,7 +14,7 @@ export async function resolveId( skip: readonly { importer: string | undefined; plugin: Plugin; source: string }[] | null, customOptions: CustomPluginOptions | undefined, isEntry: boolean, - assertions: Record + attributes: Record ): Promise { const pluginResult = await resolveIdViaPlugins( source, @@ -24,7 +24,7 @@ export async function resolveId( skip, customOptions, isEntry, - assertions + attributes ); if (pluginResult != null) { diff --git a/src/utils/resolveIdViaPlugins.ts b/src/utils/resolveIdViaPlugins.ts index 6934dcc23..afe96a821 100644 --- a/src/utils/resolveIdViaPlugins.ts +++ b/src/utils/resolveIdViaPlugins.ts @@ -11,7 +11,7 @@ export function resolveIdViaPlugins( skip: readonly { importer: string | undefined; plugin: Plugin; source: string }[] | null, customOptions: CustomPluginOptions | undefined, isEntry: boolean, - assertions: Record + attributes: Record ): Promise<[NonNullable, Plugin] | null> { let skipped: Set | null = null; let replaceContext: ReplaceContext | null = null; @@ -24,20 +24,20 @@ export function resolveIdViaPlugins( } replaceContext = (pluginContext, plugin): PluginContext => ({ ...pluginContext, - resolve: (source, importer, { assertions, custom, isEntry, skipSelf } = BLANK) => + resolve: (source, importer, { attributes, custom, isEntry, skipSelf } = BLANK) => moduleLoaderResolveId( source, importer, custom, isEntry, - assertions || EMPTY_OBJECT, + attributes || EMPTY_OBJECT, skipSelf ? [...skip, { importer, plugin, source }] : skip ) }); } return pluginDriver.hookFirstAndGetPlugin( 'resolveId', - [source, importer, { assertions, custom: customOptions, isEntry }], + [source, importer, { attributes, custom: customOptions, isEntry }], replaceContext, skipped ); diff --git a/src/utils/treeshakeNode.ts b/src/utils/treeshakeNode.ts index 47375d870..4bc767a64 100644 --- a/src/utils/treeshakeNode.ts +++ b/src/utils/treeshakeNode.ts @@ -1,27 +1,7 @@ import type MagicString from 'magic-string'; -import * as NodeType from '../ast/nodes/NodeType'; import type { Node } from '../ast/nodes/shared/Node'; export function treeshakeNode(node: Node, code: MagicString, start: number, end: number): void { code.remove(start, end); - if (node.annotations) { - for (const annotation of node.annotations) { - if (annotation.start < start) { - code.remove(annotation.start, annotation.end); - } else { - return; - } - } - } -} - -export function removeAnnotations(node: Node, code: MagicString): void { - if (!node.annotations && node.parent.type === NodeType.ExpressionStatement) { - node = node.parent as Node; - } - if (node.annotations) { - for (const annotation of node.annotations) { - code.remove(annotation.start, annotation.end); - } - } + node.removeAnnotations(code); } diff --git a/src/utils/urls.ts b/src/utils/urls.ts index 9701bae0d..fbfffa918 100644 --- a/src/utils/urls.ts +++ b/src/utils/urls.ts @@ -16,6 +16,8 @@ export const URL_OUTPUT_DYNAMICIMPORTFUNCTION = 'configuration-options/#output-dynamicimportfunction'; export const URL_OUTPUT_EXPORTS = 'configuration-options/#output-exports'; export const URL_OUTPUT_EXTEND = 'configuration-options/#output-extend'; +export const URL_OUTPUT_EXTERNALIMPORTATTRIBUTES = + 'configuration-options/#output-externalimportattributes'; export const URL_OUTPUT_FORMAT = 'configuration-options/#output-format'; export const URL_OUTPUT_GENERATEDCODE = 'configuration-options/#output-generatedcode'; export const URL_OUTPUT_EXPERIMENTALDEEPCHUNKOPTIMIZATION = diff --git a/test/browser/index.js b/test/browser/index.js index 2167a4210..dd06cc691 100644 --- a/test/browser/index.js +++ b/test/browser/index.js @@ -1,10 +1,13 @@ // since we don't run the browser tests in an actual browser, we need to make `performance` // globally accessible same as in the browser. this can be removed once `performance` is // available globally in all supported platforms. [currently global for node.js v16+]. -// @ts-expect-error ignore +const { readFile } = require('node:fs/promises'); +const { basename, resolve } = require('node:path'); + global.performance = require('node:perf_hooks').performance; -const { basename, resolve } = require('node:path'); +global.fetch = url => readFile(url.href.replace('file://', '')); + const fixturify = require('fixturify'); /** @@ -69,7 +72,7 @@ runTestSuiteWithSamples( } assertOutputMatches(output, directory); } - ); + ).timeout(30_000); } ); diff --git a/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-emitted-entry/_config.js b/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-emitted-entry/_config.js index 23c912f99..c6e1913fd 100644 --- a/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-emitted-entry/_config.js +++ b/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-emitted-entry/_config.js @@ -26,7 +26,7 @@ module.exports = defineTest({ buildEnd() { assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(ID_MAIN))), { id: ID_MAIN, - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -36,6 +36,7 @@ module.exports = defineTest({ type: 'ImportDeclaration', start: 0, end: 30, + source: { type: 'Literal', start: 22, end: 29, raw: "'./lib'", value: './lib' }, specifiers: [ { type: 'ImportSpecifier', @@ -45,7 +46,7 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 9, end: 14, name: 'value' } } ], - source: { type: 'Literal', start: 22, end: 29, value: './lib', raw: "'./lib'" } + attributes: [] }, { type: 'ExpressionStatement', @@ -55,16 +56,16 @@ module.exports = defineTest({ type: 'CallExpression', start: 31, end: 49, + arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], callee: { type: 'MemberExpression', start: 31, end: 42, - object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, - property: { type: 'Identifier', start: 39, end: 42, name: 'log' }, computed: false, - optional: false + object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, + optional: false, + property: { type: 'Identifier', start: 39, end: 42, name: 'log' } }, - arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], optional: false } } @@ -85,7 +86,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: ID_LIB, meta: {}, @@ -104,7 +105,7 @@ module.exports = defineTest({ }); assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(ID_DEP))), { id: ID_DEP, - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -114,6 +115,7 @@ module.exports = defineTest({ type: 'ImportDeclaration', start: 0, end: 30, + source: { type: 'Literal', start: 22, end: 29, raw: "'./lib'", value: './lib' }, specifiers: [ { type: 'ImportSpecifier', @@ -123,7 +125,7 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 9, end: 14, name: 'value' } } ], - source: { type: 'Literal', start: 22, end: 29, value: './lib', raw: "'./lib'" } + attributes: [] }, { type: 'ExpressionStatement', @@ -133,16 +135,16 @@ module.exports = defineTest({ type: 'CallExpression', start: 31, end: 49, + arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], callee: { type: 'MemberExpression', start: 31, end: 42, - object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, - property: { type: 'Identifier', start: 39, end: 42, name: 'log' }, computed: false, - optional: false + object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, + optional: false, + property: { type: 'Identifier', start: 39, end: 42, name: 'log' } }, - arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], optional: false } } @@ -163,7 +165,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: ID_LIB, meta: {}, diff --git a/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-entry/_config.js b/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-entry/_config.js index 012b74b0d..972f1c1d5 100644 --- a/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-entry/_config.js +++ b/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-entry/_config.js @@ -22,7 +22,7 @@ module.exports = defineTest({ buildEnd() { assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(ID_MAIN))), { id: ID_MAIN, - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -32,6 +32,7 @@ module.exports = defineTest({ type: 'ImportDeclaration', start: 0, end: 30, + source: { type: 'Literal', start: 22, end: 29, raw: "'./lib'", value: './lib' }, specifiers: [ { type: 'ImportSpecifier', @@ -41,7 +42,7 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 9, end: 14, name: 'value' } } ], - source: { type: 'Literal', start: 22, end: 29, value: './lib', raw: "'./lib'" } + attributes: [] }, { type: 'ExpressionStatement', @@ -51,16 +52,16 @@ module.exports = defineTest({ type: 'CallExpression', start: 31, end: 49, + arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], callee: { type: 'MemberExpression', start: 31, end: 42, - object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, - property: { type: 'Identifier', start: 39, end: 42, name: 'log' }, computed: false, - optional: false + object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, + optional: false, + property: { type: 'Identifier', start: 39, end: 42, name: 'log' } }, - arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], optional: false } } @@ -81,7 +82,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: ID_LIB, meta: {}, @@ -100,7 +101,7 @@ module.exports = defineTest({ }); assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(ID_DEP))), { id: ID_DEP, - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -110,6 +111,7 @@ module.exports = defineTest({ type: 'ImportDeclaration', start: 0, end: 30, + source: { type: 'Literal', start: 22, end: 29, raw: "'./lib'", value: './lib' }, specifiers: [ { type: 'ImportSpecifier', @@ -119,7 +121,7 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 9, end: 14, name: 'value' } } ], - source: { type: 'Literal', start: 22, end: 29, value: './lib', raw: "'./lib'" } + attributes: [] }, { type: 'ExpressionStatement', @@ -129,16 +131,16 @@ module.exports = defineTest({ type: 'CallExpression', start: 31, end: 49, + arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], callee: { type: 'MemberExpression', start: 31, end: 42, - object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, - property: { type: 'Identifier', start: 39, end: 42, name: 'log' }, computed: false, - optional: false + object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, + optional: false, + property: { type: 'Identifier', start: 39, end: 42, name: 'log' } }, - arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], optional: false } } @@ -159,7 +161,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: ID_LIB, meta: {}, diff --git a/test/chunking-form/samples/implicit-dependencies/multiple-dependencies/_config.js b/test/chunking-form/samples/implicit-dependencies/multiple-dependencies/_config.js index 0596b22ac..a75754208 100644 --- a/test/chunking-form/samples/implicit-dependencies/multiple-dependencies/_config.js +++ b/test/chunking-form/samples/implicit-dependencies/multiple-dependencies/_config.js @@ -35,7 +35,7 @@ module.exports = defineTest({ buildEnd() { assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(ID_MAIN1))), { id: ID_MAIN1, - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -45,6 +45,7 @@ module.exports = defineTest({ type: 'ImportDeclaration', start: 0, end: 30, + source: { type: 'Literal', start: 21, end: 29, raw: "'./lib1'", value: './lib1' }, specifiers: [ { type: 'ImportSpecifier', @@ -54,12 +55,13 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 9, end: 13, name: 'lib1' } } ], - source: { type: 'Literal', start: 21, end: 29, value: './lib1', raw: "'./lib1'" } + attributes: [] }, { type: 'ImportDeclaration', start: 31, end: 63, + source: { type: 'Literal', start: 53, end: 62, raw: "'./lib1b'", value: './lib1b' }, specifiers: [ { type: 'ImportSpecifier', @@ -69,12 +71,13 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 40, end: 45, name: 'lib1b' } } ], - source: { type: 'Literal', start: 53, end: 62, value: './lib1b', raw: "'./lib1b'" } + attributes: [] }, { type: 'ImportDeclaration', start: 64, end: 94, + source: { type: 'Literal', start: 85, end: 93, raw: "'./lib2'", value: './lib2' }, specifiers: [ { type: 'ImportSpecifier', @@ -84,7 +87,7 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 73, end: 77, name: 'lib2' } } ], - source: { type: 'Literal', start: 85, end: 93, value: './lib2', raw: "'./lib2'" } + attributes: [] }, { type: 'ExpressionStatement', @@ -94,21 +97,21 @@ module.exports = defineTest({ type: 'CallExpression', start: 95, end: 135, + arguments: [ + { type: 'Literal', start: 107, end: 114, raw: "'main1'", value: 'main1' }, + { type: 'Identifier', start: 116, end: 120, name: 'lib1' }, + { type: 'Identifier', start: 123, end: 128, name: 'lib1b' }, + { type: 'Identifier', start: 130, end: 134, name: 'lib2' } + ], callee: { type: 'MemberExpression', start: 95, end: 106, - object: { type: 'Identifier', start: 95, end: 102, name: 'console' }, - property: { type: 'Identifier', start: 103, end: 106, name: 'log' }, computed: false, - optional: false + object: { type: 'Identifier', start: 95, end: 102, name: 'console' }, + optional: false, + property: { type: 'Identifier', start: 103, end: 106, name: 'log' } }, - arguments: [ - { type: 'Literal', start: 107, end: 114, value: 'main1', raw: "'main1'" }, - { type: 'Identifier', start: 116, end: 120, name: 'lib1' }, - { type: 'Identifier', start: 123, end: 128, name: 'lib1b' }, - { type: 'Identifier', start: 130, end: 134, name: 'lib2' } - ], optional: false } } @@ -129,7 +132,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [ID_DEP], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: ID_LIB1, meta: {}, @@ -138,7 +141,7 @@ module.exports = defineTest({ syntheticNamedExports: false }, { - assertions: {}, + attributes: {}, external: false, id: ID_LIB1B, meta: {}, @@ -147,7 +150,7 @@ module.exports = defineTest({ syntheticNamedExports: false }, { - assertions: {}, + attributes: {}, external: false, id: ID_LIB2, meta: {}, @@ -166,7 +169,7 @@ module.exports = defineTest({ }); assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(ID_MAIN2))), { id: ID_MAIN2, - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -176,6 +179,7 @@ module.exports = defineTest({ type: 'ImportDeclaration', start: 0, end: 30, + source: { type: 'Literal', start: 21, end: 29, raw: "'./lib1'", value: './lib1' }, specifiers: [ { type: 'ImportSpecifier', @@ -185,12 +189,13 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 9, end: 13, name: 'lib1' } } ], - source: { type: 'Literal', start: 21, end: 29, value: './lib1', raw: "'./lib1'" } + attributes: [] }, { type: 'ImportDeclaration', start: 31, end: 63, + source: { type: 'Literal', start: 53, end: 62, raw: "'./lib1b'", value: './lib1b' }, specifiers: [ { type: 'ImportSpecifier', @@ -200,12 +205,13 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 40, end: 45, name: 'lib1b' } } ], - source: { type: 'Literal', start: 53, end: 62, value: './lib1b', raw: "'./lib1b'" } + attributes: [] }, { type: 'ImportDeclaration', start: 64, end: 94, + source: { type: 'Literal', start: 85, end: 93, raw: "'./lib3'", value: './lib3' }, specifiers: [ { type: 'ImportSpecifier', @@ -215,7 +221,7 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 73, end: 77, name: 'lib3' } } ], - source: { type: 'Literal', start: 85, end: 93, value: './lib3', raw: "'./lib3'" } + attributes: [] }, { type: 'ExpressionStatement', @@ -225,21 +231,21 @@ module.exports = defineTest({ type: 'CallExpression', start: 95, end: 134, + arguments: [ + { type: 'Literal', start: 107, end: 114, raw: "'main2'", value: 'main2' }, + { type: 'Identifier', start: 116, end: 120, name: 'lib1' }, + { type: 'Identifier', start: 122, end: 127, name: 'lib1b' }, + { type: 'Identifier', start: 129, end: 133, name: 'lib3' } + ], callee: { type: 'MemberExpression', start: 95, end: 106, - object: { type: 'Identifier', start: 95, end: 102, name: 'console' }, - property: { type: 'Identifier', start: 103, end: 106, name: 'log' }, computed: false, - optional: false + object: { type: 'Identifier', start: 95, end: 102, name: 'console' }, + optional: false, + property: { type: 'Identifier', start: 103, end: 106, name: 'log' } }, - arguments: [ - { type: 'Literal', start: 107, end: 114, value: 'main2', raw: "'main2'" }, - { type: 'Identifier', start: 116, end: 120, name: 'lib1' }, - { type: 'Identifier', start: 122, end: 127, name: 'lib1b' }, - { type: 'Identifier', start: 129, end: 133, name: 'lib3' } - ], optional: false } } @@ -260,7 +266,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [ID_DEP], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: ID_LIB1, meta: {}, @@ -269,7 +275,7 @@ module.exports = defineTest({ syntheticNamedExports: false }, { - assertions: {}, + attributes: {}, external: false, id: ID_LIB1B, meta: {}, @@ -278,7 +284,7 @@ module.exports = defineTest({ syntheticNamedExports: false }, { - assertions: {}, + attributes: {}, external: false, id: ID_LIB3, meta: {}, @@ -297,7 +303,7 @@ module.exports = defineTest({ }); assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(ID_DEP))), { id: ID_DEP, - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -307,6 +313,7 @@ module.exports = defineTest({ type: 'ImportDeclaration', start: 0, end: 30, + source: { type: 'Literal', start: 21, end: 29, raw: "'./lib1'", value: './lib1' }, specifiers: [ { type: 'ImportSpecifier', @@ -316,12 +323,13 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 9, end: 13, name: 'lib1' } } ], - source: { type: 'Literal', start: 21, end: 29, value: './lib1', raw: "'./lib1'" } + attributes: [] }, { type: 'ImportDeclaration', start: 31, end: 61, + source: { type: 'Literal', start: 52, end: 60, raw: "'./lib2'", value: './lib2' }, specifiers: [ { type: 'ImportSpecifier', @@ -331,12 +339,13 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 40, end: 44, name: 'lib2' } } ], - source: { type: 'Literal', start: 52, end: 60, value: './lib2', raw: "'./lib2'" } + attributes: [] }, { type: 'ImportDeclaration', start: 62, end: 92, + source: { type: 'Literal', start: 83, end: 91, raw: "'./lib3'", value: './lib3' }, specifiers: [ { type: 'ImportSpecifier', @@ -346,7 +355,7 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 71, end: 75, name: 'lib3' } } ], - source: { type: 'Literal', start: 83, end: 91, value: './lib3', raw: "'./lib3'" } + attributes: [] }, { type: 'ExpressionStatement', @@ -356,20 +365,20 @@ module.exports = defineTest({ type: 'CallExpression', start: 93, end: 122, + arguments: [ + { type: 'Identifier', start: 105, end: 109, name: 'lib1' }, + { type: 'Identifier', start: 111, end: 115, name: 'lib2' }, + { type: 'Identifier', start: 117, end: 121, name: 'lib3' } + ], callee: { type: 'MemberExpression', start: 93, end: 104, - object: { type: 'Identifier', start: 93, end: 100, name: 'console' }, - property: { type: 'Identifier', start: 101, end: 104, name: 'log' }, computed: false, - optional: false + object: { type: 'Identifier', start: 93, end: 100, name: 'console' }, + optional: false, + property: { type: 'Identifier', start: 101, end: 104, name: 'log' } }, - arguments: [ - { type: 'Identifier', start: 105, end: 109, name: 'lib1' }, - { type: 'Identifier', start: 111, end: 115, name: 'lib2' }, - { type: 'Identifier', start: 117, end: 121, name: 'lib3' } - ], optional: false } } @@ -390,7 +399,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: ID_LIB1, meta: {}, @@ -399,7 +408,7 @@ module.exports = defineTest({ syntheticNamedExports: false }, { - assertions: {}, + attributes: {}, external: false, id: ID_LIB2, meta: {}, @@ -408,7 +417,7 @@ module.exports = defineTest({ syntheticNamedExports: false }, { - assertions: {}, + attributes: {}, external: false, id: ID_LIB3, meta: {}, diff --git a/test/chunking-form/samples/implicit-dependencies/single-dependency/_config.js b/test/chunking-form/samples/implicit-dependencies/single-dependency/_config.js index ef874d950..7a16431e4 100644 --- a/test/chunking-form/samples/implicit-dependencies/single-dependency/_config.js +++ b/test/chunking-form/samples/implicit-dependencies/single-dependency/_config.js @@ -21,7 +21,7 @@ module.exports = defineTest({ buildEnd() { assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(ID_MAIN))), { id: ID_MAIN, - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -31,6 +31,7 @@ module.exports = defineTest({ type: 'ImportDeclaration', start: 0, end: 30, + source: { type: 'Literal', start: 22, end: 29, raw: "'./lib'", value: './lib' }, specifiers: [ { type: 'ImportSpecifier', @@ -40,7 +41,7 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 9, end: 14, name: 'value' } } ], - source: { type: 'Literal', start: 22, end: 29, value: './lib', raw: "'./lib'" } + attributes: [] }, { type: 'ExpressionStatement', @@ -50,16 +51,16 @@ module.exports = defineTest({ type: 'CallExpression', start: 31, end: 49, + arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], callee: { type: 'MemberExpression', start: 31, end: 42, - object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, - property: { type: 'Identifier', start: 39, end: 42, name: 'log' }, computed: false, - optional: false + object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, + optional: false, + property: { type: 'Identifier', start: 39, end: 42, name: 'log' } }, - arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], optional: false } } @@ -80,7 +81,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [ID_DEP], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: ID_LIB, meta: {}, @@ -99,7 +100,7 @@ module.exports = defineTest({ }); assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(ID_DEP))), { id: ID_DEP, - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -109,6 +110,7 @@ module.exports = defineTest({ type: 'ImportDeclaration', start: 0, end: 30, + source: { type: 'Literal', start: 22, end: 29, raw: "'./lib'", value: './lib' }, specifiers: [ { type: 'ImportSpecifier', @@ -118,7 +120,7 @@ module.exports = defineTest({ local: { type: 'Identifier', start: 9, end: 14, name: 'value' } } ], - source: { type: 'Literal', start: 22, end: 29, value: './lib', raw: "'./lib'" } + attributes: [] }, { type: 'ExpressionStatement', @@ -128,16 +130,16 @@ module.exports = defineTest({ type: 'CallExpression', start: 31, end: 49, + arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], callee: { type: 'MemberExpression', start: 31, end: 42, - object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, - property: { type: 'Identifier', start: 39, end: 42, name: 'log' }, computed: false, - optional: false + object: { type: 'Identifier', start: 31, end: 38, name: 'console' }, + optional: false, + property: { type: 'Identifier', start: 39, end: 42, name: 'log' } }, - arguments: [{ type: 'Identifier', start: 43, end: 48, name: 'value' }], optional: false } } @@ -158,7 +160,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: ID_LIB, meta: {}, diff --git a/test/cli/samples/validate/_config.js b/test/cli/samples/validate/_config.js index 3b410ed0d..823456c59 100644 --- a/test/cli/samples/validate/_config.js +++ b/test/cli/samples/validate/_config.js @@ -8,7 +8,7 @@ module.exports = defineTest({ stderr: stderr => assertIncludes( stderr, - `(!) Chunk "out.js" is not valid JavaScript: Unterminated comment (3:20). + `(!) Chunk "out.js" is not valid JavaScript: Unterminated block comment. out.js (3:20) 1: console.log(2 ); 2: diff --git a/test/cli/samples/watch/bundle-error/_config.js b/test/cli/samples/watch/bundle-error/_config.js index 09425be26..588f9ed50 100644 --- a/test/cli/samples/watch/bundle-error/_config.js +++ b/test/cli/samples/watch/bundle-error/_config.js @@ -16,7 +16,7 @@ module.exports = defineTest({ setTimeout(() => unlinkSync(mainFile), 300); }, abortOnStderr(data) { - if (data.includes('[!] RollupError: Unexpected token')) { + if (data.includes('[!] RollupError: Expression expected')) { setTimeout(() => atomicWriteFileSync(mainFile, 'export default 42;'), 500); return false; } diff --git a/test/form/index.js b/test/form/index.js index 2305d78c8..c14e97413 100644 --- a/test/form/index.js +++ b/test/form/index.js @@ -6,7 +6,12 @@ const { basename, resolve } = require('node:path'); */ // @ts-expect-error not included in types const { rollup } = require('../../dist/rollup'); -const { compareLogs, normaliseOutput, runTestSuiteWithSamples } = require('../utils.js'); +const { + compareLogs, + normaliseOutput, + runTestSuiteWithSamples, + verifyAstPlugin +} = require('../utils.js'); const FORMATS = ['amd', 'cjs', 'system', 'es', 'iife', 'umd']; @@ -43,7 +48,15 @@ runTestSuiteWithSamples( } }, strictDeprecations: true, - ...config.options + ...config.options, + plugins: + config.verifyAst === false + ? config.options?.plugins + : config.options?.plugins === undefined + ? verifyAstPlugin + : Array.isArray(config.options.plugins) + ? [...config.options.plugins, verifyAstPlugin] + : config.options.plugins })); await generateAndTestBundle( bundle, diff --git a/test/form/samples/absolute-path-resolver/a.js b/test/form/samples/absolute-path-resolver/a.js index 3223031dc..7ad3ccb5b 100644 --- a/test/form/samples/absolute-path-resolver/a.js +++ b/test/form/samples/absolute-path-resolver/a.js @@ -1,3 +1,3 @@ export var a = () => { console.log('props'); -}; \ No newline at end of file +}; diff --git a/test/form/samples/acorn-external-plugins/_config.js b/test/form/samples/acorn-external-plugins/_config.js deleted file mode 100644 index 2789b15c1..000000000 --- a/test/form/samples/acorn-external-plugins/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -const jsx = require('acorn-jsx'); - -module.exports = defineTest({ - description: 'supports official acorn plugins that may rely on a shared acorn instance', - options: { - acornInjectPlugins: [jsx()] - } -}); diff --git a/test/form/samples/acorn-external-plugins/_expected.js b/test/form/samples/acorn-external-plugins/_expected.js deleted file mode 100644 index d8d373310..000000000 --- a/test/form/samples/acorn-external-plugins/_expected.js +++ /dev/null @@ -1,3 +0,0 @@ -var main =
This is not JavaScript
; - -export { main as default }; diff --git a/test/form/samples/acorn-external-plugins/main.js b/test/form/samples/acorn-external-plugins/main.js deleted file mode 100644 index 5113b9c30..000000000 --- a/test/form/samples/acorn-external-plugins/main.js +++ /dev/null @@ -1 +0,0 @@ -export default
This is not JavaScript
; diff --git a/test/form/samples/big-int/_config.js b/test/form/samples/big-int/_config.js index cdd9c2424..256ffa6ca 100644 --- a/test/form/samples/big-int/_config.js +++ b/test/form/samples/big-int/_config.js @@ -1,3 +1,3 @@ module.exports = defineTest({ - description: 'supports bigint via acorn plugin' + description: 'supports bigint' }); diff --git a/test/form/samples/custom-dynamic-import-no-interop/_config.js b/test/form/samples/custom-dynamic-import-no-interop/_config.js index 910798c4d..91f8f55c3 100644 --- a/test/form/samples/custom-dynamic-import-no-interop/_config.js +++ b/test/form/samples/custom-dynamic-import-no-interop/_config.js @@ -5,11 +5,13 @@ module.exports = defineTest({ output: { interop: 'auto' }, - plugins: { - name: 'test', - renderDynamicImport() { - return { left: 'getIt(', right: ')' }; + plugins: [ + { + name: 'test', + renderDynamicImport() { + return { left: 'getIt(', right: ')' }; + } } - } + ] } }); diff --git a/test/form/samples/import-assertions/removes-dynamic-assertions/_config.js b/test/form/samples/deprecated/removes-dynamic-assertions/_config.js similarity index 88% rename from test/form/samples/import-assertions/removes-dynamic-assertions/_config.js rename to test/form/samples/deprecated/removes-dynamic-assertions/_config.js index 5330ee734..cc9d7dadd 100644 --- a/test/form/samples/import-assertions/removes-dynamic-assertions/_config.js +++ b/test/form/samples/deprecated/removes-dynamic-assertions/_config.js @@ -1,7 +1,8 @@ module.exports = defineTest({ description: 'keep import assertions for dynamic imports', - expectedWarnings: ['UNRESOLVED_IMPORT'], + expectedWarnings: ['UNRESOLVED_IMPORT', 'DEPRECATED_FEATURE'], options: { + strictDeprecations: false, external: id => { if (id === 'unresolved') return null; return true; diff --git a/test/form/samples/import-assertions/removes-dynamic-assertions/_expected.js b/test/form/samples/deprecated/removes-dynamic-assertions/_expected.js similarity index 100% rename from test/form/samples/import-assertions/removes-dynamic-assertions/_expected.js rename to test/form/samples/deprecated/removes-dynamic-assertions/_expected.js diff --git a/test/form/samples/import-assertions/keep-dynamic-assertions/main.js b/test/form/samples/deprecated/removes-dynamic-assertions/main.js similarity index 100% rename from test/form/samples/import-assertions/keep-dynamic-assertions/main.js rename to test/form/samples/deprecated/removes-dynamic-assertions/main.js diff --git a/test/form/samples/import-assertions/removes-static-assertions/_config.js b/test/form/samples/deprecated/removes-static-attributes/_config.js similarity index 72% rename from test/form/samples/import-assertions/removes-static-assertions/_config.js rename to test/form/samples/deprecated/removes-static-attributes/_config.js index 8f8d7c07f..0fae6d851 100644 --- a/test/form/samples/import-assertions/removes-static-assertions/_config.js +++ b/test/form/samples/deprecated/removes-static-attributes/_config.js @@ -1,7 +1,8 @@ module.exports = defineTest({ description: 'keeps any import assertions on input', - expectedWarnings: ['UNRESOLVED_IMPORT'], + expectedWarnings: ['UNRESOLVED_IMPORT', 'DEPRECATED_FEATURE'], options: { + strictDeprecations: false, external: id => { if (id === 'unresolved') return null; return true; diff --git a/test/form/samples/import-assertions/removes-static-assertions/_expected.js b/test/form/samples/deprecated/removes-static-attributes/_expected.js similarity index 100% rename from test/form/samples/import-assertions/removes-static-assertions/_expected.js rename to test/form/samples/deprecated/removes-static-attributes/_expected.js diff --git a/test/form/samples/import-assertions/keeps-static-assertions/main.js b/test/form/samples/deprecated/removes-static-attributes/main.js similarity index 100% rename from test/form/samples/import-assertions/keeps-static-assertions/main.js rename to test/form/samples/deprecated/removes-static-attributes/main.js diff --git a/test/form/samples/emit-asset-file/_config.js b/test/form/samples/emit-asset-file/_config.js index 8086990f7..24bca655e 100644 --- a/test/form/samples/emit-asset-file/_config.js +++ b/test/form/samples/emit-asset-file/_config.js @@ -5,39 +5,41 @@ const path = require('node:path'); module.exports = defineTest({ description: 'supports emitting assets from plugin hooks', options: { - plugins: { - name: 'test', - resolveId(id, importee) { - if (id.endsWith('.svg')) { - return path.resolve(path.dirname(importee), id); + plugins: [ + { + name: 'test', + resolveId(id, importee) { + if (id.endsWith('.svg')) { + return path.resolve(path.dirname(importee), id); + } + }, + load(id) { + if (id.endsWith('.svg')) { + return `export default import.meta.ROLLUP_FILE_URL_${this.emitFile({ + type: 'asset', + name: path.basename(id), + source: readFileSync(id) + })};`; + } + }, + generateBundle(options, outputBundle) { + const keys = Object.keys(outputBundle); + assert.strictEqual(keys.length, 2); + assert.strictEqual(keys[0], 'assets/logo-a2a2cdc4.svg'); + const asset = outputBundle[keys[0]]; + assert.strictEqual(asset.fileName, 'assets/logo-a2a2cdc4.svg'); + if (asset.type !== 'asset') { + throw new Error(`Unexpected asset type ${asset.type}.`); + } + /** @type {any} */ + const source = asset.source; + assert.ok( + source.equals(readFileSync(path.resolve(__dirname, 'logo.svg'))), + 'asset has correct source' + ); + assert.ok(keys[1].endsWith('.js'), `${keys[1]} ends with ".js"`); } - }, - load(id) { - if (id.endsWith('.svg')) { - return `export default import.meta.ROLLUP_FILE_URL_${this.emitFile({ - type: 'asset', - name: path.basename(id), - source: readFileSync(id) - })};`; - } - }, - generateBundle(options, outputBundle) { - const keys = Object.keys(outputBundle); - assert.strictEqual(keys.length, 2); - assert.strictEqual(keys[0], 'assets/logo-a2a2cdc4.svg'); - const asset = outputBundle[keys[0]]; - assert.strictEqual(asset.fileName, 'assets/logo-a2a2cdc4.svg'); - if (asset.type !== 'asset') { - throw new Error(`Unexpected asset type ${asset.type}.`); - } - /** @type {any} */ - const source = asset.source; - assert.ok( - source.equals(readFileSync(path.resolve(__dirname, 'logo.svg'))), - 'asset has correct source' - ); - assert.ok(keys[1].endsWith('.js'), `${keys[1]} ends with ".js"`); } - } + ] } }); diff --git a/test/form/samples/emit-file-tree-shaken-access/_config.js b/test/form/samples/emit-file-tree-shaken-access/_config.js index 124940e78..03475f0ea 100644 --- a/test/form/samples/emit-file-tree-shaken-access/_config.js +++ b/test/form/samples/emit-file-tree-shaken-access/_config.js @@ -4,22 +4,24 @@ const path = require('node:path'); module.exports = defineTest({ description: 'does not include format globals when tree-shaking an asset access', options: { - plugins: { - name: 'test', - resolveId(id, importee) { - if (id.endsWith('.svg')) { - return path.resolve(path.dirname(importee), id); - } - }, - load(id) { - if (id.endsWith('.svg')) { - return `export default import.meta.ROLLUP_FILE_URL_${this.emitFile({ - type: 'asset', - name: path.basename(id), - source: readFileSync(id) - })};`; + plugins: [ + { + name: 'test', + resolveId(id, importee) { + if (id.endsWith('.svg')) { + return path.resolve(path.dirname(importee), id); + } + }, + load(id) { + if (id.endsWith('.svg')) { + return `export default import.meta.ROLLUP_FILE_URL_${this.emitFile({ + type: 'asset', + name: path.basename(id), + source: readFileSync(id) + })};`; + } } } - } + ] } }); diff --git a/test/form/samples/emit-uint8array-no-buffer/_config.js b/test/form/samples/emit-uint8array-no-buffer/_config.js index bdce9965b..2d77cc8a2 100644 --- a/test/form/samples/emit-uint8array-no-buffer/_config.js +++ b/test/form/samples/emit-uint8array-no-buffer/_config.js @@ -9,21 +9,23 @@ module.exports = defineTest({ global.Buffer = Buffer; }, options: { - plugins: { - name: 'test', - resolveId(id) { - if (id.startsWith('asset')) { - return id; - } - }, - load(id) { - if (id.startsWith('asset')) { - return `export default import.meta.ROLLUP_FILE_URL_${this.emitFile({ - type: 'asset', - source: Uint8Array.from([...id].map(char => char.charCodeAt(0))) - })};`; + plugins: [ + { + name: 'test', + resolveId(id) { + if (id.startsWith('asset')) { + return id; + } + }, + load(id) { + if (id.startsWith('asset')) { + return `export default import.meta.ROLLUP_FILE_URL_${this.emitFile({ + type: 'asset', + source: Uint8Array.from([...id].map(char => char.charCodeAt(0))) + })};`; + } } } - } + ] } }); diff --git a/test/form/samples/entry-with-unused-synthetic-exports/_config.js b/test/form/samples/entry-with-unused-synthetic-exports/_config.js index 67dd54b20..e79ba880f 100644 --- a/test/form/samples/entry-with-unused-synthetic-exports/_config.js +++ b/test/form/samples/entry-with-unused-synthetic-exports/_config.js @@ -1,11 +1,13 @@ module.exports = defineTest({ description: 'does not include unused synthetic namespace object in entry points', options: { - plugins: { - name: 'test-plugin', - transform(code) { - return { code, syntheticNamedExports: '__moduleExports' }; + plugins: [ + { + name: 'test-plugin', + transform(code) { + return { code, syntheticNamedExports: '__moduleExports' }; + } } - } + ] } }); diff --git a/test/form/samples/export-globals/_config.js b/test/form/samples/export-globals/_config.js index 6d54b2cfe..d4fb00a05 100644 --- a/test/form/samples/export-globals/_config.js +++ b/test/form/samples/export-globals/_config.js @@ -1,6 +1,3 @@ -// Changed due to https://github.com/acornjs/acorn/issues/806 -// Consider reverting this change should this become an acorn option - module.exports = defineTest({ description: 'Supports reexports of globals with namespace access', options: { diff --git a/test/form/samples/hoisted-vars-in-dead-branches/_expected.js b/test/form/samples/hoisted-vars-in-dead-branches/_expected.js index 86e711f27..d9656038e 100644 --- a/test/form/samples/hoisted-vars-in-dead-branches/_expected.js +++ b/test/form/samples/hoisted-vars-in-dead-branches/_expected.js @@ -1,4 +1,4 @@ -var a, b; { +var b, a; { console.log(a, b); } diff --git a/test/form/samples/import-assertions/assertion-shapes/_config.js b/test/form/samples/import-assertions/assertion-shapes/_config.js deleted file mode 100644 index 4629f8754..000000000 --- a/test/form/samples/import-assertions/assertion-shapes/_config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = defineTest({ - description: 'handles special shapes of assertions', - options: { - external: () => true - } -}); diff --git a/test/form/samples/import-attributes/attribute-shapes/_config.js b/test/form/samples/import-attributes/attribute-shapes/_config.js new file mode 100644 index 000000000..e0cd94cea --- /dev/null +++ b/test/form/samples/import-attributes/attribute-shapes/_config.js @@ -0,0 +1,7 @@ +module.exports = defineTest({ + description: 'handles special shapes of attributes', + options: { + external: () => true + }, + expectedWarnings: ['INVALID_IMPORT_ATTRIBUTE'] +}); diff --git a/test/form/samples/import-assertions/assertion-shapes/_expected.js b/test/form/samples/import-attributes/attribute-shapes/_expected.js similarity index 100% rename from test/form/samples/import-assertions/assertion-shapes/_expected.js rename to test/form/samples/import-attributes/attribute-shapes/_expected.js diff --git a/test/form/samples/import-assertions/assertion-shapes/main.js b/test/form/samples/import-attributes/attribute-shapes/main.js similarity index 100% rename from test/form/samples/import-assertions/assertion-shapes/main.js rename to test/form/samples/import-attributes/attribute-shapes/main.js diff --git a/test/form/samples/import-assertions/keep-dynamic-assertions/_config.js b/test/form/samples/import-attributes/keep-dynamic-attributes/_config.js similarity index 91% rename from test/form/samples/import-assertions/keep-dynamic-assertions/_config.js rename to test/form/samples/import-attributes/keep-dynamic-attributes/_config.js index 6cd9a1555..a75f18189 100644 --- a/test/form/samples/import-assertions/keep-dynamic-assertions/_config.js +++ b/test/form/samples/import-attributes/keep-dynamic-attributes/_config.js @@ -1,5 +1,5 @@ module.exports = defineTest({ - description: 'keep import assertions for dynamic imports', + description: 'keep import attributes for dynamic imports', expectedWarnings: ['UNRESOLVED_IMPORT'], options: { external: id => { diff --git a/test/form/samples/import-assertions/keep-dynamic-assertions/_expected/amd.js b/test/form/samples/import-attributes/keep-dynamic-attributes/_expected/amd.js similarity index 100% rename from test/form/samples/import-assertions/keep-dynamic-assertions/_expected/amd.js rename to test/form/samples/import-attributes/keep-dynamic-attributes/_expected/amd.js diff --git a/test/form/samples/import-assertions/keep-dynamic-assertions/_expected/cjs.js b/test/form/samples/import-attributes/keep-dynamic-attributes/_expected/cjs.js similarity index 100% rename from test/form/samples/import-assertions/keep-dynamic-assertions/_expected/cjs.js rename to test/form/samples/import-attributes/keep-dynamic-attributes/_expected/cjs.js diff --git a/test/form/samples/import-assertions/keep-dynamic-assertions/_expected/es.js b/test/form/samples/import-attributes/keep-dynamic-attributes/_expected/es.js similarity index 100% rename from test/form/samples/import-assertions/keep-dynamic-assertions/_expected/es.js rename to test/form/samples/import-attributes/keep-dynamic-attributes/_expected/es.js diff --git a/test/form/samples/import-assertions/keep-dynamic-assertions/_expected/iife.js b/test/form/samples/import-attributes/keep-dynamic-attributes/_expected/iife.js similarity index 100% rename from test/form/samples/import-assertions/keep-dynamic-assertions/_expected/iife.js rename to test/form/samples/import-attributes/keep-dynamic-attributes/_expected/iife.js diff --git a/test/form/samples/import-assertions/keep-dynamic-assertions/_expected/system.js b/test/form/samples/import-attributes/keep-dynamic-attributes/_expected/system.js similarity index 100% rename from test/form/samples/import-assertions/keep-dynamic-assertions/_expected/system.js rename to test/form/samples/import-attributes/keep-dynamic-attributes/_expected/system.js diff --git a/test/form/samples/import-assertions/keep-dynamic-assertions/_expected/umd.js b/test/form/samples/import-attributes/keep-dynamic-attributes/_expected/umd.js similarity index 100% rename from test/form/samples/import-assertions/keep-dynamic-assertions/_expected/umd.js rename to test/form/samples/import-attributes/keep-dynamic-attributes/_expected/umd.js diff --git a/test/form/samples/import-assertions/removes-dynamic-assertions/main.js b/test/form/samples/import-attributes/keep-dynamic-attributes/main.js similarity index 100% rename from test/form/samples/import-assertions/removes-dynamic-assertions/main.js rename to test/form/samples/import-attributes/keep-dynamic-attributes/main.js diff --git a/test/form/samples/import-assertions/keeps-static-assertions/_config.js b/test/form/samples/import-attributes/keeps-static-attributes/_config.js similarity index 78% rename from test/form/samples/import-assertions/keeps-static-assertions/_config.js rename to test/form/samples/import-attributes/keeps-static-attributes/_config.js index 5dfbc1b2c..c9572989e 100644 --- a/test/form/samples/import-assertions/keeps-static-assertions/_config.js +++ b/test/form/samples/import-attributes/keeps-static-attributes/_config.js @@ -1,5 +1,5 @@ module.exports = defineTest({ - description: 'keeps any import assertions on input', + description: 'keeps any import attributes on input', expectedWarnings: ['UNRESOLVED_IMPORT'], options: { external: id => { diff --git a/test/form/samples/import-assertions/keeps-static-assertions/_expected/amd.js b/test/form/samples/import-attributes/keeps-static-attributes/_expected/amd.js similarity index 100% rename from test/form/samples/import-assertions/keeps-static-assertions/_expected/amd.js rename to test/form/samples/import-attributes/keeps-static-attributes/_expected/amd.js diff --git a/test/form/samples/import-assertions/keeps-static-assertions/_expected/cjs.js b/test/form/samples/import-attributes/keeps-static-attributes/_expected/cjs.js similarity index 100% rename from test/form/samples/import-assertions/keeps-static-assertions/_expected/cjs.js rename to test/form/samples/import-attributes/keeps-static-attributes/_expected/cjs.js diff --git a/test/form/samples/import-assertions/keeps-static-assertions/_expected/es.js b/test/form/samples/import-attributes/keeps-static-attributes/_expected/es.js similarity index 100% rename from test/form/samples/import-assertions/keeps-static-assertions/_expected/es.js rename to test/form/samples/import-attributes/keeps-static-attributes/_expected/es.js diff --git a/test/form/samples/import-assertions/keeps-static-assertions/_expected/iife.js b/test/form/samples/import-attributes/keeps-static-attributes/_expected/iife.js similarity index 100% rename from test/form/samples/import-assertions/keeps-static-assertions/_expected/iife.js rename to test/form/samples/import-attributes/keeps-static-attributes/_expected/iife.js diff --git a/test/form/samples/import-assertions/keeps-static-assertions/_expected/system.js b/test/form/samples/import-attributes/keeps-static-attributes/_expected/system.js similarity index 100% rename from test/form/samples/import-assertions/keeps-static-assertions/_expected/system.js rename to test/form/samples/import-attributes/keeps-static-attributes/_expected/system.js diff --git a/test/form/samples/import-assertions/keeps-static-assertions/_expected/umd.js b/test/form/samples/import-attributes/keeps-static-attributes/_expected/umd.js similarity index 100% rename from test/form/samples/import-assertions/keeps-static-assertions/_expected/umd.js rename to test/form/samples/import-attributes/keeps-static-attributes/_expected/umd.js diff --git a/test/form/samples/import-assertions/removes-static-assertions/main.js b/test/form/samples/import-attributes/keeps-static-attributes/main.js similarity index 100% rename from test/form/samples/import-assertions/removes-static-assertions/main.js rename to test/form/samples/import-attributes/keeps-static-attributes/main.js diff --git a/test/form/samples/import-assertions/plugin-assertions-resolvedynamicimport/_config.js b/test/form/samples/import-attributes/plugin-attributes-resolvedynamicimport/_config.js similarity index 71% rename from test/form/samples/import-assertions/plugin-assertions-resolvedynamicimport/_config.js rename to test/form/samples/import-attributes/plugin-attributes-resolvedynamicimport/_config.js index a0ec44b6b..77e37956d 100644 --- a/test/form/samples/import-assertions/plugin-assertions-resolvedynamicimport/_config.js +++ b/test/form/samples/import-attributes/plugin-attributes-resolvedynamicimport/_config.js @@ -1,13 +1,13 @@ module.exports = defineTest({ - description: 'allows plugins to read and write import assertions in resolveDynamicImport', + description: 'allows plugins to read and write import attributes in resolveDynamicImport', options: { plugins: [ { name: 'test', - resolveDynamicImport(specifier, importer, { assertions }) { + resolveDynamicImport(specifier, importer, { attributes }) { const resolutionOptions = { external: true, - assertions: Object.fromEntries(Object.keys(assertions).map(key => [key, 'changed'])) + attributes: Object.fromEntries(Object.keys(attributes).map(key => [key, 'changed'])) }; if (typeof specifier === 'object') { if (specifier.type === 'TemplateLiteral') { diff --git a/test/form/samples/import-assertions/plugin-assertions-resolvedynamicimport/_expected.js b/test/form/samples/import-attributes/plugin-attributes-resolvedynamicimport/_expected.js similarity index 100% rename from test/form/samples/import-assertions/plugin-assertions-resolvedynamicimport/_expected.js rename to test/form/samples/import-attributes/plugin-attributes-resolvedynamicimport/_expected.js diff --git a/test/form/samples/import-assertions/plugin-assertions-resolvedynamicimport/main.js b/test/form/samples/import-attributes/plugin-attributes-resolvedynamicimport/main.js similarity index 100% rename from test/form/samples/import-assertions/plugin-assertions-resolvedynamicimport/main.js rename to test/form/samples/import-attributes/plugin-attributes-resolvedynamicimport/main.js diff --git a/test/form/samples/import-assertions/plugin-assertions-resolveid/_config.js b/test/form/samples/import-attributes/plugin-attributes-resolveid/_config.js similarity index 56% rename from test/form/samples/import-assertions/plugin-assertions-resolveid/_config.js rename to test/form/samples/import-attributes/plugin-attributes-resolveid/_config.js index 53b921dda..1b61ac24c 100644 --- a/test/form/samples/import-assertions/plugin-assertions-resolveid/_config.js +++ b/test/form/samples/import-attributes/plugin-attributes-resolveid/_config.js @@ -1,15 +1,15 @@ module.exports = defineTest({ - description: 'allows plugins to read and write import assertions in resolveId', + description: 'allows plugins to read and write import attributes in resolveId', options: { output: { name: 'bundle' }, plugins: [ { name: 'test', - resolveId(source, importer, { assertions, isEntry }) { + resolveId(source, importer, { attributes, isEntry }) { return { id: source, external: !isEntry, - assertions: Object.fromEntries(Object.keys(assertions).map(key => [key, 'changed'])) + attributes: Object.fromEntries(Object.keys(attributes).map(key => [key, 'changed'])) }; } } diff --git a/test/form/samples/import-assertions/plugin-assertions-resolveid/_expected.js b/test/form/samples/import-attributes/plugin-attributes-resolveid/_expected.js similarity index 100% rename from test/form/samples/import-assertions/plugin-assertions-resolveid/_expected.js rename to test/form/samples/import-attributes/plugin-attributes-resolveid/_expected.js diff --git a/test/form/samples/import-assertions/plugin-assertions-resolveid/main.js b/test/form/samples/import-attributes/plugin-attributes-resolveid/main.js similarity index 100% rename from test/form/samples/import-assertions/plugin-assertions-resolveid/main.js rename to test/form/samples/import-attributes/plugin-attributes-resolveid/main.js diff --git a/test/form/samples/import-attributes/removes-dynamic-attributes/_config.js b/test/form/samples/import-attributes/removes-dynamic-attributes/_config.js new file mode 100644 index 000000000..0c8e6bfc1 --- /dev/null +++ b/test/form/samples/import-attributes/removes-dynamic-attributes/_config.js @@ -0,0 +1,29 @@ +module.exports = defineTest({ + description: 'keep import attributes for dynamic imports', + expectedWarnings: ['UNRESOLVED_IMPORT'], + options: { + external: id => { + if (id === 'unresolved') return null; + return true; + }, + plugins: [ + { + name: 'test', + resolveDynamicImport(specifier) { + if (typeof specifier === 'object') { + if (specifier.type === 'TemplateLiteral') { + return "'resolvedString'"; + } + if (specifier.type === 'BinaryExpression') { + return { id: 'resolved-id', external: true }; + } + } else if (specifier === 'external-resolved') { + return { id: 'resolved-different', external: true }; + } + return null; + } + } + ], + output: { externalImportAttributes: false } + } +}); diff --git a/test/form/samples/import-attributes/removes-dynamic-attributes/_expected.js b/test/form/samples/import-attributes/removes-dynamic-attributes/_expected.js new file mode 100644 index 000000000..2d4172646 --- /dev/null +++ b/test/form/samples/import-attributes/removes-dynamic-attributes/_expected.js @@ -0,0 +1,6 @@ +import('external'); +import(globalThis.unknown); +import('resolvedString'); +import('resolved-id'); +import('resolved-different'); +import('unresolved'); diff --git a/test/form/samples/import-attributes/removes-dynamic-attributes/main.js b/test/form/samples/import-attributes/removes-dynamic-attributes/main.js new file mode 100644 index 000000000..38bfed638 --- /dev/null +++ b/test/form/samples/import-attributes/removes-dynamic-attributes/main.js @@ -0,0 +1,6 @@ +import('external', { assert: { type: 'special' } }); +import(globalThis.unknown, { assert: { type: 'special' } }); +import(`external-${globalThis.unknown}`, { assert: { type: 'special' } }); +import('external' + globalThis.unknown, { assert: { type: 'special' } }); +import('external-resolved', { assert: { type: 'special' } }); +import('unresolved', { assert: { type: 'special' } }); diff --git a/test/form/samples/import-attributes/removes-static-attributes/_config.js b/test/form/samples/import-attributes/removes-static-attributes/_config.js new file mode 100644 index 000000000..92caa7dde --- /dev/null +++ b/test/form/samples/import-attributes/removes-static-attributes/_config.js @@ -0,0 +1,11 @@ +module.exports = defineTest({ + description: 'keeps any import attributes on input', + expectedWarnings: ['UNRESOLVED_IMPORT'], + options: { + external: id => { + if (id === 'unresolved') return null; + return true; + }, + output: { name: 'bundle', externalImportAttributes: false } + } +}); diff --git a/test/form/samples/import-attributes/removes-static-attributes/_expected.js b/test/form/samples/import-attributes/removes-static-attributes/_expected.js new file mode 100644 index 000000000..40f55f223 --- /dev/null +++ b/test/form/samples/import-attributes/removes-static-attributes/_expected.js @@ -0,0 +1,7 @@ +import { a } from 'a'; +import * as b from 'b'; +export { c } from 'c'; +export * from 'd'; +import 'unresolved'; + +console.log(a, b, d); diff --git a/test/form/samples/import-attributes/removes-static-attributes/main.js b/test/form/samples/import-attributes/removes-static-attributes/main.js new file mode 100644 index 000000000..02b154c86 --- /dev/null +++ b/test/form/samples/import-attributes/removes-static-attributes/main.js @@ -0,0 +1,9 @@ +import { a } from 'a' assert { type: 'a', extra: 'extra' }; +import * as b from 'b' assert { type: 'b' }; +export { c } from 'c' assert { type: 'c' }; +export * from 'd' assert { type: 'd' }; +import 'unresolved' assert { type: 'e' }; + +console.log(a, b, d); + + diff --git a/test/form/samples/import-named-exported-global-with-alias/_config.js b/test/form/samples/import-named-exported-global-with-alias/_config.js index 2be7a8e17..ed0df9a03 100644 --- a/test/form/samples/import-named-exported-global-with-alias/_config.js +++ b/test/form/samples/import-named-exported-global-with-alias/_config.js @@ -1,6 +1,3 @@ -// Changed due to https://github.com/acornjs/acorn/issues/806 -// Consider reverting this change should this become an acorn option - module.exports = defineTest({ description: 'allow globals to be exported and imported', expectedWarnings: ['EMPTY_BUNDLE'], diff --git a/test/form/samples/make-absolute-externals-relative/make-relative-false/_config.js b/test/form/samples/make-absolute-externals-relative/make-relative-false/_config.js index a2498b029..753fdada4 100644 --- a/test/form/samples/make-absolute-externals-relative/make-relative-false/_config.js +++ b/test/form/samples/make-absolute-externals-relative/make-relative-false/_config.js @@ -18,30 +18,36 @@ module.exports = defineTest({ ) return true; }, - plugins: { - name: 'test', - async buildStart() { - // eslint-disable-next-line unicorn/consistent-function-scoping - const testExternal = async (source, expected) => - assert.deepStrictEqual((await this.resolve(source, ID_MAIN)).external, expected, source); + plugins: [ + { + name: 'test', + async buildStart() { + // eslint-disable-next-line unicorn/consistent-function-scoping + const testExternal = async (source, expected) => + assert.deepStrictEqual( + (await this.resolve(source, ID_MAIN)).external, + expected, + source + ); - await testExternal('./relativeUnresolved.js', true); - await testExternal('/absolute.js', 'absolute'); - await testExternal('./pluginDirect.js', true); - await testExternal('/pluginDifferentAbsolute.js', 'absolute'); - await testExternal('./pluginTrue.js', 'absolute'); - await testExternal('./pluginForceAbsolute.js', 'absolute'); - await testExternal('./pluginForceRelative.js', true); - }, - resolveId(source) { - if (source.endsWith('/pluginDirect.js')) return false; - if (source.endsWith('/pluginDifferentAbsolute.js')) return '/pluginAbsolute.js'; - if (source.endsWith('/pluginTrue.js')) return { id: '/pluginTrue.js', external: true }; - if (source.endsWith('/pluginForceAbsolute.js')) - return { id: '/pluginForceAbsolute.js', external: 'absolute' }; - if (source.endsWith('/pluginForceRelative.js')) - return { id: path.join(__dirname, 'pluginForceRelative.js'), external: 'relative' }; + await testExternal('./relativeUnresolved.js', true); + await testExternal('/absolute.js', 'absolute'); + await testExternal('./pluginDirect.js', true); + await testExternal('/pluginDifferentAbsolute.js', 'absolute'); + await testExternal('./pluginTrue.js', 'absolute'); + await testExternal('./pluginForceAbsolute.js', 'absolute'); + await testExternal('./pluginForceRelative.js', true); + }, + resolveId(source) { + if (source.endsWith('/pluginDirect.js')) return false; + if (source.endsWith('/pluginDifferentAbsolute.js')) return '/pluginAbsolute.js'; + if (source.endsWith('/pluginTrue.js')) return { id: '/pluginTrue.js', external: true }; + if (source.endsWith('/pluginForceAbsolute.js')) + return { id: '/pluginForceAbsolute.js', external: 'absolute' }; + if (source.endsWith('/pluginForceRelative.js')) + return { id: path.join(__dirname, 'pluginForceRelative.js'), external: 'relative' }; + } } - } + ] } }); diff --git a/test/form/samples/make-absolute-externals-relative/make-relative-relative/_config.js b/test/form/samples/make-absolute-externals-relative/make-relative-relative/_config.js index 5d7df6077..bfb7505bb 100644 --- a/test/form/samples/make-absolute-externals-relative/make-relative-relative/_config.js +++ b/test/form/samples/make-absolute-externals-relative/make-relative-relative/_config.js @@ -21,33 +21,39 @@ module.exports = defineTest({ ) return true; }, - plugins: { - name: 'test', - async buildStart() { - // eslint-disable-next-line unicorn/consistent-function-scoping - const testExternal = async (source, expected) => - assert.deepStrictEqual((await this.resolve(source, ID_MAIN)).external, expected, source); + plugins: [ + { + name: 'test', + async buildStart() { + // eslint-disable-next-line unicorn/consistent-function-scoping + const testExternal = async (source, expected) => + assert.deepStrictEqual( + (await this.resolve(source, ID_MAIN)).external, + expected, + source + ); - await testExternal('./relativeUnresolved.js', true); - await testExternal('./relativeMissing.js', true); - await testExternal('./relativeExisting.js', true); - await testExternal('/absolute.js', 'absolute'); - await testExternal('./pluginDirect.js', true); - await testExternal('/pluginDifferentAbsolute.js', 'absolute'); - await testExternal('./pluginTrue.js', true); - await testExternal('./pluginForceAbsolute.js', 'absolute'); - await testExternal('./pluginForceRelative.js', true); - }, - resolveId(source) { - if (source.endsWith('/pluginDirect.js')) return false; - if (source.endsWith('/pluginDifferentAbsolute.js')) return '/pluginAbsolute.js'; - if (source.endsWith('/pluginTrue.js')) - return { id: path.join(__dirname, 'pluginTrue.js'), external: true }; - if (source.endsWith('/pluginForceAbsolute.js')) - return { id: '/pluginForceAbsolute.js', external: 'absolute' }; - if (source.endsWith('/pluginForceRelative.js')) - return { id: path.join(__dirname, 'pluginForceRelative.js'), external: 'relative' }; + await testExternal('./relativeUnresolved.js', true); + await testExternal('./relativeMissing.js', true); + await testExternal('./relativeExisting.js', true); + await testExternal('/absolute.js', 'absolute'); + await testExternal('./pluginDirect.js', true); + await testExternal('/pluginDifferentAbsolute.js', 'absolute'); + await testExternal('./pluginTrue.js', true); + await testExternal('./pluginForceAbsolute.js', 'absolute'); + await testExternal('./pluginForceRelative.js', true); + }, + resolveId(source) { + if (source.endsWith('/pluginDirect.js')) return false; + if (source.endsWith('/pluginDifferentAbsolute.js')) return '/pluginAbsolute.js'; + if (source.endsWith('/pluginTrue.js')) + return { id: path.join(__dirname, 'pluginTrue.js'), external: true }; + if (source.endsWith('/pluginForceAbsolute.js')) + return { id: '/pluginForceAbsolute.js', external: 'absolute' }; + if (source.endsWith('/pluginForceRelative.js')) + return { id: path.join(__dirname, 'pluginForceRelative.js'), external: 'relative' }; + } } - } + ] } }); diff --git a/test/form/samples/make-absolute-externals-relative/make-relative-true/_config.js b/test/form/samples/make-absolute-externals-relative/make-relative-true/_config.js index 29807ce3c..d78601043 100644 --- a/test/form/samples/make-absolute-externals-relative/make-relative-true/_config.js +++ b/test/form/samples/make-absolute-externals-relative/make-relative-true/_config.js @@ -20,35 +20,41 @@ module.exports = defineTest({ ) return true; }, - plugins: { - name: 'test', - async buildStart() { - // eslint-disable-next-line unicorn/consistent-function-scoping - const testExternal = async (source, expected) => - assert.deepStrictEqual((await this.resolve(source, ID_MAIN)).external, expected, source); + plugins: [ + { + name: 'test', + async buildStart() { + // eslint-disable-next-line unicorn/consistent-function-scoping + const testExternal = async (source, expected) => + assert.deepStrictEqual( + (await this.resolve(source, ID_MAIN)).external, + expected, + source + ); - await testExternal('./relativeUnresolved.js', true); - await testExternal('./relativeMissing.js', true); - await testExternal('./relativeExisting.js', true); - await testExternal('/absolute.js', true); - await testExternal('./pluginDirect.js', true); - await testExternal('/pluginDifferentAbsolute.js', true); - await testExternal('./pluginTrue.js', true); - await testExternal('./pluginForceAbsolute.js', 'absolute'); - await testExternal('./pluginForceRelative.js', true); - }, - resolveId(source) { - if (source.endsWith('/pluginDirect.js')) return false; - if (source.endsWith('/pluginDifferentAbsolute.js')) - return path.join(__dirname, 'pluginAbsolute.js'); - if (source.endsWith('/pluginTrue.js')) - return { id: path.join(__dirname, 'pluginTrue.js'), external: true }; - if (source.endsWith('/pluginForceAbsolute.js')) - return { id: '/pluginForceAbsolute.js', external: 'absolute' }; - if (source.endsWith('/pluginForceRelative.js')) - return { id: path.join(__dirname, 'pluginForceRelative.js'), external: 'relative' }; - if (source === '/absolute.js') return path.join(__dirname, 'absolute.js'); + await testExternal('./relativeUnresolved.js', true); + await testExternal('./relativeMissing.js', true); + await testExternal('./relativeExisting.js', true); + await testExternal('/absolute.js', true); + await testExternal('./pluginDirect.js', true); + await testExternal('/pluginDifferentAbsolute.js', true); + await testExternal('./pluginTrue.js', true); + await testExternal('./pluginForceAbsolute.js', 'absolute'); + await testExternal('./pluginForceRelative.js', true); + }, + resolveId(source) { + if (source.endsWith('/pluginDirect.js')) return false; + if (source.endsWith('/pluginDifferentAbsolute.js')) + return path.join(__dirname, 'pluginAbsolute.js'); + if (source.endsWith('/pluginTrue.js')) + return { id: path.join(__dirname, 'pluginTrue.js'), external: true }; + if (source.endsWith('/pluginForceAbsolute.js')) + return { id: '/pluginForceAbsolute.js', external: 'absolute' }; + if (source.endsWith('/pluginForceRelative.js')) + return { id: path.join(__dirname, 'pluginForceRelative.js'), external: 'relative' }; + if (source === '/absolute.js') return path.join(__dirname, 'absolute.js'); + } } - } + ] } }); diff --git a/test/form/samples/module-no-treeshake/_config.js b/test/form/samples/module-no-treeshake/_config.js index db7e5f18a..49b72992f 100644 --- a/test/form/samples/module-no-treeshake/_config.js +++ b/test/form/samples/module-no-treeshake/_config.js @@ -5,37 +5,39 @@ function getCode(id) { module.exports = defineTest({ description: 'allows disabling tree-shaking for modules', options: { - plugins: { - resolveId(id) { - if (id.startsWith('dep')) { - if (id === 'depResolved') { - return { - id, - moduleSideEffects: 'no-treeshake' - }; + plugins: [ + { + resolveId(id) { + if (id.startsWith('dep')) { + if (id === 'depResolved') { + return { + id, + moduleSideEffects: 'no-treeshake' + }; + } + return id; } - return id; - } - }, - load(id) { - if (id.startsWith('dep')) { - if (id === 'depLoaded') { + }, + load(id) { + if (id.startsWith('dep')) { + if (id === 'depLoaded') { + return { + code: getCode(id), + moduleSideEffects: 'no-treeshake' + }; + } + return getCode(id); + } + }, + transform(code, id) { + if (id === 'depTransformed') { return { code: getCode(id), moduleSideEffects: 'no-treeshake' }; } - return getCode(id); - } - }, - transform(code, id) { - if (id === 'depTransformed') { - return { - code: getCode(id), - moduleSideEffects: 'no-treeshake' - }; } } - } + ] } }); diff --git a/test/form/samples/nested-pure-comments/main.js b/test/form/samples/nested-pure-comments/main.js index 1e4ce33d8..d9791f075 100644 --- a/test/form/samples/nested-pure-comments/main.js +++ b/test/form/samples/nested-pure-comments/main.js @@ -21,4 +21,6 @@ false /*@__PURE__*/ || keep(); // Calls with parentheses /*@__PURE__*/(remove()); +/*@__PURE__*/(((remove()))); /*@__PURE__*/(new Remove()); +/*@__PURE__*/(((new Remove()))); diff --git a/test/form/samples/no-side-effects-function-declaration-preserve/_config.js b/test/form/samples/no-side-effects-function-declaration-preserve/_config.js index 8791127a9..098620f28 100644 --- a/test/form/samples/no-side-effects-function-declaration-preserve/_config.js +++ b/test/form/samples/no-side-effects-function-declaration-preserve/_config.js @@ -1,5 +1,3 @@ -// tests compiled from https://github.com/mishoo/UglifyJS2/blob/88c8f4e363e0d585b33ea29df560243d3dc74ce1/test/compress/pure_funcs.js - module.exports = defineTest({ description: 'preserve __NO_SIDE_EFFECTS__ annotations for function declarations' }); diff --git a/test/form/samples/no-side-effects-function-declaration-preserve/_expected.js b/test/form/samples/no-side-effects-function-declaration-preserve/_expected.js index 33772214e..841bb6ee0 100644 --- a/test/form/samples/no-side-effects-function-declaration-preserve/_expected.js +++ b/test/form/samples/no-side-effects-function-declaration-preserve/_expected.js @@ -31,13 +31,13 @@ const fnC = /*#__NO_SIDE_EFFECTS__*/ (args) => { }; -/*#__NO_SIDE_EFFECTS__*/ +/*#__NO_SIDE_EFFECTS__*/ const fnD = (args) => { console.log(args); return args }; -/*#__NO_SIDE_EFFECTS__*/ +/*#__NO_SIDE_EFFECTS__*/ const fnE = (args) => { console.log(args); return args @@ -45,10 +45,10 @@ const fnE = (args) => { /** * This is a jsdoc comment, with no side effects annotation - * + * * @param {any} args * @__NO_SIDE_EFFECTS__ - */ + */ const fnF = (args) => { console.log(args); return args @@ -56,17 +56,6 @@ const fnF = (args) => { const fnAlias = fnA; -/** - * Have both annotations - * - * @__PURE__ - * @__NO_SIDE_EFFECTS__ - */ -const fnBothAnnotations = (args) => { - console.log(args); - return args -}; - // This annonation get ignored let fnLet = (args) => { @@ -74,4 +63,4 @@ let fnLet = (args) => { return args }; -export { fnA, fnAlias, fnB, fnBothAnnotations, fnC, fnD, fnE, fnEffects, fnF, fnFromSub, fnLet, fnPure }; +export { fnA, fnAlias, fnB, fnC, fnD, fnE, fnEffects, fnF, fnFromSub, fnLet, fnPure }; diff --git a/test/form/samples/no-side-effects-function-declaration-preserve/functions.js b/test/form/samples/no-side-effects-function-declaration-preserve/functions.js index 399b6a6c3..59c37d8d9 100644 --- a/test/form/samples/no-side-effects-function-declaration-preserve/functions.js +++ b/test/form/samples/no-side-effects-function-declaration-preserve/functions.js @@ -26,7 +26,7 @@ export const fnC = /*#__NO_SIDE_EFFECTS__*/ (args) => { } -/*#__NO_SIDE_EFFECTS__*/ +/*#__NO_SIDE_EFFECTS__*/ const fnD = (args) => { console.log(args) return args @@ -34,7 +34,7 @@ const fnD = (args) => { export { fnD } -/*#__NO_SIDE_EFFECTS__*/ +/*#__NO_SIDE_EFFECTS__*/ export const fnE = (args) => { console.log(args) return args @@ -42,16 +42,16 @@ export const fnE = (args) => { /** * This is a jsdoc comment, with no side effects annotation - * + * * @param {any} args * @__NO_SIDE_EFFECTS__ - */ + */ export const fnF = (args) => { console.log(args) return args } -/*#__NO_SIDE_EFFECTS__*/ +/*#__NO_SIDE_EFFECTS__*/ export default function fnDefault(args) { console.log(args) return args @@ -61,17 +61,6 @@ export * from './sub-functions' export const fnAlias = fnA -/** - * Have both annotations - * - * @__PURE__ - * @__NO_SIDE_EFFECTS__ - */ -export const fnBothAnnotations = (args) => { - console.log(args) - return args -} - // This annonation get ignored /** @__NO_SIDE_EFFECTS__ */ export let fnLet = (args) => { diff --git a/test/form/samples/no-side-effects-function-declaration/_config.js b/test/form/samples/no-side-effects-function-declaration/_config.js index c3178070c..5d7379912 100644 --- a/test/form/samples/no-side-effects-function-declaration/_config.js +++ b/test/form/samples/no-side-effects-function-declaration/_config.js @@ -1,5 +1,3 @@ -// tests compiled from https://github.com/mishoo/UglifyJS2/blob/88c8f4e363e0d585b33ea29df560243d3dc74ce1/test/compress/pure_funcs.js - module.exports = defineTest({ description: '__NO_SIDE_EFFECTS__ annotations for function declarations' }); diff --git a/test/form/samples/no-side-effects-function-declaration/functions.js b/test/form/samples/no-side-effects-function-declaration/functions.js index 61954b3ae..83d130ce8 100644 --- a/test/form/samples/no-side-effects-function-declaration/functions.js +++ b/test/form/samples/no-side-effects-function-declaration/functions.js @@ -26,7 +26,7 @@ export const fnC = /*#__NO_SIDE_EFFECTS__*/ (args) => { } -/*#__NO_SIDE_EFFECTS__*/ +/*#__NO_SIDE_EFFECTS__*/ const fnD = (args) => { console.log(args) return args @@ -34,7 +34,7 @@ const fnD = (args) => { export { fnD } -/*#__NO_SIDE_EFFECTS__*/ +/*#__NO_SIDE_EFFECTS__*/ export const fnE = (args) => { console.log(args) return args @@ -42,10 +42,10 @@ export const fnE = (args) => { /** * This is a jsdoc comment, with pure annotation - * + * * @param {any} args * @__NO_SIDE_EFFECTS__ - */ + */ export const fnF = (args) => { console.log(args) return args @@ -59,7 +59,7 @@ export async function fnG(args) { /** * #__NO_SIDE_EFFECTS__ - */ + */ export const fnH = async (args) => { console.log(args) return args @@ -73,7 +73,7 @@ export const fnI = /*#__NO_SIDE_EFFECTS__*/ async (args) => { /** * #__NO_SIDE_EFFECTS__ - */ + */ export function * fnJ(args) { console.log(args) return args @@ -81,13 +81,13 @@ export function * fnJ(args) { /** * #__NO_SIDE_EFFECTS__ - */ + */ export async function * fnK(args) { console.log(args) return args } -/*#__NO_SIDE_EFFECTS__*/ +/*#__NO_SIDE_EFFECTS__*/ export default function fnDefault(args) { console.log(args) return args diff --git a/test/form/samples/ns-external-star-reexport/_config.js b/test/form/samples/ns-external-star-reexport/_config.js index 506491a80..a556f5bcd 100644 --- a/test/form/samples/ns-external-star-reexport/_config.js +++ b/test/form/samples/ns-external-star-reexport/_config.js @@ -2,17 +2,19 @@ module.exports = defineTest({ description: 'supports namespaces with external star reexports', options: { external: ['external1', 'external2'], - plugins: { - transform(code, id) { - if (id.endsWith('override.js')) { - return { - code, - syntheticNamedExports: true - }; + plugins: [ + { + transform(code, id) { + if (id.endsWith('override.js')) { + return { + code, + syntheticNamedExports: true + }; + } + return null; } - return null; } - }, + ], output: { globals: { external1: 'external1', diff --git a/test/form/samples/pure-comment-line-break/_expected.js b/test/form/samples/pure-comment-line-break/_expected.js index 134dcf3ff..45f13faa7 100644 --- a/test/form/samples/pure-comment-line-break/_expected.js +++ b/test/form/samples/pure-comment-line-break/_expected.js @@ -1,39 +1,45 @@ const x = 'code'; -console.log('should remain impure'); +console.log('code0'); -console.log('should remain impure'); +console.log('code1'); -console.log('code'); -console.log('should remain impure'); +console.log('code2'); -console.log('code'); -console.log('should remain impure'); -console.log('should remain impure'); +console.log('code3'); -console.log('code'); -console.log('should remain impure'); +console.log('code4'); -console.log('code'), -console.log('should remain impure'); +console.log('code5'); -console.log('code'), -console.log('should remain impure'); +console.log('code6'); -console.log('should remain impure'); +console.log('code7'); -console.log('code'); -console.log('should remain impure'); +console.log('code8'); -console.log('should remain impure'); +console.log('code9'); -console.log('should remain impure') ; +console.log('code10'), +console.log('code11'); -console.log('code'); -console.log('should remain impure', x); +console.log('code12'), +console.log('code13'); + +console.log('code14'); + +console.log('code15'); +console.log('code16'); + +console.log('code17'); + +console.log('code18') ; + +console.log('code19'); +console.log('code20', x); { - console.log('should remain impure'); + console.log('code21'); } keep1() ; keep2(); keep3() ; diff --git a/test/form/samples/pure-comment-line-break/dep.js b/test/form/samples/pure-comment-line-break/dep.js index 724095977..86c31d2f7 100644 --- a/test/form/samples/pure-comment-line-break/dep.js +++ b/test/form/samples/pure-comment-line-break/dep.js @@ -1,3 +1,3 @@ const x = 'code';//@__PURE__ export default x; -console.log('should remain impure'); +console.log('code0'); diff --git a/test/form/samples/pure-comment-line-break/main.js b/test/form/samples/pure-comment-line-break/main.js index cadb2158f..2484e4d82 100644 --- a/test/form/samples/pure-comment-line-break/main.js +++ b/test/form/samples/pure-comment-line-break/main.js @@ -1,46 +1,57 @@ /*@__PURE__*/ (() => {})(); -console.log('should remain impure'); -console.log('code');//@__PURE__ +console.log('code1'); /*@__PURE__*/ +(() => {})(), /*@__PURE__*/(() => {})(); + +console.log('code2'); /*@__PURE__*/ +(() => {})() || /*@__PURE__*/(() => {})(); + +console.log('code3'); /*@__PURE__*/ +(() => {})() + /*@__PURE__*/(() => {})(); + +console.log('code4'); /*@__PURE__*/ +(() => {})() ? /*@__PURE__*/(() => {})() : /*@__PURE__*/(() => {})(); + +console.log('code5'); /*@__PURE__*/ +foo?.bar(); + +console.log('code6');//@__PURE__ (() => {})(); -console.log('should remain impure'); -console.log('code')/*@__PURE__*/; +console.log('code7')/*@__PURE__*/; (() => {})(); -console.log('should remain impure'); +console.log('code8'); (() => {})();//@__PURE__ (() => {})(); -console.log('should remain impure'); -console.log('code');/*@__PURE__*///@__PURE__ +console.log('code9');/*@__PURE__*///@__PURE__ /*@__PURE__*/ (() => {})(); -console.log('should remain impure'); -console.log('code'),//@__PURE__ -(() => {})(),console.log('should remain impure'); +console.log('code10'),//@__PURE__ +(() => {})(),console.log('code11'); -console.log('code')/*@__PURE__*/, -(() => {})(),console.log('should remain impure'); +console.log('code12')/*@__PURE__*/, +(() => {})(),console.log('code13'); (() => {})(),//@__PURE__ -(() => {})(),console.log('should remain impure'); +(() => {})(),console.log('code14'); -console.log('code');//@__PURE__ -;console.log('should remain impure'); +console.log('code15');//@__PURE__ +;console.log('code16'); -/*@__PURE__*/true && console.log('should remain impure'); +/*@__PURE__*/true && console.log('code17'); -/*@__PURE__*/true ? console.log('should remain impure') : console.log('code'); +/*@__PURE__*/true ? console.log('code18') : console.log('removed'); -console.log('code');//@__PURE__ +console.log('code19');//@__PURE__ import code from './dep.js'; -console.log('should remain impure', code); +console.log('code20', code); /*@__PURE__*/ if (true) { - console.log('should remain impure'); + console.log('code21'); } /*@__PURE__*/ drop1(); diff --git a/test/form/samples/pure-comment-scenarios-simple/_expected.js b/test/form/samples/pure-comment-scenarios-simple/_expected.js index 58e48fb60..562d2bce0 100644 --- a/test/form/samples/pure-comment-scenarios-simple/_expected.js +++ b/test/form/samples/pure-comment-scenarios-simple/_expected.js @@ -7,8 +7,8 @@ (w(), y()); /*@__PURE__*/(g() || h())(x(), y()); /*@__PURE__*/new (g() || h())(x(), y()); -(/*@__PURE__*/ (a() || b()))(c(), d()); -new (/*@__PURE__*/ (a() || b()))(c(), d()); +( (a() || b()))(c(), d()); +new ( (a() || b()))(c(), d()); [ /*@__PURE__*/ x(), y() ]; [ /*@__PURE__*/ new x(), y() ]; [ w(), /*@__PURE__*/ x(), y() ]; @@ -22,9 +22,9 @@ new (/*@__PURE__*/ (a() || b()))(c(), d()); ( e).x(1).y(2).z(3); ( f.x)(1).y(2).z(3); (/*@__PURE__*/ g.x(1)).y(2).z(3); -( h.x(1).y)(2).z(3); +(/*@__PURE__*/ h.x(1).y)(2).z(3); (/*@__PURE__*/ i.x(1).y(2)).z(3); -( j.x(1).y(2).z)(3); +(/*@__PURE__*/ j.x(1).y(2).z)(3); new ( k)(); new ( l)(1)(2)(3); (/*@__PURE__*/ new m(1))(2)(3); @@ -32,6 +32,6 @@ new ( l)(1)(2)(3); new ( o).x(1).y(2).z(3); /* */ new ( p.x)(1).y(2).z(3); (/*@__PURE__*/ new q.x(1)).y(2).z(3); -( new r.x(1).y)(2).z(3); +(/*@__PURE__*/ new r.x(1).y)(2).z(3); (/*@__PURE__*/ new s.x(1).y(2)).z(3); -( new t.x(1).y(2).z)(3); +(/*@__PURE__*/ new t.x(1).y(2).z)(3); diff --git a/test/form/samples/relative-external-ids/_config.js b/test/form/samples/relative-external-ids/_config.js index 159cea043..bee86d610 100644 --- a/test/form/samples/relative-external-ids/_config.js +++ b/test/form/samples/relative-external-ids/_config.js @@ -22,26 +22,28 @@ module.exports = defineTest({ } } }, - plugins: { - resolveId(id) { - switch (id) { - case './hook.js': { - return false; - } - case './hookNested.js': { - return false; - } - case 'resolved': { - return { id: './resolved.js', external: true }; - } - case 'resolvedNested': { - return { id: './resolvedNested.js', external: true }; - } - default: { - return null; + plugins: [ + { + resolveId(id) { + switch (id) { + case './hook.js': { + return false; + } + case './hookNested.js': { + return false; + } + case 'resolved': { + return { id: './resolved.js', external: true }; + } + case 'resolvedNested': { + return { id: './resolvedNested.js', external: true }; + } + default: { + return null; + } } } } - } + ] } }); diff --git a/test/form/samples/resolution-order/_config.js b/test/form/samples/resolution-order/_config.js index cca0484c4..38eec40c2 100644 --- a/test/form/samples/resolution-order/_config.js +++ b/test/form/samples/resolution-order/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'does not depend on the resolution order of modules for tree-shaking (#2753)', options: { - plugins: { - resolveId(id) { - if (id === './utcWeek') { - return new Promise(resolve => setTimeout(resolve, 0)); + plugins: [ + { + resolveId(id) { + if (id === './utcWeek') { + return new Promise(resolve => setTimeout(resolve, 0)); + } } } - } + ] } }); diff --git a/test/form/samples/side-effects-internal-modules/_config.js b/test/form/samples/side-effects-internal-modules/_config.js index 973ecfeda..091fe7d8c 100644 --- a/test/form/samples/side-effects-internal-modules/_config.js +++ b/test/form/samples/side-effects-internal-modules/_config.js @@ -11,18 +11,20 @@ module.exports = defineTest({ return false; } }, - plugins: { - name: 'test-plugin', - resolveId(id) { - if (id === 'virtual') { - return VIRTUAL_ID; - } - }, - load(id) { - if (id === VIRTUAL_ID) { - return "console.log('effect')"; + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (id === 'virtual') { + return VIRTUAL_ID; + } + }, + load(id) { + if (id === VIRTUAL_ID) { + return "console.log('effect')"; + } } } - } + ] } }); diff --git a/test/form/samples/supports-core-js/_config.js b/test/form/samples/supports-core-js/_config.js index ad8e2ea80..070775017 100644 --- a/test/form/samples/supports-core-js/_config.js +++ b/test/form/samples/supports-core-js/_config.js @@ -1,5 +1,6 @@ module.exports = defineTest({ description: 'supports core-js', + verifyAst: false, options: { // check against tree-shake: false when updating the polyfill treeshake: true, diff --git a/test/form/samples/system-uninitialized/_config.js b/test/form/samples/system-uninitialized/_config.js index 871cd4092..685acc69d 100644 --- a/test/form/samples/system-uninitialized/_config.js +++ b/test/form/samples/system-uninitialized/_config.js @@ -1,6 +1,3 @@ -// Changed due to https://github.com/acornjs/acorn/issues/806 -// Consider reverting this change should this become an acorn option - module.exports = defineTest({ description: 'supports uninitialized binding exports', options: { diff --git a/test/form/samples/treeshake-deterministic-dynamic-import/_expected.js b/test/form/samples/treeshake-deterministic-dynamic-import/_expected.js index 8a69e51d0..f8330f85c 100644 --- a/test/form/samples/treeshake-deterministic-dynamic-import/_expected.js +++ b/test/form/samples/treeshake-deterministic-dynamic-import/_expected.js @@ -155,15 +155,6 @@ var bail1$1 = /*#__PURE__*/Object.freeze({ named1: named1 }); -var bail2 = '@included-bail-2'; -const named2 = 'bail2'; - -var bail2$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - default: bail2, - named2: named2 -}); - var bail3 = '@included-bail-3'; const named3 = 'bail3'; @@ -173,6 +164,15 @@ var bail3$1 = /*#__PURE__*/Object.freeze({ named3: named3 }); +var bail2 = '@included-bail-2'; +const named2 = 'bail2'; + +var bail2$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + default: bail2, + named2: named2 +}); + var bail4 = '@included-bail-4'; const named4 = 'bail4'; diff --git a/test/form/samples/unknown-token-effects/_config.js b/test/form/samples/unknown-token-effects/_config.js deleted file mode 100644 index c917c7ca2..000000000 --- a/test/form/samples/unknown-token-effects/_config.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = defineTest({ - description: 'does not tree-shake unknown tokens', - options: { - acornInjectPlugins: Parser => - class extends Parser { - parseExprAtom(referenceDestructuringErrors) { - if (this.type.keyword === 'do') { - this.eat(this.type); - const node = this.startNode(); - node.body = this.parseBlock(); - return this.finishNode(node, 'DoExpression'); - } - return super.parseExprAtom(referenceDestructuringErrors); - } - } - } -}); diff --git a/test/form/samples/unknown-token-effects/_expected.js b/test/form/samples/unknown-token-effects/_expected.js deleted file mode 100644 index ecb186398..000000000 --- a/test/form/samples/unknown-token-effects/_expected.js +++ /dev/null @@ -1,34 +0,0 @@ -(do { - () => console.log('retained'); -}()); -(do { - null; -}.y); -(do { - ({ y: () => console.log('retained') }); -}.y()); -(do { - ({ - set y(value) { - console.log(value); - } - }); -}.y = 'retained'); - -const functionUsedInExpr = () => 1; -const objectUsedInExpr = { value: 2 }; -const valueUsedInExpr = 3; - -const exprValue = do { - if (unknownCondition1) { - functionUsedInExpr(); - } else if (unknownCondition2) { - objectUsedInExpr.value; - } else if (unknownCondition3) { - valueUsedInExpr; - } else { - 'direct value'; - } -}; - -export { exprValue }; diff --git a/test/form/samples/unknown-token-effects/main.js b/test/form/samples/unknown-token-effects/main.js deleted file mode 100644 index 624210488..000000000 --- a/test/form/samples/unknown-token-effects/main.js +++ /dev/null @@ -1,32 +0,0 @@ -(do { - () => console.log('retained'); -}()); -(do { - null; -}.y); -(do { - ({ y: () => console.log('retained') }); -}.y()); -(do { - ({ - set y(value) { - console.log(value); - } - }); -}.y = 'retained'); - -const functionUsedInExpr = () => 1; -const objectUsedInExpr = { value: 2 }; -const valueUsedInExpr = 3; - -export const exprValue = do { - if (unknownCondition1) { - functionUsedInExpr(); - } else if (unknownCondition2) { - objectUsedInExpr.value; - } else if (unknownCondition3) { - valueUsedInExpr; - } else { - 'direct value' - } -}; diff --git a/test/function/index.js b/test/function/index.js index d00b26669..ddf4fbaa8 100644 --- a/test/function/index.js +++ b/test/function/index.js @@ -5,7 +5,12 @@ const path = require('node:path'); */ // @ts-expect-error not included in types const rollup = require('../../dist/rollup'); -const { compareError, compareLogs, runTestSuiteWithSamples } = require('../utils.js'); +const { + compareError, + compareLogs, + runTestSuiteWithSamples, + verifyAstPlugin +} = require('../utils.js'); function requireWithContext(code, context, exports) { const module = { exports }; @@ -67,6 +72,14 @@ runTestSuiteWithSamples( process.chdir(directory); const logs = []; const warnings = []; + const plugins = + config.verifyAst === false + ? config.options?.plugins + : config.options?.plugins === undefined + ? verifyAstPlugin + : Array.isArray(config.options.plugins) + ? [...config.options.plugins, verifyAstPlugin] + : config.options.plugins; return rollup .rollup({ @@ -78,7 +91,8 @@ runTestSuiteWithSamples( } }, strictDeprecations: true, - ...config.options + ...config.options, + plugins }) .then(bundle => { let unintendedError; diff --git a/test/function/samples/add-watch-file-generate/_config.js b/test/function/samples/add-watch-file-generate/_config.js index 1a36f9f8a..862acfce3 100644 --- a/test/function/samples/add-watch-file-generate/_config.js +++ b/test/function/samples/add-watch-file-generate/_config.js @@ -3,12 +3,14 @@ const path = require('node:path'); module.exports = defineTest({ description: 'throws when adding watch files during generate', options: { - plugins: { - name: 'test-plugin', - renderStart() { - this.addWatchFile(path.join(__dirname, 'watched.js')); + plugins: [ + { + name: 'test-plugin', + renderStart() { + this.addWatchFile(path.join(__dirname, 'watched.js')); + } } - } + ] }, generateError: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/allow-reserved/_config.js b/test/function/samples/allow-reserved/_config.js deleted file mode 100644 index 810d2959e..000000000 --- a/test/function/samples/allow-reserved/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = defineTest({ - description: 'allow reserved identifiers via custom acorn options', - options: { - acorn: { - allowReserved: true - } - } -}); diff --git a/test/function/samples/allow-reserved/main.js b/test/function/samples/allow-reserved/main.js deleted file mode 100644 index 00782b93d..000000000 --- a/test/function/samples/allow-reserved/main.js +++ /dev/null @@ -1,4 +0,0 @@ -var x = function await() { - return 42; -}; -assert.equal(x(), 42); diff --git a/test/function/samples/bundle-facade-order/_config.js b/test/function/samples/bundle-facade-order/_config.js index 9dd3332ec..2c45be4d5 100644 --- a/test/function/samples/bundle-facade-order/_config.js +++ b/test/function/samples/bundle-facade-order/_config.js @@ -8,21 +8,23 @@ module.exports = defineTest({ 'main-alias': 'main', other: 'other' }, - plugins: { - name: 'test-plugin', - generateBundle(options, bundle) { - assert.deepStrictEqual( - Object.keys(bundle).map(id => [id, bundle[id].code]), - [ - ['main.js', "'use strict';\n\nvar main = 'main1';\n\nmodule.exports = main;\n"], - ['other.js', "'use strict';\n\nvar other = 'main2';\n\nmodule.exports = other;\n"], + plugins: [ + { + name: 'test-plugin', + generateBundle(options, bundle) { + assert.deepStrictEqual( + Object.keys(bundle).map(id => [id, bundle[id].code]), [ - 'main-alias.js', - "'use strict';\n\nvar main = require('./main.js');\n\n\n\nmodule.exports = main;\n" + ['main.js', "'use strict';\n\nvar main = 'main1';\n\nmodule.exports = main;\n"], + ['other.js', "'use strict';\n\nvar other = 'main2';\n\nmodule.exports = other;\n"], + [ + 'main-alias.js', + "'use strict';\n\nvar main = require('./main.js');\n\n\n\nmodule.exports = main;\n" + ] ] - ] - ); + ); + } } - } + ] } }); diff --git a/test/function/samples/call-marked-pure-with-plugin-parse-ast/_config.js b/test/function/samples/call-marked-pure-with-plugin-parse-ast/_config.js index 9fe44391a..d736faba6 100644 --- a/test/function/samples/call-marked-pure-with-plugin-parse-ast/_config.js +++ b/test/function/samples/call-marked-pure-with-plugin-parse-ast/_config.js @@ -8,11 +8,7 @@ module.exports = defineTest({ plugins: [ { transform(code) { - const comments = []; - const ast = this.parse(code, { onComment: comments }); - if (comments.length != 5 || comments.some(({ value }) => !value.includes('PURE'))) { - throw new Error('failed to get comments'); - } + const ast = this.parse(code); return { ast, code, map: null }; } } diff --git a/test/function/samples/cannot-resolve-sourcemap-warning/_config.js b/test/function/samples/cannot-resolve-sourcemap-warning/_config.js index 89dfd06cd..cfec197b8 100644 --- a/test/function/samples/cannot-resolve-sourcemap-warning/_config.js +++ b/test/function/samples/cannot-resolve-sourcemap-warning/_config.js @@ -4,12 +4,14 @@ const ID_MAIN = path.join(__dirname, 'main.js'); module.exports = defineTest({ description: 'handles when a sourcemap cannot be resolved in a warning', options: { - plugins: { - name: 'test-plugin', - transform() { - return { code: 'export default this', map: { mappings: '' } }; + plugins: [ + { + name: 'test-plugin', + transform() { + return { code: 'export default this', map: { mappings: '' } }; + } } - } + ] }, warnings: [ { diff --git a/test/function/samples/check-exports-exportedBindings-as-a-supplementary-test/_config.js b/test/function/samples/check-exports-exportedBindings-as-a-supplementary-test/_config.js index c2b0ddb5a..dbfddc29c 100644 --- a/test/function/samples/check-exports-exportedBindings-as-a-supplementary-test/_config.js +++ b/test/function/samples/check-exports-exportedBindings-as-a-supplementary-test/_config.js @@ -23,12 +23,14 @@ const expectedResult = { module.exports = defineTest({ description: 'check exports and exportedBindings in moduleParsed as a supplementary test', options: { - plugins: { - name: 'test-plugin', - moduleParsed(moduleInfo) { - const { exports, exportedBindings, id } = moduleInfo; - assert.deepStrictEqual({ exports, exportedBindings }, expectedResult[id]); + plugins: [ + { + name: 'test-plugin', + moduleParsed(moduleInfo) { + const { exports, exportedBindings, id } = moduleInfo; + assert.deepStrictEqual({ exports, exportedBindings }, expectedResult[id]); + } } - } + ] } }); diff --git a/test/function/samples/context-resolve/_config.js b/test/function/samples/context-resolve/_config.js index 680305939..985585d5c 100644 --- a/test/function/samples/context-resolve/_config.js +++ b/test/function/samples/context-resolve/_config.js @@ -6,7 +6,7 @@ const tests = [ source: './existing', expected: { id: path.join(__dirname, 'existing.js'), - assertions: {}, + attributes: {}, external: false, meta: {}, resolvedBy: 'rollup', @@ -26,7 +26,7 @@ const tests = [ source: './marked-directly-external-relative', expected: { id: path.join(__dirname, 'marked-directly-external-relative'), - assertions: {}, + attributes: {}, external: true, meta: {}, moduleSideEffects: true, @@ -38,7 +38,7 @@ const tests = [ source: './marked-external-relative', expected: { id: path.join(__dirname, 'marked-external-relative'), - assertions: {}, + attributes: {}, external: true, meta: {}, moduleSideEffects: true, @@ -50,7 +50,7 @@ const tests = [ source: 'marked-external-absolute', expected: { id: 'marked-external-absolute', - assertions: {}, + attributes: {}, external: true, meta: {}, moduleSideEffects: true, @@ -62,7 +62,7 @@ const tests = [ source: 'resolved-name', expected: { id: 'resolved:resolved-name', - assertions: {}, + attributes: {}, external: false, meta: {}, moduleSideEffects: true, @@ -74,7 +74,7 @@ const tests = [ source: 'resolved-false', expected: { id: 'resolved-false', - assertions: {}, + attributes: {}, external: true, meta: {}, resolvedBy: 'rollup', @@ -86,7 +86,7 @@ const tests = [ source: 'resolved-object', expected: { id: 'resolved:resolved-object', - assertions: {}, + attributes: {}, external: false, meta: {}, moduleSideEffects: true, @@ -98,7 +98,7 @@ const tests = [ source: 'resolved-object-non-external', expected: { id: 'resolved:resolved-object-non-external', - assertions: {}, + attributes: {}, external: false, meta: {}, moduleSideEffects: true, @@ -110,7 +110,7 @@ const tests = [ source: 'resolved-object-external', expected: { id: 'resolved:resolved-object-external', - assertions: {}, + attributes: {}, external: true, meta: {}, moduleSideEffects: true, diff --git a/test/function/samples/deprecated/dynamic-import-name-warn/_config.js b/test/function/samples/deprecated/dynamic-import-name-warn/_config.js index 60e45b2b3..611625380 100644 --- a/test/function/samples/deprecated/dynamic-import-name-warn/_config.js +++ b/test/function/samples/deprecated/dynamic-import-name-warn/_config.js @@ -11,11 +11,13 @@ module.exports = defineTest({ options: { strictDeprecations: false, input: 'main.js', - plugins: { - resolveDynamicImport() { - return false; + plugins: [ + { + resolveDynamicImport() { + return false; + } } - }, + ], output: { dynamicImportFunction: 'myImporter', format: 'cjs', diff --git a/test/function/samples/deprecated/dynamic-import-name/_config.js b/test/function/samples/deprecated/dynamic-import-name/_config.js index 6a93ad208..123c660a5 100644 --- a/test/function/samples/deprecated/dynamic-import-name/_config.js +++ b/test/function/samples/deprecated/dynamic-import-name/_config.js @@ -12,11 +12,13 @@ module.exports = defineTest({ options: { strictDeprecations: false, input: 'main.js', - plugins: { - resolveDynamicImport() { - return false; + plugins: [ + { + resolveDynamicImport() { + return false; + } } - }, + ], output: { dynamicImportFunction: 'myImporter', format: 'es' diff --git a/test/function/samples/deprecated/inline-dynamic-imports-bundle/_config.js b/test/function/samples/deprecated/inline-dynamic-imports-bundle/_config.js index 3a1c929fc..d62ae029e 100644 --- a/test/function/samples/deprecated/inline-dynamic-imports-bundle/_config.js +++ b/test/function/samples/deprecated/inline-dynamic-imports-bundle/_config.js @@ -6,14 +6,16 @@ module.exports = defineTest({ options: { strictDeprecations: false, inlineDynamicImports: true, - plugins: { - generateBundle(options, bundle) { - assert.deepStrictEqual(Object.keys(bundle['main.js'].modules), [ - path.join(__dirname, 'lib.js'), - path.join(__dirname, 'main.js') - ]); + plugins: [ + { + generateBundle(options, bundle) { + assert.deepStrictEqual(Object.keys(bundle['main.js'].modules), [ + path.join(__dirname, 'lib.js'), + path.join(__dirname, 'main.js') + ]); + } } - } + ] }, warnings: [ { diff --git a/test/function/samples/deprecated/manual-chunks-info/_config.js b/test/function/samples/deprecated/manual-chunks-info/_config.js index 6a7d57050..816969b70 100644 --- a/test/function/samples/deprecated/manual-chunks-info/_config.js +++ b/test/function/samples/deprecated/manual-chunks-info/_config.js @@ -20,7 +20,7 @@ module.exports = defineTest({ { [getId('dynamic')]: { id: getId('dynamic'), - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -81,7 +81,7 @@ module.exports = defineTest({ code: "export const promise = import('external');\nexport { default as internal } from './lib';\n", dynamicallyImportedIdResolutions: [ { - assertions: {}, + attributes: {}, external: true, id: 'external', meta: {}, @@ -100,7 +100,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: getId('lib'), meta: {}, @@ -119,7 +119,7 @@ module.exports = defineTest({ }, [getId('lib')]: { id: getId('lib'), - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -155,7 +155,7 @@ module.exports = defineTest({ }, [getId('main')]: { id: getId('main'), - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -238,7 +238,7 @@ module.exports = defineTest({ code: "export const promise = import('./dynamic');\nexport { default as value } from './lib';\nexport { external } from 'external';\n", dynamicallyImportedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: getId('dynamic'), meta: {}, @@ -257,7 +257,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: getId('lib'), meta: {}, @@ -266,7 +266,7 @@ module.exports = defineTest({ syntheticNamedExports: false }, { - assertions: {}, + attributes: {}, external: true, id: 'external', meta: {}, @@ -285,7 +285,7 @@ module.exports = defineTest({ }, external: { id: 'external', - assertions: {}, + attributes: {}, ast: null, code: null, dynamicallyImportedIdResolutions: [], diff --git a/test/function/samples/deprecated/plugin-module-ids/_config.js b/test/function/samples/deprecated/plugin-module-ids/_config.js index e296b0c91..576b77cc4 100644 --- a/test/function/samples/deprecated/plugin-module-ids/_config.js +++ b/test/function/samples/deprecated/plugin-module-ids/_config.js @@ -8,16 +8,18 @@ module.exports = defineTest({ options: { strictDeprecations: false, external: ['path'], - plugins: { - renderStart() { - rendered = true; - assert.deepStrictEqual([...this.moduleIds].sort(), [ - path.join(__dirname, 'foo.js'), - path.join(__dirname, 'main.js'), - 'path' - ]); + plugins: [ + { + renderStart() { + rendered = true; + assert.deepStrictEqual([...this.moduleIds].sort(), [ + path.join(__dirname, 'foo.js'), + path.join(__dirname, 'main.js'), + 'path' + ]); + } } - } + ] }, bundle() { assert.ok(rendered); diff --git a/test/function/samples/deprecated/resolve-id-external/_config.js b/test/function/samples/deprecated/resolve-id-external/_config.js index c1cb13a30..fc6c913dc 100644 --- a/test/function/samples/deprecated/resolve-id-external/_config.js +++ b/test/function/samples/deprecated/resolve-id-external/_config.js @@ -35,47 +35,49 @@ module.exports = defineTest({ return JSON.parse(id.split('-')[3]); } }, - plugins: { - name: 'test-plugin', - resolveId(id) { - if (!path.isAbsolute(id)) { - return { - id, - external: true, - moduleSideEffects: JSON.parse(id.split('-')[1]) - }; - } - }, - buildEnd() { - assert.deepStrictEqual( - getObject( - [...this.getModuleIds()] - .filter(id => !path.isAbsolute(id)) - .map(id => [id, this.getModuleInfo(id).hasModuleSideEffects]) - ), - { - 'sideeffects-false-usereffects-false': false, - 'sideeffects-false-usereffects-false-unused-import': false, - 'sideeffects-false-usereffects-false-used-import': false, - 'sideeffects-false-usereffects-true': false, - 'sideeffects-false-usereffects-true-unused-import': false, - 'sideeffects-false-usereffects-true-used-import': false, - 'sideeffects-null-usereffects-false': false, - 'sideeffects-null-usereffects-false-unused-import': false, - 'sideeffects-null-usereffects-false-used-import': false, - 'sideeffects-null-usereffects-true': true, - 'sideeffects-null-usereffects-true-unused-import': true, - 'sideeffects-null-usereffects-true-used-import': true, - 'sideeffects-true-usereffects-false': true, - 'sideeffects-true-usereffects-false-unused-import': true, - 'sideeffects-true-usereffects-false-used-import': true, - 'sideeffects-true-usereffects-true': true, - 'sideeffects-true-usereffects-true-unused-import': true, - 'sideeffects-true-usereffects-true-used-import': true + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (!path.isAbsolute(id)) { + return { + id, + external: true, + moduleSideEffects: JSON.parse(id.split('-')[1]) + }; } - ); + }, + buildEnd() { + assert.deepStrictEqual( + getObject( + [...this.getModuleIds()] + .filter(id => !path.isAbsolute(id)) + .map(id => [id, this.getModuleInfo(id).hasModuleSideEffects]) + ), + { + 'sideeffects-false-usereffects-false': false, + 'sideeffects-false-usereffects-false-unused-import': false, + 'sideeffects-false-usereffects-false-used-import': false, + 'sideeffects-false-usereffects-true': false, + 'sideeffects-false-usereffects-true-unused-import': false, + 'sideeffects-false-usereffects-true-used-import': false, + 'sideeffects-null-usereffects-false': false, + 'sideeffects-null-usereffects-false-unused-import': false, + 'sideeffects-null-usereffects-false-used-import': false, + 'sideeffects-null-usereffects-true': true, + 'sideeffects-null-usereffects-true-unused-import': true, + 'sideeffects-null-usereffects-true-used-import': true, + 'sideeffects-true-usereffects-false': true, + 'sideeffects-true-usereffects-false-unused-import': true, + 'sideeffects-true-usereffects-false-used-import': true, + 'sideeffects-true-usereffects-true': true, + 'sideeffects-true-usereffects-true-unused-import': true, + 'sideeffects-true-usereffects-true-used-import': true + } + ); + } } - } + ] }, warnings(warnings) { for (const warning of warnings) { diff --git a/test/function/samples/deprecated/resolve-id/_config.js b/test/function/samples/deprecated/resolve-id/_config.js index 825b6a69a..c7f4077a8 100644 --- a/test/function/samples/deprecated/resolve-id/_config.js +++ b/test/function/samples/deprecated/resolve-id/_config.js @@ -33,58 +33,60 @@ module.exports = defineTest({ return JSON.parse(id.split('-')[3]); } }, - plugins: { - name: 'test-plugin', - resolveId(id) { - if (!path.isAbsolute(id)) { - return { - id, - external: false, - moduleSideEffects: JSON.parse(id.split('-')[1]) - }; - } - }, - load(id) { - if (!path.isAbsolute(id)) { - const sideEffects = JSON.parse(id.split('-')[1]); - const userEffects = JSON.parse(id.split('-')[3]); - assert.strictEqual( - this.getModuleInfo(id).hasModuleSideEffects, - typeof sideEffects === 'boolean' ? sideEffects : userEffects + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (!path.isAbsolute(id)) { + return { + id, + external: false, + moduleSideEffects: JSON.parse(id.split('-')[1]) + }; + } + }, + load(id) { + if (!path.isAbsolute(id)) { + const sideEffects = JSON.parse(id.split('-')[1]); + const userEffects = JSON.parse(id.split('-')[3]); + assert.strictEqual( + this.getModuleInfo(id).hasModuleSideEffects, + typeof sideEffects === 'boolean' ? sideEffects : userEffects + ); + return `export const value = '${id}'; sideEffects.push(value);`; + } + }, + buildEnd() { + assert.deepStrictEqual( + getObject( + [...this.getModuleIds()] + .filter(id => !path.isAbsolute(id)) + .map(id => [id, this.getModuleInfo(id).hasModuleSideEffects]) + ), + { + 'sideeffects-false-usereffects-false': false, + 'sideeffects-false-usereffects-false-unused-import': false, + 'sideeffects-false-usereffects-false-used-import': false, + 'sideeffects-false-usereffects-true': false, + 'sideeffects-false-usereffects-true-unused-import': false, + 'sideeffects-false-usereffects-true-used-import': false, + 'sideeffects-null-usereffects-false': false, + 'sideeffects-null-usereffects-false-unused-import': false, + 'sideeffects-null-usereffects-false-used-import': false, + 'sideeffects-null-usereffects-true': true, + 'sideeffects-null-usereffects-true-unused-import': true, + 'sideeffects-null-usereffects-true-used-import': true, + 'sideeffects-true-usereffects-false': true, + 'sideeffects-true-usereffects-false-unused-import': true, + 'sideeffects-true-usereffects-false-used-import': true, + 'sideeffects-true-usereffects-true': true, + 'sideeffects-true-usereffects-true-unused-import': true, + 'sideeffects-true-usereffects-true-used-import': true + } ); - return `export const value = '${id}'; sideEffects.push(value);`; } - }, - buildEnd() { - assert.deepStrictEqual( - getObject( - [...this.getModuleIds()] - .filter(id => !path.isAbsolute(id)) - .map(id => [id, this.getModuleInfo(id).hasModuleSideEffects]) - ), - { - 'sideeffects-false-usereffects-false': false, - 'sideeffects-false-usereffects-false-unused-import': false, - 'sideeffects-false-usereffects-false-used-import': false, - 'sideeffects-false-usereffects-true': false, - 'sideeffects-false-usereffects-true-unused-import': false, - 'sideeffects-false-usereffects-true-used-import': false, - 'sideeffects-null-usereffects-false': false, - 'sideeffects-null-usereffects-false-unused-import': false, - 'sideeffects-null-usereffects-false-used-import': false, - 'sideeffects-null-usereffects-true': true, - 'sideeffects-null-usereffects-true-unused-import': true, - 'sideeffects-null-usereffects-true-used-import': true, - 'sideeffects-true-usereffects-false': true, - 'sideeffects-true-usereffects-false-unused-import': true, - 'sideeffects-true-usereffects-false-used-import': true, - 'sideeffects-true-usereffects-true': true, - 'sideeffects-true-usereffects-true-unused-import': true, - 'sideeffects-true-usereffects-true-used-import': true - } - ); } - } + ] }, warnings(warnings) { for (const warning of warnings) { diff --git a/test/function/samples/deprecations/externalImportAssertions/_config.js b/test/function/samples/deprecations/externalImportAssertions/_config.js new file mode 100644 index 000000000..ef167bd3a --- /dev/null +++ b/test/function/samples/deprecations/externalImportAssertions/_config.js @@ -0,0 +1,12 @@ +module.exports = defineTest({ + description: 'marks the "output.externalImportAssertions" option as deprecated', + options: { + output: { externalImportAssertions: false } + }, + generateError: { + code: 'DEPRECATED_FEATURE', + message: + 'The "output.externalImportAssertions" option is deprecated. Use the "output.externalImportAttributes" option instead.', + url: 'https://rollupjs.org/configuration-options/#output-externalimportattributes' + } +}); diff --git a/test/function/samples/deprecations/externalImportAssertions/_expected.js b/test/function/samples/deprecations/externalImportAssertions/_expected.js new file mode 100644 index 000000000..2d4172646 --- /dev/null +++ b/test/function/samples/deprecations/externalImportAssertions/_expected.js @@ -0,0 +1,6 @@ +import('external'); +import(globalThis.unknown); +import('resolvedString'); +import('resolved-id'); +import('resolved-different'); +import('unresolved'); diff --git a/test/function/samples/deprecations/externalImportAssertions/main.js b/test/function/samples/deprecations/externalImportAssertions/main.js new file mode 100644 index 000000000..38bfed638 --- /dev/null +++ b/test/function/samples/deprecations/externalImportAssertions/main.js @@ -0,0 +1,6 @@ +import('external', { assert: { type: 'special' } }); +import(globalThis.unknown, { assert: { type: 'special' } }); +import(`external-${globalThis.unknown}`, { assert: { type: 'special' } }); +import('external' + globalThis.unknown, { assert: { type: 'special' } }); +import('external-resolved', { assert: { type: 'special' } }); +import('unresolved', { assert: { type: 'special' } }); diff --git a/test/function/samples/deprecations/plugin-module-ids/_config.js b/test/function/samples/deprecations/plugin-module-ids/_config.js index 0b49a46c9..627a5c399 100644 --- a/test/function/samples/deprecations/plugin-module-ids/_config.js +++ b/test/function/samples/deprecations/plugin-module-ids/_config.js @@ -2,12 +2,14 @@ module.exports = defineTest({ description: 'provides all module ids on the plugin context', options: { external: ['path'], - plugins: { - name: 'test', - renderStart() { - console.log([...this.moduleIds]); + plugins: [ + { + name: 'test', + renderStart() { + console.log([...this.moduleIds]); + } } - } + ] }, generateError: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/double-default-export/_config.js b/test/function/samples/double-default-export/_config.js index a6760044b..f6643d7ef 100644 --- a/test/function/samples/double-default-export/_config.js +++ b/test/function/samples/double-default-export/_config.js @@ -6,28 +6,23 @@ module.exports = defineTest({ description: 'throws on double default exports', error: { cause: { - loc: { - column: 7, - line: 2 - }, - message: "Duplicate export 'default' (2:7)", - pos: 25, - raisedAt: 34 + message: 'the name `default` is exported multiple times', + pos: 18 }, code: 'PARSE_ERROR', - message: `Duplicate export 'default'`, + message: 'the name `default` is exported multiple times', id: ID_FOO, - pos: 25, + pos: 18, watchFiles: [ID_FOO, ID_MAIN], loc: { file: ID_FOO, line: 2, - column: 7 + column: 0 }, frame: ` 1: export default 1; 2: export default 2; - ^ + ^ ` } }); diff --git a/test/function/samples/double-named-export/_config.js b/test/function/samples/double-named-export/_config.js index 7e671029a..e8131fd68 100644 --- a/test/function/samples/double-named-export/_config.js +++ b/test/function/samples/double-named-export/_config.js @@ -6,16 +6,11 @@ module.exports = defineTest({ description: 'throws on duplicate named exports', error: { cause: { - loc: { - column: 9, - line: 3 - }, - message: "Duplicate export 'foo' (3:9)", - pos: 38, - raisedAt: 43 + message: 'the name `foo` is exported multiple times', + pos: 38 }, code: 'PARSE_ERROR', - message: `Duplicate export 'foo'`, + message: 'the name `foo` is exported multiple times', id: ID_FOO, pos: 38, watchFiles: [ID_FOO, ID_MAIN], diff --git a/test/function/samples/double-named-reexport/_config.js b/test/function/samples/double-named-reexport/_config.js index 4488a569c..68f71c1db 100644 --- a/test/function/samples/double-named-reexport/_config.js +++ b/test/function/samples/double-named-reexport/_config.js @@ -6,16 +6,11 @@ module.exports = defineTest({ description: 'throws on duplicate named exports', error: { cause: { - loc: { - column: 9, - line: 3 - }, - message: "Duplicate export 'foo' (3:9)", - pos: 38, - raisedAt: 43 + message: 'the name `foo` is exported multiple times', + pos: 38 }, code: 'PARSE_ERROR', - message: `Duplicate export 'foo'`, + message: 'the name `foo` is exported multiple times', id: ID_FOO, pos: 38, watchFiles: [ID_FOO, ID_MAIN], diff --git a/test/function/samples/duplicate-import-fails/_config.js b/test/function/samples/duplicate-import-fails/_config.js index f4dee4a93..14450a068 100644 --- a/test/function/samples/duplicate-import-fails/_config.js +++ b/test/function/samples/duplicate-import-fails/_config.js @@ -5,16 +5,11 @@ module.exports = defineTest({ description: 'disallows duplicate imports', error: { cause: { - loc: { - column: 9, - line: 2 - }, - message: "Identifier 'a' has already been declared (2:9)", - pos: 36, - raisedAt: 39 + message: 'the name `a` is defined multiple times', + pos: 36 }, code: 'PARSE_ERROR', - message: `Identifier 'a' has already been declared`, + message: 'the name `a` is defined multiple times', id: ID_MAIN, pos: 36, watchFiles: [ID_MAIN], diff --git a/test/function/samples/duplicate-import-specifier-fails/_config.js b/test/function/samples/duplicate-import-specifier-fails/_config.js index 17dd9bafc..2ea759b83 100644 --- a/test/function/samples/duplicate-import-specifier-fails/_config.js +++ b/test/function/samples/duplicate-import-specifier-fails/_config.js @@ -5,16 +5,11 @@ module.exports = defineTest({ description: 'disallows duplicate import specifiers', error: { cause: { - loc: { - column: 12, - line: 1 - }, - message: "Identifier 'a' has already been declared (1:12)", - pos: 12, - raisedAt: 15 + message: 'the name `a` is defined multiple times', + pos: 12 }, code: 'PARSE_ERROR', - message: `Identifier 'a' has already been declared`, + message: 'the name `a` is defined multiple times', id: ID_MAIN, pos: 12, watchFiles: [ID_MAIN], diff --git a/test/function/samples/emit-chunk-hash/_config.js b/test/function/samples/emit-chunk-hash/_config.js index cf145f5a8..625408540 100644 --- a/test/function/samples/emit-chunk-hash/_config.js +++ b/test/function/samples/emit-chunk-hash/_config.js @@ -8,13 +8,15 @@ module.exports = defineTest({ output: { chunkFileNames: '[name]-[hash].js' }, - plugins: { - buildStart() { - referenceId = this.emitFile({ type: 'chunk', id: 'emitted' }); - }, - generateBundle() { - assert.strictEqual(this.getFileName(referenceId), 'emitted-38bdd9b2.js'); + plugins: [ + { + buildStart() { + referenceId = this.emitFile({ type: 'chunk', id: 'emitted' }); + }, + generateBundle() { + assert.strictEqual(this.getFileName(referenceId), 'emitted-38bdd9b2.js'); + } } - } + ] } }); diff --git a/test/function/samples/emit-chunk-manual-asset-source/_config.js b/test/function/samples/emit-chunk-manual-asset-source/_config.js index 36dd0dcc4..8faf60754 100644 --- a/test/function/samples/emit-chunk-manual-asset-source/_config.js +++ b/test/function/samples/emit-chunk-manual-asset-source/_config.js @@ -8,20 +8,22 @@ module.exports = defineTest({ manualChunks: { foo: ['manual.js'] }, assetFileNames: '[name]-[hash][extname]' }, - plugins: { - transform(code, id) { - if (id.endsWith('manual.js')) { - referenceId = this.emitFile({ type: 'asset', name: 'emitted.txt' }); + plugins: [ + { + transform(code, id) { + if (id.endsWith('manual.js')) { + referenceId = this.emitFile({ type: 'asset', name: 'emitted.txt' }); + } + }, + moduleParsed({ id }) { + if (id.endsWith('manual.js')) { + this.setAssetSource(referenceId, 'emitted'); + } + }, + generateBundle() { + assert.strictEqual(this.getFileName(referenceId), 'emitted-f57bfbce.txt'); } - }, - moduleParsed({ id }) { - if (id.endsWith('manual.js')) { - this.setAssetSource(referenceId, 'emitted'); - } - }, - generateBundle() { - assert.strictEqual(this.getFileName(referenceId), 'emitted-f57bfbce.txt'); } - } + ] } }); diff --git a/test/function/samples/emit-chunk-manual/_config.js b/test/function/samples/emit-chunk-manual/_config.js index 09e17c86d..d9d513c58 100644 --- a/test/function/samples/emit-chunk-manual/_config.js +++ b/test/function/samples/emit-chunk-manual/_config.js @@ -8,15 +8,17 @@ module.exports = defineTest({ manualChunks: { foo: ['manual.js'] }, assetFileNames: '[name]-[hash][extname]' }, - plugins: { - transform(code, id) { - if (id.endsWith('manual.js')) { - referenceId = this.emitFile({ type: 'asset', name: 'emitted.txt', source: 'emitted' }); + plugins: [ + { + transform(code, id) { + if (id.endsWith('manual.js')) { + referenceId = this.emitFile({ type: 'asset', name: 'emitted.txt', source: 'emitted' }); + } + }, + generateBundle() { + assert.strictEqual(this.getFileName(referenceId), 'emitted-f57bfbce.txt'); } - }, - generateBundle() { - assert.strictEqual(this.getFileName(referenceId), 'emitted-f57bfbce.txt'); } - } + ] } }); diff --git a/test/function/samples/emit-file/asset-source-invalid/_config.js b/test/function/samples/emit-file/asset-source-invalid/_config.js index e7176b36e..276756509 100644 --- a/test/function/samples/emit-file/asset-source-invalid/_config.js +++ b/test/function/samples/emit-file/asset-source-invalid/_config.js @@ -1,13 +1,15 @@ module.exports = defineTest({ description: 'throws when setting an empty asset source', options: { - plugins: { - name: 'test-plugin', - buildStart() { - const assetId = this.emitFile({ type: 'asset', name: 'test.ext' }); - this.setAssetSource(assetId, null); + plugins: [ + { + name: 'test-plugin', + buildStart() { + const assetId = this.emitFile({ type: 'asset', name: 'test.ext' }); + this.setAssetSource(assetId, null); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/asset-source-invalid2/_config.js b/test/function/samples/emit-file/asset-source-invalid2/_config.js index f835adc9b..8edc13a8c 100644 --- a/test/function/samples/emit-file/asset-source-invalid2/_config.js +++ b/test/function/samples/emit-file/asset-source-invalid2/_config.js @@ -1,13 +1,15 @@ module.exports = defineTest({ description: 'throws when setting an empty asset source', options: { - plugins: { - name: 'test-plugin', - buildStart() { - const assetId = this.emitFile({ type: 'asset', fileName: 'test.ext' }); - this.setAssetSource(assetId, null); + plugins: [ + { + name: 'test-plugin', + buildStart() { + const assetId = this.emitFile({ type: 'asset', fileName: 'test.ext' }); + this.setAssetSource(assetId, null); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/asset-source-invalid3/_config.js b/test/function/samples/emit-file/asset-source-invalid3/_config.js index 0cf25fa9a..a5a2754f2 100644 --- a/test/function/samples/emit-file/asset-source-invalid3/_config.js +++ b/test/function/samples/emit-file/asset-source-invalid3/_config.js @@ -1,13 +1,15 @@ module.exports = defineTest({ description: 'throws when setting an empty asset source', options: { - plugins: { - name: 'test-plugin', - buildStart() { - const assetId = this.emitFile({ type: 'asset' }); - this.setAssetSource(assetId, null); + plugins: [ + { + name: 'test-plugin', + buildStart() { + const assetId = this.emitFile({ type: 'asset' }); + this.setAssetSource(assetId, null); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/asset-source-invalid4/_config.js b/test/function/samples/emit-file/asset-source-invalid4/_config.js index e1b66fa77..1f13ddf8c 100644 --- a/test/function/samples/emit-file/asset-source-invalid4/_config.js +++ b/test/function/samples/emit-file/asset-source-invalid4/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'throws when setting an empty asset source', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ type: 'asset', source: null }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ type: 'asset', source: null }); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/asset-source-missing/_config.js b/test/function/samples/emit-file/asset-source-missing/_config.js index 5989d82a6..544d0a299 100644 --- a/test/function/samples/emit-file/asset-source-missing/_config.js +++ b/test/function/samples/emit-file/asset-source-missing/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'throws when not setting the asset source', options: { - plugins: { - name: 'test-plugin', - load() { - this.emitFile({ type: 'asset', name: 'test.ext' }); + plugins: [ + { + name: 'test-plugin', + load() { + this.emitFile({ type: 'asset', name: 'test.ext' }); + } } - } + ] }, generateError: { code: 'ASSET_SOURCE_MISSING', diff --git a/test/function/samples/emit-file/asset-source-missing2/_config.js b/test/function/samples/emit-file/asset-source-missing2/_config.js index b2ec171c5..f4a4f1330 100644 --- a/test/function/samples/emit-file/asset-source-missing2/_config.js +++ b/test/function/samples/emit-file/asset-source-missing2/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'throws when not setting the asset source', options: { - plugins: { - name: 'test-plugin', - load() { - this.emitFile({ type: 'asset' }); + plugins: [ + { + name: 'test-plugin', + load() { + this.emitFile({ type: 'asset' }); + } } - } + ] }, generateError: { code: 'ASSET_SOURCE_MISSING', diff --git a/test/function/samples/emit-file/asset-source-missing3/_config.js b/test/function/samples/emit-file/asset-source-missing3/_config.js index f924cf85b..09537c85b 100644 --- a/test/function/samples/emit-file/asset-source-missing3/_config.js +++ b/test/function/samples/emit-file/asset-source-missing3/_config.js @@ -1,13 +1,15 @@ module.exports = defineTest({ description: 'throws when accessing the file name before the asset source is set', options: { - plugins: { - name: 'test-plugin', - buildStart() { - const assetId = this.emitFile({ type: 'asset', name: 'test.ext' }); - this.getFileName(assetId); + plugins: [ + { + name: 'test-plugin', + buildStart() { + const assetId = this.emitFile({ type: 'asset', name: 'test.ext' }); + this.getFileName(assetId); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/asset-source-missing4/_config.js b/test/function/samples/emit-file/asset-source-missing4/_config.js index 9e1b27eb3..82200e980 100644 --- a/test/function/samples/emit-file/asset-source-missing4/_config.js +++ b/test/function/samples/emit-file/asset-source-missing4/_config.js @@ -1,13 +1,15 @@ module.exports = defineTest({ description: 'throws when accessing the file name before the asset source is set', options: { - plugins: { - name: 'test-plugin', - buildStart() { - const assetId = this.emitFile({ type: 'asset' }); - this.getFileName(assetId); + plugins: [ + { + name: 'test-plugin', + buildStart() { + const assetId = this.emitFile({ type: 'asset' }); + this.getFileName(assetId); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/asset-source-missing5/_config.js b/test/function/samples/emit-file/asset-source-missing5/_config.js index 346496edb..eb24df981 100644 --- a/test/function/samples/emit-file/asset-source-missing5/_config.js +++ b/test/function/samples/emit-file/asset-source-missing5/_config.js @@ -1,15 +1,17 @@ module.exports = defineTest({ description: 'throws when not setting the asset source and accessing the asset URL', options: { - plugins: { - name: 'test-plugin', - load() { - return `export default import.meta.ROLLUP_FILE_URL_${this.emitFile({ - type: 'asset', - name: 'test.ext' - })};`; + plugins: [ + { + name: 'test-plugin', + load() { + return `export default import.meta.ROLLUP_FILE_URL_${this.emitFile({ + type: 'asset', + name: 'test.ext' + })};`; + } } - } + ] }, generateError: { code: 'ASSET_NOT_FINALISED', diff --git a/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/_config.js b/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/_config.js index 065cde79c..38735eaa0 100644 --- a/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/_config.js +++ b/test/function/samples/emit-file/chunk-filename-not-available-buildEnd/_config.js @@ -4,15 +4,17 @@ module.exports = defineTest({ description: 'Throws when accessing the filename before it has been generated in buildEnd', options: { input: 'main.js', - plugins: { - name: 'test-plugin', - buildStart() { - chunkId = this.emitFile({ type: 'chunk', id: 'chunk.js' }); - }, - buildEnd() { - this.getFileName(chunkId); + plugins: [ + { + name: 'test-plugin', + buildStart() { + chunkId = this.emitFile({ type: 'chunk', id: 'chunk.js' }); + }, + buildEnd() { + this.getFileName(chunkId); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/chunk-filename-not-available-renderStart/_config.js b/test/function/samples/emit-file/chunk-filename-not-available-renderStart/_config.js index 8879dc2cb..ce3bb7634 100644 --- a/test/function/samples/emit-file/chunk-filename-not-available-renderStart/_config.js +++ b/test/function/samples/emit-file/chunk-filename-not-available-renderStart/_config.js @@ -4,15 +4,17 @@ module.exports = defineTest({ description: 'Throws when accessing the filename before it has been generated in renderStart', options: { input: 'main.js', - plugins: { - name: 'test-plugin', - buildStart() { - chunkId = this.emitFile({ type: 'chunk', id: 'chunk.js' }); - }, - renderStart() { - this.getFileName(chunkId); + plugins: [ + { + name: 'test-plugin', + buildStart() { + chunkId = this.emitFile({ type: 'chunk', id: 'chunk.js' }); + }, + renderStart() { + this.getFileName(chunkId); + } } - } + ] }, generateError: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/chunk-filename-not-available/_config.js b/test/function/samples/emit-file/chunk-filename-not-available/_config.js index 9eaa429e4..0d7d45e91 100644 --- a/test/function/samples/emit-file/chunk-filename-not-available/_config.js +++ b/test/function/samples/emit-file/chunk-filename-not-available/_config.js @@ -2,13 +2,15 @@ module.exports = defineTest({ description: 'Throws when accessing the filename before it has been generated', options: { input: 'main.js', - plugins: { - name: 'test-plugin', - buildStart() { - const chunkId = this.emitFile({ type: 'chunk', id: 'chunk.js' }); - this.getFileName(chunkId); + plugins: [ + { + name: 'test-plugin', + buildStart() { + const chunkId = this.emitFile({ type: 'chunk', id: 'chunk.js' }); + this.getFileName(chunkId); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/chunk-not-found/_config.js b/test/function/samples/emit-file/chunk-not-found/_config.js index ebfa97a6b..458540b30 100644 --- a/test/function/samples/emit-file/chunk-not-found/_config.js +++ b/test/function/samples/emit-file/chunk-not-found/_config.js @@ -5,11 +5,13 @@ module.exports = defineTest({ description: 'Throws if an emitted entry chunk cannot be resolved', options: { input: 'main.js', - plugins: { - buildStart() { - this.emitFile({ type: 'chunk', id: 'not-found.js' }); + plugins: [ + { + buildStart() { + this.emitFile({ type: 'chunk', id: 'not-found.js' }); + } } - } + ] }, error: { code: 'UNRESOLVED_ENTRY', diff --git a/test/function/samples/emit-file/emit-from-output-options/_config.js b/test/function/samples/emit-file/emit-from-output-options/_config.js index ddbf0a832..67c990065 100644 --- a/test/function/samples/emit-file/emit-from-output-options/_config.js +++ b/test/function/samples/emit-file/emit-from-output-options/_config.js @@ -2,14 +2,16 @@ module.exports = defineTest({ description: 'throws when trying to emit files from the outputOptions hook', options: { input: 'main', - plugins: { - outputOptions() { - this.emitFile({ - type: 'asset', - source: 'asset' - }); + plugins: [ + { + outputOptions() { + this.emitFile({ + type: 'asset', + source: 'asset' + }); + } } - } + ] }, generateError: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/file-references-in-bundle/_config.js b/test/function/samples/emit-file/file-references-in-bundle/_config.js index 3f676dc34..815c35b56 100644 --- a/test/function/samples/emit-file/file-references-in-bundle/_config.js +++ b/test/function/samples/emit-file/file-references-in-bundle/_config.js @@ -5,28 +5,30 @@ module.exports = defineTest({ description: 'lists referenced files in the bundle', options: { input: 'main', - plugins: { - transform() { - return `export const asset = import.meta.ROLLUP_FILE_URL_${this.emitFile({ - type: 'asset', - name: 'asset.txt', - source: 'asset' - })};\nexport const chunk = import.meta.ROLLUP_FILE_URL_${this.emitFile({ - type: 'chunk', - id: 'ref.js' - })};\nexport const urlEncoding = import.meta.ROLLUP_FILE_URL_${this.emitFile({ - type: 'chunk', - id: 'My%2FFile.js' - })}`; - }, - generateBundle(options, bundle) { - assert.deepStrictEqual(bundle['main.js'].referencedFiles, [ - 'assets/asset.txt', - 'chunks/ref.js', - 'chunks/My%2FFile.js' - ]); + plugins: [ + { + transform() { + return `export const asset = import.meta.ROLLUP_FILE_URL_${this.emitFile({ + type: 'asset', + name: 'asset.txt', + source: 'asset' + })};\nexport const chunk = import.meta.ROLLUP_FILE_URL_${this.emitFile({ + type: 'chunk', + id: 'ref.js' + })};\nexport const urlEncoding = import.meta.ROLLUP_FILE_URL_${this.emitFile({ + type: 'chunk', + id: 'My%2FFile.js' + })}`; + }, + generateBundle(options, bundle) { + assert.deepStrictEqual(bundle['main.js'].referencedFiles, [ + 'assets/asset.txt', + 'chunks/ref.js', + 'chunks/My%2FFile.js' + ]); + } } - }, + ], output: { assetFileNames: 'assets/[name][extname]', chunkFileNames: 'chunks/[name].js' diff --git a/test/function/samples/emit-file/invalid-asset-name/_config.js b/test/function/samples/emit-file/invalid-asset-name/_config.js index acaa2f0f8..27e2dd184 100644 --- a/test/function/samples/emit-file/invalid-asset-name/_config.js +++ b/test/function/samples/emit-file/invalid-asset-name/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'throws for invalid asset names', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ type: 'asset', name: '/test.ext', source: 'content' }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ type: 'asset', name: '/test.ext', source: 'content' }); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/invalid-asset-name3/_config.js b/test/function/samples/emit-file/invalid-asset-name3/_config.js index bd071edc7..a882176e1 100644 --- a/test/function/samples/emit-file/invalid-asset-name3/_config.js +++ b/test/function/samples/emit-file/invalid-asset-name3/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'throws for invalid asset names with absolute path on Windows OS', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ type: 'asset', name: 'F:\\test.ext', source: 'content' }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ type: 'asset', name: 'F:\\test.ext', source: 'content' }); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/invalid-chunk-id/_config.js b/test/function/samples/emit-file/invalid-chunk-id/_config.js index d72840d73..9b168b7fb 100644 --- a/test/function/samples/emit-file/invalid-chunk-id/_config.js +++ b/test/function/samples/emit-file/invalid-chunk-id/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'throws for invalid chunk ids', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ type: 'chunk', id: null }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ type: 'chunk', id: null }); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/invalid-file-type/_config.js b/test/function/samples/emit-file/invalid-file-type/_config.js index a34d42ee7..32d7ffaf4 100644 --- a/test/function/samples/emit-file/invalid-file-type/_config.js +++ b/test/function/samples/emit-file/invalid-file-type/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'throws for invalid file types', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ type: 'unknown' }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ type: 'unknown' }); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/invalid-prebuilt-chunk-filename/_config.js b/test/function/samples/emit-file/invalid-prebuilt-chunk-filename/_config.js index dd4e8d9ad..36035d57c 100644 --- a/test/function/samples/emit-file/invalid-prebuilt-chunk-filename/_config.js +++ b/test/function/samples/emit-file/invalid-prebuilt-chunk-filename/_config.js @@ -1,15 +1,17 @@ module.exports = defineTest({ description: 'throws for invalid prebuilt chunks filename', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ - type: 'prebuilt-chunk', - code: 'console.log("my-chunk")' - }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ + type: 'prebuilt-chunk', + code: 'console.log("my-chunk")' + }); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/invalid-prebuit-chunk-code/_config.js b/test/function/samples/emit-file/invalid-prebuit-chunk-code/_config.js index f93d6727f..5b02a32bf 100644 --- a/test/function/samples/emit-file/invalid-prebuit-chunk-code/_config.js +++ b/test/function/samples/emit-file/invalid-prebuit-chunk-code/_config.js @@ -1,15 +1,17 @@ module.exports = defineTest({ description: 'throws for invalid prebuilt chunks code', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ - type: 'prebuilt-chunk', - fileName: 'my-chunk.js' - }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ + type: 'prebuilt-chunk', + fileName: 'my-chunk.js' + }); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/invalid-reference-id/_config.js b/test/function/samples/emit-file/invalid-reference-id/_config.js index e12a5463e..b7589ef7e 100644 --- a/test/function/samples/emit-file/invalid-reference-id/_config.js +++ b/test/function/samples/emit-file/invalid-reference-id/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'throws for invalid reference ids', options: { - plugins: { - name: 'test-plugin', - load() { - return `export default import.meta.ROLLUP_FILE_URL_invalid;`; + plugins: [ + { + name: 'test-plugin', + load() { + return `export default import.meta.ROLLUP_FILE_URL_invalid;`; + } } - } + ] }, generateError: { code: 'FILE_NOT_FOUND', diff --git a/test/function/samples/emit-file/invalid-set-asset-source-id/_config.js b/test/function/samples/emit-file/invalid-set-asset-source-id/_config.js index ea28ec801..a47185b38 100644 --- a/test/function/samples/emit-file/invalid-set-asset-source-id/_config.js +++ b/test/function/samples/emit-file/invalid-set-asset-source-id/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'throws for invalid asset ids', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.setAssetSource('invalid', 'content'); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.setAssetSource('invalid', 'content'); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/modules-loaded/_config.js b/test/function/samples/emit-file/modules-loaded/_config.js index 9e76edeff..c6b726214 100644 --- a/test/function/samples/emit-file/modules-loaded/_config.js +++ b/test/function/samples/emit-file/modules-loaded/_config.js @@ -2,12 +2,14 @@ module.exports = defineTest({ description: 'Throws when adding a chunk after the modules have finished loading', options: { input: 'main.js', - plugins: { - name: 'test-plugin', - buildEnd() { - this.emitFile({ type: 'chunk', id: 'chunk.js' }); + plugins: [ + { + name: 'test-plugin', + buildEnd() { + this.emitFile({ type: 'chunk', id: 'chunk.js' }); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/no-input/_config.js b/test/function/samples/emit-file/no-input/_config.js index 0665e74b5..e6eaaf3ee 100644 --- a/test/function/samples/emit-file/no-input/_config.js +++ b/test/function/samples/emit-file/no-input/_config.js @@ -2,11 +2,13 @@ module.exports = defineTest({ description: 'It is not necessary to provide an input if a dynamic entry is emitted', options: { input: undefined, - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ type: 'chunk', id: 'chunk.js' }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ type: 'chunk', id: 'chunk.js' }); + } } - } + ] } }); diff --git a/test/function/samples/emit-file/set-asset-source-chunk/_config.js b/test/function/samples/emit-file/set-asset-source-chunk/_config.js index ede439795..0ee34ff46 100644 --- a/test/function/samples/emit-file/set-asset-source-chunk/_config.js +++ b/test/function/samples/emit-file/set-asset-source-chunk/_config.js @@ -1,13 +1,15 @@ module.exports = defineTest({ description: 'throws when trying to set the asset source of a chunk', options: { - plugins: { - name: 'test-plugin', - buildStart() { - const referenceId = this.emitFile({ type: 'chunk', id: 'chunk' }); - this.setAssetSource(referenceId, 'hello world'); + plugins: [ + { + name: 'test-plugin', + buildStart() { + const referenceId = this.emitFile({ type: 'chunk', id: 'chunk' }); + this.setAssetSource(referenceId, 'hello world'); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/set-asset-source-transform/_config.js b/test/function/samples/emit-file/set-asset-source-transform/_config.js index 667055fdb..246c294ed 100644 --- a/test/function/samples/emit-file/set-asset-source-transform/_config.js +++ b/test/function/samples/emit-file/set-asset-source-transform/_config.js @@ -3,14 +3,16 @@ const path = require('node:path'); module.exports = defineTest({ description: 'throws when setting the asset source in the transform hook', options: { - plugins: { - name: 'test-plugin', - transform(code) { - const assetId = this.emitFile({ type: 'asset', name: 'test.ext' }); - this.setAssetSource(assetId, 'asdf'); - return code; + plugins: [ + { + name: 'test-plugin', + transform(code) { + const assetId = this.emitFile({ type: 'asset', name: 'test.ext' }); + this.setAssetSource(assetId, 'asdf'); + return code; + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/set-asset-source-twice/_config.js b/test/function/samples/emit-file/set-asset-source-twice/_config.js index 695ed5de0..fd06baa2b 100644 --- a/test/function/samples/emit-file/set-asset-source-twice/_config.js +++ b/test/function/samples/emit-file/set-asset-source-twice/_config.js @@ -1,14 +1,16 @@ module.exports = defineTest({ description: 'throws when setting the asset source twice', options: { - plugins: { - name: 'test-plugin', - buildEnd() { - const assetId = this.emitFile({ type: 'asset', name: 'test.ext' }); - this.setAssetSource(assetId, 'hello world'); - this.setAssetSource(assetId, 'another'); + plugins: [ + { + name: 'test-plugin', + buildEnd() { + const assetId = this.emitFile({ type: 'asset', name: 'test.ext' }); + this.setAssetSource(assetId, 'hello world'); + this.setAssetSource(assetId, 'another'); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/set-asset-source-twice2/_config.js b/test/function/samples/emit-file/set-asset-source-twice2/_config.js index 45bcbb9fb..620da4a0c 100644 --- a/test/function/samples/emit-file/set-asset-source-twice2/_config.js +++ b/test/function/samples/emit-file/set-asset-source-twice2/_config.js @@ -1,14 +1,16 @@ module.exports = defineTest({ description: 'throws when setting the asset source twice', options: { - plugins: { - name: 'test-plugin', - buildEnd() { - const assetId = this.emitFile({ type: 'asset' }); - this.setAssetSource(assetId, 'hello world'); - this.setAssetSource(assetId, 'another'); + plugins: [ + { + name: 'test-plugin', + buildEnd() { + const assetId = this.emitFile({ type: 'asset' }); + this.setAssetSource(assetId, 'hello world'); + this.setAssetSource(assetId, 'another'); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/emit-file/set-source-in-output-options/_config.js b/test/function/samples/emit-file/set-source-in-output-options/_config.js index 1f19e4a67..0db140834 100644 --- a/test/function/samples/emit-file/set-source-in-output-options/_config.js +++ b/test/function/samples/emit-file/set-source-in-output-options/_config.js @@ -4,14 +4,16 @@ module.exports = defineTest({ description: 'throws when trying to set file sources in the outputOptions hook', options: { input: 'main', - plugins: { - buildStart() { - referenceId = this.emitFile({ type: 'asset' }); - }, - outputOptions() { - this.setAssetSource(referenceId, 'not allowed'); + plugins: [ + { + buildStart() { + referenceId = this.emitFile({ type: 'asset' }); + }, + outputOptions() { + this.setAssetSource(referenceId, 'not allowed'); + } } - } + ] }, generateError: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/error-parse-json/_config.js b/test/function/samples/error-parse-json/_config.js index d3a36449a..f02689a2b 100644 --- a/test/function/samples/error-parse-json/_config.js +++ b/test/function/samples/error-parse-json/_config.js @@ -8,12 +8,7 @@ module.exports = defineTest({ error: { cause: { pos: 10, - loc: { - line: 2, - column: 8 - }, - raisedAt: 11, - message: 'Unexpected token (2:8)' + message: "Expected ';', '}' or " }, code: 'PARSE_ERROR', id: ID_JSON, @@ -30,6 +25,7 @@ module.exports = defineTest({ 3: } `, watchFiles: [ID_JSON, ID_MAIN], - message: 'Unexpected token (Note that you need @rollup/plugin-json to import JSON files)' + message: + "Expected ';', '}' or (Note that you need @rollup/plugin-json to import JSON files)" } }); diff --git a/test/function/samples/error-parse-unknown-extension/_config.js b/test/function/samples/error-parse-unknown-extension/_config.js index ca130f979..d9268c3cb 100644 --- a/test/function/samples/error-parse-unknown-extension/_config.js +++ b/test/function/samples/error-parse-unknown-extension/_config.js @@ -8,12 +8,7 @@ module.exports = defineTest({ error: { cause: { pos: 0, - loc: { - line: 1, - column: 0 - }, - raisedAt: 1, - message: 'Unexpected token (1:0)' + message: 'Expression expected' }, code: 'PARSE_ERROR', id: ID_CSS, @@ -30,6 +25,7 @@ module.exports = defineTest({ 3: } `, watchFiles: [ID_CSS, ID_MAIN], - message: 'Unexpected token (Note that you need plugins to import files that are not JavaScript)' + message: + 'Expression expected (Note that you need plugins to import files that are not JavaScript)' } }); diff --git a/test/function/samples/export-global/_config.js b/test/function/samples/export-global/_config.js index 888caf9ae..88af9fd8b 100644 --- a/test/function/samples/export-global/_config.js +++ b/test/function/samples/export-global/_config.js @@ -1,12 +1,7 @@ const assert = require('node:assert'); -// This used to be "any global variables in scope can be re-exported" -// This, however, is actually not allowed by the spec and acorn, -// see https://github.com/acornjs/acorn/issues/806 -// Consider reverting this change should this become an acorn option - module.exports = defineTest({ - description: '"variables corresponding to globals can be exported"', + description: 'variables corresponding to globals can be exported', exports(exports) { assert.equal(exports.Buffer, Buffer); diff --git a/test/function/samples/export-global/main.js b/test/function/samples/export-global/main.js index aea02862f..66c7efc94 100644 --- a/test/function/samples/export-global/main.js +++ b/test/function/samples/export-global/main.js @@ -1,2 +1,2 @@ const MyBuffer = Buffer; -export { MyBuffer as Buffer }; +export { MyBuffer as Buffer }; diff --git a/test/function/samples/export-not-at-top-level-fails/_config.js b/test/function/samples/export-not-at-top-level-fails/_config.js index 74eca72d4..a7f314181 100644 --- a/test/function/samples/export-not-at-top-level-fails/_config.js +++ b/test/function/samples/export-not-at-top-level-fails/_config.js @@ -6,12 +6,7 @@ module.exports = defineTest({ error: { cause: { pos: 19, - loc: { - line: 2, - column: 2 - }, - raisedAt: 25, - message: "'import' and 'export' may only appear at the top level (2:2)" + message: "'import', and 'export' cannot be used outside of module code" }, code: 'PARSE_ERROR', id: ID_MAIN, @@ -28,6 +23,6 @@ module.exports = defineTest({ 3: } `, watchFiles: [ID_MAIN], - message: "'import' and 'export' may only appear at the top level" + message: "'import', and 'export' cannot be used outside of module code" } }); diff --git a/test/function/samples/external-entry-point-object/_config.js b/test/function/samples/external-entry-point-object/_config.js index 4618a0f27..d406ffa25 100644 --- a/test/function/samples/external-entry-point-object/_config.js +++ b/test/function/samples/external-entry-point-object/_config.js @@ -1,11 +1,13 @@ module.exports = defineTest({ description: 'throws for entry points that are resolved as an external object by plugins', options: { - plugins: { - resolveId(id) { - return { id, external: true }; + plugins: [ + { + resolveId(id) { + return { id, external: true }; + } } - } + ] }, error: { code: 'UNRESOLVED_ENTRY', diff --git a/test/function/samples/external-entry-point/_config.js b/test/function/samples/external-entry-point/_config.js index bfaa5d822..e4aabd39e 100644 --- a/test/function/samples/external-entry-point/_config.js +++ b/test/function/samples/external-entry-point/_config.js @@ -1,11 +1,13 @@ module.exports = defineTest({ description: 'throws for entry points that are resolved as false by plugins', options: { - plugins: { - resolveId() { - return false; + plugins: [ + { + resolveId() { + return false; + } } - } + ] }, error: { code: 'UNRESOLVED_ENTRY', diff --git a/test/function/samples/external-resolved/_config.js b/test/function/samples/external-resolved/_config.js index 9e00a9bac..9a1826619 100644 --- a/test/function/samples/external-resolved/_config.js +++ b/test/function/samples/external-resolved/_config.js @@ -30,27 +30,29 @@ module.exports = defineTest({ testedIds.push(id); return id.startsWith('resolved'); }, - plugins: { - name: 'test-plugin', - resolveId(source) { - switch (source) { - case 'resolve-string': { - return 'resolved-string'; - } - case 'resolve-external': { - return false; - } - case 'resolve-object': { - return { id: 'resolved-object', external: false }; - } - case 'resolve-object-external': { - return { id: 'resolved-object-external', external: true }; - } - default: { - return null; + plugins: [ + { + name: 'test-plugin', + resolveId(source) { + switch (source) { + case 'resolve-string': { + return 'resolved-string'; + } + case 'resolve-external': { + return false; + } + case 'resolve-object': { + return { id: 'resolved-object', external: false }; + } + case 'resolve-object-external': { + return { id: 'resolved-object-external', external: true }; + } + default: { + return null; + } } } } - } + ] } }); diff --git a/test/function/samples/function-asm-directive/main.js b/test/function/samples/function-asm-directive/main.js index 48744f957..252fa6ccb 100644 --- a/test/function/samples/function-asm-directive/main.js +++ b/test/function/samples/function-asm-directive/main.js @@ -2,4 +2,4 @@ export function a() { "use asm"; return 1; -} \ No newline at end of file +} diff --git a/test/function/samples/function-directive-not-first/main.js b/test/function/samples/function-directive-not-first/main.js index 55e83d932..b37630754 100644 --- a/test/function/samples/function-directive-not-first/main.js +++ b/test/function/samples/function-directive-not-first/main.js @@ -2,4 +2,4 @@ export function a() { const x = 1; "use asm"; return x; -} \ No newline at end of file +} diff --git a/test/function/samples/handle-missing-export-source/_config.js b/test/function/samples/handle-missing-export-source/_config.js index 80f965ccb..4e16bba9b 100644 --- a/test/function/samples/handle-missing-export-source/_config.js +++ b/test/function/samples/handle-missing-export-source/_config.js @@ -1,15 +1,18 @@ module.exports = defineTest({ description: 'does not fail if a pre-generated AST is omitting the source property of an unused named export (#3210)', + verifyAst: false, options: { - plugins: { - transform(code, id) { - if (id.endsWith('foo.js')) { - const ast = this.parse(code); - delete ast.body.find(node => node.type === 'ExportNamedDeclaration').source; - return { code, ast }; + plugins: [ + { + transform(code, id) { + if (id.endsWith('foo.js')) { + const ast = this.parse(code); + delete ast.body.find(node => node.type === 'ExportNamedDeclaration').source; + return { code, ast }; + } } } - } + ] } }); diff --git a/test/function/samples/implicit-dependencies/dependant-dynamic-import-no-effects/_config.js b/test/function/samples/implicit-dependencies/dependant-dynamic-import-no-effects/_config.js index e9ad92105..c5449ab26 100644 --- a/test/function/samples/implicit-dependencies/dependant-dynamic-import-no-effects/_config.js +++ b/test/function/samples/implicit-dependencies/dependant-dynamic-import-no-effects/_config.js @@ -3,16 +3,18 @@ const path = require('node:path'); module.exports = defineTest({ description: 'throws when a module that is loaded before an emitted chunk is fully tree-shaken', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ - type: 'chunk', - id: 'dep.js', - implicitlyLoadedAfterOneOf: ['dependant'] - }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ + type: 'chunk', + id: 'dep.js', + implicitlyLoadedAfterOneOf: ['dependant'] + }); + } } - } + ] }, error: { code: 'MISSING_IMPLICIT_DEPENDANT', diff --git a/test/function/samples/implicit-dependencies/dependant-dynamic-import-not-included/_config.js b/test/function/samples/implicit-dependencies/dependant-dynamic-import-not-included/_config.js index fbc85389e..8050503e3 100644 --- a/test/function/samples/implicit-dependencies/dependant-dynamic-import-not-included/_config.js +++ b/test/function/samples/implicit-dependencies/dependant-dynamic-import-not-included/_config.js @@ -4,21 +4,23 @@ module.exports = defineTest({ description: 'throws when a module that is loaded before an emitted chunk is only linked to the module graph via a tree-shaken dynamic import', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ - type: 'chunk', - id: 'dep1.js', - implicitlyLoadedAfterOneOf: ['dependant'] - }); - this.emitFile({ - type: 'chunk', - id: 'dep2.js', - implicitlyLoadedAfterOneOf: ['dependant'] - }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ + type: 'chunk', + id: 'dep1.js', + implicitlyLoadedAfterOneOf: ['dependant'] + }); + this.emitFile({ + type: 'chunk', + id: 'dep2.js', + implicitlyLoadedAfterOneOf: ['dependant'] + }); + } } - } + ] }, error: { code: 'MISSING_IMPLICIT_DEPENDANT', diff --git a/test/function/samples/implicit-dependencies/dependant-not-part-of-graph/_config.js b/test/function/samples/implicit-dependencies/dependant-not-part-of-graph/_config.js index 1239ea0e1..1f13bd683 100644 --- a/test/function/samples/implicit-dependencies/dependant-not-part-of-graph/_config.js +++ b/test/function/samples/implicit-dependencies/dependant-not-part-of-graph/_config.js @@ -4,26 +4,28 @@ module.exports = defineTest({ description: 'throws when a module that is loaded before an emitted chunk is not part of the module graph', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ - type: 'chunk', - id: 'dep1.js', - implicitlyLoadedAfterOneOf: ['dependant'] - }); - this.emitFile({ - type: 'chunk', - id: 'dep2.js', - implicitlyLoadedAfterOneOf: ['dependant'] - }); - this.emitFile({ - type: 'chunk', - id: 'dep3.js', - implicitlyLoadedAfterOneOf: ['dependant'] - }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ + type: 'chunk', + id: 'dep1.js', + implicitlyLoadedAfterOneOf: ['dependant'] + }); + this.emitFile({ + type: 'chunk', + id: 'dep2.js', + implicitlyLoadedAfterOneOf: ['dependant'] + }); + this.emitFile({ + type: 'chunk', + id: 'dep3.js', + implicitlyLoadedAfterOneOf: ['dependant'] + }); + } } - } + ] }, error: { code: 'MISSING_IMPLICIT_DEPENDANT', diff --git a/test/function/samples/implicit-dependencies/external-dependant/_config.js b/test/function/samples/implicit-dependencies/external-dependant/_config.js index 41d775740..3a44a3bc3 100644 --- a/test/function/samples/implicit-dependencies/external-dependant/_config.js +++ b/test/function/samples/implicit-dependencies/external-dependant/_config.js @@ -3,16 +3,18 @@ const path = require('node:path'); module.exports = defineTest({ description: 'throws when a module that is loaded before an emitted chunk does not exist', options: { - plugins: { - name: 'test-plugin', - buildStart() { - this.emitFile({ - type: 'chunk', - id: 'dep.js', - implicitlyLoadedAfterOneOf: ['does-not-exist'] - }); + plugins: [ + { + name: 'test-plugin', + buildStart() { + this.emitFile({ + type: 'chunk', + id: 'dep.js', + implicitlyLoadedAfterOneOf: ['does-not-exist'] + }); + } } - } + ] }, error: { code: 'MISSING_IMPLICIT_DEPENDANT', diff --git a/test/function/samples/implicit-dependencies/missing-dependant/_config.js b/test/function/samples/implicit-dependencies/missing-dependant/_config.js index 3b833ff05..5fbdd5d7e 100644 --- a/test/function/samples/implicit-dependencies/missing-dependant/_config.js +++ b/test/function/samples/implicit-dependencies/missing-dependant/_config.js @@ -3,21 +3,23 @@ const path = require('node:path'); module.exports = defineTest({ description: 'throws when a module that is loaded before an emitted chunk is external', options: { - plugins: { - name: 'test-plugin', - resolveId(id) { - if (id === 'external') { - return false; + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (id === 'external') { + return false; + } + }, + buildStart() { + this.emitFile({ + type: 'chunk', + id: 'dep.js', + implicitlyLoadedAfterOneOf: ['external'] + }); } - }, - buildStart() { - this.emitFile({ - type: 'chunk', - id: 'dep.js', - implicitlyLoadedAfterOneOf: ['external'] - }); } - } + ] }, error: { code: 'MISSING_IMPLICIT_DEPENDANT', diff --git a/test/function/samples/import-assertions/plugin-assertions-this-resolve/_config.js b/test/function/samples/import-assertions/plugin-assertions-this-resolve/_config.js index fa8f8b69e..982aa5b54 100644 --- a/test/function/samples/import-assertions/plugin-assertions-this-resolve/_config.js +++ b/test/function/samples/import-assertions/plugin-assertions-this-resolve/_config.js @@ -1,7 +1,7 @@ const assert = require('node:assert'); module.exports = defineTest({ - description: 'allows plugins to provide assertions for this.resolve', + description: 'allows plugins to provide attributes for this.resolve', options: { plugins: [ { @@ -10,10 +10,10 @@ module.exports = defineTest({ assert.deepStrictEqual( await this.resolve('external', undefined, { skipSelf: true, - assertions: { a: 'c', b: 'd' } + attributes: { a: 'c', b: 'd' } }), { - assertions: { a: 'changed', b: 'changed' }, + attributes: { a: 'changed', b: 'changed' }, external: true, id: 'external', meta: {}, @@ -26,20 +26,20 @@ module.exports = defineTest({ }, { name: 'second', - async resolveId(source, importer, { assertions }) { + async resolveId(source, importer, { attributes }) { if (source === 'external') { - return this.resolve(source, importer, { assertions, skipSelf: true }); + return this.resolve(source, importer, { attributes, skipSelf: true }); } } }, { name: 'third', - async resolveId(source, importer, { assertions }) { + async resolveId(source, importer, { attributes }) { if (source === 'external') { return { id: source, external: true, - assertions: Object.fromEntries(Object.keys(assertions).map(key => [key, 'changed'])) + attributes: Object.fromEntries(Object.keys(attributes).map(key => [key, 'changed'])) }; } } diff --git a/test/function/samples/import-assertions/warn-assertion-conflicts/_config.js b/test/function/samples/import-assertions/warn-assertion-conflicts/_config.js index 45bfe811d..0b3503d14 100644 --- a/test/function/samples/import-assertions/warn-assertion-conflicts/_config.js +++ b/test/function/samples/import-assertions/warn-assertion-conflicts/_config.js @@ -2,13 +2,13 @@ const path = require('node:path'); const ID_MAIN = path.join(__dirname, 'main.js'); module.exports = defineTest({ - description: 'warns for conflicting import assertions', + description: 'warns for conflicting import attributes', options: { external: id => id.startsWith('external') }, warnings: [ { - code: 'INCONSISTENT_IMPORT_ASSERTIONS', + code: 'INCONSISTENT_IMPORT_ATTRIBUTES', frame: ` 1: import './other.js'; 2: import 'external' assert { type: 'foo' }; @@ -23,11 +23,11 @@ module.exports = defineTest({ line: 3 }, message: - 'Module "main.js" tried to import "external" with "type": "bar" assertions, but it was already imported elsewhere with "type": "foo" assertions. Please ensure that import assertions for the same module are always consistent.', + 'Module "main.js" tried to import "external" with "type": "bar" attributes, but it was already imported elsewhere with "type": "foo" attributes. Please ensure that import attributes for the same module are always consistent.', pos: 63 }, { - code: 'INCONSISTENT_IMPORT_ASSERTIONS', + code: 'INCONSISTENT_IMPORT_ATTRIBUTES', frame: ` 2: import 'external' assert { type: 'foo' }; 3: import 'external' assert { type: 'bar' }; @@ -42,23 +42,23 @@ module.exports = defineTest({ line: 4 }, message: - 'Module "main.js" tried to import "external" with no assertions, but it was already imported elsewhere with "type": "foo" assertions. Please ensure that import assertions for the same module are always consistent.', + 'Module "main.js" tried to import "external" with no attributes, but it was already imported elsewhere with "type": "foo" attributes. Please ensure that import attributes for the same module are always consistent.', pos: 105 }, { - code: 'INCONSISTENT_IMPORT_ASSERTIONS', + code: 'INCONSISTENT_IMPORT_ATTRIBUTES', message: - 'Module "main.js" tried to import "external" with "type": "baz" assertions, but it was already imported elsewhere with "type": "foo" assertions. Please ensure that import assertions for the same module are always consistent.' + 'Module "main.js" tried to import "external" with "type": "baz" attributes, but it was already imported elsewhere with "type": "foo" attributes. Please ensure that import attributes for the same module are always consistent.' }, { - code: 'INCONSISTENT_IMPORT_ASSERTIONS', + code: 'INCONSISTENT_IMPORT_ATTRIBUTES', message: - 'Module "other.js" tried to import "external" with "type": "quuz" assertions, but it was already imported elsewhere with "type": "foo" assertions. Please ensure that import assertions for the same module are always consistent.' + 'Module "other.js" tried to import "external" with "type": "quuz" attributes, but it was already imported elsewhere with "type": "foo" attributes. Please ensure that import attributes for the same module are always consistent.' }, { - code: 'INCONSISTENT_IMPORT_ASSERTIONS', + code: 'INCONSISTENT_IMPORT_ATTRIBUTES', message: - 'Module "other.js" tried to import "dep.js" with "type": "bar" assertions, but it was already imported elsewhere with "type": "foo" assertions. Please ensure that import assertions for the same module are always consistent.' + 'Module "other.js" tried to import "dep.js" with "type": "bar" attributes, but it was already imported elsewhere with "type": "foo" attributes. Please ensure that import attributes for the same module are always consistent.' } ] }); diff --git a/test/function/samples/import-assertions/warn-unresolvable-assertions/_config.js b/test/function/samples/import-assertions/warn-unresolvable-assertions/_config.js new file mode 100644 index 000000000..a5c68b355 --- /dev/null +++ b/test/function/samples/import-assertions/warn-unresolvable-assertions/_config.js @@ -0,0 +1,141 @@ +const path = require('node:path'); +const ID_MAIN = path.join(__dirname, 'main.js'); + +module.exports = defineTest({ + description: 'warns for dynamic import attributes that cannot be resolved', + verifyAst: false, + options: { + external: id => id.startsWith('external') + }, + warnings: [ + { + code: 'INVALID_IMPORT_ATTRIBUTE', + message: + 'Rollup could not statically analyze an import attribute of a dynamic import in "main.js". Import attributes need to have string keys and values. The attribute will be removed.', + id: ID_MAIN, + pos: 0, + loc: { + column: 0, + file: ID_MAIN, + line: 1 + }, + frame: ` + 1: import('external1', undefined); + ^ + 2: import('external2', global); + 3: import('external3', { with: 'invalid' });` + }, + { + code: 'INVALID_IMPORT_ATTRIBUTE', + message: + 'Rollup could not statically analyze an import attribute of a dynamic import in "main.js". Import attributes need to have string keys and values. The attribute will be removed.', + id: ID_MAIN, + pos: 32, + loc: { + column: 0, + file: ID_MAIN, + line: 2 + }, + frame: ` + 1: import('external1', undefined); + 2: import('external2', global); + ^ + 3: import('external3', { with: 'invalid' }); + 4: import('external4', { with: { foo } });` + }, + { + code: 'INVALID_IMPORT_ATTRIBUTE', + message: + 'Rollup could not statically analyze an import attribute of a dynamic import in "main.js". Import attributes need to have string keys and values. The attribute will be removed.', + id: ID_MAIN, + pos: 133, + loc: { + column: 30, + file: ID_MAIN, + line: 4 + }, + frame: ` + 2: import('external2', global); + 3: import('external3', { with: 'invalid' }); + 4: import('external4', { with: { foo } }); + ^ + 5: import('external5', { with: { foo: bar } }); + 6: import('external6', { with: { foo() {} } });` + }, + { + code: 'INVALID_IMPORT_ATTRIBUTE', + message: + 'Rollup could not statically analyze an import attribute of a dynamic import in "main.js". Import attributes need to have string keys and values. The attribute will be removed.', + id: ID_MAIN, + pos: 173, + loc: { + column: 30, + file: ID_MAIN, + line: 5 + }, + frame: ` + 3: import('external3', { with: 'invalid' }); + 4: import('external4', { with: { foo } }); + 5: import('external5', { with: { foo: bar } }); + ^ + 6: import('external6', { with: { foo() {} } }); + 7: import('external7', { with: { [invalid]: 'foo' } });` + }, + { + code: 'INVALID_IMPORT_ATTRIBUTE', + message: + 'Rollup could not statically analyze an import attribute of a dynamic import in "main.js". Import attributes need to have string keys and values. The attribute will be removed.', + id: ID_MAIN, + pos: 218, + loc: { + column: 30, + file: ID_MAIN, + line: 6 + }, + frame: ` + 4: import('external4', { with: { foo } }); + 5: import('external5', { with: { foo: bar } }); + 6: import('external6', { with: { foo() {} } }); + ^ + 7: import('external7', { with: { [invalid]: 'foo' } }); + 8: import('external8', { with: { foo: 'valid' } });` + }, + { + code: 'INVALID_IMPORT_ATTRIBUTE', + message: + 'Rollup could not statically analyze an import attribute of a dynamic import in "main.js". Import attributes need to have string keys and values. The attribute will be removed.', + id: ID_MAIN, + pos: 263, + loc: { + column: 30, + file: ID_MAIN, + line: 7 + }, + frame: ` + 5: import('external5', { with: { foo: bar } }); + 6: import('external6', { with: { foo() {} } }); + 7: import('external7', { with: { [invalid]: 'foo' } }); + ^ + 8: import('external8', { with: { foo: 'valid' } });` + }, + { + code: 'INVALID_IMPORT_ATTRIBUTE', + message: + 'Rollup could not statically analyze the options argument of a dynamic import in "main.js". Dynamic import options need to be an object with a nested attributes object.', + id: ID_MAIN, + pos: 61, + loc: { + column: 0, + file: ID_MAIN, + line: 3 + }, + frame: ` + 1: import('external1', undefined); + 2: import('external2', global); + 3: import('external3', { with: 'invalid' }); + ^ + 4: import('external4', { with: { foo } }); + 5: import('external5', { with: { foo: bar } });` + } + ] +}); diff --git a/test/function/samples/import-assertions/warn-unresolvable-assertions/main.js b/test/function/samples/import-assertions/warn-unresolvable-assertions/main.js new file mode 100644 index 000000000..fdc32760c --- /dev/null +++ b/test/function/samples/import-assertions/warn-unresolvable-assertions/main.js @@ -0,0 +1,8 @@ +import('external1', undefined); +import('external2', global); +import('external3', { with: 'invalid' }); +import('external4', { with: { foo } }); +import('external5', { with: { foo: bar } }); +import('external6', { with: { foo() {} } }); +import('external7', { with: { [invalid]: 'foo' } }); +import('external8', { with: { foo: 'valid' } }); diff --git a/test/function/samples/import-not-at-top-level-fails/_config.js b/test/function/samples/import-not-at-top-level-fails/_config.js index 9cf9999a0..9339c8017 100644 --- a/test/function/samples/import-not-at-top-level-fails/_config.js +++ b/test/function/samples/import-not-at-top-level-fails/_config.js @@ -6,12 +6,7 @@ module.exports = defineTest({ error: { cause: { pos: 19, - loc: { - line: 2, - column: 2 - }, - raisedAt: 25, - message: "'import' and 'export' may only appear at the top level (2:2)" + message: "'import', and 'export' cannot be used outside of module code" }, code: 'PARSE_ERROR', id: ID_MAIN, @@ -28,6 +23,6 @@ module.exports = defineTest({ 3: } `, watchFiles: [ID_MAIN], - message: "'import' and 'export' may only appear at the top level" + message: "'import', and 'export' cannot be used outside of module code" } }); diff --git a/test/function/samples/inline-dynamic-imports-bundle/_config.js b/test/function/samples/inline-dynamic-imports-bundle/_config.js index c5c4a99d7..a0e47b6a7 100644 --- a/test/function/samples/inline-dynamic-imports-bundle/_config.js +++ b/test/function/samples/inline-dynamic-imports-bundle/_config.js @@ -5,13 +5,15 @@ module.exports = defineTest({ description: 'ignores non-bundled modules when inlining dynamic imports', options: { output: { inlineDynamicImports: true }, - plugins: { - generateBundle(options, bundle) { - assert.deepStrictEqual(Object.keys(bundle['main.js'].modules), [ - path.join(__dirname, 'lib.js'), - path.join(__dirname, 'main.js') - ]); + plugins: [ + { + generateBundle(options, bundle) { + assert.deepStrictEqual(Object.keys(bundle['main.js'].modules), [ + path.join(__dirname, 'lib.js'), + path.join(__dirname, 'main.js') + ]); + } } - } + ] } }); diff --git a/test/function/samples/internal-reexports-from-external/_config.js b/test/function/samples/internal-reexports-from-external/_config.js index 88e1dcb3a..ba58c6ea6 100644 --- a/test/function/samples/internal-reexports-from-external/_config.js +++ b/test/function/samples/internal-reexports-from-external/_config.js @@ -6,17 +6,19 @@ module.exports = defineTest({ description: 'supports namespaces with external star reexports', options: { external: ['fs', 'path'], - plugins: { - transform(code, id) { - if (id.endsWith('override.js')) { - return { - code, - syntheticNamedExports: true - }; + plugins: [ + { + transform(code, id) { + if (id.endsWith('override.js')) { + return { + code, + syntheticNamedExports: true + }; + } + return null; } - return null; } - } + ] }, exports(exports) { assert.strictEqual(exports.fs.readFile, fs.readFile); diff --git a/test/function/samples/invalid-addon-hook/_config.js b/test/function/samples/invalid-addon-hook/_config.js index 685dd940e..af0868765 100644 --- a/test/function/samples/invalid-addon-hook/_config.js +++ b/test/function/samples/invalid-addon-hook/_config.js @@ -1,9 +1,7 @@ module.exports = defineTest({ description: 'throws when providing a non-string value for an addon hook', options: { - plugins: { - intro: 42 - } + plugins: [{ intro: 42 }] }, generateError: { code: 'ADDON_ERROR', diff --git a/test/function/samples/manual-chunks-info/_config.js b/test/function/samples/manual-chunks-info/_config.js index 6bcbf2c1c..93dac2272 100644 --- a/test/function/samples/manual-chunks-info/_config.js +++ b/test/function/samples/manual-chunks-info/_config.js @@ -21,7 +21,7 @@ module.exports = defineTest({ { [getId('dynamic')]: { id: getId('dynamic'), - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -82,7 +82,7 @@ module.exports = defineTest({ code: "export const promise = import('external');\nexport { default as internal } from './lib';\n", dynamicallyImportedIdResolutions: [ { - assertions: {}, + attributes: {}, external: true, id: 'external', meta: {}, @@ -101,7 +101,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: getId('lib'), meta: {}, @@ -120,7 +120,7 @@ module.exports = defineTest({ }, [getId('lib')]: { id: getId('lib'), - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -156,7 +156,7 @@ module.exports = defineTest({ }, [getId('main')]: { id: getId('main'), - assertions: {}, + attributes: {}, ast: { type: 'Program', start: 0, @@ -239,7 +239,7 @@ module.exports = defineTest({ code: "export const promise = import('./dynamic');\nexport { default as value } from './lib';\nexport { external } from 'external';\n", dynamicallyImportedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: getId('dynamic'), meta: {}, @@ -262,7 +262,7 @@ module.exports = defineTest({ implicitlyLoadedBefore: [], importedIdResolutions: [ { - assertions: {}, + attributes: {}, external: false, id: getId('lib'), meta: {}, @@ -271,7 +271,7 @@ module.exports = defineTest({ syntheticNamedExports: false }, { - assertions: {}, + attributes: {}, external: true, id: 'external', meta: {}, @@ -290,7 +290,7 @@ module.exports = defineTest({ }, external: { id: 'external', - assertions: {}, + attributes: {}, ast: null, code: null, dynamicallyImportedIdResolutions: [], diff --git a/test/function/samples/module-parsed-hook/_config.js b/test/function/samples/module-parsed-hook/_config.js index 3987d551c..2bc4027b4 100644 --- a/test/function/samples/module-parsed-hook/_config.js +++ b/test/function/samples/module-parsed-hook/_config.js @@ -9,129 +9,131 @@ const ID_DEP = path.join(__dirname, 'dep.js'); module.exports = defineTest({ description: 'calls the moduleParsedHook once a module is parsed', options: { - plugins: { - name: 'test-plugin', - moduleParsed(moduleInfo) { - parsedModules.push(moduleInfo); - }, - buildEnd() { - assert.deepStrictEqual(JSON.parse(JSON.stringify(parsedModules)), [ - { - id: ID_MAIN, - assertions: {}, - ast: { - type: 'Program', - start: 0, - end: 34, - body: [ - { - type: 'ExportNamedDeclaration', - start: 0, - end: 33, - declaration: null, - specifiers: [ - { - type: 'ExportSpecifier', - start: 9, - end: 14, - local: { type: 'Identifier', start: 9, end: 14, name: 'value' }, - exported: { type: 'Identifier', start: 9, end: 14, name: 'value' } - } - ], - source: { - type: 'Literal', - start: 22, - end: 32, - value: './dep.js', - raw: "'./dep.js'" - } - } - ], - sourceType: 'module' - }, - code: "export { value } from './dep.js';\n", - dynamicallyImportedIdResolutions: [], - dynamicallyImportedIds: [], - dynamicImporters: [], - exportedBindings: { '.': [], './dep.js': ['value'] }, - exports: ['value'], - hasDefaultExport: false, - moduleSideEffects: true, - implicitlyLoadedAfterOneOf: [], - implicitlyLoadedBefore: [], - importedIdResolutions: [ - { - assertions: {}, - external: false, - id: ID_DEP, - meta: {}, - moduleSideEffects: true, - resolvedBy: 'rollup', - syntheticNamedExports: false - } - ], - importedIds: [ID_DEP], - importers: [], - isEntry: true, - isExternal: false, - isIncluded: false, - meta: {}, - syntheticNamedExports: false - }, - { - id: ID_DEP, - assertions: {}, - ast: { - type: 'Program', - start: 0, - end: 25, - body: [ - { - type: 'ExportNamedDeclaration', - start: 0, - end: 24, - declaration: { - type: 'VariableDeclaration', - start: 7, - end: 24, - declarations: [ + plugins: [ + { + name: 'test-plugin', + moduleParsed(moduleInfo) { + parsedModules.push(moduleInfo); + }, + buildEnd() { + assert.deepStrictEqual(JSON.parse(JSON.stringify(parsedModules)), [ + { + id: ID_MAIN, + attributes: {}, + ast: { + type: 'Program', + start: 0, + end: 34, + body: [ + { + type: 'ExportNamedDeclaration', + start: 0, + end: 33, + declaration: null, + specifiers: [ { - type: 'VariableDeclarator', - start: 13, - end: 23, - id: { type: 'Identifier', start: 13, end: 18, name: 'value' }, - init: { type: 'Literal', start: 21, end: 23, value: 42, raw: '42' } + type: 'ExportSpecifier', + start: 9, + end: 14, + local: { type: 'Identifier', start: 9, end: 14, name: 'value' }, + exported: { type: 'Identifier', start: 9, end: 14, name: 'value' } } ], - kind: 'const' - }, - specifiers: [], - source: null + source: { + type: 'Literal', + start: 22, + end: 32, + value: './dep.js', + raw: "'./dep.js'" + } + } + ], + sourceType: 'module' + }, + code: "export { value } from './dep.js';\n", + dynamicallyImportedIdResolutions: [], + dynamicallyImportedIds: [], + dynamicImporters: [], + exportedBindings: { '.': [], './dep.js': ['value'] }, + exports: ['value'], + hasDefaultExport: false, + moduleSideEffects: true, + implicitlyLoadedAfterOneOf: [], + implicitlyLoadedBefore: [], + importedIdResolutions: [ + { + attributes: {}, + external: false, + id: ID_DEP, + meta: {}, + moduleSideEffects: true, + resolvedBy: 'rollup', + syntheticNamedExports: false } ], - sourceType: 'module' + importedIds: [ID_DEP], + importers: [], + isEntry: true, + isExternal: false, + isIncluded: false, + meta: {}, + syntheticNamedExports: false }, - code: 'export const value = 42;\n', - dynamicallyImportedIdResolutions: [], - dynamicallyImportedIds: [], - dynamicImporters: [], - exportedBindings: { '.': ['value'] }, - exports: ['value'], - hasDefaultExport: false, - moduleSideEffects: true, - implicitlyLoadedAfterOneOf: [], - implicitlyLoadedBefore: [], - importedIdResolutions: [], - importedIds: [], - importers: [ID_MAIN], - isEntry: false, - isExternal: false, - isIncluded: true, - meta: {}, - syntheticNamedExports: false - } - ]); + { + id: ID_DEP, + attributes: {}, + ast: { + type: 'Program', + start: 0, + end: 25, + body: [ + { + type: 'ExportNamedDeclaration', + start: 0, + end: 24, + declaration: { + type: 'VariableDeclaration', + start: 7, + end: 24, + declarations: [ + { + type: 'VariableDeclarator', + start: 13, + end: 23, + id: { type: 'Identifier', start: 13, end: 18, name: 'value' }, + init: { type: 'Literal', start: 21, end: 23, value: 42, raw: '42' } + } + ], + kind: 'const' + }, + specifiers: [], + source: null + } + ], + sourceType: 'module' + }, + code: 'export const value = 42;\n', + dynamicallyImportedIdResolutions: [], + dynamicallyImportedIds: [], + dynamicImporters: [], + exportedBindings: { '.': ['value'] }, + exports: ['value'], + hasDefaultExport: false, + moduleSideEffects: true, + implicitlyLoadedAfterOneOf: [], + implicitlyLoadedBefore: [], + importedIdResolutions: [], + importedIds: [], + importers: [ID_MAIN], + isEntry: false, + isExternal: false, + isIncluded: true, + meta: {}, + syntheticNamedExports: false + } + ]); + } } - } + ] } }); diff --git a/test/function/samples/module-side-effects/array/_config.js b/test/function/samples/module-side-effects/array/_config.js index 06eb5a435..0b64a85a9 100644 --- a/test/function/samples/module-side-effects/array/_config.js +++ b/test/function/samples/module-side-effects/array/_config.js @@ -35,22 +35,24 @@ module.exports = defineTest({ 'pluginsideeffects-true-external-listed' ] }, - plugins: { - name: 'test-plugin', - resolveId(id) { - if (!path.isAbsolute(id)) { - const moduleSideEffects = JSON.parse(id.split('-')[1]); - if (moduleSideEffects) { - return { id, moduleSideEffects }; + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (!path.isAbsolute(id)) { + const moduleSideEffects = JSON.parse(id.split('-')[1]); + if (moduleSideEffects) { + return { id, moduleSideEffects }; + } + return id; + } + }, + load(id) { + if (!path.isAbsolute(id)) { + return `export const value = '${id}'; sideEffects.push(value);`; } - return id; - } - }, - load(id) { - if (!path.isAbsolute(id)) { - return `export const value = '${id}'; sideEffects.push(value);`; } } - } + ] } }); diff --git a/test/function/samples/module-side-effects/external-false/_config.js b/test/function/samples/module-side-effects/external-false/_config.js index 0b3c82f5f..c1854672f 100644 --- a/test/function/samples/module-side-effects/external-false/_config.js +++ b/test/function/samples/module-side-effects/external-false/_config.js @@ -20,29 +20,31 @@ module.exports = defineTest({ treeshake: { moduleSideEffects: 'no-external' }, - plugins: { - name: 'test-plugin', - resolveId(id) { - if (!path.isAbsolute(id)) { - if (id === 'internal') { - return id; + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (!path.isAbsolute(id)) { + if (id === 'internal') { + return id; + } + if (id === 'implicit-external') { + return null; + } + const moduleSideEffects = JSON.parse(id.split('-')[1]); + if (moduleSideEffects) { + return { id, moduleSideEffects, external: true }; + } + return { id, external: true }; } - if (id === 'implicit-external') { - return null; + }, + load(id) { + if (!path.isAbsolute(id)) { + return `export const value = '${id}'; sideEffects.push(value);`; } - const moduleSideEffects = JSON.parse(id.split('-')[1]); - if (moduleSideEffects) { - return { id, moduleSideEffects, external: true }; - } - return { id, external: true }; - } - }, - load(id) { - if (!path.isAbsolute(id)) { - return `export const value = '${id}'; sideEffects.push(value);`; } } - } + ] }, warnings: [ { diff --git a/test/function/samples/module-side-effects/global-false/_config.js b/test/function/samples/module-side-effects/global-false/_config.js index 828d4ffe4..05f8d9f6e 100644 --- a/test/function/samples/module-side-effects/global-false/_config.js +++ b/test/function/samples/module-side-effects/global-false/_config.js @@ -19,22 +19,24 @@ module.exports = defineTest({ treeshake: { moduleSideEffects: false }, - plugins: { - name: 'test-plugin', - resolveId(id) { - if (!path.isAbsolute(id)) { - const moduleSideEffects = JSON.parse(id.split('-')[1]); - if (moduleSideEffects) { - return { id, moduleSideEffects }; + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (!path.isAbsolute(id)) { + const moduleSideEffects = JSON.parse(id.split('-')[1]); + if (moduleSideEffects) { + return { id, moduleSideEffects }; + } + return id; + } + }, + load(id) { + if (!path.isAbsolute(id)) { + return `export const value = '${id}'; sideEffects.push(value);`; } - return id; - } - }, - load(id) { - if (!path.isAbsolute(id)) { - return `export const value = '${id}'; sideEffects.push(value);`; } } - } + ] } }); diff --git a/test/function/samples/module-side-effects/load/_config.js b/test/function/samples/module-side-effects/load/_config.js index b31dec74d..8937c4ac8 100644 --- a/test/function/samples/module-side-effects/load/_config.js +++ b/test/function/samples/module-side-effects/load/_config.js @@ -23,22 +23,24 @@ module.exports = defineTest({ return JSON.parse(id.split('-')[1]); } }, - plugins: { - name: 'test-plugin', - resolveId(id) { - if (!path.isAbsolute(id)) { - return id; - } - }, - load(id) { - if (!path.isAbsolute(id)) { - const moduleSideEffects = JSON.parse(id.split('-')[3]); - return { - code: `export const value = '${id}'; sideEffects.push(value);`, - moduleSideEffects - }; + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (!path.isAbsolute(id)) { + return id; + } + }, + load(id) { + if (!path.isAbsolute(id)) { + const moduleSideEffects = JSON.parse(id.split('-')[3]); + return { + code: `export const value = '${id}'; sideEffects.push(value);`, + moduleSideEffects + }; + } } } - } + ] } }); diff --git a/test/function/samples/module-side-effects/resolve-id-external/_config.js b/test/function/samples/module-side-effects/resolve-id-external/_config.js index 2e0aa6c06..576cf8386 100644 --- a/test/function/samples/module-side-effects/resolve-id-external/_config.js +++ b/test/function/samples/module-side-effects/resolve-id-external/_config.js @@ -37,48 +37,50 @@ module.exports = defineTest({ return JSON.parse(id.split('-')[3]); } }, - plugins: { - name: 'test-plugin', - resolveId(id) { - if (!path.isAbsolute(id)) { - return { - id, - external: true, - moduleSideEffects: JSON.parse(id.split('-')[1]) - }; - } - }, - buildEnd() { - assert.deepStrictEqual( - getObject( - [...this.getModuleIds()] - .filter(id => !path.isAbsolute(id)) - .sort() - .map(id => [id, this.getModuleInfo(id).moduleSideEffects]) - ), - { - 'sideeffects-false-usereffects-false': false, - 'sideeffects-false-usereffects-false-unused-import': false, - 'sideeffects-false-usereffects-false-used-import': false, - 'sideeffects-false-usereffects-true': false, - 'sideeffects-false-usereffects-true-unused-import': false, - 'sideeffects-false-usereffects-true-used-import': false, - 'sideeffects-null-usereffects-false': false, - 'sideeffects-null-usereffects-false-unused-import': false, - 'sideeffects-null-usereffects-false-used-import': false, - 'sideeffects-null-usereffects-true': true, - 'sideeffects-null-usereffects-true-unused-import': true, - 'sideeffects-null-usereffects-true-used-import': true, - 'sideeffects-true-usereffects-false': true, - 'sideeffects-true-usereffects-false-unused-import': true, - 'sideeffects-true-usereffects-false-used-import': true, - 'sideeffects-true-usereffects-true': true, - 'sideeffects-true-usereffects-true-unused-import': true, - 'sideeffects-true-usereffects-true-used-import': true + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (!path.isAbsolute(id)) { + return { + id, + external: true, + moduleSideEffects: JSON.parse(id.split('-')[1]) + }; } - ); + }, + buildEnd() { + assert.deepStrictEqual( + getObject( + [...this.getModuleIds()] + .filter(id => !path.isAbsolute(id)) + .sort() + .map(id => [id, this.getModuleInfo(id).moduleSideEffects]) + ), + { + 'sideeffects-false-usereffects-false': false, + 'sideeffects-false-usereffects-false-unused-import': false, + 'sideeffects-false-usereffects-false-used-import': false, + 'sideeffects-false-usereffects-true': false, + 'sideeffects-false-usereffects-true-unused-import': false, + 'sideeffects-false-usereffects-true-used-import': false, + 'sideeffects-null-usereffects-false': false, + 'sideeffects-null-usereffects-false-unused-import': false, + 'sideeffects-null-usereffects-false-used-import': false, + 'sideeffects-null-usereffects-true': true, + 'sideeffects-null-usereffects-true-unused-import': true, + 'sideeffects-null-usereffects-true-used-import': true, + 'sideeffects-true-usereffects-false': true, + 'sideeffects-true-usereffects-false-unused-import': true, + 'sideeffects-true-usereffects-false-used-import': true, + 'sideeffects-true-usereffects-true': true, + 'sideeffects-true-usereffects-true-unused-import': true, + 'sideeffects-true-usereffects-true-used-import': true + } + ); + } } - } + ] }, warnings(warnings) { for (const warning of warnings) { diff --git a/test/function/samples/module-side-effects/resolve-id/_config.js b/test/function/samples/module-side-effects/resolve-id/_config.js index 7ad65ab72..22fa2af86 100644 --- a/test/function/samples/module-side-effects/resolve-id/_config.js +++ b/test/function/samples/module-side-effects/resolve-id/_config.js @@ -32,58 +32,60 @@ module.exports = defineTest({ return JSON.parse(id.split('-')[3]); } }, - plugins: { - name: 'test-plugin', - resolveId(id) { - if (!path.isAbsolute(id)) { - return { - id, - external: false, - moduleSideEffects: JSON.parse(id.split('-')[1]) - }; - } - }, - load(id) { - if (!path.isAbsolute(id)) { - const sideEffects = JSON.parse(id.split('-')[1]); - const userEffects = JSON.parse(id.split('-')[3]); - assert.strictEqual( - this.getModuleInfo(id).moduleSideEffects, - typeof sideEffects === 'boolean' ? sideEffects : userEffects + plugins: [ + { + name: 'test-plugin', + resolveId(id) { + if (!path.isAbsolute(id)) { + return { + id, + external: false, + moduleSideEffects: JSON.parse(id.split('-')[1]) + }; + } + }, + load(id) { + if (!path.isAbsolute(id)) { + const sideEffects = JSON.parse(id.split('-')[1]); + const userEffects = JSON.parse(id.split('-')[3]); + assert.strictEqual( + this.getModuleInfo(id).moduleSideEffects, + typeof sideEffects === 'boolean' ? sideEffects : userEffects + ); + return `export const value = '${id}'; sideEffects.push(value);`; + } + }, + buildEnd() { + assert.deepStrictEqual( + getObject( + [...this.getModuleIds()] + .filter(id => !path.isAbsolute(id)) + .sort() + .map(id => [id, this.getModuleInfo(id).moduleSideEffects]) + ), + { + 'sideeffects-false-usereffects-false': false, + 'sideeffects-false-usereffects-false-unused-import': false, + 'sideeffects-false-usereffects-false-used-import': false, + 'sideeffects-false-usereffects-true': false, + 'sideeffects-false-usereffects-true-unused-import': false, + 'sideeffects-false-usereffects-true-used-import': false, + 'sideeffects-null-usereffects-false': false, + 'sideeffects-null-usereffects-false-unused-import': false, + 'sideeffects-null-usereffects-false-used-import': false, + 'sideeffects-null-usereffects-true': true, + 'sideeffects-null-usereffects-true-unused-import': true, + 'sideeffects-null-usereffects-true-used-import': true, + 'sideeffects-true-usereffects-false': true, + 'sideeffects-true-usereffects-false-unused-import': true, + 'sideeffects-true-usereffects-false-used-import': true, + 'sideeffects-true-usereffects-true': true, + 'sideeffects-true-usereffects-true-unused-import': true, + 'sideeffects-true-usereffects-true-used-import': true + } ); - return `export const value = '${id}'; sideEffects.push(value);`; } - }, - buildEnd() { - assert.deepStrictEqual( - getObject( - [...this.getModuleIds()] - .filter(id => !path.isAbsolute(id)) - .sort() - .map(id => [id, this.getModuleInfo(id).moduleSideEffects]) - ), - { - 'sideeffects-false-usereffects-false': false, - 'sideeffects-false-usereffects-false-unused-import': false, - 'sideeffects-false-usereffects-false-used-import': false, - 'sideeffects-false-usereffects-true': false, - 'sideeffects-false-usereffects-true-unused-import': false, - 'sideeffects-false-usereffects-true-used-import': false, - 'sideeffects-null-usereffects-false': false, - 'sideeffects-null-usereffects-false-unused-import': false, - 'sideeffects-null-usereffects-false-used-import': false, - 'sideeffects-null-usereffects-true': true, - 'sideeffects-null-usereffects-true-unused-import': true, - 'sideeffects-null-usereffects-true-used-import': true, - 'sideeffects-true-usereffects-false': true, - 'sideeffects-true-usereffects-false-unused-import': true, - 'sideeffects-true-usereffects-false-used-import': true, - 'sideeffects-true-usereffects-true': true, - 'sideeffects-true-usereffects-true-unused-import': true, - 'sideeffects-true-usereffects-true-used-import': true - } - ); } - } + ] } }); diff --git a/test/function/samples/non-function-hook-async/_config.js b/test/function/samples/non-function-hook-async/_config.js index fb9aabc78..615a143ee 100644 --- a/test/function/samples/non-function-hook-async/_config.js +++ b/test/function/samples/non-function-hook-async/_config.js @@ -1,9 +1,7 @@ module.exports = defineTest({ description: 'throws when providing a value for an async function hook', options: { - plugins: { - resolveId: 'value' - } + plugins: [{ resolveId: 'value' }] }, error: { code: 'INVALID_PLUGIN_HOOK', diff --git a/test/function/samples/non-function-hook-sync/_config.js b/test/function/samples/non-function-hook-sync/_config.js index f592d0883..3c7e75e4c 100644 --- a/test/function/samples/non-function-hook-sync/_config.js +++ b/test/function/samples/non-function-hook-sync/_config.js @@ -1,9 +1,11 @@ module.exports = defineTest({ description: 'throws when providing a value for a sync function hook', options: { - plugins: { - outputOptions: 'value' - } + plugins: [ + { + outputOptions: 'value' + } + ] }, generateError: { code: 'INVALID_PLUGIN_HOOK', diff --git a/test/function/samples/optional-catch-binding/_config.js b/test/function/samples/optional-catch-binding/_config.js index 5f8cc6162..5ecb6a927 100644 --- a/test/function/samples/optional-catch-binding/_config.js +++ b/test/function/samples/optional-catch-binding/_config.js @@ -1,7 +1,7 @@ const assert = require('node:assert'); module.exports = defineTest({ - description: 'allows optional catch binding with appropriate acorn settings', + description: 'allows optional catch binding', exports(exports) { assert.equal(exports.foo, true); } diff --git a/test/function/samples/options-async-hook/_config.js b/test/function/samples/options-async-hook/_config.js index 382cb0bac..c9d67b796 100644 --- a/test/function/samples/options-async-hook/_config.js +++ b/test/function/samples/options-async-hook/_config.js @@ -3,6 +3,7 @@ const { promises: fs } = require('node:fs'); module.exports = defineTest({ description: 'resolves promises between sequential options hooks', + verifyAst: false, options: { input: 'super-unused', treeshake: false, diff --git a/test/function/samples/options-hook/_config.js b/test/function/samples/options-hook/_config.js index 4eba7691f..c428caf5c 100644 --- a/test/function/samples/options-hook/_config.js +++ b/test/function/samples/options-hook/_config.js @@ -2,54 +2,50 @@ const assert = require('node:assert'); module.exports = defineTest({ description: 'allows to read and modify options in the options hook', + verifyAst: false, options: { input: 'unused', treeshake: false, - plugins: { - name: 'test-plugin', - buildStart(options) { - assert.deepStrictEqual(JSON.parse(JSON.stringify(options)), { - acorn: { - ecmaVersion: 'latest', - sourceType: 'module' - }, - acornInjectPlugins: [null], - context: 'undefined', - experimentalCacheExpiry: 10, - experimentalLogSideEffects: false, - input: ['used'], - logLevel: 'info', - makeAbsoluteExternalsRelative: 'ifRelativeSource', - maxParallelFileOps: 20, - maxParallelFileReads: 20, - perf: false, - plugins: [ - { - name: 'test-plugin' - } - ], - preserveEntrySignatures: 'exports-only', - preserveSymlinks: false, - shimMissingExports: false, - strictDeprecations: true, - treeshake: false - }); - assert.ok(/^\d+\.\d+\.\d+/.test(this.meta.rollupVersion)); - assert.strictEqual(this.meta.watchMode, false); - }, - options(options) { - assert.deepStrictEqual(JSON.parse(JSON.stringify(options)), { - input: 'unused', - plugins: { - name: 'test-plugin' - }, - strictDeprecations: true, - treeshake: false - }); - assert.ok(/^\d+\.\d+\.\d+/.test(this.meta.rollupVersion)); - assert.strictEqual(this.meta.watchMode, false); - return { ...options, input: 'used' }; + plugins: [ + { + name: 'test-plugin', + buildStart(options) { + assert.deepStrictEqual(JSON.parse(JSON.stringify(options)), { + context: 'undefined', + experimentalCacheExpiry: 10, + experimentalLogSideEffects: false, + input: ['used'], + logLevel: 'info', + makeAbsoluteExternalsRelative: 'ifRelativeSource', + maxParallelFileOps: 20, + maxParallelFileReads: 20, + perf: false, + plugins: [ + { + name: 'test-plugin' + } + ], + preserveEntrySignatures: 'exports-only', + preserveSymlinks: false, + shimMissingExports: false, + strictDeprecations: true, + treeshake: false + }); + assert.ok(/^\d+\.\d+\.\d+/.test(this.meta.rollupVersion)); + assert.strictEqual(this.meta.watchMode, false); + }, + options(options) { + assert.deepStrictEqual(JSON.parse(JSON.stringify(options)), { + input: 'unused', + plugins: [{ name: 'test-plugin' }], + strictDeprecations: true, + treeshake: false + }); + assert.ok(/^\d+\.\d+\.\d+/.test(this.meta.rollupVersion)); + assert.strictEqual(this.meta.watchMode, false); + return { ...options, input: 'used' }; + } } - } + ] } }); diff --git a/test/function/samples/options-in-renderstart/_config.js b/test/function/samples/options-in-renderstart/_config.js index 5ffe74bfa..1e4c7b38b 100644 --- a/test/function/samples/options-in-renderstart/_config.js +++ b/test/function/samples/options-in-renderstart/_config.js @@ -5,19 +5,23 @@ module.exports = defineTest({ description: 'makes input and output options available in renderStart', options: { context: 'global', - plugins: { - name: 'input-plugin', - renderStart(outputOptions, inputOptions) { - checkedOptions.push('input-plugin', outputOptions.format, inputOptions.context); - } - }, - output: { - plugins: { - name: 'output-plugin', + plugins: [ + { + name: 'input-plugin', renderStart(outputOptions, inputOptions) { - checkedOptions.push('output-plugin', outputOptions.format, inputOptions.context); + checkedOptions.push('input-plugin', outputOptions.format, inputOptions.context); } } + ], + output: { + plugins: [ + { + name: 'output-plugin', + renderStart(outputOptions, inputOptions) { + checkedOptions.push('output-plugin', outputOptions.format, inputOptions.context); + } + } + ] } }, exports: () => { diff --git a/test/function/samples/output-options-hook/_config.js b/test/function/samples/output-options-hook/_config.js index e967acfc4..5c3d6e338 100644 --- a/test/function/samples/output-options-hook/_config.js +++ b/test/function/samples/output-options-hook/_config.js @@ -12,68 +12,71 @@ module.exports = defineTest({ output: { banner: "throw new Error('unused')" }, - plugins: { - name: 'test-plugin', - renderChunk(code, chunk, options) { - assert.deepStrictEqual(JSON.parse(JSON.stringify(options)), { - amd: { - define: 'define', - autoId: false, - forceJsExtensionForImports: false - }, - assetFileNames: 'assets/[name]-[hash][extname]', - chunkFileNames: '[name]-[hash].js', - compact: false, - dynamicImportInCjs: true, - entryFileNames: '[name].js', - esModule: 'if-default-prop', - experimentalDeepDynamicChunkOptimization: false, - experimentalMinChunkSize: 1, - exports: 'auto', - extend: false, - externalImportAssertions: true, - externalLiveBindings: true, - format: 'cjs', - freeze: true, - generatedCode: { - arrowFunctions: false, - constBindings: false, - objectShorthand: false, - reservedNamesAsProps: true, - symbols: false - }, - globals: {}, - hoistTransitiveImports: true, - indent: true, - inlineDynamicImports: false, - manualChunks: {}, - minifyInternalExports: false, - namespaceToStringTag: false, - noConflict: false, - paths: {}, - plugins: [], - preferConst: false, - preserveModules: false, - sourcemap: false, - sourcemapExcludeSources: false, - strict: true, - systemNullSetters: true, - validate: false - }); - assert.strictEqual(options.banner(), 'exports.bar = 43;'); - assert.ok(/^\d+\.\d+\.\d+/.test(this.meta.rollupVersion)); - assert.strictEqual(this.meta.watchMode, false); - }, - outputOptions(options) { - assert.deepStrictEqual(JSON.parse(JSON.stringify(options)), { - banner: "throw new Error('unused')", - exports: 'auto', - format: 'cjs' - }); - assert.ok(/^\d+\.\d+\.\d+/.test(this.meta.rollupVersion)); - assert.strictEqual(this.meta.watchMode, false); - return { ...options, banner: 'exports.bar = 43;' }; + plugins: [ + { + name: 'test-plugin', + renderChunk(code, chunk, options) { + assert.deepStrictEqual(JSON.parse(JSON.stringify(options)), { + amd: { + define: 'define', + autoId: false, + forceJsExtensionForImports: false + }, + assetFileNames: 'assets/[name]-[hash][extname]', + chunkFileNames: '[name]-[hash].js', + compact: false, + dynamicImportInCjs: true, + entryFileNames: '[name].js', + esModule: 'if-default-prop', + experimentalDeepDynamicChunkOptimization: false, + experimentalMinChunkSize: 1, + exports: 'auto', + extend: false, + externalImportAssertions: true, + externalImportAttributes: true, + externalLiveBindings: true, + format: 'cjs', + freeze: true, + generatedCode: { + arrowFunctions: false, + constBindings: false, + objectShorthand: false, + reservedNamesAsProps: true, + symbols: false + }, + globals: {}, + hoistTransitiveImports: true, + indent: true, + inlineDynamicImports: false, + manualChunks: {}, + minifyInternalExports: false, + namespaceToStringTag: false, + noConflict: false, + paths: {}, + plugins: [], + preferConst: false, + preserveModules: false, + sourcemap: false, + sourcemapExcludeSources: false, + strict: true, + systemNullSetters: true, + validate: false + }); + assert.strictEqual(options.banner(), 'exports.bar = 43;'); + assert.ok(/^\d+\.\d+\.\d+/.test(this.meta.rollupVersion)); + assert.strictEqual(this.meta.watchMode, false); + }, + outputOptions(options) { + assert.deepStrictEqual(JSON.parse(JSON.stringify(options)), { + banner: "throw new Error('unused')", + exports: 'auto', + format: 'cjs' + }); + assert.ok(/^\d+\.\d+\.\d+/.test(this.meta.rollupVersion)); + assert.strictEqual(this.meta.watchMode, false); + return { ...options, banner: 'exports.bar = 43;' }; + } } - } + ] } }); diff --git a/test/function/samples/plugin-cache/anonymous-delete/_config.js b/test/function/samples/plugin-cache/anonymous-delete/_config.js index ce7dbf233..c75a26f99 100644 --- a/test/function/samples/plugin-cache/anonymous-delete/_config.js +++ b/test/function/samples/plugin-cache/anonymous-delete/_config.js @@ -1,11 +1,13 @@ module.exports = defineTest({ description: 'throws for anonymous plugins deleting from the cache', options: { - plugins: { - buildStart() { - this.cache.delete('asdf'); + plugins: [ + { + buildStart() { + this.cache.delete('asdf'); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/plugin-cache/anonymous-get/_config.js b/test/function/samples/plugin-cache/anonymous-get/_config.js index 8dbacf0d3..462bb41ae 100644 --- a/test/function/samples/plugin-cache/anonymous-get/_config.js +++ b/test/function/samples/plugin-cache/anonymous-get/_config.js @@ -1,11 +1,13 @@ module.exports = defineTest({ description: 'throws for anonymous plugins reading the cache', options: { - plugins: { - buildStart() { - this.cache.get('asdf'); + plugins: [ + { + buildStart() { + this.cache.get('asdf'); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/plugin-cache/anonymous-has/_config.js b/test/function/samples/plugin-cache/anonymous-has/_config.js index ef142eda8..1822b951a 100644 --- a/test/function/samples/plugin-cache/anonymous-has/_config.js +++ b/test/function/samples/plugin-cache/anonymous-has/_config.js @@ -1,11 +1,13 @@ module.exports = defineTest({ description: 'throws for anonymous plugins checking the cache', options: { - plugins: { - buildStart() { - this.cache.has('asdf'); + plugins: [ + { + buildStart() { + this.cache.has('asdf'); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/plugin-cache/anonymous-set/_config.js b/test/function/samples/plugin-cache/anonymous-set/_config.js index 5349a5234..8aee27bf0 100644 --- a/test/function/samples/plugin-cache/anonymous-set/_config.js +++ b/test/function/samples/plugin-cache/anonymous-set/_config.js @@ -1,11 +1,13 @@ module.exports = defineTest({ description: 'throws for anonymous plugins adding to the cache', options: { - plugins: { - buildStart() { - this.cache.set('asdf', 'asdf'); + plugins: [ + { + buildStart() { + this.cache.set('asdf', 'asdf'); + } } - } + ] }, error: { code: 'PLUGIN_ERROR', diff --git a/test/function/samples/plugin-module-information-no-cache/_config.js b/test/function/samples/plugin-module-information-no-cache/_config.js index 3ea09c6a8..33d04f0da 100644 --- a/test/function/samples/plugin-module-information-no-cache/_config.js +++ b/test/function/samples/plugin-module-information-no-cache/_config.js @@ -32,7 +32,7 @@ module.exports = defineTest({ sourceType: 'module' }; assert.deepStrictEqual(JSON.parse(JSON.stringify(info)), { - assertions: {}, + attributes: {}, ast, code: 'export default 42;\n', dynamicallyImportedIdResolutions: [], diff --git a/test/function/samples/plugin-module-information/_config.js b/test/function/samples/plugin-module-information/_config.js index 9890061d0..4624d7348 100644 --- a/test/function/samples/plugin-module-information/_config.js +++ b/test/function/samples/plugin-module-information/_config.js @@ -13,437 +13,444 @@ module.exports = defineTest({ description: 'provides module information on the plugin context', options: { external: ['path'], - plugins: { - load(id) { - assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(id))), { - assertions: {}, - ast: null, - code: null, - dynamicImporters: [], - exportedBindings: { - '.': [] - }, - exports: [], - hasDefaultExport: null, - dynamicallyImportedIdResolutions: [], - dynamicallyImportedIds: [], - moduleSideEffects: true, - id, - implicitlyLoadedAfterOneOf: [], - implicitlyLoadedBefore: [], - importedIdResolutions: [], - importedIds: [], - importers: [], - isEntry: id === ID_MAIN, - isExternal: false, - isIncluded: null, - meta: {}, - syntheticNamedExports: false - }); - }, - renderStart() { - rendered = true; - assert.deepStrictEqual( - getObject( - [...this.getModuleIds()].map(id => [ - id, - JSON.parse(JSON.stringify(this.getModuleInfo(id))) - ]) - ), - { - [ID_FOO]: { - id: ID_FOO, - assertions: {}, - ast: { - type: 'Program', - start: 0, - end: 66, - body: [ - { - type: 'ImportDeclaration', - start: 0, - end: 24, - specifiers: [ - { - type: 'ImportDefaultSpecifier', - start: 7, - end: 11, - local: { type: 'Identifier', start: 7, end: 11, name: 'path' } - } - ], - source: { type: 'Literal', start: 17, end: 23, value: 'path', raw: "'path'" } - }, - { - type: 'ExportNamedDeclaration', - start: 26, - end: 65, - declaration: { - type: 'VariableDeclaration', - start: 33, - end: 65, - declarations: [ + plugins: [ + { + load(id) { + assert.deepStrictEqual(JSON.parse(JSON.stringify(this.getModuleInfo(id))), { + attributes: {}, + ast: null, + code: null, + dynamicImporters: [], + exportedBindings: { + '.': [] + }, + exports: [], + hasDefaultExport: null, + dynamicallyImportedIdResolutions: [], + dynamicallyImportedIds: [], + moduleSideEffects: true, + id, + implicitlyLoadedAfterOneOf: [], + implicitlyLoadedBefore: [], + importedIdResolutions: [], + importedIds: [], + importers: [], + isEntry: id === ID_MAIN, + isExternal: false, + isIncluded: null, + meta: {}, + syntheticNamedExports: false + }); + }, + renderStart() { + rendered = true; + assert.deepStrictEqual( + getObject( + [...this.getModuleIds()].map(id => [ + id, + JSON.parse(JSON.stringify(this.getModuleInfo(id))) + ]) + ), + { + [ID_FOO]: { + id: ID_FOO, + attributes: {}, + ast: { + type: 'Program', + start: 0, + end: 66, + body: [ + { + type: 'ImportDeclaration', + start: 0, + end: 24, + specifiers: [ { - type: 'VariableDeclarator', - start: 39, - end: 64, - id: { type: 'Identifier', start: 39, end: 42, name: 'foo' }, - init: { - type: 'CallExpression', - start: 45, + type: 'ImportDefaultSpecifier', + start: 7, + end: 11, + local: { type: 'Identifier', start: 7, end: 11, name: 'path' } + } + ], + source: { type: 'Literal', start: 17, end: 23, value: 'path', raw: "'path'" } + }, + { + type: 'ExportNamedDeclaration', + start: 26, + end: 65, + declaration: { + type: 'VariableDeclaration', + start: 33, + end: 65, + declarations: [ + { + type: 'VariableDeclarator', + start: 39, end: 64, - callee: { - type: 'MemberExpression', + id: { type: 'Identifier', start: 39, end: 42, name: 'foo' }, + init: { + type: 'CallExpression', start: 45, - end: 57, - object: { type: 'Identifier', start: 45, end: 49, name: 'path' }, - property: { type: 'Identifier', start: 50, end: 57, name: 'resolve' }, - computed: false, + end: 64, + callee: { + type: 'MemberExpression', + start: 45, + end: 57, + object: { type: 'Identifier', start: 45, end: 49, name: 'path' }, + property: { + type: 'Identifier', + start: 50, + end: 57, + name: 'resolve' + }, + computed: false, + optional: false + }, + arguments: [ + { type: 'Literal', start: 58, end: 63, value: 'foo', raw: "'foo'" } + ], optional: false - }, - arguments: [ - { type: 'Literal', start: 58, end: 63, value: 'foo', raw: "'foo'" } - ], - optional: false + } } - } - ], - kind: 'const' - }, - specifiers: [], - source: null + ], + kind: 'const' + }, + specifiers: [], + source: null + } + ], + sourceType: 'module' + }, + code: "import path from 'path';\n\nexport const foo = path.resolve('foo');\n", + dynamicallyImportedIdResolutions: [], + exportedBindings: { '.': ['foo'] }, + exports: ['foo'], + dynamicallyImportedIds: [], + dynamicImporters: [], + hasDefaultExport: false, + moduleSideEffects: true, + implicitlyLoadedAfterOneOf: [], + implicitlyLoadedBefore: [], + importedIdResolutions: [ + { + attributes: {}, + external: true, + id: ID_PATH, + meta: {}, + moduleSideEffects: true, + resolvedBy: 'rollup', + syntheticNamedExports: false } ], - sourceType: 'module' + importedIds: [ID_PATH], + importers: [ID_MAIN, ID_NESTED], + isEntry: false, + isExternal: false, + isIncluded: true, + meta: {}, + syntheticNamedExports: false }, - code: "import path from 'path';\n\nexport const foo = path.resolve('foo');\n", - dynamicallyImportedIdResolutions: [], - exportedBindings: { '.': ['foo'] }, - exports: ['foo'], - dynamicallyImportedIds: [], - dynamicImporters: [], - hasDefaultExport: false, - moduleSideEffects: true, - implicitlyLoadedAfterOneOf: [], - implicitlyLoadedBefore: [], - importedIdResolutions: [ - { - assertions: {}, - external: true, - id: ID_PATH, - meta: {}, - moduleSideEffects: true, - resolvedBy: 'rollup', - syntheticNamedExports: false - } - ], - importedIds: [ID_PATH], - importers: [ID_MAIN, ID_NESTED], - isEntry: false, - isExternal: false, - isIncluded: true, - meta: {}, - syntheticNamedExports: false - }, - [ID_MAIN]: { - id: ID_MAIN, - assertions: {}, - ast: { - type: 'Program', - start: 0, - end: 159, - body: [ - { - type: 'ExportNamedDeclaration', - start: 0, - end: 31, - declaration: null, - specifiers: [ - { - type: 'ExportSpecifier', - start: 9, - end: 12, - local: { type: 'Identifier', start: 9, end: 12, name: 'foo' }, - exported: { type: 'Identifier', start: 9, end: 12, name: 'foo' } + [ID_MAIN]: { + id: ID_MAIN, + attributes: {}, + ast: { + type: 'Program', + start: 0, + end: 159, + body: [ + { + type: 'ExportNamedDeclaration', + start: 0, + end: 31, + declaration: null, + specifiers: [ + { + type: 'ExportSpecifier', + start: 9, + end: 12, + local: { type: 'Identifier', start: 9, end: 12, name: 'foo' }, + exported: { type: 'Identifier', start: 9, end: 12, name: 'foo' } + } + ], + source: { + type: 'Literal', + start: 20, + end: 30, + value: './foo.js', + raw: "'./foo.js'" } - ], - source: { - type: 'Literal', - start: 20, - end: 30, - value: './foo.js', - raw: "'./foo.js'" - } - }, - { - type: 'ExportNamedDeclaration', - start: 32, - end: 80, - declaration: { - type: 'VariableDeclaration', - start: 39, + }, + { + type: 'ExportNamedDeclaration', + start: 32, end: 80, - declarations: [ - { - type: 'VariableDeclarator', - start: 45, - end: 79, - id: { type: 'Identifier', start: 45, end: 51, name: 'nested' }, - init: { - type: 'ImportExpression', - start: 54, + declaration: { + type: 'VariableDeclaration', + start: 39, + end: 80, + declarations: [ + { + type: 'VariableDeclarator', + start: 45, end: 79, - source: { - type: 'Literal', - start: 61, - end: 78, - value: './nested/nested', - raw: "'./nested/nested'" + id: { type: 'Identifier', start: 45, end: 51, name: 'nested' }, + init: { + type: 'ImportExpression', + start: 54, + end: 79, + source: { + type: 'Literal', + start: 61, + end: 78, + value: './nested/nested', + raw: "'./nested/nested'" + } } } - } - ], - kind: 'const' + ], + kind: 'const' + }, + specifiers: [], + source: null }, - specifiers: [], - source: null - }, - { - type: 'ExportNamedDeclaration', - start: 81, - end: 116, - declaration: { - type: 'VariableDeclaration', - start: 88, + { + type: 'ExportNamedDeclaration', + start: 81, end: 116, - declarations: [ - { - type: 'VariableDeclarator', - start: 94, - end: 115, - id: { type: 'Identifier', start: 94, end: 98, name: 'path' }, - init: { - type: 'ImportExpression', - start: 101, + declaration: { + type: 'VariableDeclaration', + start: 88, + end: 116, + declarations: [ + { + type: 'VariableDeclarator', + start: 94, end: 115, - source: { - type: 'Literal', - start: 108, - end: 114, - value: 'path', - raw: "'path'" + id: { type: 'Identifier', start: 94, end: 98, name: 'path' }, + init: { + type: 'ImportExpression', + start: 101, + end: 115, + source: { + type: 'Literal', + start: 108, + end: 114, + value: 'path', + raw: "'path'" + } } } - } - ], - kind: 'const' + ], + kind: 'const' + }, + specifiers: [], + source: null }, - specifiers: [], - source: null - }, - { - type: 'ExportNamedDeclaration', - start: 117, - end: 158, - declaration: { - type: 'VariableDeclaration', - start: 124, + { + type: 'ExportNamedDeclaration', + start: 117, end: 158, - declarations: [ - { - type: 'VariableDeclarator', - start: 130, - end: 157, - id: { type: 'Identifier', start: 130, end: 139, name: 'pathAgain' }, - init: { - type: 'ImportExpression', - start: 142, + declaration: { + type: 'VariableDeclaration', + start: 124, + end: 158, + declarations: [ + { + type: 'VariableDeclarator', + start: 130, end: 157, - source: { type: 'Identifier', start: 149, end: 156, name: 'thePath' } + id: { type: 'Identifier', start: 130, end: 139, name: 'pathAgain' }, + init: { + type: 'ImportExpression', + start: 142, + end: 157, + source: { type: 'Identifier', start: 149, end: 156, name: 'thePath' } + } } - } - ], - kind: 'const' - }, - specifiers: [], - source: null + ], + kind: 'const' + }, + specifiers: [], + source: null + } + ], + sourceType: 'module' + }, + code: "export { foo } from './foo.js';\nexport const nested = import('./nested/nested');\nexport const path = import('path');\nexport const pathAgain = import(thePath);\n", + dynamicallyImportedIdResolutions: [ + { + attributes: {}, + external: false, + id: ID_NESTED, + meta: {}, + moduleSideEffects: true, + resolvedBy: 'rollup', + syntheticNamedExports: false + }, + { + attributes: {}, + external: true, + id: ID_PATH, + meta: {}, + moduleSideEffects: true, + resolvedBy: 'rollup', + syntheticNamedExports: false } ], - sourceType: 'module' - }, - code: "export { foo } from './foo.js';\nexport const nested = import('./nested/nested');\nexport const path = import('path');\nexport const pathAgain = import(thePath);\n", - dynamicallyImportedIdResolutions: [ - { - assertions: {}, - external: false, - id: ID_NESTED, - meta: {}, - moduleSideEffects: true, - resolvedBy: 'rollup', - syntheticNamedExports: false + dynamicallyImportedIds: [ID_NESTED, ID_PATH], + dynamicImporters: [], + exportedBindings: { + '.': ['nested', 'path', 'pathAgain'], + './foo.js': ['foo'] }, - { - assertions: {}, - external: true, - id: ID_PATH, - meta: {}, - moduleSideEffects: true, - resolvedBy: 'rollup', - syntheticNamedExports: false - } - ], - dynamicallyImportedIds: [ID_NESTED, ID_PATH], - dynamicImporters: [], - exportedBindings: { - '.': ['nested', 'path', 'pathAgain'], - './foo.js': ['foo'] - }, - exports: ['nested', 'path', 'pathAgain', 'foo'], - hasDefaultExport: false, - moduleSideEffects: true, - implicitlyLoadedAfterOneOf: [], - implicitlyLoadedBefore: [], - importedIdResolutions: [ - { - assertions: {}, - external: false, - id: ID_FOO, - meta: {}, - moduleSideEffects: true, - resolvedBy: 'rollup', - syntheticNamedExports: false - } - ], - importedIds: [ID_FOO], - importers: [], - isEntry: true, - isExternal: false, - isIncluded: true, - meta: {}, - syntheticNamedExports: false - }, - [ID_NESTED]: { - id: ID_NESTED, - assertions: {}, - ast: { - type: 'Program', - start: 0, - end: 72, - body: [ + exports: ['nested', 'path', 'pathAgain', 'foo'], + hasDefaultExport: false, + moduleSideEffects: true, + implicitlyLoadedAfterOneOf: [], + implicitlyLoadedBefore: [], + importedIdResolutions: [ { - type: 'ImportDeclaration', - start: 0, - end: 32, - specifiers: [ - { - type: 'ImportSpecifier', - start: 9, - end: 12, - imported: { type: 'Identifier', start: 9, end: 12, name: 'foo' }, - local: { type: 'Identifier', start: 9, end: 12, name: 'foo' } + attributes: {}, + external: false, + id: ID_FOO, + meta: {}, + moduleSideEffects: true, + resolvedBy: 'rollup', + syntheticNamedExports: false + } + ], + importedIds: [ID_FOO], + importers: [], + isEntry: true, + isExternal: false, + isIncluded: true, + meta: {}, + syntheticNamedExports: false + }, + [ID_NESTED]: { + id: ID_NESTED, + attributes: {}, + ast: { + type: 'Program', + start: 0, + end: 72, + body: [ + { + type: 'ImportDeclaration', + start: 0, + end: 32, + specifiers: [ + { + type: 'ImportSpecifier', + start: 9, + end: 12, + imported: { type: 'Identifier', start: 9, end: 12, name: 'foo' }, + local: { type: 'Identifier', start: 9, end: 12, name: 'foo' } + } + ], + source: { + type: 'Literal', + start: 20, + end: 31, + value: '../foo.js', + raw: "'../foo.js'" } - ], - source: { - type: 'Literal', - start: 20, - end: 31, - value: '../foo.js', - raw: "'../foo.js'" - } - }, - { - type: 'ExportNamedDeclaration', - start: 34, - end: 71, - declaration: { - type: 'VariableDeclaration', - start: 41, + }, + { + type: 'ExportNamedDeclaration', + start: 34, end: 71, - declarations: [ - { - type: 'VariableDeclarator', - start: 47, - end: 70, - id: { type: 'Identifier', start: 47, end: 53, name: 'nested' }, - init: { - type: 'BinaryExpression', - start: 56, + declaration: { + type: 'VariableDeclaration', + start: 41, + end: 71, + declarations: [ + { + type: 'VariableDeclarator', + start: 47, end: 70, - left: { - type: 'Literal', + id: { type: 'Identifier', start: 47, end: 53, name: 'nested' }, + init: { + type: 'BinaryExpression', start: 56, - end: 64, - value: 'nested', - raw: "'nested'" - }, - operator: '+', - right: { type: 'Identifier', start: 67, end: 70, name: 'foo' } + end: 70, + left: { + type: 'Literal', + start: 56, + end: 64, + value: 'nested', + raw: "'nested'" + }, + operator: '+', + right: { type: 'Identifier', start: 67, end: 70, name: 'foo' } + } } - } - ], - kind: 'const' - }, - specifiers: [], - source: null + ], + kind: 'const' + }, + specifiers: [], + source: null + } + ], + sourceType: 'module' + }, + code: "import { foo } from '../foo.js';\n\nexport const nested = 'nested' + foo;\n", + dynamicallyImportedIdResolutions: [], + dynamicallyImportedIds: [], + dynamicImporters: [ID_MAIN], + exports: ['nested'], + exportedBindings: { '.': ['nested'] }, + hasDefaultExport: false, + moduleSideEffects: true, + implicitlyLoadedAfterOneOf: [], + implicitlyLoadedBefore: [], + importedIdResolutions: [ + { + attributes: {}, + external: false, + id: ID_FOO, + meta: {}, + moduleSideEffects: true, + resolvedBy: 'rollup', + syntheticNamedExports: false } ], - sourceType: 'module' + importedIds: [ID_FOO], + importers: [], + isEntry: false, + isExternal: false, + isIncluded: true, + meta: {}, + syntheticNamedExports: false }, - code: "import { foo } from '../foo.js';\n\nexport const nested = 'nested' + foo;\n", - dynamicallyImportedIdResolutions: [], - dynamicallyImportedIds: [], - dynamicImporters: [ID_MAIN], - exports: ['nested'], - exportedBindings: { '.': ['nested'] }, - hasDefaultExport: false, - moduleSideEffects: true, - implicitlyLoadedAfterOneOf: [], - implicitlyLoadedBefore: [], - importedIdResolutions: [ - { - assertions: {}, - external: false, - id: ID_FOO, - meta: {}, - moduleSideEffects: true, - resolvedBy: 'rollup', - syntheticNamedExports: false - } - ], - importedIds: [ID_FOO], - importers: [], - isEntry: false, - isExternal: false, - isIncluded: true, - meta: {}, - syntheticNamedExports: false - }, - [ID_PATH]: { - id: ID_PATH, - assertions: {}, - ast: null, - code: null, - dynamicallyImportedIdResolutions: [], - dynamicallyImportedIds: [], - dynamicImporters: [ID_MAIN], - exportedBindings: null, - exports: null, - hasDefaultExport: null, - moduleSideEffects: true, - implicitlyLoadedAfterOneOf: [], - implicitlyLoadedBefore: [], - importedIdResolutions: [], - importedIds: [], - importers: [ID_FOO], - isEntry: false, - isExternal: true, - isIncluded: null, - meta: {}, - syntheticNamedExports: false + [ID_PATH]: { + id: ID_PATH, + attributes: {}, + ast: null, + code: null, + dynamicallyImportedIdResolutions: [], + dynamicallyImportedIds: [], + dynamicImporters: [ID_MAIN], + exportedBindings: null, + exports: null, + hasDefaultExport: null, + moduleSideEffects: true, + implicitlyLoadedAfterOneOf: [], + implicitlyLoadedBefore: [], + importedIdResolutions: [], + importedIds: [], + importers: [ID_FOO], + isEntry: false, + isExternal: true, + isIncluded: null, + meta: {}, + syntheticNamedExports: false + } } - } - ); + ); + } } - } + ] }, context: { thePath: 'path' diff --git a/test/function/samples/plugin-parse-ast-receives-comments/_config.js b/test/function/samples/plugin-parse-ast-receives-comments/_config.js deleted file mode 100644 index 2b25e4518..000000000 --- a/test/function/samples/plugin-parse-ast-receives-comments/_config.js +++ /dev/null @@ -1,24 +0,0 @@ -const assert = require('node:assert'); - -const comments = []; - -module.exports = defineTest({ - description: 'plugin parse ast receives comments', - options: { - plugins: [ - { - transform(code) { - const ast = this.parse(code, { - onComment(...parameters) { - comments.push(parameters); - } - }); - return { ast, code, map: null }; - } - } - ] - }, - after() { - assert.ok(comments.length > 0); - } -}); diff --git a/test/function/samples/plugin-parse-ast-receives-comments/main.js b/test/function/samples/plugin-parse-ast-receives-comments/main.js deleted file mode 100644 index fbc4f47c0..000000000 --- a/test/function/samples/plugin-parse-ast-receives-comments/main.js +++ /dev/null @@ -1,4 +0,0 @@ -/* this is a comment */ -export function main() { - // this is also a comment -} \ No newline at end of file diff --git a/test/function/samples/preload-module/_config.js b/test/function/samples/preload-module/_config.js index 9cc42cc09..80c169f58 100644 --- a/test/function/samples/preload-module/_config.js +++ b/test/function/samples/preload-module/_config.js @@ -32,7 +32,7 @@ module.exports = defineTest({ }); assert.deepStrictEqual(moduleInfo, { id: ID_MAIN, - assertions: {}, + attributes: {}, code: "import './dep';\nassert.ok(true);\n", dynamicImporters: [], exportedBindings: { @@ -75,7 +75,7 @@ module.exports = defineTest({ }); assert.deepStrictEqual(moduleInfo, { id: ID_DEP, - assertions: {}, + attributes: {}, code: 'assert.ok(true);\n', dynamicImporters: [], exportedBindings: { diff --git a/test/function/samples/preserve-symlink/_config.js b/test/function/samples/preserve-symlink/_config.js index cdc08ad12..60c64eb5a 100644 --- a/test/function/samples/preserve-symlink/_config.js +++ b/test/function/samples/preserve-symlink/_config.js @@ -1,5 +1,5 @@ module.exports = defineTest({ - skip: process.platform === 'win32', + skipIfWindows: true, description: 'follows symlinks', options: { preserveSymlinks: true diff --git a/test/function/samples/reassign-import-fails/_config.js b/test/function/samples/reassign-import-fails/_config.js index 71ca9a3ee..48cd70097 100644 --- a/test/function/samples/reassign-import-fails/_config.js +++ b/test/function/samples/reassign-import-fails/_config.js @@ -1,11 +1,14 @@ const path = require('node:path'); const ID_MAIN = path.join(__dirname, 'main.js'); -const ID_FOO = path.join(__dirname, 'foo.js'); module.exports = defineTest({ description: 'disallows assignments to imported bindings', error: { - code: 'ILLEGAL_REASSIGNMENT', + code: 'PARSE_ERROR', + cause: { + message: 'cannot reassign to an imported binding', + pos: 113 + }, id: ID_MAIN, pos: 113, loc: { @@ -18,8 +21,8 @@ module.exports = defineTest({ 7: 8: x = 10; ^`, - watchFiles: [ID_FOO, ID_MAIN], - message: 'Illegal reassignment of import "x" in "main.js".' + watchFiles: [ID_MAIN], + message: 'cannot reassign to an imported binding' } }); diff --git a/test/function/samples/reassign-import-fails/foo.js b/test/function/samples/reassign-import-fails/foo.js deleted file mode 100644 index 35ba80666..000000000 --- a/test/function/samples/reassign-import-fails/foo.js +++ /dev/null @@ -1 +0,0 @@ -export var x = 1; diff --git a/test/function/samples/reassign-import-not-at-top-level-fails/_config.js b/test/function/samples/reassign-import-not-at-top-level-fails/_config.js index d26f7c87f..fe0020431 100644 --- a/test/function/samples/reassign-import-not-at-top-level-fails/_config.js +++ b/test/function/samples/reassign-import-not-at-top-level-fails/_config.js @@ -1,11 +1,14 @@ const path = require('node:path'); const ID_MAIN = path.join(__dirname, 'main.js'); -const ID_FOO = path.join(__dirname, 'foo.js'); module.exports = defineTest({ description: 'disallows assignments to imported bindings not at the top level', error: { - code: 'ILLEGAL_REASSIGNMENT', + code: 'PARSE_ERROR', + cause: { + message: 'cannot reassign to an imported binding', + pos: 95 + }, id: ID_MAIN, pos: 95, loc: { @@ -19,8 +22,8 @@ module.exports = defineTest({ 7: x = 1; ^ 8: }`, - watchFiles: [ID_FOO, ID_MAIN], - message: 'Illegal reassignment of import "x" in "main.js".' + watchFiles: [ID_MAIN], + message: 'cannot reassign to an imported binding' } }); diff --git a/test/function/samples/reassign-import-not-at-top-level-fails/foo.js b/test/function/samples/reassign-import-not-at-top-level-fails/foo.js deleted file mode 100644 index 35ba80666..000000000 --- a/test/function/samples/reassign-import-not-at-top-level-fails/foo.js +++ /dev/null @@ -1 +0,0 @@ -export var x = 1; diff --git a/test/function/samples/resolve-id-object/_config.js b/test/function/samples/resolve-id-object/_config.js index 0b7d12261..ebb1f5b50 100644 --- a/test/function/samples/resolve-id-object/_config.js +++ b/test/function/samples/resolve-id-object/_config.js @@ -3,22 +3,24 @@ const path = require('node:path'); module.exports = defineTest({ description: 'allows resolving an id with an object', options: { - plugins: { - resolveId(importee) { - const fooId = path.join(__dirname, 'foo.js'); - switch (importee) { - case 'internal1': { - return { id: fooId }; - } - case 'internal2': { - return { id: fooId, external: false }; - } - case 'external': { - return { id: 'my-external', external: true }; + plugins: [ + { + resolveId(importee) { + const fooId = path.join(__dirname, 'foo.js'); + switch (importee) { + case 'internal1': { + return { id: fooId }; + } + case 'internal2': { + return { id: fooId, external: false }; + } + case 'external': { + return { id: 'my-external', external: true }; + } } } } - } + ] }, context: { require(id) { diff --git a/test/function/samples/resolve-relative-external-id/_config.js b/test/function/samples/resolve-relative-external-id/_config.js index c56c40537..07a900195 100644 --- a/test/function/samples/resolve-relative-external-id/_config.js +++ b/test/function/samples/resolve-relative-external-id/_config.js @@ -5,30 +5,32 @@ module.exports = defineTest({ description: 'resolves relative external ids', options: { external: [path.join(__dirname, 'external.js'), path.join(__dirname, 'nested', 'external.js')], - plugins: { - async buildStart() { - assert.deepStrictEqual(await this.resolve('./external.js'), { - assertions: {}, - external: true, - id: path.join(__dirname, 'external.js'), - meta: {}, - moduleSideEffects: true, - resolvedBy: 'rollup', - syntheticNamedExports: false - }); - assert.deepStrictEqual( - await this.resolve('./external.js', path.join(__dirname, 'nested', 'some-file.js')), - { - assertions: {}, + plugins: [ + { + async buildStart() { + assert.deepStrictEqual(await this.resolve('./external.js'), { + attributes: {}, external: true, - id: path.join(__dirname, 'nested', 'external.js'), + id: path.join(__dirname, 'external.js'), meta: {}, moduleSideEffects: true, resolvedBy: 'rollup', syntheticNamedExports: false - } - ); + }); + assert.deepStrictEqual( + await this.resolve('./external.js', path.join(__dirname, 'nested', 'some-file.js')), + { + attributes: {}, + external: true, + id: path.join(__dirname, 'nested', 'external.js'), + meta: {}, + moduleSideEffects: true, + resolvedBy: 'rollup', + syntheticNamedExports: false + } + ); + } } - } + ] } }); diff --git a/test/function/samples/side-effect-free-module-function/_config.js b/test/function/samples/side-effect-free-module-function/_config.js index 827d480db..d354e3143 100644 --- a/test/function/samples/side-effect-free-module-function/_config.js +++ b/test/function/samples/side-effect-free-module-function/_config.js @@ -2,10 +2,12 @@ module.exports = defineTest({ description: 'correctly include functions with side effects from side-effect-free modules (#3942)', options: { - plugins: { - transform() { - return { moduleSideEffects: false }; + plugins: [ + { + transform() { + return { moduleSideEffects: false }; + } } - } + ] } }); diff --git a/test/function/samples/symlink/_config.js b/test/function/samples/symlink/_config.js index 39859d6f1..65f9bbbb2 100644 --- a/test/function/samples/symlink/_config.js +++ b/test/function/samples/symlink/_config.js @@ -1,4 +1,4 @@ module.exports = defineTest({ - skip: process.platform === 'win32', + skipIfWindows: true, description: 'follows symlinks' }); diff --git a/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/_config.js b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/_config.js index 3bbcc0207..7de33d901 100644 --- a/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/_config.js +++ b/test/function/samples/synthetic-named-exports/synthetic-named-export-as-default/_config.js @@ -1,11 +1,13 @@ module.exports = defineTest({ description: 'makes sure default exports of synthetic named exports are snapshots', options: { - plugins: { - name: 'test-plugin', - transform() { - return { syntheticNamedExports: '__synthetic' }; + plugins: [ + { + name: 'test-plugin', + transform() { + return { syntheticNamedExports: '__synthetic' }; + } } - } + ] } }); diff --git a/test/function/samples/transform-empty-string/_config.js b/test/function/samples/transform-empty-string/_config.js index 77af26005..0af89d975 100644 --- a/test/function/samples/transform-empty-string/_config.js +++ b/test/function/samples/transform-empty-string/_config.js @@ -9,13 +9,15 @@ module.exports = defineTest({ assert.deepStrictEqual(sideEffects, ['this happens']); }, options: { - plugins: { - name: 'test-plugin', - transform(code, id) { - if (id.endsWith('transformed.js')) { - return ''; + plugins: [ + { + name: 'test-plugin', + transform(code, id) { + if (id.endsWith('transformed.js')) { + return ''; + } } } - } + ] } }); diff --git a/test/function/samples/transform-without-code-warn-ast/_config.js b/test/function/samples/transform-without-code-warn-ast/_config.js index 891825a0e..405b92e74 100644 --- a/test/function/samples/transform-without-code-warn-ast/_config.js +++ b/test/function/samples/transform-without-code-warn-ast/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'warns when returning a map but no code from a transform hook', options: { - plugins: { - name: 'test-plugin', - transform() { - return { ast: {} }; + plugins: [ + { + name: 'test-plugin', + transform() { + return { ast: {} }; + } } - } + ] }, warnings: [ { diff --git a/test/function/samples/transform-without-code-warn-map/_config.js b/test/function/samples/transform-without-code-warn-map/_config.js index 26221ba80..4b91262e6 100644 --- a/test/function/samples/transform-without-code-warn-map/_config.js +++ b/test/function/samples/transform-without-code-warn-map/_config.js @@ -1,12 +1,14 @@ module.exports = defineTest({ description: 'warns when returning a map but no code from a transform hook', options: { - plugins: { - name: 'test-plugin', - transform() { - return { map: { mappings: '' } }; + plugins: [ + { + name: 'test-plugin', + transform() { + return { map: { mappings: '' } }; + } } - } + ] }, warnings: [ { diff --git a/test/function/samples/transform-without-code/_config.js b/test/function/samples/transform-without-code/_config.js index 7f145702a..71e49ed2f 100644 --- a/test/function/samples/transform-without-code/_config.js +++ b/test/function/samples/transform-without-code/_config.js @@ -7,33 +7,35 @@ module.exports = defineTest({ description: 'allows using the transform hook for annotations only without returning a code property and breaking sourcemaps', options: { - plugins: { - name: 'test-plugin', - transform() { - return { meta: { test: true } }; - }, - async generateBundle(options, bundle) { - const { code, map } = bundle['main.js']; - const line = 3; - const column = 11; - assert.strictEqual(code.split('\n')[line - 1].slice(column, column + 2), '42'); + plugins: [ + { + name: 'test-plugin', + transform() { + return { meta: { test: true } }; + }, + async generateBundle(options, bundle) { + const { code, map } = bundle['main.js']; + const line = 3; + const column = 11; + assert.strictEqual(code.split('\n')[line - 1].slice(column, column + 2), '42'); - const smc = await new SourceMapConsumer(map); - const originalLoc = smc.originalPositionFor({ line, column }); - assert.notStrictEqual(originalLoc.line, null); - const originalCode = readFileSync(path.join(__dirname, 'main.js'), 'utf8'); - assert.strictEqual( - originalCode - .split('\n') - [originalLoc.line - 1].slice(originalLoc.column, originalLoc.column + 2), - '42' - ); + const smc = await new SourceMapConsumer(map); + const originalLoc = smc.originalPositionFor({ line, column }); + assert.notStrictEqual(originalLoc.line, null); + const originalCode = readFileSync(path.join(__dirname, 'main.js'), 'utf8'); + assert.strictEqual( + originalCode + .split('\n') + [originalLoc.line - 1].slice(originalLoc.column, originalLoc.column + 2), + '42' + ); - for (const id of this.getModuleIds()) { - assert.strictEqual(this.getModuleInfo(id).meta.test, true); + for (const id of this.getModuleIds()) { + assert.strictEqual(this.getModuleInfo(id).meta.test, true); + } } } - }, + ], output: { sourcemap: true } diff --git a/test/function/samples/update-expression-of-import-fails/_config.js b/test/function/samples/update-expression-of-import-fails/_config.js index c4a525ab4..a961315b1 100644 --- a/test/function/samples/update-expression-of-import-fails/_config.js +++ b/test/function/samples/update-expression-of-import-fails/_config.js @@ -1,11 +1,14 @@ const path = require('node:path'); const ID_MAIN = path.join(__dirname, 'main.js'); -const ID_FOO = path.join(__dirname, 'foo.js'); module.exports = defineTest({ description: 'disallows updates to imported bindings', error: { - code: 'ILLEGAL_REASSIGNMENT', + code: 'PARSE_ERROR', + cause: { + message: 'cannot reassign to an imported binding', + pos: 28 + }, id: ID_MAIN, pos: 28, loc: { @@ -18,8 +21,8 @@ module.exports = defineTest({ 2: 3: a++; ^`, - watchFiles: [ID_FOO, ID_MAIN], - message: 'Illegal reassignment of import "a" in "main.js".' + watchFiles: [ID_MAIN], + message: 'cannot reassign to an imported binding' } }); diff --git a/test/function/samples/update-expression-of-import-fails/foo.js b/test/function/samples/update-expression-of-import-fails/foo.js deleted file mode 100644 index 7fad5c5de..000000000 --- a/test/function/samples/update-expression-of-import-fails/foo.js +++ /dev/null @@ -1 +0,0 @@ -export var a = 0; diff --git a/test/function/samples/uses-supplied-ast/_config.js b/test/function/samples/uses-supplied-ast/_config.js index 367086d73..6ac87f34c 100644 --- a/test/function/samples/uses-supplied-ast/_config.js +++ b/test/function/samples/uses-supplied-ast/_config.js @@ -22,6 +22,7 @@ modules.foo.ast._ignoredProp = {}; module.exports = defineTest({ description: 'uses supplied AST', + verifyAst: false, options: { plugins: [ { diff --git a/test/function/samples/validate-output/_config.js b/test/function/samples/validate-output/_config.js index 42b7cc5bf..4cb4989a4 100644 --- a/test/function/samples/validate-output/_config.js +++ b/test/function/samples/validate-output/_config.js @@ -11,7 +11,7 @@ module.exports = defineTest({ }, generateError: { code: 'CHUNK_INVALID', - message: 'Chunk "main.js" is not valid JavaScript: Unterminated comment (5:0).', + message: 'Chunk "main.js" is not valid JavaScript: Unterminated block comment.', frame: ` 3: throw new Error('Not executed'); 4: @@ -21,6 +21,7 @@ module.exports = defineTest({ column: 0, file: 'main.js', line: 5 - } + }, + pos: 49 } }); diff --git a/test/function/samples/warning-low-resolution-location/_config.js b/test/function/samples/warning-low-resolution-location/_config.js index 3c6fc0f4c..885a9df7b 100644 --- a/test/function/samples/warning-low-resolution-location/_config.js +++ b/test/function/samples/warning-low-resolution-location/_config.js @@ -5,16 +5,21 @@ const ID_MAIN = path.join(__dirname, 'main.js'); module.exports = defineTest({ description: 'handles when a low resolution sourcemap is used to report an error', options: { - plugins: { - name: 'test-plugin', - transform() { - // each entry of each line consist of - // [generatedColumn, sourceIndex, sourceLine, sourceColumn]; - // this mapping only maps the first line to itself - const decodedMap = [[[0], [0, 0, 0, 0], [1]]]; - return { code: 'export default this', map: { mappings: encode(decodedMap), sources: [] } }; + plugins: [ + { + name: 'test-plugin', + transform() { + // each entry of each line consist of + // [generatedColumn, sourceIndex, sourceLine, sourceColumn]; + // this mapping only maps the first line to itself + const decodedMap = [[[0], [0, 0, 0, 0], [1]]]; + return { + code: 'export default this', + map: { mappings: encode(decodedMap), sources: [] } + }; + } } - } + ] }, warnings: [ { diff --git a/test/function/samples/warnings-to-string/_config.js b/test/function/samples/warnings-to-string/_config.js index afc8c0dd9..678c9739f 100644 --- a/test/function/samples/warnings-to-string/_config.js +++ b/test/function/samples/warnings-to-string/_config.js @@ -3,12 +3,14 @@ const assert = require('node:assert'); module.exports = defineTest({ description: 'provides a string conversion for warnings', options: { - plugins: { - name: 'test-plugin', - transform(code) { - this.warn('This might be removed', code.indexOf('removed')); + plugins: [ + { + name: 'test-plugin', + transform(code) { + this.warn('This might be removed', code.indexOf('removed')); + } } - } + ] }, warnings(warnings) { assert.deepStrictEqual(warnings.map(String), [ diff --git a/test/incremental/index.js b/test/incremental/index.js index 304b73e48..fc949c30f 100644 --- a/test/incremental/index.js +++ b/test/incremental/index.js @@ -1,5 +1,4 @@ const assert = require('node:assert'); -const acorn = require('acorn'); /** * @type {import('../../src/rollup/types')} Rollup */ @@ -188,28 +187,6 @@ describe('incremental', () => { }); }); - it('keeps ASTs between runs', () => - rollup - .rollup({ - input: 'entry', - plugins: [plugin] - }) - .then(bundle => { - const asts = {}; - for (const module of bundle.cache.modules) { - asts[module.id] = module.ast; - } - - assert.deepEqual( - asts.entry, - acorn.parse(modules.entry, { sourceType: 'module', ecmaVersion: 2020 }) - ); - assert.deepEqual( - asts.foo, - acorn.parse(modules.foo, { sourceType: 'module', ecmaVersion: 2020 }) - ); - })); - it('recovers from errors', () => { modules.entry = `import foo from 'foo'; import bar from 'bar'; export default foo + bar;`; @@ -264,7 +241,7 @@ describe('incremental', () => { assert.deepEqual(bundle.cache.modules[1].resolvedIds, { foo: { id: 'foo', - assertions: {}, + attributes: {}, external: false, meta: {}, moduleSideEffects: true, @@ -273,7 +250,7 @@ describe('incremental', () => { }, external: { id: 'external', - assertions: {}, + attributes: {}, external: true, meta: {}, moduleSideEffects: true, @@ -361,7 +338,7 @@ describe('incremental', () => { assert.deepStrictEqual(resolvedSources, { __proto__: null, bar: { - assertions: {}, + attributes: {}, external: false, id: 'bar', meta: {}, @@ -383,7 +360,7 @@ describe('incremental', () => { assert.deepStrictEqual(resolvedSources, { __proto__: null, foo: { - assertions: {}, + attributes: {}, external: false, id: 'foo', meta: {}, diff --git a/test/misc/acorn-plugins.js b/test/misc/acorn-plugins.js deleted file mode 100644 index 618c6b3c3..000000000 --- a/test/misc/acorn-plugins.js +++ /dev/null @@ -1,45 +0,0 @@ -const assert = require('node:assert'); -const rollup = require('../../dist/rollup'); -const { executeBundle, loader } = require('../utils.js'); - -describe('acorn plugins', () => { - it('injects plugins passed in acornInjectPlugins', async () => { - let pluginAInjected = false; - let pluginBInjected = false; - - const bundle = await rollup.rollup({ - input: 'x.js', - plugins: [loader({ 'x.js': `export const foo = 42` })], - acornInjectPlugins: [ - function pluginA(Parser) { - assert.equal(typeof Parser.parse, 'function'); - return class extends Parser { - readToken(code) { - pluginAInjected = true; - super.readToken(code); - } - }; - }, - function pluginB(Parser) { - assert.equal(typeof Parser.parse, 'function'); - return class extends Parser { - readToken(code) { - pluginBInjected = true; - super.readToken(code); - } - }; - } - ] - }); - const result = await executeBundle(bundle); - assert.equal(result.foo, 42); - assert( - pluginAInjected, - 'A plugin passed via acornInjectPlugins should inject itself into Acorn.' - ); - assert( - pluginBInjected, - 'A plugin passed via acornInjectPlugins should inject itself into Acorn.' - ); - }); -}); diff --git a/test/misc/index.js b/test/misc/index.js index 39d3f8846..2782f23e2 100644 --- a/test/misc/index.js +++ b/test/misc/index.js @@ -1,4 +1,3 @@ -require('./acorn-plugins'); require('./bundle-information'); require('./get-log-filter'); require('./iife'); diff --git a/test/misc/misc.js b/test/misc/misc.js index 76e4d68af..560af20f2 100644 --- a/test/misc/misc.js +++ b/test/misc/misc.js @@ -16,8 +16,6 @@ describe('misc', () => { load: freeze(() => `export default 0;`) } ]), - acornInjectPlugins: freeze([]), - acorn: freeze({}), treeshake: freeze({}) }) ); @@ -249,32 +247,6 @@ console.log(x); assert.ok(subsubfeature.code.startsWith("import { fn } from '../../../main'")); }); - it('throws the proper error on max call stack exception', async () => { - const count = 10_000; - let source = ''; - for (let index = 0; index < count; index++) { - source += `if (foo) {`; - } - for (let index = 0; index < count; index++) { - source += '}'; - } - try { - await rollup.rollup({ - input: { - input: 'input' - }, - plugins: [ - loader({ - input: source - }) - ] - }); - } catch (error) { - assert.notDeepStrictEqual(error.message, 'Maximum call stack size exceeded'); - assert.strictEqual(error.name, 'RollupError'); - } - }); - it('supports rendering es after rendering iife with inlined dynamic imports', async () => { const bundle = await rollup.rollup({ input: 'main.js', diff --git a/test/misc/optionList.js b/test/misc/optionList.js index e34a54586..b869f7e7b 100644 --- a/test/misc/optionList.js +++ b/test/misc/optionList.js @@ -1,6 +1,6 @@ exports.input = - 'acorn, acornInjectPlugins, cache, context, experimentalCacheExpiry, experimentalLogSideEffects, external, inlineDynamicImports, input, logLevel, makeAbsoluteExternalsRelative, manualChunks, maxParallelFileOps, maxParallelFileReads, moduleContext, onLog, onwarn, perf, plugins, preserveEntrySignatures, preserveModules, preserveSymlinks, shimMissingExports, strictDeprecations, treeshake, watch'; + 'cache, context, experimentalCacheExpiry, experimentalLogSideEffects, external, inlineDynamicImports, input, logLevel, makeAbsoluteExternalsRelative, manualChunks, maxParallelFileOps, maxParallelFileReads, moduleContext, onLog, onwarn, perf, plugins, preserveEntrySignatures, preserveModules, preserveSymlinks, shimMissingExports, strictDeprecations, treeshake, watch'; exports.flags = - 'acorn, acornInjectPlugins, amd, assetFileNames, banner, bundleConfigAsCjs, c, cache, chunkFileNames, compact, config, configPlugin, context, d, dir, dynamicImportFunction, dynamicImportInCjs, e, entryFileNames, environment, esModule, experimentalCacheExpiry, experimentalDeepDynamicChunkOptimization, experimentalLogSideEffects, experimentalMinChunkSize, exports, extend, external, externalImportAssertions, externalLiveBindings, f, failAfterWarnings, file, filterLogs, footer, format, freeze, g, generatedCode, globals, h, hoistTransitiveImports, i, indent, inlineDynamicImports, input, interop, intro, logLevel, m, makeAbsoluteExternalsRelative, manualChunks, maxParallelFileOps, maxParallelFileReads, minifyInternalExports, moduleContext, n, name, namespaceToStringTag, noConflict, o, onLog, onwarn, outro, p, paths, perf, plugin, plugins, preferConst, preserveEntrySignatures, preserveModules, preserveModulesRoot, preserveSymlinks, sanitizeFileName, shimMissingExports, silent, sourcemap, sourcemapBaseUrl, sourcemapExcludeSources, sourcemapFile, sourcemapFileNames, stdin, strict, strictDeprecations, systemNullSetters, treeshake, v, validate, w, waitForBundleInput, watch'; + 'amd, assetFileNames, banner, bundleConfigAsCjs, c, cache, chunkFileNames, compact, config, configPlugin, context, d, dir, dynamicImportFunction, dynamicImportInCjs, e, entryFileNames, environment, esModule, experimentalCacheExpiry, experimentalDeepDynamicChunkOptimization, experimentalLogSideEffects, experimentalMinChunkSize, exports, extend, external, externalImportAssertions, externalImportAttributes, externalLiveBindings, f, failAfterWarnings, file, filterLogs, footer, format, freeze, g, generatedCode, globals, h, hoistTransitiveImports, i, indent, inlineDynamicImports, input, interop, intro, logLevel, m, makeAbsoluteExternalsRelative, manualChunks, maxParallelFileOps, maxParallelFileReads, minifyInternalExports, moduleContext, n, name, namespaceToStringTag, noConflict, o, onLog, onwarn, outro, p, paths, perf, plugin, plugins, preferConst, preserveEntrySignatures, preserveModules, preserveModulesRoot, preserveSymlinks, sanitizeFileName, shimMissingExports, silent, sourcemap, sourcemapBaseUrl, sourcemapExcludeSources, sourcemapFile, sourcemapFileNames, stdin, strict, strictDeprecations, systemNullSetters, treeshake, v, validate, w, waitForBundleInput, watch'; exports.output = - 'amd, assetFileNames, banner, chunkFileNames, compact, dir, dynamicImportFunction, dynamicImportInCjs, entryFileNames, esModule, experimentalDeepDynamicChunkOptimization, experimentalMinChunkSize, exports, extend, externalImportAssertions, externalLiveBindings, file, footer, format, freeze, generatedCode, globals, hoistTransitiveImports, indent, inlineDynamicImports, interop, intro, manualChunks, minifyInternalExports, name, namespaceToStringTag, noConflict, outro, paths, plugins, preferConst, preserveModules, preserveModulesRoot, sanitizeFileName, sourcemap, sourcemapBaseUrl, sourcemapExcludeSources, sourcemapFile, sourcemapFileNames, sourcemapIgnoreList, sourcemapPathTransform, strict, systemNullSetters, validate'; + 'amd, assetFileNames, banner, chunkFileNames, compact, dir, dynamicImportFunction, dynamicImportInCjs, entryFileNames, esModule, experimentalDeepDynamicChunkOptimization, experimentalMinChunkSize, exports, extend, externalImportAssertions, externalImportAttributes, externalLiveBindings, file, footer, format, freeze, generatedCode, globals, hoistTransitiveImports, indent, inlineDynamicImports, interop, intro, manualChunks, minifyInternalExports, name, namespaceToStringTag, noConflict, outro, paths, plugins, preferConst, preserveModules, preserveModulesRoot, sanitizeFileName, sourcemap, sourcemapBaseUrl, sourcemapExcludeSources, sourcemapFile, sourcemapFileNames, sourcemapIgnoreList, sourcemapPathTransform, strict, systemNullSetters, validate'; diff --git a/test/utils.js b/test/utils.js index f2fae99d1..fdd1433a4 100644 --- a/test/utils.js +++ b/test/utils.js @@ -20,6 +20,8 @@ const { } = require('node:fs'); const { basename, join } = require('node:path'); const { platform, version } = require('node:process'); +const { Parser } = require('acorn'); +const { importAssertions } = require('acorn-import-assertions'); const fixturify = require('fixturify'); if (!globalThis.defineTest) { @@ -418,3 +420,57 @@ exports.replaceDirectoryInStringifiedObject = function replaceDirectoryInStringi '**/' ); }; + +const acornParser = Parser.extend(importAssertions); + +exports.verifyAstPlugin = { + name: 'verify-ast', + moduleParsed: ({ ast, code }) => { + const acornAst = acornParser.parse(code, { ecmaVersion: 'latest', sourceType: 'module' }); + assert.deepStrictEqual( + JSON.parse(JSON.stringify(ast, replaceStringifyValues), reviveStringifyValues), + JSON.parse(JSON.stringify(acornAst, replaceStringifyValues), reviveStringifyValues) + ); + } +}; + +const replaceStringifyValues = (key, value) => { + switch (value?.type) { + case 'ImportDeclaration': + case 'ExportNamedDeclaration': + case 'ExportAllDeclaration': { + const { attributes } = value; + if (attributes) { + delete value.attributes; + if (attributes.length > 0) { + value.assertions = attributes; + } + } + break; + } + case 'ImportExpression': { + const { options } = value; + delete value.options; + if (options) { + value.arguments = [options]; + } + } + } + + return key.startsWith('_') + ? undefined + : typeof value == 'bigint' + ? `~BigInt${value.toString()}` + : value instanceof RegExp + ? `~RegExp${JSON.stringify({ flags: value.flags, source: value.source })}` + : value; +}; + +const reviveStringifyValues = (_, value) => + typeof value === 'string' + ? value.startsWith('~BigInt') + ? BigInt(value.slice(7)) + : value.startsWith('~RegExp') + ? new RegExp(JSON.parse(value.slice(7)).source, JSON.parse(value.slice(7)).flags) + : value + : value; diff --git a/test/watch/index.js b/test/watch/index.js index e7b8cf973..10f2516fb 100644 --- a/test/watch/index.js +++ b/test/watch/index.js @@ -524,7 +524,7 @@ describe('rollup.watch', () => { }, 'START', 'BUNDLE_START', - 'ERROR:Unexpected token', + "ERROR:Expected '{', got 'nope'", 'END', () => { atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); @@ -552,7 +552,7 @@ describe('rollup.watch', () => { return sequence(watcher, [ 'START', 'BUNDLE_START', - 'ERROR:Unexpected token', + 'ERROR:Expression expected', 'END', () => { assert.strictEqual(existsSync('../_tmp/output/bundle.js'), false); @@ -671,7 +671,7 @@ describe('rollup.watch', () => { }, 'START', 'BUNDLE_START', - 'ERROR:Unexpected token', + "ERROR:Expected '{', got 'nope'", 'END', () => { unlinkSync('test/_tmp/input/main.js'); @@ -709,7 +709,7 @@ describe('rollup.watch', () => { }, 'START', 'BUNDLE_START', - 'ERROR:Unexpected token', + "ERROR:Expected '{', got 'nope'", 'END', () => { unlinkSync('test/_tmp/input/dep.js'); diff --git a/tsconfig.json b/tsconfig.json index 4b0974ca4..0ae0e885e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,6 @@ "strict": true, "target": "ES2022" }, - "include": ["typings/**/*.d.ts", "src", "cli", "browser", "rollup.config.ts"], + "include": ["typings/**/*.d.ts", "src", "cli", "browser", "rollup.config.ts", "native", "wasm.d.ts"], "exclude": ["dist", "node_modules", "test/typescript", "browser/dist"] } diff --git a/wasm.d.ts b/wasm.d.ts new file mode 100644 index 000000000..cbd5efcac --- /dev/null +++ b/wasm.d.ts @@ -0,0 +1,6 @@ +// eslint-disable-next-line import/no-unresolved +import './wasm/bindings_wasm_bg.wasm'; + +declare module './wasm/bindings_wasm_bg.wasm' { + export default function wasm(): Promise; +} diff --git a/wasm/bindings_wasm.d.ts b/wasm/bindings_wasm.d.ts new file mode 100644 index 000000000..07c63eddf --- /dev/null +++ b/wasm/bindings_wasm.d.ts @@ -0,0 +1,47 @@ +/* tslint:disable */ +/* eslint-disable */ +/** +* @param {string} code +* @returns {Uint8Array} +*/ +export function parse(code: string): Uint8Array; +/** +* @param {string} query +* @param {any} opts +* @returns {any} +*/ +export function browserslist(query: string, opts: any): any; + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly parse: (a: number, b: number, c: number) => void; + readonly browserslist: (a: number, b: number, c: number, d: number) => void; + readonly __wbindgen_malloc: (a: number, b: number) => number; + readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; + readonly __wbindgen_add_to_stack_pointer: (a: number) => number; + readonly __wbindgen_free: (a: number, b: number, c: number) => void; + readonly __wbindgen_exn_store: (a: number) => void; +} + +export type SyncInitInput = BufferSource | WebAssembly.Module; +/** +* Instantiates the given `module`, which can either be bytes or +* a precompiled `WebAssembly.Module`. +* +* @param {SyncInitInput} module +* +* @returns {InitOutput} +*/ +export function initSync(module: SyncInitInput): InitOutput; + +/** +* If `module_or_path` is {RequestInfo} or {URL}, makes a request and +* for everything else, calls `WebAssembly.instantiate` directly. +* +* @param {InitInput | Promise} module_or_path +* +* @returns {Promise} +*/ +export default function __wbg_init (module_or_path?: InitInput | Promise): Promise; diff --git a/wasm/bindings_wasm_bg.wasm.d.ts b/wasm/bindings_wasm_bg.wasm.d.ts new file mode 100644 index 000000000..2c81912b7 --- /dev/null +++ b/wasm/bindings_wasm_bg.wasm.d.ts @@ -0,0 +1,10 @@ +/* tslint:disable */ +/* eslint-disable */ +export const memory: WebAssembly.Memory; +export function parse(a: number, b: number, c: number): void; +export function browserslist(a: number, b: number, c: number, d: number): void; +export function __wbindgen_malloc(a: number, b: number): number; +export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number; +export function __wbindgen_add_to_stack_pointer(a: number): number; +export function __wbindgen_free(a: number, b: number, c: number): void; +export function __wbindgen_exn_store(a: number): void;