From 7bf3aa18d1c05657b71094a1077c634cafcd04c6 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Mon, 17 Aug 2026 00:05:59 +0000 Subject: [PATCH] chore: update swc to v1.16.0 --- deps/swc/Cargo.lock | 438 +-- deps/swc/Cargo.toml | 14 +- .../swc/bindings/binding_core_wasm/Cargo.toml | 2 +- .../bindings/binding_core_wasm/src/types.rs | 29 +- .../bindings/binding_es_ast_viewer/Cargo.toml | 2 +- .../swc/bindings/binding_html_wasm/Cargo.toml | 2 +- .../bindings/binding_minifier_wasm/Cargo.toml | 2 +- .../binding_minifier_wasm/src/types.rs | 29 +- .../.cargo/config.toml | 3 + .../binding_nodejs_support_wasm/Cargo.toml | 40 + .../binding_nodejs_support_wasm/LICENSE | 201 + .../binding_nodejs_support_wasm/README.md | 26 + .../binding_nodejs_support_wasm/package.json | 5 + .../rstest.config.mjs | 4 + .../scripts/build.sh | 16 + .../scripts/patch.mjs | 31 + .../scripts/test.sh | 9 + .../src/error_reporter.rs | 881 +++++ .../binding_nodejs_support_wasm/src/lib.rs | 308 ++ .../binding_nodejs_support_wasm/src/nodejs.rs | 1750 +++++++++ .../binding_react_compiler_node/Cargo.toml | 1 + .../src/diagnostics.rs | 281 ++ .../binding_react_compiler_node/src/lib.rs | 2 + .../binding_react_compiler_node/src/lint.rs | 257 ++ .../src/support.rs | 43 +- .../binding_typescript_wasm/Cargo.toml | 2 +- .../binding_typescript_wasm/src/lib.rs | 48 +- deps/swc/bindings/swc_cli/Cargo.toml | 4 +- deps/swc/crates/ast_node/Cargo.toml | 2 +- .../swc/crates/ast_node/src/ast_node_macro.rs | 20 +- .../crates/ast_node/src/encoding/decode.rs | 8 +- .../crates/ast_node/src/encoding/encode.rs | 5 +- deps/swc/crates/ast_node/src/lib.rs | 71 +- deps/swc/crates/binding_macros/Cargo.toml | 12 +- deps/swc/crates/dbg-swc/Cargo.toml | 20 +- deps/swc/crates/hstr/Cargo.toml | 5 +- deps/swc/crates/hstr/benches/libs.rs | 22 - deps/swc/crates/hstr/src/lib.rs | 40 +- deps/swc/crates/hstr/src/wtf8/mod.rs | 27 + .../swc/crates/hstr/src/wtf8/not_quite_std.rs | 46 +- deps/swc/crates/jsdoc/Cargo.toml | 12 +- deps/swc/crates/preset_env_base/Cargo.toml | 2 +- deps/swc/crates/swc-ast-explorer/Cargo.toml | 8 +- deps/swc/crates/swc/Cargo.toml | 70 +- deps/swc/crates/swc/examples/node_counter.rs | 4 +- deps/swc/crates/swc/src/builder.rs | 2 +- deps/swc/crates/swc/src/config/mod.rs | 63 +- deps/swc/crates/swc_allocator/Cargo.toml | 5 +- deps/swc/crates/swc_atoms/Cargo.toml | 10 +- deps/swc/crates/swc_atoms/src/lib.rs | 35 - deps/swc/crates/swc_atoms/src/wtf8_atom.rs | 41 - deps/swc/crates/swc_bundler/Cargo.toml | 36 +- .../swc_bundler/src/bundler/chunk/cjs.rs | 3 +- .../src/bundler/chunk/computed_key.rs | 3 +- .../swc_bundler/src/bundler/finalize.rs | 3 +- deps/swc/crates/swc_cli_impl/Cargo.toml | 4 +- deps/swc/crates/swc_common/Cargo.toml | 20 +- deps/swc/crates/swc_common/src/cache.rs | 85 +- deps/swc/crates/swc_common/src/comments.rs | 12 - .../swc_common/src/errors/diagnostic.rs | 24 - deps/swc/crates/swc_common/src/errors/mod.rs | 30 - .../crates/swc_common/src/errors/snippet.rs | 6 - deps/swc/crates/swc_common/src/lib.rs | 12 - .../swc_common/src/plugin/diagnostics.rs | 8 +- .../swc_common/src/plugin/serialized.rs | 101 +- deps/swc/crates/swc_common/src/syntax_pos.rs | 235 +- .../swc_common/src/syntax_pos/hygiene.rs | 38 +- deps/swc/crates/swc_common/src/unknown.rs | 51 - deps/swc/crates/swc_compiler_base/Cargo.toml | 18 +- deps/swc/crates/swc_config/Cargo.toml | 2 +- deps/swc/crates/swc_core/Cargo.toml | 91 +- deps/swc/crates/swc_core/build.rs | 41 +- deps/swc/crates/swc_core/src/lib.rs | 7 +- deps/swc/crates/swc_css/Cargo.toml | 20 +- deps/swc/crates/swc_css_ast/Cargo.toml | 16 +- deps/swc/crates/swc_css_ast/src/at_rule.rs | 22 - deps/swc/crates/swc_css_ast/src/selector.rs | 22 - deps/swc/crates/swc_css_ast/src/token.rs | 34 - deps/swc/crates/swc_css_ast/src/value.rs | 33 - deps/swc/crates/swc_css_codegen/Cargo.toml | 18 +- deps/swc/crates/swc_css_compat/Cargo.toml | 18 +- deps/swc/crates/swc_css_lints/Cargo.toml | 16 +- deps/swc/crates/swc_css_minifier/Cargo.toml | 18 +- deps/swc/crates/swc_css_modules/Cargo.toml | 18 +- deps/swc/crates/swc_css_parser/Cargo.toml | 14 +- deps/swc/crates/swc_css_prefixer/Cargo.toml | 20 +- deps/swc/crates/swc_css_utils/Cargo.toml | 8 +- deps/swc/crates/swc_css_visit/Cargo.toml | 8 +- deps/swc/crates/swc_ecma_ast/Cargo.toml | 18 +- deps/swc/crates/swc_ecma_ast/src/class.rs | 10 +- deps/swc/crates/swc_ecma_ast/src/decl.rs | 6 - deps/swc/crates/swc_ecma_ast/src/expr.rs | 119 +- deps/swc/crates/swc_ecma_ast/src/function.rs | 44 +- deps/swc/crates/swc_ecma_ast/src/ident.rs | 26 - deps/swc/crates/swc_ecma_ast/src/jsx.rs | 6 +- deps/swc/crates/swc_ecma_ast/src/lib.rs | 376 +- deps/swc/crates/swc_ecma_ast/src/lit.rs | 113 +- .../crates/swc_ecma_ast/src/module_decl.rs | 6 - deps/swc/crates/swc_ecma_ast/src/operators.rs | 24 - deps/swc/crates/swc_ecma_ast/src/prop.rs | 32 +- deps/swc/crates/swc_ecma_ast/src/stmt.rs | 1 + .../swc/crates/swc_ecma_ast/src/typescript.rs | 44 +- deps/swc/crates/swc_ecma_codegen/Cargo.toml | 43 +- deps/swc/crates/swc_ecma_codegen/src/class.rs | 21 +- deps/swc/crates/swc_ecma_codegen/src/lib.rs | 163 +- deps/swc/crates/swc_ecma_codegen/src/lit.rs | 184 +- .../swc/crates/swc_ecma_codegen/src/object.rs | 49 +- deps/swc/crates/swc_ecma_codegen/src/stmt.rs | 9 + .../crates/swc_ecma_codegen/src/typescript.rs | 31 +- .../swc_ecma_compat_bugfixes/Cargo.toml | 20 +- .../src/edge_default_param.rs | 2 +- ...turing_collision_in_function_expression.rs | 4 +- .../src/template_literal_caching.rs | 2 +- .../crates/swc_ecma_compat_common/Cargo.toml | 10 +- .../swc_ecma_compat_common/src/macros.rs | 86 +- .../crates/swc_ecma_compat_es2015/Cargo.toml | 26 +- .../swc_ecma_compat_es2015/src/arrow.rs | 48 +- .../src/block_scoped_fn.rs | 33 +- .../src/block_scoping/mod.rs | 45 +- .../src/block_scoping/vars.rs | 21 +- .../src/classes/constructor.rs | 12 +- .../swc_ecma_compat_es2015/src/classes/mod.rs | 3 +- .../src/classes/prop_name.rs | 3 +- .../src/computed_props.rs | 32 +- .../src/destructuring.rs | 16 +- .../swc_ecma_compat_es2015/src/generator.rs | 40 +- .../swc_ecma_compat_es2015/src/new_target.rs | 24 +- .../src/object_super.rs | 2 +- .../swc_ecma_compat_es2015/src/parameters.rs | 122 +- .../src/template_literal.rs | 6 +- .../crates/swc_ecma_compat_es2016/Cargo.toml | 14 +- .../crates/swc_ecma_compat_es2017/Cargo.toml | 12 +- .../crates/swc_ecma_compat_es2018/Cargo.toml | 10 +- .../crates/swc_ecma_compat_es2019/Cargo.toml | 16 +- .../crates/swc_ecma_compat_es2020/Cargo.toml | 16 +- .../crates/swc_ecma_compat_es2021/Cargo.toml | 10 +- .../crates/swc_ecma_compat_es2022/Cargo.toml | 18 +- .../src/class_properties/mod.rs | 24 +- .../src/optional_chaining_impl.rs | 26 +- .../swc/crates/swc_ecma_compat_es3/Cargo.toml | 10 +- .../crates/swc_ecma_compat_regexp/Cargo.toml | 8 +- .../crates/swc_ecma_ext_transforms/Cargo.toml | 10 +- deps/swc/crates/swc_ecma_hooks/Cargo.toml | 10 +- .../crates/swc_ecma_hooks/src/generated.rs | 708 +++- deps/swc/crates/swc_ecma_lexer/Cargo.toml | 20 +- .../swc_ecma_lexer/src/common/lexer/mod.rs | 4 +- .../swc_ecma_lexer/src/common/lexer/token.rs | 4 +- .../src/common/parser/buffer.rs | 2 +- .../src/common/parser/class_and_fn.rs | 110 +- .../swc_ecma_lexer/src/common/parser/expr.rs | 8 +- .../src/common/parser/object.rs | 85 +- .../swc_ecma_lexer/src/common/parser/pat.rs | 83 +- .../swc_ecma_lexer/src/common/parser/stmt.rs | 1 + deps/swc/crates/swc_ecma_lexer/src/input.rs | 2 +- .../crates/swc_ecma_lexer/src/lexer/jsx.rs | 4 +- deps/swc/crates/swc_ecma_lexer/src/token.rs | 4 +- deps/swc/crates/swc_ecma_lints/Cargo.toml | 20 +- .../src/rules/critical_rules.rs | 2 +- .../src/rules/no_empty_function.rs | 78 +- .../swc_ecma_lints/src/rules/no_loop_func.rs | 21 +- .../src/rules/no_use_before_define.rs | 20 +- .../swc_ecma_lints/src/rules/prefer_const.rs | 14 +- deps/swc/crates/swc_ecma_loader/Cargo.toml | 6 +- deps/swc/crates/swc_ecma_minifier/AGENTS.md | 30 + deps/swc/crates/swc_ecma_minifier/Cargo.toml | 28 +- .../crates/swc_ecma_minifier/fuzz/Cargo.lock | 31 +- .../crates/swc_ecma_minifier/src/cli/bin.rs | 5 +- .../src/compress/optimize/arguments.rs | 118 +- .../src/compress/optimize/evaluate.rs | 134 +- .../src/compress/optimize/iife.rs | 99 +- .../src/compress/optimize/inline.rs | 75 +- .../src/compress/optimize/mod.rs | 103 +- .../src/compress/optimize/sequences.rs | 61 +- .../src/compress/optimize/strings.rs | 12 +- .../src/compress/optimize/unused.rs | 140 +- .../src/compress/optimize/util.rs | 17 - .../src/compress/pure/arrows.rs | 18 +- .../src/compress/pure/bools.rs | 6 +- .../src/compress/pure/conds.rs | 25 +- .../src/compress/pure/evaluate.rs | 160 +- .../src/compress/pure/member_expr.rs | 96 +- .../src/compress/pure/misc.rs | 77 +- .../src/compress/pure/mod.rs | 8 +- .../src/compress/pure/vars.rs | 12 - deps/swc/crates/swc_ecma_minifier/src/eval.rs | 3 +- .../src/pass/mangle_names/preserver.rs | 20 +- .../swc_ecma_minifier/src/program_data.rs | 6 - .../src/usage_analyzer/alias/mod.rs | 8 +- .../src/usage_analyzer/analyzer/mod.rs | 235 +- .../src/usage_analyzer/analyzer/storage.rs | 2 - .../crates/swc_ecma_minifier/src/util/mod.rs | 32 +- .../crates/swc_ecma_minifier/src/util/size.rs | 4 +- deps/swc/crates/swc_ecma_parser/Cargo.toml | 18 +- deps/swc/crates/swc_ecma_parser/src/error.rs | 2 + deps/swc/crates/swc_ecma_parser/src/legacy.rs | 2 +- .../crates/swc_ecma_parser/src/lexer/mod.rs | 136 +- .../crates/swc_ecma_parser/src/lexer/state.rs | 24 +- .../crates/swc_ecma_parser/src/lexer/token.rs | 2 +- .../src/parser/class_and_fn.rs | 113 +- .../crates/swc_ecma_parser/src/parser/expr.rs | 8 +- .../swc_ecma_parser/src/parser/input.rs | 2 +- .../crates/swc_ecma_parser/src/parser/jsx.rs | 2 +- .../swc_ecma_parser/src/parser/object.rs | 88 +- .../crates/swc_ecma_parser/src/parser/pat.rs | 83 +- .../crates/swc_ecma_parser/src/parser/stmt.rs | 8 +- .../swc_ecma_parser/src/parser/typescript.rs | 1 + .../swc/crates/swc_ecma_preset_env/Cargo.toml | 24 +- .../swc/crates/swc_ecma_preset_env/src/lib.rs | 8 +- deps/swc/crates/swc_ecma_quote/Cargo.toml | 8 +- .../crates/swc_ecma_quote_macros/Cargo.toml | 10 +- .../swc_ecma_quote_macros/src/ast/expr.rs | 1 + .../swc_ecma_quote_macros/src/ast/mod.rs | 2 +- .../swc_ecma_quote_macros/src/ast/prop.rs | 4 +- .../swc_ecma_quote_macros/src/ast/stmt.rs | 3 +- .../src/ast/typescript.rs | 1 + .../crates/swc_ecma_react_compiler/Cargo.toml | 20 +- .../src/convert_ast.rs | 128 +- .../src/convert_ast_reverse.rs | 33 +- .../src/convert_scope.rs | 582 ++- .../src/diagnostics.rs | 478 ++- .../swc_ecma_react_compiler/src/fast_check.rs | 274 +- .../crates/swc_ecma_react_compiler/src/lib.rs | 51 +- .../swc_ecma_react_compiler/src/prefilter.rs | 149 - .../src/preserved_ast.rs | 13 + deps/swc/crates/swc_ecma_regexp/Cargo.toml | 10 +- .../swc/crates/swc_ecma_regexp_ast/Cargo.toml | 8 +- .../crates/swc_ecma_regexp_visit/Cargo.toml | 8 +- deps/swc/crates/swc_ecma_testing/Cargo.toml | 4 +- .../crates/swc_ecma_transformer/Cargo.toml | 20 +- .../src/common/statement_injector.rs | 9 +- .../src/common/var_declarations.rs | 25 +- .../src/es2017/async_to_generator.rs | 87 +- .../swc_ecma_transformer/src/es2017/mod.rs | 11 +- .../src/es2018/object_rest_spread.rs | 14 +- .../src/es2022/class_static_block.rs | 3 +- .../src/es2022/private_property_in_object.rs | 5 +- .../swc_ecma_transformer/src/hook_utils.rs | 6 +- .../crates/swc_ecma_transformer/src/lib.rs | 2 + .../swc/crates/swc_ecma_transforms/Cargo.toml | 30 +- .../swc_ecma_transforms_base/Cargo.toml | 20 +- .../swc_ecma_transforms_base/src/fixer.rs | 159 +- .../src/helpers/_array_like_to_array.js | 5 - .../src/helpers/_array_with_holes.js | 3 - .../src/helpers/_array_without_holes.js | 3 - .../src/helpers/_assert_this_initialized.js | 6 - .../src/helpers/_async_to_generator.js | 29 - .../src/helpers/_await_async_generator.js | 3 - .../src/helpers/_await_value.js | 3 - .../src/helpers/_call_super.js | 11 - .../helpers/_check_private_redeclaration.js | 5 - .../_class_apply_descriptor_destructure.js | 20 - .../helpers/_class_apply_descriptor_get.js | 6 - .../helpers/_class_apply_descriptor_set.js | 13 - .../helpers/_class_apply_descriptor_update.js | 26 - .../src/helpers/_class_call_check.js | 5 - .../_class_check_private_static_access.js | 5 - ...s_check_private_static_field_descriptor.js | 5 - .../_class_extract_field_descriptor.js | 6 - .../src/helpers/_class_name_tdz_error.js | 3 - .../_class_private_field_destructure.js | 4 - .../src/helpers/_class_private_field_get.js | 4 - .../src/helpers/_class_private_field_init.js | 4 - .../_class_private_field_loose_base.js | 6 - .../helpers/_class_private_field_loose_key.js | 4 - .../src/helpers/_class_private_field_set.js | 5 - .../helpers/_class_private_field_update.js | 4 - .../src/helpers/_class_private_method_get.js | 6 - .../src/helpers/_class_private_method_init.js | 4 - .../src/helpers/_class_private_method_set.js | 3 - ..._class_static_private_field_destructure.js | 5 - .../_class_static_private_field_spec_get.js | 5 - .../_class_static_private_field_spec_set.js | 6 - .../_class_static_private_field_update.js | 5 - .../_class_static_private_method_get.js | 4 - .../src/helpers/_construct.js | 15 - .../src/helpers/_create_class.js | 14 - .../_create_for_of_iterator_helper_loose.js | 18 - .../src/helpers/_create_super.js | 13 - .../src/helpers/_defaults.js | 11 - .../helpers/_define_enumerable_properties.js | 19 - .../src/helpers/_define_property.js | 8 - .../src/helpers/_export_star.js | 13 - .../src/helpers/_extends.js | 14 - .../src/helpers/_get.js | 16 - .../src/helpers/_get_prototype_of.js | 6 - .../src/helpers/_identity.js | 1 - .../src/helpers/_inherits.js | 9 - .../src/helpers/_inherits_loose.js | 5 - .../helpers/_initializer_define_property.js | 9 - .../helpers/_initializer_warning_helper.js | 7 - .../src/helpers/_instanceof.js | 9 - .../src/helpers/_interop_require_default.js | 3 - .../src/helpers/_interop_require_wildcard.js | 37 - .../src/helpers/_is_native_function.js | 3 - .../helpers/_is_native_reflect_construct.js | 14 - .../src/helpers/_iterable_to_array.js | 3 - .../src/helpers/_iterable_to_array_limit.js | 24 - .../helpers/_iterable_to_array_limit_loose.js | 10 - .../src/helpers/_jsx.js | 30 - .../src/helpers/_new_arrow_check.js | 5 - .../src/helpers/_non_iterable_rest.js | 5 - .../src/helpers/_non_iterable_spread.js | 5 - .../helpers/_object_destructuring_empty.js | 4 - .../src/helpers/_object_spread.js | 17 - .../src/helpers/_object_spread_props.js | 24 - .../_object_without_properties_loose.js | 13 - .../src/helpers/_overload_yield.js | 4 - .../helpers/_possible_constructor_return.js | 6 - .../src/helpers/_read_only_error.js | 3 - .../src/helpers/_set_prototype_of.js | 7 - .../src/helpers/_skip_first_generator_next.js | 7 - .../src/helpers/_sliced_to_array.js | 3 - .../src/helpers/_sliced_to_array_loose.js | 4 - .../src/helpers/_super_prop_base.js | 7 - .../src/helpers/_tagged_template_literal.js | 6 - .../helpers/_tagged_template_literal_loose.js | 7 - .../src/helpers/_throw.js | 3 - .../src/helpers/_to_array.js | 3 - .../src/helpers/_to_consumable_array.js | 3 - .../src/helpers/_to_primitive.js | 10 - .../src/helpers/_to_property_key.js | 4 - .../helpers/_ts_add_disposable_resource.js | 22 - .../src/helpers/_ts_decorate.js | 6 - .../src/helpers/_ts_dispose_resources.js | 33 - .../src/helpers/_ts_metadata.js | 3 - .../src/helpers/_ts_param.js | 3 - .../_ts_rewrite_relative_import_extension.js | 8 - .../src/helpers/_ts_values.js | 11 - .../src/helpers/_type_of.js | 4 - .../helpers/_unsupported_iterable_to_array.js | 8 - .../src/helpers/_update.js | 10 - .../src/helpers/_using.js | 19 - .../src/helpers/_wrap_async_generator.js | 5 - .../src/helpers/_wrap_native_super.js | 21 - .../src/helpers/_write_only_error.js | 3 - .../_apply_decorated_descriptor.rs} | 31 +- .../_apply_decs_2203_r.rs} | 320 +- .../_apply_decs_2311.rs} | 201 +- .../helpers/generated/_array_like_to_array.rs | 27 + .../helpers/generated/_array_with_holes.rs | 23 + .../helpers/generated/_array_without_holes.rs | 23 + .../generated/_assert_this_initialized.rs | 25 + .../_async_generator.rs} | 30 +- .../_async_generator_delegate.rs} | 31 +- .../_async_iterator.rs} | 32 +- .../helpers/generated/_async_to_generator.rs | 50 + .../generated/_await_async_generator.rs | 23 + .../src/helpers/generated/_await_value.rs | 23 + .../src/helpers/generated/_call_super.rs | 31 + .../generated/_check_private_redeclaration.rs | 25 + .../_class_apply_descriptor_destructure.rs | 42 + .../generated/_class_apply_descriptor_get.rs | 25 + .../generated/_class_apply_descriptor_set.rs | 32 + .../_class_apply_descriptor_update.rs | 47 + .../helpers/generated/_class_call_check.rs | 23 + .../_class_check_private_static_access.rs | 23 + ...s_check_private_static_field_descriptor.rs | 25 + .../_class_extract_field_descriptor.rs | 25 + .../generated/_class_name_tdz_error.rs | 23 + .../_class_private_field_destructure.rs | 24 + .../generated/_class_private_field_get.rs | 24 + .../generated/_class_private_field_init.rs | 24 + .../_class_private_field_loose_base.rs | 27 + .../_class_private_field_loose_key.rs | 25 + .../generated/_class_private_field_set.rs | 25 + .../generated/_class_private_field_update.rs | 24 + .../generated/_class_private_method_get.rs | 25 + .../generated/_class_private_method_init.rs | 24 + .../generated/_class_private_method_set.rs | 23 + ..._class_static_private_field_destructure.rs | 26 + .../_class_static_private_field_update.rs | 26 + .../_class_static_private_method_get.rs | 25 + .../src/helpers/generated/_construct.rs | 37 + .../src/helpers/generated/_create_class.rs | 37 + .../_create_for_of_iterator_helper_loose.rs | 39 + .../src/helpers/generated/_create_super.rs | 36 + .../{_decorate.js => generated/_decorate.rs} | 130 +- .../src/helpers/generated/_defaults.rs | 32 + .../_define_enumerable_properties.rs | 43 + .../src/helpers/generated/_define_property.rs | 27 + .../{_dispose.js => generated/_dispose.rs} | 32 +- .../src/helpers/generated/_export_star.rs | 34 + .../src/helpers/generated/_extends.rs | 32 + .../src/helpers/generated/_get.rs | 38 + .../helpers/generated/_get_prototype_of.rs | 27 + .../src/helpers/generated/_identity.rs | 23 + .../src/helpers/generated/_inherits.rs | 29 + .../src/helpers/generated/_inherits_loose.rs | 25 + .../generated/_initializer_define_property.rs | 30 + .../generated/_initializer_warning_helper.rs | 28 + .../src/helpers/generated/_instanceof.rs | 27 + .../generated/_interop_require_default.rs | 23 + .../generated/_interop_require_wildcard.rs | 55 + .../helpers/generated/_is_native_function.rs | 23 + .../generated/_is_native_reflect_construct.rs | 34 + .../helpers/generated/_iterable_to_array.rs | 25 + .../generated/_iterable_to_array_limit.rs | 48 + .../_iterable_to_array_limit_loose.rs | 34 + .../src/helpers/generated/_new_arrow_check.rs | 23 + .../helpers/generated/_non_iterable_rest.rs | 23 + .../helpers/generated/_non_iterable_spread.rs | 23 + .../generated/_object_destructuring_empty.rs | 25 + .../src/helpers/generated/_object_spread.rs | 40 + .../helpers/generated/_object_spread_props.rs | 47 + .../_object_without_properties.rs} | 22 +- .../_object_without_properties_loose.rs | 33 + .../src/helpers/generated/_overload_yield.rs | 24 + .../generated/_possible_constructor_return.rs | 25 + .../src/helpers/generated/_read_only_error.rs | 23 + .../helpers/{_set.js => generated/_set.rs} | 40 +- .../helpers/generated/_set_prototype_of.rs | 29 + .../generated/_skip_first_generator_next.rs | 28 + .../src/helpers/generated/_sliced_to_array.rs | 23 + .../generated/_sliced_to_array_loose.rs | 23 + .../src/helpers/generated/_super_prop_base.rs | 28 + .../generated/_tagged_template_literal.rs | 25 + .../_tagged_template_literal_loose.rs | 27 + .../src/helpers/generated/_throw.rs | 23 + .../src/helpers/generated/_to_array.rs | 23 + .../helpers/generated/_to_consumable_array.rs | 23 + .../src/helpers/generated/_to_primitive.rs | 33 + .../src/helpers/generated/_to_property_key.rs | 25 + .../generated/_ts_add_disposable_resource.rs | 59 + .../src/helpers/generated/_ts_decorate.rs | 33 + .../generated/_ts_dispose_resources.rs | 62 + .../_ts_generator.rs} | 24 +- .../src/helpers/generated/_ts_metadata.rs | 25 + .../src/helpers/generated/_ts_param.rs | 25 + .../_ts_rewrite_relative_import_extension.rs | 28 + .../src/helpers/generated/_ts_values.rs | 37 + .../src/helpers/generated/_type_of.rs | 25 + .../_unsupported_iterable_to_array.rs | 30 + .../src/helpers/generated/_update.rs | 30 + .../src/helpers/generated/_using.rs | 40 + .../_using_ctx.rs} | 47 +- .../generated/_wrap_async_generator.rs | 25 + .../helpers/generated/_wrap_native_super.rs | 40 + .../_wrap_reg_exp.rs} | 22 +- .../helpers/generated/_write_only_error.rs | 23 + .../src/helpers/generated/mod.rs | 1070 ++++++ .../src/helpers/mod.rs | 485 +-- .../src/hygiene/mod.rs | 12 +- .../src/rename/analyer_and_collector.rs | 24 +- .../src/rename/analyzer/mod.rs | 13 +- .../src/rename/analyzer/scope.rs | 19 +- .../src/rename/mod.rs | 18 + .../src/resolver/mod.rs | 67 +- .../swc_ecma_transforms_classes/Cargo.toml | 12 +- .../src/super_field.rs | 13 - .../swc_ecma_transforms_compat/Cargo.toml | 44 +- .../swc_ecma_transforms_module/Cargo.toml | 30 +- .../swc_ecma_transforms_module/README.md | 390 ++ .../swc_ecma_transforms_module/src/amd.rs | 318 +- .../src/amd/emit.rs | 87 + .../src/common_js.rs | 294 +- .../src/import_analysis.rs | 23 +- .../swc_ecma_transforms_module/src/lib.rs | 3 +- .../src/module_decl_strip.rs | 812 ---- .../src/module_record.rs | 974 +++++ .../src/module_ref_rewriter.rs | 5 +- .../swc_ecma_transforms_module/src/path.rs | 217 +- .../rewriter/import_rewriter_typescript.rs | 51 +- .../src/syntax_strip.rs | 119 + .../src/system_js.rs | 1214 +----- .../src/system_js/emit.rs | 517 +++ .../src/system_js/ir.rs | 231 ++ .../src/system_js/lower.rs | 596 +++ .../src/system_js/pattern.rs | 74 + .../src/system_js/rewrite.rs | 308 ++ .../src/system_js/util.rs | 51 + .../swc_ecma_transforms_module/src/umd.rs | 473 +-- .../src/umd/config.rs | 2 +- .../src/umd/emit.rs | 260 ++ .../swc_ecma_transforms_module/src/util.rs | 69 +- .../swc_ecma_transforms_module/src/wtf8.rs | 11 +- .../Cargo.toml | 33 +- .../src/debug.rs | 10 - .../src/json_parse.rs | 154 +- .../src/simplify/branch/mod.rs | 2 +- .../src/simplify/dce/mod.rs | 401 +- .../src/simplify/expr/mod.rs | 297 +- .../swc_ecma_transforms_proposal/Cargo.toml | 26 +- .../src/decorator_impl.rs | 91 +- .../src/decorators/mod.rs | 6 +- .../swc_ecma_transforms_react/Cargo.toml | 30 +- .../swc_ecma_transforms_react/src/jsx/mod.rs | 344 +- .../src/jsx_self/mod.rs | 126 +- .../src/refresh/hook.rs | 94 +- .../src/refresh/util.rs | 4 +- .../swc_ecma_transforms_testing/Cargo.toml | 20 +- .../swc_ecma_transforms_typescript/Cargo.toml | 28 +- .../src/semantic.rs | 10 +- .../src/shared.rs | 10 +- .../src/transform.rs | 60 +- .../src/ts_enum.rs | 181 +- .../src/utils.rs | 4 +- deps/swc/crates/swc_ecma_utils/Cargo.toml | 12 +- .../crates/swc_ecma_utils/src/constructor.rs | 8 - deps/swc/crates/swc_ecma_utils/src/factory.rs | 5 +- .../src/function/fn_env_hoister.rs | 239 +- deps/swc/crates/swc_ecma_utils/src/lib.rs | 214 +- deps/swc/crates/swc_ecma_utils/src/number.rs | 123 + deps/swc/crates/swc_ecma_visit/Cargo.toml | 8 +- .../crates/swc_ecma_visit/src/generated.rs | 3204 ++++++++++++---- deps/swc/crates/swc_ecmascript/Cargo.toml | 21 +- .../swc/crates/swc_error_reporters/Cargo.toml | 4 +- deps/swc/crates/swc_estree_ast/Cargo.toml | 6 +- deps/swc/crates/swc_estree_ast/src/jsx.rs | 4 +- deps/swc/crates/swc_estree_compat/Cargo.toml | 28 +- .../swc_estree_compat/src/babelify/class.rs | 12 +- .../swc_estree_compat/src/babelify/expr.rs | 10 +- .../src/babelify/function.rs | 30 +- .../swc_estree_compat/src/babelify/prop.rs | 71 +- .../swc_estree_compat/src/babelify/stmt.rs | 17 +- .../swc_estree_compat/src/swcify/class.rs | 24 +- .../swc_estree_compat/src/swcify/expr.rs | 37 +- .../swc_estree_compat/src/swcify/function.rs | 91 + .../swc_estree_compat/src/swcify/mod.rs | 1 + .../swc_estree_compat/src/swcify/stmt.rs | 32 +- deps/swc/crates/swc_graph_analyzer/Cargo.toml | 2 +- deps/swc/crates/swc_html/Cargo.toml | 10 +- deps/swc/crates/swc_html_ast/Cargo.toml | 16 +- deps/swc/crates/swc_html_ast/src/base.rs | 22 - deps/swc/crates/swc_html_ast/src/token.rs | 22 - deps/swc/crates/swc_html_codegen/Cargo.toml | 18 +- deps/swc/crates/swc_html_minifier/Cargo.toml | 40 +- deps/swc/crates/swc_html_minifier/src/lib.rs | 16 +- deps/swc/crates/swc_html_parser/Cargo.toml | 16 +- deps/swc/crates/swc_html_utils/Cargo.toml | 4 +- deps/swc/crates/swc_html_visit/Cargo.toml | 8 +- deps/swc/crates/swc_node_bundler/Cargo.toml | 26 +- deps/swc/crates/swc_node_comments/Cargo.toml | 6 +- .../swc_plugin_backend_tests/Cargo.toml | 21 +- .../swc_plugin_backend_wasmer/Cargo.toml | 9 +- .../src/filesystem_cache.rs | 106 + .../swc_plugin_backend_wasmer/src/lib.rs | 12 + .../swc_plugin_backend_wasmtime/Cargo.toml | 6 +- deps/swc/crates/swc_plugin_macro/Cargo.toml | 2 +- deps/swc/crates/swc_plugin_macro/src/lib.rs | 28 +- deps/swc/crates/swc_plugin_proxy/Cargo.toml | 6 +- .../read_returned_result_from_host.rs | 29 +- deps/swc/crates/swc_plugin_runner/Cargo.toml | 16 +- deps/swc/crates/swc_plugin_runner/build.rs | 18 - .../src/transform_executor.rs | 8 - .../crates/swc_transform_common/Cargo.toml | 4 +- deps/swc/crates/swc_ts_fast_strip/Cargo.toml | 22 +- .../swc_ts_fast_strip/benches/assets.rs | 40 +- .../benches/assets/README.md | 12 + .../assets/ant-design.vitest.config.ts | 195 + .../benches/assets/docusaurus.config.ts | 908 +++++ .../benches/assets/graphile.config.ts | 747 ++++ .../benches/assets/hono.types.test.ts | 3294 +++++++++++++++++ .../typescript-eslint.generate-configs.mts | 454 +++ deps/swc/crates/swc_ts_fast_strip/src/lib.rs | 404 +- .../swc/crates/swc_ts_fast_strip/src/strip.rs | 271 ++ .../swc_ts_fast_strip_binding/Cargo.toml | 15 +- .../benches/assets.rs | 49 + .../swc_ts_fast_strip_binding/src/lib.rs | 48 +- deps/swc/crates/swc_typescript/Cargo.toml | 20 +- .../swc_typescript/src/fast_dts/class.rs | 7 +- .../swc_typescript/src/fast_dts/enum.rs | 174 +- .../swc_typescript/src/fast_dts/function.rs | 18 +- .../swc_typescript/src/fast_dts/inferrer.rs | 8 +- .../swc_typescript/src/fast_dts/types.rs | 93 +- .../src/fast_dts/util/ast_ext.rs | 19 +- .../src/fast_dts/visitors/type_usage.rs | 1 + deps/swc/crates/swc_xml/Cargo.toml | 10 +- deps/swc/crates/swc_xml_ast/Cargo.toml | 6 +- deps/swc/crates/swc_xml_codegen/Cargo.toml | 14 +- deps/swc/crates/swc_xml_parser/Cargo.toml | 14 +- deps/swc/crates/swc_xml_visit/Cargo.toml | 8 +- deps/swc/crates/testing/Cargo.toml | 8 +- deps/swc/crates/testing_macros/Cargo.toml | 5 +- deps/swc/crates/testing_macros/src/fixture.rs | 83 +- deps/swc/crates/testing_macros/src/lib.rs | 9 +- deps/swc/tools/generate-code/Cargo.toml | 2 +- .../generate-code/src/generators/helpers.rs | 571 +++ .../tools/generate-code/src/generators/mod.rs | 1 + deps/swc/tools/generate-code/src/main.rs | 219 +- 579 files changed, 29874 insertions(+), 11491 deletions(-) create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/.cargo/config.toml create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/Cargo.toml create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/LICENSE create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/README.md create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/package.json create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/rstest.config.mjs create mode 100755 deps/swc/bindings/binding_nodejs_support_wasm/scripts/build.sh create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/scripts/patch.mjs create mode 100755 deps/swc/bindings/binding_nodejs_support_wasm/scripts/test.sh create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/src/error_reporter.rs create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/src/lib.rs create mode 100644 deps/swc/bindings/binding_nodejs_support_wasm/src/nodejs.rs create mode 100644 deps/swc/bindings/binding_react_compiler_node/src/diagnostics.rs create mode 100644 deps/swc/bindings/binding_react_compiler_node/src/lint.rs delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_like_to_array.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_with_holes.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_without_holes.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_assert_this_initialized.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_to_generator.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_await_async_generator.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_await_value.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_call_super.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_check_private_redeclaration.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_destructure.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_get.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_set.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_update.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_call_check.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_check_private_static_access.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_check_private_static_field_descriptor.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_extract_field_descriptor.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_name_tdz_error.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_destructure.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_get.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_init.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_loose_base.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_loose_key.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_set.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_update.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_get.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_init.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_set.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_destructure.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_spec_get.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_spec_set.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_update.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_method_get.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_construct.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_class.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_for_of_iterator_helper_loose.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_super.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_defaults.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_define_enumerable_properties.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_define_property.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_export_star.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_extends.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_get.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_get_prototype_of.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_identity.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_inherits.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_inherits_loose.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_initializer_define_property.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_initializer_warning_helper.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_instanceof.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_interop_require_default.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_interop_require_wildcard.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_is_native_function.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_is_native_reflect_construct.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array_limit.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array_limit_loose.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_jsx.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_new_arrow_check.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_non_iterable_rest.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_non_iterable_spread.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_destructuring_empty.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_spread.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_spread_props.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_without_properties_loose.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_overload_yield.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_possible_constructor_return.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_read_only_error.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_set_prototype_of.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_skip_first_generator_next.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_sliced_to_array.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_sliced_to_array_loose.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_super_prop_base.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_tagged_template_literal.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_tagged_template_literal_loose.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_throw.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_array.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_consumable_array.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_primitive.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_property_key.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_add_disposable_resource.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_decorate.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_dispose_resources.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_metadata.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_param.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_rewrite_relative_import_extension.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_values.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_type_of.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_unsupported_iterable_to_array.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_update.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_using.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_async_generator.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_native_super.js delete mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/_write_only_error.js rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_apply_decorated_descriptor.js => generated/_apply_decorated_descriptor.rs} (51%) rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_apply_decs_2203_r.js => generated/_apply_decs_2203_r.rs} (71%) rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_apply_decs_2311.js => generated/_apply_decs_2311.rs} (61%) create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_like_to_array.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_with_holes.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_without_holes.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_assert_this_initialized.rs rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_async_generator.js => generated/_async_generator.rs} (74%) rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_async_generator_delegate.js => generated/_async_generator_delegate.rs} (58%) rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_async_iterator.js => generated/_async_iterator.rs} (63%) create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_to_generator.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_await_async_generator.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_await_value.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_call_super.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_check_private_redeclaration.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_destructure.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_get.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_set.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_update.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_call_check.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_check_private_static_access.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_check_private_static_field_descriptor.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_extract_field_descriptor.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_name_tdz_error.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_destructure.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_get.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_init.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_loose_base.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_loose_key.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_set.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_update.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_get.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_init.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_set.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_field_destructure.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_field_update.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_method_get.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_construct.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_class.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_for_of_iterator_helper_loose.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_super.rs rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_decorate.js => generated/_decorate.rs} (75%) create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_defaults.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_define_enumerable_properties.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_define_property.rs rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_dispose.js => generated/_dispose.rs} (57%) create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_export_star.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_extends.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_get.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_get_prototype_of.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_identity.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_inherits.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_inherits_loose.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_initializer_define_property.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_initializer_warning_helper.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_instanceof.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_interop_require_default.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_interop_require_wildcard.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_is_native_function.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_is_native_reflect_construct.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array_limit.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array_limit_loose.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_new_arrow_check.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_non_iterable_rest.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_non_iterable_spread.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_destructuring_empty.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_spread.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_spread_props.rs rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_object_without_properties.js => generated/_object_without_properties.rs} (54%) create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_without_properties_loose.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_overload_yield.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_possible_constructor_return.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_read_only_error.rs rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_set.js => generated/_set.rs} (52%) create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_set_prototype_of.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_skip_first_generator_next.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_sliced_to_array.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_sliced_to_array_loose.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_super_prop_base.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_tagged_template_literal.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_tagged_template_literal_loose.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_throw.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_array.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_consumable_array.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_primitive.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_property_key.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_add_disposable_resource.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_decorate.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_dispose_resources.rs rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_ts_generator.js => generated/_ts_generator.rs} (72%) create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_metadata.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_param.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_rewrite_relative_import_extension.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_values.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_type_of.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_unsupported_iterable_to_array.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_update.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_using.rs rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_using_ctx.js => generated/_using_ctx.rs} (60%) create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_async_generator.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_native_super.rs rename deps/swc/crates/swc_ecma_transforms_base/src/helpers/{_wrap_reg_exp.js => generated/_wrap_reg_exp.rs} (80%) create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_write_only_error.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/mod.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/README.md create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/amd/emit.rs delete mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/module_decl_strip.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/module_record.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/syntax_strip.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/system_js/emit.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/system_js/ir.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/system_js/lower.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/system_js/pattern.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/system_js/rewrite.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/system_js/util.rs create mode 100644 deps/swc/crates/swc_ecma_transforms_module/src/umd/emit.rs create mode 100644 deps/swc/crates/swc_estree_compat/src/swcify/function.rs create mode 100644 deps/swc/crates/swc_plugin_backend_wasmer/src/filesystem_cache.rs delete mode 100644 deps/swc/crates/swc_plugin_runner/build.rs create mode 100644 deps/swc/crates/swc_ts_fast_strip/benches/assets/README.md create mode 100644 deps/swc/crates/swc_ts_fast_strip/benches/assets/ant-design.vitest.config.ts create mode 100644 deps/swc/crates/swc_ts_fast_strip/benches/assets/docusaurus.config.ts create mode 100644 deps/swc/crates/swc_ts_fast_strip/benches/assets/graphile.config.ts create mode 100644 deps/swc/crates/swc_ts_fast_strip/benches/assets/hono.types.test.ts create mode 100644 deps/swc/crates/swc_ts_fast_strip/benches/assets/typescript-eslint.generate-configs.mts create mode 100644 deps/swc/crates/swc_ts_fast_strip/src/strip.rs create mode 100644 deps/swc/crates/swc_ts_fast_strip_binding/benches/assets.rs create mode 100644 deps/swc/tools/generate-code/src/generators/helpers.rs diff --git a/deps/swc/Cargo.lock b/deps/swc/Cargo.lock index 799963b7c..c221a18ae 100644 --- a/deps/swc/Cargo.lock +++ b/deps/swc/Cargo.lock @@ -168,9 +168,9 @@ checksum = "70033777eb8b5124a81a1889416543dddef2de240019b674c81285a2635a7e1e" [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "approx" @@ -240,7 +240,7 @@ dependencies = [ [[package]] name = "ast_node" -version = "5.0.0" +version = "7.0.0" dependencies = [ "quote", "swc_macros_common", @@ -395,7 +395,7 @@ dependencies = [ [[package]] name = "binding_core_wasm" -version = "1.15.43" +version = "1.16.0" dependencies = [ "anyhow", "getrandom 0.3.4", @@ -408,7 +408,7 @@ dependencies = [ [[package]] name = "binding_es_ast_viewer" -version = "1.15.43" +version = "1.16.0" dependencies = [ "anyhow", "swc_core", @@ -444,7 +444,7 @@ dependencies = [ [[package]] name = "binding_html_wasm" -version = "1.15.43" +version = "1.16.0" dependencies = [ "anyhow", "getrandom 0.3.4", @@ -470,7 +470,7 @@ dependencies = [ [[package]] name = "binding_macros" -version = "69.0.0" +version = "75.0.0" dependencies = [ "anyhow", "console_error_panic_hook", @@ -509,7 +509,7 @@ dependencies = [ [[package]] name = "binding_minifier_wasm" -version = "1.15.43" +version = "1.16.0" dependencies = [ "getrandom 0.3.4", "serde", @@ -518,6 +518,29 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "binding_nodejs_support_wasm" +version = "1.16.0" +dependencies = [ + "anyhow", + "js-sys", + "miette", + "owo-colors", + "serde", + "serde-wasm-bindgen", + "serde_json", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_visit", + "swc_error_reporters", + "swc_ts_fast_strip", + "tracing", + "unicode-width 0.2.2", + "wasm-bindgen", + "wasm-bindgen-futures", +] + [[package]] name = "binding_react_compiler_node" version = "0.2.0" @@ -527,6 +550,7 @@ dependencies = [ "napi-build", "napi-derive", "serde", + "serde_json", "swc_core", "swc_ecma_react_compiler", "swc_malloc", @@ -535,7 +559,7 @@ dependencies = [ [[package]] name = "binding_typescript_wasm" -version = "1.15.43" +version = "1.16.0" dependencies = [ "anyhow", "js-sys", @@ -615,9 +639,9 @@ dependencies = [ [[package]] name = "browserslist-data" -version = "0.1.5" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21d369bf3fe9811518eead42e2cdf9ed9915579242864297689894c0f1089712" +checksum = "77d121add86b74ceac9755a74ec3b4abc1f4935711aede468f26a36dc685dc80" dependencies = [ "ahash 0.8.12", "chrono", @@ -625,16 +649,16 @@ dependencies = [ [[package]] name = "browserslist-rs" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd48a6ca358df4f7000e3fb5f08738b1b91a0e5d5f862e2f77b2b14647547f5" +checksum = "ec54e3c5c50eae1f8d771c7ffc311c1cc8e5e3c85b9fd87b557633bbe9b7cb01" dependencies = [ "ahash 0.8.12", "browserslist-data", "chrono", "either", - "itertools 0.13.0", - "nom 7.1.3", + "itertools 0.15.0", + "nom 8.0.0", "serde", "serde_json", "thiserror 1.0.69", @@ -738,7 +762,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c02af038c863b51d496dd4a2eabdf781f8f7ab68025e13b984b7f2c525560454" dependencies = [ "bytes", - "rkyv 0.8.16", "serde", ] @@ -1573,9 +1596,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] @@ -1703,7 +1726,6 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", "syn 2.0.110", ] @@ -1773,7 +1795,7 @@ dependencies = [ [[package]] name = "dbg-swc" -version = "57.0.0" +version = "62.0.0" dependencies = [ "anyhow", "clap 3.2.25", @@ -1835,16 +1857,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" dependencies = [ - "derive_builder_macro 0.12.0", -] - -[[package]] -name = "derive_builder" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" -dependencies = [ - "derive_builder_macro 0.20.0", + "derive_builder_macro", ] [[package]] @@ -1859,38 +1872,16 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_builder_core" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" -dependencies = [ - "darling 0.20.10", - "proc-macro2", - "quote", - "syn 2.0.110", -] - [[package]] name = "derive_builder_macro" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" dependencies = [ - "derive_builder_core 0.12.0", + "derive_builder_core", "syn 1.0.109", ] -[[package]] -name = "derive_builder_macro" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" -dependencies = [ - "derive_builder_core 0.20.0", - "syn 2.0.110", -] - [[package]] name = "derive_more" version = "0.99.18" @@ -2039,9 +2030,9 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "either" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" [[package]] name = "embedded-io" @@ -2579,18 +2570,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "getset" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "gimli" version = "0.28.1" @@ -2721,8 +2700,6 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "allocator-api2", - "equivalent", "foldhash 0.1.5", "serde", ] @@ -2743,6 +2720,11 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "heapless" @@ -2804,7 +2786,7 @@ checksum = "ec9d92d097f4749b64e8cc33d924d9f40a2d4eb91402b458014b781f5733d60f" [[package]] name = "hstr" -version = "3.0.6" +version = "4.0.1" dependencies = [ "compact_str", "criterion", @@ -2815,11 +2797,9 @@ dependencies = [ "once_cell", "par-iter", "rand 0.8.6", - "rkyv 0.8.16", "rustc-hash 2.1.1", "serde", "serde_json", - "smartstring", "smol_str", "string_cache", "swc_malloc", @@ -3335,6 +3315,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -3353,7 +3342,7 @@ dependencies = [ [[package]] name = "jsdoc" -version = "23.0.0" +version = "26.0.0" dependencies = [ "cbor4ii", "dashmap 6.1.0", @@ -3671,11 +3660,11 @@ checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "lru" -version = "0.16.3" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +checksum = "5d2f2f9b4ba7e6b24d95e7e899329d35be83bcded72c8540cdd5368932d1d90a" dependencies = [ - "hashbrown 0.16.0", + "hashbrown 0.17.1", ] [[package]] @@ -3993,6 +3982,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + [[package]] name = "normpath" version = "0.2.0" @@ -4146,15 +4144,6 @@ dependencies = [ "syn 2.0.110", ] -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - [[package]] name = "object" version = "0.32.2" @@ -4606,7 +4595,7 @@ dependencies = [ [[package]] name = "preset_env_base" -version = "8.0.1" +version = "9.0.0" dependencies = [ "anyhow", "browserslist-rs", @@ -5016,11 +5005,11 @@ dependencies = [ [[package]] name = "regress" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ef7fa9ed0256d64a688a3747d0fef7a88851c18a5e1d57f115f38ec2e09366" +checksum = "158a764437582235e3501f683b93a0a6f8d825d04a789dbe5ed30b8799b8908a" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.0", "memchr", ] @@ -5114,9 +5103,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73389e0c99e664f919275ab5b5b0471391fe9a8de61e1dff9b1eaf56a90f16e3" +checksum = "815cc8a37159a463064825246cadb07961e25cd9885908606f6d08a98d8f8874" dependencies = [ "bytecheck 0.8.1", "bytes", @@ -5126,7 +5115,7 @@ dependencies = [ "ptr_meta 0.3.0", "rancor", "rend 0.5.2", - "rkyv_derive 0.8.16", + "rkyv_derive 0.8.17", "tinyvec", "uuid", ] @@ -5144,9 +5133,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2ed0b54125315fb36bd021e82d314d1c126548f871634b483f46b31d13cac6" +checksum = "c0ed1a78a1b19d184b0daa629dd9a024573173ec7d485b287cb369fb3607cc1c" dependencies = [ "proc-macro2", "quote", @@ -5669,17 +5658,6 @@ dependencies = [ "serde", ] -[[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 = "smol_str" version = "0.2.2" @@ -5814,7 +5792,7 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "swc" -version = "69.0.0" +version = "75.0.0" dependencies = [ "ansi_term", "anyhow", @@ -5904,7 +5882,7 @@ dependencies = [ [[package]] name = "swc_allocator" -version = "4.0.1" +version = "5.0.0" dependencies = [ "allocator-api2", "bumpalo", @@ -5926,22 +5904,19 @@ dependencies = [ [[package]] name = "swc_atoms" -version = "9.0.3" +version = "10.0.0" dependencies = [ "arbitrary", - "bytecheck 0.8.1", "cbor4ii", "hstr", "once_cell", - "rancor", - "rkyv 0.8.16", "serde", "shrink-to-fit", ] [[package]] name = "swc_bundler" -version = "51.0.1" +version = "56.0.0" dependencies = [ "anyhow", "crc", @@ -5983,7 +5958,7 @@ dependencies = [ [[package]] name = "swc_cli" -version = "0.116.3" +version = "0.122.2" dependencies = [ "anyhow", "par-core", @@ -5992,7 +5967,7 @@ dependencies = [ [[package]] name = "swc_cli_impl" -version = "71.0.0" +version = "77.0.0" dependencies = [ "anyhow", "assert_cmd", @@ -6012,13 +5987,12 @@ dependencies = [ [[package]] name = "swc_common" -version = "23.0.2" +version = "26.0.0" dependencies = [ "anyhow", "arbitrary", "ast_node", "better_scoped_tls", - "bytecheck 0.8.1", "bytes-str", "cbor4ii", "either", @@ -6027,8 +6001,6 @@ dependencies = [ "once_cell", "par-iter", "parking_lot", - "rancor", - "rkyv 0.8.16", "rustc-hash 2.1.1", "serde", "serde_json", @@ -6046,7 +6018,7 @@ dependencies = [ [[package]] name = "swc_compiler_base" -version = "59.0.0" +version = "64.0.0" dependencies = [ "anyhow", "base64 0.22.1", @@ -6071,7 +6043,7 @@ dependencies = [ [[package]] name = "swc_config" -version = "5.0.0" +version = "6.0.0" dependencies = [ "anyhow", "bytes-str", @@ -6100,7 +6072,7 @@ dependencies = [ [[package]] name = "swc_core" -version = "71.0.3" +version = "77.0.0" dependencies = [ "anyhow", "binding_macros", @@ -6149,12 +6121,11 @@ dependencies = [ "swc_transform_common", "swc_typescript", "testing", - "vergen", ] [[package]] name = "swc_css" -version = "28.0.0" +version = "31.0.0" dependencies = [ "swc_css_ast", "swc_css_codegen", @@ -6169,12 +6140,10 @@ dependencies = [ [[package]] name = "swc_css_ast" -version = "23.0.0" +version = "26.0.0" dependencies = [ - "bytecheck 0.8.1", "cbor4ii", "is-macro", - "rkyv 0.8.16", "serde", "string_enum", "swc_atoms", @@ -6183,7 +6152,7 @@ dependencies = [ [[package]] name = "swc_css_codegen" -version = "23.0.0" +version = "26.0.0" dependencies = [ "auto_impl", "bitflags 2.10.0", @@ -6209,7 +6178,7 @@ dependencies = [ [[package]] name = "swc_css_compat" -version = "23.0.0" +version = "26.0.0" dependencies = [ "bitflags 2.10.0", "serde", @@ -6225,7 +6194,7 @@ dependencies = [ [[package]] name = "swc_css_lints" -version = "25.0.0" +version = "29.0.0" dependencies = [ "anyhow", "auto_impl", @@ -6246,7 +6215,7 @@ dependencies = [ [[package]] name = "swc_css_minifier" -version = "23.0.0" +version = "26.0.0" dependencies = [ "rustc-hash 2.1.1", "serde", @@ -6262,7 +6231,7 @@ dependencies = [ [[package]] name = "swc_css_modules" -version = "23.0.0" +version = "26.0.0" dependencies = [ "indexmap 2.12.0", "rustc-hash 2.1.1", @@ -6279,7 +6248,7 @@ dependencies = [ [[package]] name = "swc_css_parser" -version = "23.0.0" +version = "26.0.0" dependencies = [ "codspeed-criterion-compat", "lexical", @@ -6295,7 +6264,7 @@ dependencies = [ [[package]] name = "swc_css_prefixer" -version = "28.0.0" +version = "31.0.0" dependencies = [ "once_cell", "preset_env_base", @@ -6314,7 +6283,7 @@ dependencies = [ [[package]] name = "swc_css_utils" -version = "23.0.0" +version = "26.0.0" dependencies = [ "once_cell", "rustc-hash 2.1.1", @@ -6327,7 +6296,7 @@ dependencies = [ [[package]] name = "swc_css_visit" -version = "23.0.0" +version = "26.0.0" dependencies = [ "serde", "swc_atoms", @@ -6338,18 +6307,15 @@ dependencies = [ [[package]] name = "swc_ecma_ast" -version = "25.0.0" +version = "29.0.0" dependencies = [ "arbitrary", "bitflags 2.10.0", - "bytecheck 0.8.1", "cbor4ii", "is-macro", "num-bigint", "once_cell", "phf", - "rancor", - "rkyv 0.8.16", "rustc-hash 2.1.1", "serde", "serde_json", @@ -6363,7 +6329,7 @@ dependencies = [ [[package]] name = "swc_ecma_codegen" -version = "28.0.2" +version = "32.0.0" dependencies = [ "ascii", "base64 0.22.1", @@ -6384,6 +6350,7 @@ dependencies = [ "swc_ecma_codegen_macros", "swc_ecma_parser", "swc_ecma_testing", + "swc_ecma_utils", "swc_malloc", "swc_sourcemap", "testing", @@ -6401,7 +6368,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_bugfixes" -version = "51.0.0" +version = "56.0.0" dependencies = [ "rustc-hash 2.1.1", "swc_atoms", @@ -6418,7 +6385,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_common" -version = "40.0.1" +version = "45.0.0" dependencies = [ "swc_common", "swc_ecma_ast", @@ -6428,7 +6395,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2015" -version = "50.0.0" +version = "55.0.0" dependencies = [ "arrayvec", "indexmap 2.12.0", @@ -6455,7 +6422,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2016" -version = "45.0.0" +version = "50.0.0" dependencies = [ "swc_ecma_ast", "swc_ecma_parser", @@ -6468,7 +6435,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2017" -version = "45.0.0" +version = "50.0.0" dependencies = [ "serde", "swc_common", @@ -6481,7 +6448,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2018" -version = "46.0.0" +version = "51.0.0" dependencies = [ "serde", "swc_ecma_ast", @@ -6493,7 +6460,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2019" -version = "45.0.0" +version = "50.0.0" dependencies = [ "swc_common", "swc_ecma_ast", @@ -6507,7 +6474,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2020" -version = "48.0.0" +version = "53.0.0" dependencies = [ "serde", "swc_common", @@ -6522,7 +6489,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2021" -version = "45.0.0" +version = "50.0.0" dependencies = [ "swc_ecma_ast", "swc_ecma_transformer", @@ -6533,7 +6500,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es2022" -version = "48.0.0" +version = "53.0.0" dependencies = [ "rustc-hash 2.1.1", "swc_atoms", @@ -6550,7 +6517,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_es3" -version = "36.0.0" +version = "41.0.0" dependencies = [ "swc_ecma_ast", "swc_ecma_parser", @@ -6560,7 +6527,7 @@ dependencies = [ [[package]] name = "swc_ecma_compat_regexp" -version = "6.0.0" +version = "9.0.0" dependencies = [ "icu_properties 2.1.2", "swc_ecma_regexp", @@ -6570,7 +6537,7 @@ dependencies = [ [[package]] name = "swc_ecma_ext_transforms" -version = "31.0.0" +version = "35.0.0" dependencies = [ "phf", "swc_common", @@ -6581,7 +6548,7 @@ dependencies = [ [[package]] name = "swc_ecma_hooks" -version = "0.9.0" +version = "1.0.0" dependencies = [ "swc_atoms", "swc_common", @@ -6591,16 +6558,16 @@ dependencies = [ [[package]] name = "swc_ecma_lexer" -version = "40.0.1" +version = "44.0.0" dependencies = [ "bitflags 2.10.0", + "compact_str", "either", "num-bigint", "rustc-hash 2.1.1", "seq-macro", "serde", "smallvec", - "smartstring", "stacker", "swc_atoms", "swc_common", @@ -6613,7 +6580,7 @@ dependencies = [ [[package]] name = "swc_ecma_lints" -version = "33.0.0" +version = "37.0.0" dependencies = [ "auto_impl", "codspeed-criterion-compat", @@ -6637,7 +6604,7 @@ dependencies = [ [[package]] name = "swc_ecma_loader" -version = "24.0.1" +version = "27.0.0" dependencies = [ "anyhow", "dashmap 6.1.0", @@ -6658,7 +6625,7 @@ dependencies = [ [[package]] name = "swc_ecma_minifier" -version = "56.0.1" +version = "61.0.0" dependencies = [ "ansi_term", "anyhow", @@ -6701,11 +6668,12 @@ dependencies = [ [[package]] name = "swc_ecma_parser" -version = "41.1.2" +version = "45.0.0" dependencies = [ "bitflags 2.10.0", "cbor4ii", "codspeed-criterion-compat", + "compact_str", "either", "num-bigint", "pathdiff", @@ -6715,7 +6683,6 @@ dependencies = [ "seq-macro", "serde", "serde_json", - "smartstring", "stacker", "swc_atoms", "swc_common", @@ -6729,7 +6696,7 @@ dependencies = [ [[package]] name = "swc_ecma_preset_env" -version = "57.0.0" +version = "63.0.0" dependencies = [ "anyhow", "codspeed-criterion-compat", @@ -6757,7 +6724,7 @@ dependencies = [ [[package]] name = "swc_ecma_quote" -version = "41.0.0" +version = "45.0.0" dependencies = [ "swc_common", "swc_ecma_ast", @@ -6766,7 +6733,7 @@ dependencies = [ [[package]] name = "swc_ecma_quote_macros" -version = "41.0.0" +version = "45.0.0" dependencies = [ "anyhow", "proc-macro2", @@ -6782,7 +6749,7 @@ dependencies = [ [[package]] name = "swc_ecma_react_compiler" -version = "20.0.2" +version = "24.0.0" dependencies = [ "forked_react_compiler", "forked_react_compiler_ast", @@ -6802,7 +6769,7 @@ dependencies = [ [[package]] name = "swc_ecma_regexp" -version = "0.12.0" +version = "0.15.0" dependencies = [ "phf", "rustc-hash 2.1.1", @@ -6817,7 +6784,7 @@ dependencies = [ [[package]] name = "swc_ecma_regexp_ast" -version = "0.12.0" +version = "3.0.0" dependencies = [ "bitflags 2.10.0", "cbor4ii", @@ -6834,7 +6801,7 @@ version = "0.0.1" [[package]] name = "swc_ecma_regexp_visit" -version = "0.12.0" +version = "0.15.0" dependencies = [ "serde", "swc_atoms", @@ -6845,7 +6812,7 @@ dependencies = [ [[package]] name = "swc_ecma_testing" -version = "24.0.1" +version = "27.0.0" dependencies = [ "anyhow", "hex", @@ -6856,7 +6823,7 @@ dependencies = [ [[package]] name = "swc_ecma_transformer" -version = "16.0.3" +version = "21.0.0" dependencies = [ "rustc-hash 2.1.1", "swc_atoms", @@ -6873,7 +6840,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms" -version = "56.0.0" +version = "62.0.0" dependencies = [ "par-core", "swc_common", @@ -6893,7 +6860,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_base" -version = "44.0.3" +version = "49.0.0" dependencies = [ "better_scoped_tls", "codspeed-criterion-compat", @@ -6919,7 +6886,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_classes" -version = "44.0.0" +version = "49.0.0" dependencies = [ "swc_common", "swc_ecma_ast", @@ -6930,7 +6897,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_compat" -version = "52.0.1" +version = "57.0.0" dependencies = [ "indexmap 2.12.0", "par-core", @@ -6971,7 +6938,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_module" -version = "49.0.1" +version = "55.0.0" dependencies = [ "Inflector", "anyhow", @@ -7003,7 +6970,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_optimization" -version = "47.0.1" +version = "52.0.0" dependencies = [ "bytes-str", "dashmap 6.1.0", @@ -7012,6 +6979,7 @@ dependencies = [ "par-core", "petgraph", "rustc-hash 2.1.1", + "serde", "serde_json", "swc_atoms", "swc_common", @@ -7031,7 +6999,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_proposal" -version = "44.0.1" +version = "49.0.0" dependencies = [ "either", "rustc-hash 2.1.1", @@ -7053,7 +7021,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_react" -version = "50.0.0" +version = "55.0.0" dependencies = [ "base64 0.22.1", "bytes-str", @@ -7080,7 +7048,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_testing" -version = "48.0.0" +version = "53.0.0" dependencies = [ "ansi_term", "anyhow", @@ -7104,7 +7072,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_typescript" -version = "50.0.0" +version = "55.0.0" dependencies = [ "bytes-str", "codspeed-criterion-compat", @@ -7128,7 +7096,7 @@ dependencies = [ [[package]] name = "swc_ecma_utils" -version = "31.0.1" +version = "35.0.0" dependencies = [ "dragonbox_ecma", "indexmap 2.12.0", @@ -7147,7 +7115,7 @@ dependencies = [ [[package]] name = "swc_ecma_visit" -version = "25.0.0" +version = "29.0.0" dependencies = [ "new_debug_unreachable", "num-bigint", @@ -7161,7 +7129,7 @@ dependencies = [ [[package]] name = "swc_ecmascript" -version = "64.0.0" +version = "70.0.0" dependencies = [ "par-core", "swc_ecma_ast", @@ -7186,7 +7154,7 @@ dependencies = [ [[package]] name = "swc_error_reporters" -version = "25.0.0" +version = "28.0.0" dependencies = [ "anyhow", "miette", @@ -7197,7 +7165,7 @@ dependencies = [ [[package]] name = "swc_estree_ast" -version = "23.0.0" +version = "26.0.0" dependencies = [ "better_scoped_tls", "serde", @@ -7208,7 +7176,7 @@ dependencies = [ [[package]] name = "swc_estree_compat" -version = "44.0.0" +version = "48.0.0" dependencies = [ "anyhow", "codspeed-criterion-compat", @@ -7243,7 +7211,7 @@ dependencies = [ [[package]] name = "swc_html" -version = "35.0.0" +version = "38.0.0" dependencies = [ "swc_html_ast", "swc_html_codegen", @@ -7253,12 +7221,10 @@ dependencies = [ [[package]] name = "swc_html_ast" -version = "23.0.0" +version = "26.0.0" dependencies = [ - "bytecheck 0.8.1", "cbor4ii", "is-macro", - "rkyv 0.8.16", "serde", "string_enum", "swc_atoms", @@ -7267,7 +7233,7 @@ dependencies = [ [[package]] name = "swc_html_codegen" -version = "24.0.0" +version = "27.0.0" dependencies = [ "auto_impl", "bitflags 2.10.0", @@ -7292,7 +7258,7 @@ dependencies = [ [[package]] name = "swc_html_minifier" -version = "56.0.0" +version = "61.0.0" dependencies = [ "codspeed-criterion-compat", "once_cell", @@ -7323,7 +7289,7 @@ dependencies = [ [[package]] name = "swc_html_parser" -version = "23.0.0" +version = "26.0.0" dependencies = [ "codspeed-criterion-compat", "rustc-hash 2.1.1", @@ -7340,7 +7306,7 @@ dependencies = [ [[package]] name = "swc_html_utils" -version = "16.0.0" +version = "17.0.0" dependencies = [ "once_cell", "rustc-hash 2.1.1", @@ -7351,7 +7317,7 @@ dependencies = [ [[package]] name = "swc_html_visit" -version = "23.0.0" +version = "26.0.0" dependencies = [ "serde", "swc_atoms", @@ -7379,7 +7345,7 @@ dependencies = [ [[package]] name = "swc_node_bundler" -version = "70.0.0" +version = "76.0.0" dependencies = [ "anyhow", "rustc-hash 2.1.1", @@ -7403,7 +7369,7 @@ dependencies = [ [[package]] name = "swc_node_comments" -version = "24.0.0" +version = "27.0.0" dependencies = [ "dashmap 6.1.0", "rustc-hash 2.1.1", @@ -7455,13 +7421,14 @@ dependencies = [ [[package]] name = "swc_plugin_backend_wasmer" -version = "13.0.0" +version = "17.0.0" dependencies = [ "anyhow", "enumset", "parking_lot", "swc_common", "swc_plugin_runner", + "tempfile", "wasmer", "wasmer-compiler-cranelift", "wasmer-wasix", @@ -7469,7 +7436,7 @@ dependencies = [ [[package]] name = "swc_plugin_backend_wasmtime" -version = "12.0.0" +version = "16.0.0" dependencies = [ "anyhow", "swc_common", @@ -7480,7 +7447,7 @@ dependencies = [ [[package]] name = "swc_plugin_macro" -version = "1.1.1" +version = "2.0.0" dependencies = [ "proc-macro2", "quote", @@ -7489,7 +7456,7 @@ dependencies = [ [[package]] name = "swc_plugin_proxy" -version = "26.0.0" +version = "30.0.0" dependencies = [ "better_scoped_tls", "cbor4ii", @@ -7501,7 +7468,7 @@ dependencies = [ [[package]] name = "swc_plugin_runner" -version = "30.0.0" +version = "34.0.0" dependencies = [ "anyhow", "blake3", @@ -7515,7 +7482,6 @@ dependencies = [ "swc_plugin_proxy", "swc_transform_common", "tracing", - "vergen", ] [[package]] @@ -7540,7 +7506,7 @@ dependencies = [ [[package]] name = "swc_transform_common" -version = "17.0.0" +version = "20.0.0" dependencies = [ "better_scoped_tls", "rustc-hash 2.1.1", @@ -7550,7 +7516,7 @@ dependencies = [ [[package]] name = "swc_ts_fast_strip" -version = "53.0.0" +version = "58.0.0" dependencies = [ "anyhow", "bytes-str", @@ -7571,9 +7537,10 @@ dependencies = [ [[package]] name = "swc_ts_fast_strip_binding" -version = "0.18.0" +version = "0.23.0" dependencies = [ "anyhow", + "codspeed-criterion-compat", "miette", "owo-colors", "serde", @@ -7588,7 +7555,7 @@ dependencies = [ [[package]] name = "swc_typescript" -version = "30.0.1" +version = "34.0.0" dependencies = [ "bitflags 2.10.0", "petgraph", @@ -7614,7 +7581,7 @@ dependencies = [ [[package]] name = "swc_xml" -version = "23.0.0" +version = "26.0.0" dependencies = [ "swc_xml_ast", "swc_xml_codegen", @@ -7624,7 +7591,7 @@ dependencies = [ [[package]] name = "swc_xml_ast" -version = "23.0.0" +version = "26.0.0" dependencies = [ "cbor4ii", "is-macro", @@ -7636,7 +7603,7 @@ dependencies = [ [[package]] name = "swc_xml_codegen" -version = "23.0.0" +version = "26.0.0" dependencies = [ "auto_impl", "bitflags 2.10.0", @@ -7659,7 +7626,7 @@ dependencies = [ [[package]] name = "swc_xml_parser" -version = "23.0.0" +version = "26.0.0" dependencies = [ "rustc-hash 2.1.1", "serde", @@ -7673,7 +7640,7 @@ dependencies = [ [[package]] name = "swc_xml_visit" -version = "23.0.0" +version = "26.0.0" dependencies = [ "serde", "swc_atoms", @@ -7846,7 +7813,7 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "testing" -version = "24.0.1" +version = "27.0.0" dependencies = [ "cargo_metadata", "difference", @@ -7865,7 +7832,7 @@ dependencies = [ [[package]] name = "testing_macros" -version = "1.0.1" +version = "1.0.2" dependencies = [ "anyhow", "glob", @@ -7875,6 +7842,7 @@ dependencies = [ "regex", "relative-path", "syn 2.0.110", + "tempfile", ] [[package]] @@ -7966,9 +7934,7 @@ checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", - "libc", "num-conv", - "num_threads", "powerfmt", "serde_core", "time-core", @@ -8372,34 +8338,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vergen" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c32e7318e93a9ac53693b6caccfb05ff22e04a44c7cf8a279051f24c09da286f" -dependencies = [ - "anyhow", - "cargo_metadata", - "derive_builder 0.20.0", - "getset", - "regex", - "rustversion", - "time", - "vergen-lib", -] - -[[package]] -name = "vergen-lib" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e06bee42361e43b60f363bad49d63798d0f42fb1768091812270eca00c784720" -dependencies = [ - "anyhow", - "derive_builder 0.20.0", - "getset", - "rustversion", -] - [[package]] name = "version_check" version = "0.9.5" @@ -8468,7 +8406,7 @@ dependencies = [ "ipnet", "iprange", "pin-project-lite", - "rkyv 0.8.16", + "rkyv 0.8.17", "serde", "smoltcp", "thiserror 1.0.69", @@ -8781,7 +8719,7 @@ dependencies = [ "more-asserts", "object 0.32.2", "region", - "rkyv 0.8.16", + "rkyv 0.8.17", "self_cell", "shared-buffer", "smallvec", @@ -8823,7 +8761,7 @@ dependencies = [ "anyhow", "bytesize", "ciborium", - "derive_builder 0.12.0", + "derive_builder", "hex", "indexmap 2.12.0", "saffron", @@ -8864,7 +8802,7 @@ dependencies = [ "derive_more 2.0.1", "lz4_flex", "num_enum", - "rkyv 0.8.16", + "rkyv 0.8.17", "serde", "serde_json", "thiserror 1.0.69", @@ -8918,7 +8856,7 @@ dependencies = [ "hex", "indexmap 2.12.0", "more-asserts", - "rkyv 0.8.16", + "rkyv 0.8.17", "serde", "sha2", "target-lexicon 0.12.16", @@ -8990,7 +8928,7 @@ dependencies = [ "pin-project", "pin-utils", "rand 0.8.6", - "rkyv 0.8.16", + "rkyv 0.8.17", "rusty_pool", "semver", "serde", diff --git a/deps/swc/Cargo.toml b/deps/swc/Cargo.toml index 50a6d51b3..007b1bec4 100644 --- a/deps/swc/Cargo.toml +++ b/deps/swc/Cargo.toml @@ -15,12 +15,6 @@ repository = "https://github.com/swc-project/swc.git" [workspace.dependencies] -# bytecheck version should be in sync with rkyv version. Do not bump individually. -bytecheck = "0.8.0" -rancor = "0.1.0" -rkyv = "0.8.16" - - Inflector = "0.11.4" allocator-api2 = "0.2.18" ansi_term = "0.12.1" @@ -35,7 +29,7 @@ backtrace = "0.3" base64 = "0.22.1" bitflags = "2.5.0" blake3 = "1.5.4" -browserslist-rs = "0.19.0" +browserslist-rs = "0.20.0" bumpalo = "3.16.0" bytes-str = "0.2.5" cargo_metadata = "0.18.1" @@ -68,7 +62,7 @@ kstring = "2.0.0" lazy_static = "1.4.0" lexical = "6.1.0" lightningcss = "1.0.0-alpha.68" -lru = "0.16.1" +lru = "0.18.2" memchr = "2.6.1" miette = "7.6.0" napi = { version = "3", default-features = false } @@ -97,7 +91,7 @@ radix_fmt = "1.0.0" rand = "0.8.5" rayon = "1.7.0" regex = "1.5.4" -regress = "0.10.3" +regress = "0.11.1" relative-path = "1.6.1" reqwest = "0.11.14" rustc-hash = "2" @@ -114,7 +108,6 @@ sha2 = "0.10.8" shrink-to-fit = "0.2.1" siphasher = "0.3.9" smallvec = "1.8.0" -smartstring = "1.0.1" smol_str = "0.2.0" st-map = "0.2.0" string_cache = "0.8.7" @@ -131,7 +124,6 @@ triomphe = "0.1.13" unicode-id-start = "1.2.0" unicode-width = "0.2.1" url = "2.5.4" -vergen = { version = "9.0.0", default-features = false } walkdir = "2.4.0" wasi-common = { version = "38", default-features = false } wasm-bindgen = "0.2.100" diff --git a/deps/swc/bindings/binding_core_wasm/Cargo.toml b/deps/swc/bindings/binding_core_wasm/Cargo.toml index b32d18c4d..7c5edb069 100644 --- a/deps/swc/bindings/binding_core_wasm/Cargo.toml +++ b/deps/swc/bindings/binding_core_wasm/Cargo.toml @@ -6,7 +6,7 @@ license = { workspace = true } name = "binding_core_wasm" publish = false repository = { workspace = true } -version = "1.15.43" +version = "1.16.0" [lib] bench = false diff --git a/deps/swc/bindings/binding_core_wasm/src/types.rs b/deps/swc/bindings/binding_core_wasm/src/types.rs index 4548cd57e..0fa076e72 100644 --- a/deps/swc/bindings/binding_core_wasm/src/types.rs +++ b/deps/swc/bindings/binding_core_wasm/src/types.rs @@ -1407,7 +1407,7 @@ export interface Constructor extends Node, HasSpan { params: (TsParameterProperty | Param)[]; - body?: BlockStatement; + body?: FunctionBody; accessibility?: Accessibility; @@ -1720,7 +1720,7 @@ export interface ArrowFunctionExpression extends ExpressionBase { params: Pattern[]; - body: BlockStatement | Expression; + body: FunctionBody | Expression; async: boolean; @@ -1784,9 +1784,11 @@ export interface ParenthesisExpression extends ExpressionBase { } export interface Fn extends HasSpan, HasDecorator { + thisParam?: TsThisParameter; + params: Param[]; - body?: BlockStatement; + body?: FunctionBody; generator: boolean; @@ -2295,16 +2297,13 @@ export interface AssignmentProperty extends Node { export interface GetterProperty extends PropBase, HasSpan { type: "GetterProperty"; - typeAnnotation?: TsTypeAnnotation; - - body?: BlockStatement; + function: Fn; } export interface SetterProperty extends PropBase, HasSpan { type: "SetterProperty"; - param: Pattern; - body?: BlockStatement; + function: Fn; } export interface MethodProperty extends PropBase, Fn { @@ -2329,6 +2328,12 @@ export interface BlockStatement extends Node, HasSpan { stmts: Statement[]; } +export interface FunctionBody extends Node, HasSpan { + type: "FunctionBody"; + + stmts: Statement[]; +} + export interface ExpressionStatement extends Node, HasSpan { type: "ExpressionStatement"; expression: Expression; @@ -2663,6 +2668,14 @@ export interface TsThisType extends Node, HasSpan { type: "TsThisType"; } +export interface TsThisParameter extends Node, HasSpan { + type: "TsThisParameter"; + + thisSpan: Span; + + typeAnnotation?: TsTypeAnnotation; +} + export type TsFnParameter = | BindingIdentifier | ArrayPattern diff --git a/deps/swc/bindings/binding_es_ast_viewer/Cargo.toml b/deps/swc/bindings/binding_es_ast_viewer/Cargo.toml index d3463ac53..7431961f3 100644 --- a/deps/swc/bindings/binding_es_ast_viewer/Cargo.toml +++ b/deps/swc/bindings/binding_es_ast_viewer/Cargo.toml @@ -5,7 +5,7 @@ license = { workspace = true } name = "binding_es_ast_viewer" publish = false repository = { workspace = true } -version = "1.15.43" +version = "1.16.0" [dependencies] anyhow = { workspace = true } diff --git a/deps/swc/bindings/binding_html_wasm/Cargo.toml b/deps/swc/bindings/binding_html_wasm/Cargo.toml index 0a1a99798..82d3fe0a9 100644 --- a/deps/swc/bindings/binding_html_wasm/Cargo.toml +++ b/deps/swc/bindings/binding_html_wasm/Cargo.toml @@ -6,7 +6,7 @@ license = { workspace = true } name = "binding_html_wasm" publish = false repository = { workspace = true } -version = "1.15.43" +version = "1.16.0" [lib] bench = false diff --git a/deps/swc/bindings/binding_minifier_wasm/Cargo.toml b/deps/swc/bindings/binding_minifier_wasm/Cargo.toml index 724f4f104..510d544d1 100644 --- a/deps/swc/bindings/binding_minifier_wasm/Cargo.toml +++ b/deps/swc/bindings/binding_minifier_wasm/Cargo.toml @@ -6,7 +6,7 @@ license = { workspace = true } name = "binding_minifier_wasm" publish = false repository = { workspace = true } -version = "1.15.43" +version = "1.16.0" [lib] bench = false diff --git a/deps/swc/bindings/binding_minifier_wasm/src/types.rs b/deps/swc/bindings/binding_minifier_wasm/src/types.rs index 7a7e21988..577a7d116 100644 --- a/deps/swc/bindings/binding_minifier_wasm/src/types.rs +++ b/deps/swc/bindings/binding_minifier_wasm/src/types.rs @@ -1304,7 +1304,7 @@ export interface Constructor extends Node, HasSpan { params: (TsParameterProperty | Param)[]; - body?: BlockStatement; + body?: FunctionBody; accessibility?: Accessibility; @@ -1617,7 +1617,7 @@ export interface ArrowFunctionExpression extends ExpressionBase { params: Pattern[]; - body: BlockStatement | Expression; + body: FunctionBody | Expression; async: boolean; @@ -1681,9 +1681,11 @@ export interface ParenthesisExpression extends ExpressionBase { } export interface Fn extends HasSpan, HasDecorator { + thisParam?: TsThisParameter; + params: Param[]; - body?: BlockStatement; + body?: FunctionBody; generator: boolean; @@ -2192,16 +2194,13 @@ export interface AssignmentProperty extends Node { export interface GetterProperty extends PropBase, HasSpan { type: "GetterProperty"; - typeAnnotation?: TsTypeAnnotation; - - body?: BlockStatement; + function: Fn; } export interface SetterProperty extends PropBase, HasSpan { type: "SetterProperty"; - param: Pattern; - body?: BlockStatement; + function: Fn; } export interface MethodProperty extends PropBase, Fn { @@ -2226,6 +2225,12 @@ export interface BlockStatement extends Node, HasSpan { stmts: Statement[]; } +export interface FunctionBody extends Node, HasSpan { + type: "FunctionBody"; + + stmts: Statement[]; +} + export interface ExpressionStatement extends Node, HasSpan { type: "ExpressionStatement"; expression: Expression; @@ -2569,6 +2574,14 @@ export interface TsThisType extends Node, HasSpan { type: "TsThisType"; } +export interface TsThisParameter extends Node, HasSpan { + type: "TsThisParameter"; + + thisSpan: Span; + + typeAnnotation?: TsTypeAnnotation; +} + export type TsFnParameter = | BindingIdentifier | ArrayPattern diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/.cargo/config.toml b/deps/swc/bindings/binding_nodejs_support_wasm/.cargo/config.toml new file mode 100644 index 000000000..dee02885d --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/.cargo/config.toml @@ -0,0 +1,3 @@ +[target.wasm32-unknown-unknown] +# support more stack size due to issue: https://github.com/swc-project/swc/issues/10207 +rustflags = ["-C", "link-args=-z stack-size=2097152"] diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/Cargo.toml b/deps/swc/bindings/binding_nodejs_support_wasm/Cargo.toml new file mode 100644 index 000000000..89c7c307d --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/Cargo.toml @@ -0,0 +1,40 @@ +[package] +authors = ["강동윤 "] +description = "Node.js support helpers compiled to WebAssembly" +edition = { workspace = true } +license = { workspace = true } +name = "binding_nodejs_support_wasm" +publish = false +repository = { workspace = true } +version = "1.16.0" + +[lib] +bench = false +crate-type = ["cdylib"] + +[features] +nightly = ["swc_ts_fast_strip/nightly"] + +[dependencies] +anyhow = { workspace = true } +js-sys = { workspace = true } +miette = { workspace = true } +owo-colors = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde-wasm-bindgen = { workspace = true } +serde_json = { workspace = true } +swc_common = { path = "../../crates/swc_common" } +swc_ecma_ast = { path = "../../crates/swc_ecma_ast" } +swc_ecma_parser = { path = "../../crates/swc_ecma_parser" } +swc_ecma_visit = { path = "../../crates/swc_ecma_visit" } +swc_error_reporters = { path = "../../crates/swc_error_reporters" } +swc_ts_fast_strip = { path = "../../crates/swc_ts_fast_strip", features = [ + "wasm-bindgen", +] } +tracing = { workspace = true, features = ["max_level_off"] } +unicode-width = { workspace = true } +wasm-bindgen = { workspace = true, features = ["enable-interning"] } +wasm-bindgen-futures = { workspace = true } + +[package.metadata.wasm-pack.profile.release] +wasm-opt = false diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/LICENSE b/deps/swc/bindings/binding_nodejs_support_wasm/LICENSE new file mode 100644 index 000000000..8f3eaa819 --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2024 SWC contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/README.md b/deps/swc/bindings/binding_nodejs_support_wasm/README.md new file mode 100644 index 000000000..abd29b9bb --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/README.md @@ -0,0 +1,26 @@ +# @swc/nodejs-support-wasm + +This package provides a standalone WebAssembly binding for Node.js +integrations. Its Rust crate, source, build, and test setup are independent from +`@swc/wasm-typescript`. + +It includes the TypeScript transform API from `@swc/wasm-typescript` and +additional helpers for module syntax transformation, assertion locations, and +syntax validation. + +## API + +- `transform` and `transformSync` +- `transformModuleSyntax` +- `getFirstExpression` +- `isValidSyntax` +- `isRecoverableError` + +## Contributing + +See [the main repository](https://github.com/swc-project/swc)'s contributing +guide. + +## License + +Apache 2.0 diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/package.json b/deps/swc/bindings/binding_nodejs_support_wasm/package.json new file mode 100644 index 000000000..728a4a614 --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "@rstest/core": "^0.7.8" + } +} diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/rstest.config.mjs b/deps/swc/bindings/binding_nodejs_support_wasm/rstest.config.mjs new file mode 100644 index 000000000..0e541bbdd --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/rstest.config.mjs @@ -0,0 +1,4 @@ +export default { + include: ["__tests__/**/*.{js,jsx,ts,tsx}"], + globals: true, +}; diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/scripts/build.sh b/deps/swc/bindings/binding_nodejs_support_wasm/scripts/build.sh new file mode 100755 index 000000000..c5aaa25ce --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/scripts/build.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -eux + +export CARGO_PROFILE_RELEASE_LTO="fat" +export CARGO_PROFILE_RELEASE_OPT_LEVEL="z" + +wasm-pack build \ + --out-name wasm \ + --release \ + --scope=swc \ + --target nodejs \ + "$@" +ls -al ./pkg + +node ./scripts/patch.mjs +cp ./README.md ./pkg/README.md diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/scripts/patch.mjs b/deps/swc/bindings/binding_nodejs_support_wasm/scripts/patch.mjs new file mode 100644 index 000000000..e9f96cdef --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/scripts/patch.mjs @@ -0,0 +1,31 @@ +import fs from "node:fs/promises"; + +const rawWasmPath = "pkg/wasm_bg.wasm"; +const wasmJsPath = "pkg/wasm.js"; +const packageJsonPath = "pkg/package.json"; +const rawWasmFile = await fs.readFile(rawWasmPath); +const origJsFile = await fs.readFile(wasmJsPath, "utf8"); + +const base64 = rawWasmFile.toString("base64"); +const patchedJsFile = origJsFile + .replace( + `const path = require('path').join(__dirname, 'wasm_bg.wasm');`, + "" + ) + .replace(", fatal: true", "") + .replace( + `const bytes = require('fs').readFileSync(path);`, + ` +const { Buffer } = require('node:buffer'); +const bytes = Buffer.from('${base64}', 'base64');` + ); + +await fs.writeFile(wasmJsPath, patchedJsFile); +await fs.unlink(rawWasmPath); + +const pkgJsonFile = await fs.readFile(packageJsonPath, "utf8"); +const pkgJson = JSON.parse(pkgJsonFile); +pkgJson.name = "@swc/nodejs-support-wasm"; +pkgJson.description = "SWC WebAssembly helpers for Node.js"; +pkgJson.files = pkgJson.files.filter((file) => file !== "wasm_bg.wasm"); +await fs.writeFile(packageJsonPath, JSON.stringify(pkgJson, null, 2)); diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/scripts/test.sh b/deps/swc/bindings/binding_nodejs_support_wasm/scripts/test.sh new file mode 100755 index 000000000..4c3174b05 --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/scripts/test.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -eu + +./scripts/build.sh +npx rstest "$@" + +./scripts/build.sh --features nightly +npx rstest "$@" diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/src/error_reporter.rs b/deps/swc/bindings/binding_nodejs_support_wasm/src/error_reporter.rs new file mode 100644 index 000000000..684ba3073 --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/src/error_reporter.rs @@ -0,0 +1,881 @@ +use std::fmt::{self}; + +use miette::{ + Diagnostic, GraphicalTheme, LabeledSpan, ReportHandler, SourceCode, SourceSpan, ThemeCharacters, +}; +use owo_colors::{OwoColorize, Style}; +use unicode_width::UnicodeWidthChar; + +/** +A [`ReportHandler`] that displays a given [`Report`](crate::Report) in a +quasi-graphical way, using terminal colors, unicode drawing characters, and +other such things. + +This is the default reporter bundled with `miette`. + +This printer can be customized by using [`new_themed()`](GraphicalReportHandler::new_themed) and handing it a +[`GraphicalTheme`] of your own creation (or using one of its own defaults!) + +See [`set_hook()`](crate::set_hook) for more details on customizing your global +printer. +*/ +#[derive(Debug, Clone)] +pub struct SwcReportHandler { + pub(crate) theme: GraphicalTheme, + pub(crate) context_lines: usize, + pub(crate) tab_width: usize, +} + +impl SwcReportHandler { + /// Create a new `GraphicalReportHandler` with the default + /// [`GraphicalTheme`]. This will use both unicode characters and colors. + pub fn new() -> Self { + Self { + theme: GraphicalTheme::default(), + context_lines: 1, + tab_width: 4, + } + } + + /// Set a theme for this handler. + pub fn with_theme(mut self, theme: GraphicalTheme) -> Self { + self.theme = theme; + self + } +} + +impl Default for SwcReportHandler { + fn default() -> Self { + Self::new() + } +} + +impl SwcReportHandler { + /// Render a [`Diagnostic`]. This function is mostly internal and meant to + /// be called by the toplevel [`ReportHandler`] handler, but is made public + /// to make it easier (possible) to test in isolation from global state. + pub fn render_report( + &self, + f: &mut impl fmt::Write, + diagnostic: &dyn Diagnostic, + ) -> fmt::Result { + self.render_report_inner(f, diagnostic, diagnostic.source_code()) + } + + fn render_report_inner( + &self, + f: &mut impl fmt::Write, + diagnostic: &dyn Diagnostic, + parent_src: Option<&dyn SourceCode>, + ) -> fmt::Result { + let src = diagnostic.source_code().or(parent_src); + self.render_snippets(f, diagnostic, src)?; + + Ok(()) + } + + fn render_snippets( + &self, + f: &mut impl fmt::Write, + diagnostic: &dyn Diagnostic, + opt_source: Option<&dyn SourceCode>, + ) -> fmt::Result { + let source = match opt_source { + Some(source) => source, + None => return Ok(()), + }; + let labels = match diagnostic.labels() { + Some(labels) => labels, + None => return Ok(()), + }; + + let mut labels = labels.collect::>(); + labels.sort_unstable_by_key(|l| l.inner().offset()); + + let mut contexts = Vec::with_capacity(labels.len()); + for right in labels.iter().cloned() { + let right_conts = + match source.read_span(right.inner(), self.context_lines, self.context_lines) { + Ok(cont) => cont, + Err(err) => { + writeln!( + f, + " [{} `{}` (offset: {}, length: {}): {:?}]", + "Failed to read contents for label".style(self.theme.styles.error), + right + .label() + .unwrap_or("") + .style(self.theme.styles.link), + right.offset().style(self.theme.styles.link), + right.len().style(self.theme.styles.link), + err.style(self.theme.styles.warning) + )?; + return Ok(()); + } + }; + + if contexts.is_empty() { + contexts.push((right, right_conts)); + continue; + } + + let (left, left_conts) = contexts.last().unwrap(); + if left_conts.line() + left_conts.line_count() >= right_conts.line() { + // The snippets will overlap, so we create one Big Chunky Boi + let left_end = left.offset() + left.len(); + let right_end = right.offset() + right.len(); + let new_end = std::cmp::max(left_end, right_end); + + let new_span = LabeledSpan::new( + left.label().map(String::from), + left.offset(), + new_end - left.offset(), + ); + // Check that the two contexts can be combined + if let Ok(new_conts) = + source.read_span(new_span.inner(), self.context_lines, self.context_lines) + { + contexts.pop(); + // We'll throw the contents away later + contexts.push((new_span, new_conts)); + continue; + } + } + + contexts.push((right, right_conts)); + } + for (ctx, _) in contexts { + self.render_context(f, source, &ctx, &labels[..])?; + } + + Ok(()) + } + + fn render_context( + &self, + f: &mut impl fmt::Write, + source: &dyn SourceCode, + context: &LabeledSpan, + labels: &[LabeledSpan], + ) -> fmt::Result { + let lines = self.get_lines(source, context.inner())?; + + // sorting is your friend + let labels = labels + .iter() + .zip(self.theme.styles.highlights.iter().cloned().cycle()) + .map(|(label, st)| FancySpan::new(label.label().map(String::from), *label.inner(), st)) + .collect::>(); + + // The max number of gutter-lines that will be active at any given + // point. We need this to figure out indentation, so we do one loop + // over the lines to see what the damage is gonna be. + let mut max_gutter = 0usize; + for line in &lines { + let mut num_highlights = 0; + for hl in &labels { + if !line.span_line_only(hl) && line.span_applies_gutter(hl) { + num_highlights += 1; + } + } + max_gutter = std::cmp::max(max_gutter, num_highlights); + } + + // Now it's time for the fun part--actually rendering everything! + for line in &lines { + // Then, we need to print the gutter, along with any fly-bys We + // have separate gutters depending on whether we're on the actual + // line, or on one of the "highlight lines" below it. + self.render_line_gutter(f, max_gutter, line, &labels)?; + + // And _now_ we can print out the line text itself! + self.render_line_text(f, &line.text)?; + + // Next, we write all the highlights that apply to this particular line. + let (single_line, multi_line): (Vec<_>, Vec<_>) = labels + .iter() + .filter(|hl| line.span_applies(hl)) + .partition(|hl| line.span_line_only(hl)); + if !single_line.is_empty() { + // gutter _again_ + self.render_highlight_gutter( + f, + max_gutter, + line, + &labels, + LabelRenderMode::SingleLine, + )?; + self.render_single_line_highlights(f, line, max_gutter, &single_line, &labels)?; + } + for hl in multi_line { + if hl.label().is_some() && line.span_ends(hl) && !line.span_starts(hl) { + self.render_multi_line_end(f, &labels, max_gutter, line, hl)?; + } + } + } + + Ok(()) + } + + fn render_multi_line_end( + &self, + f: &mut impl fmt::Write, + labels: &[FancySpan], + max_gutter: usize, + line: &Line, + label: &FancySpan, + ) -> fmt::Result { + if let Some(label_parts) = label.label_parts() { + // if it has a label, how long is it? + let (first, rest) = label_parts.split_first().expect( + "cannot crash because rest would have been None, see docs on the `label` field of \ + FancySpan", + ); + + if rest.is_empty() { + // gutter _again_ + self.render_highlight_gutter( + f, + max_gutter, + line, + labels, + LabelRenderMode::SingleLine, + )?; + + self.render_multi_line_end_single( + f, + first, + label.style, + LabelRenderMode::SingleLine, + )?; + } else { + // gutter _again_ + self.render_highlight_gutter( + f, + max_gutter, + line, + labels, + LabelRenderMode::MultiLineFirst, + )?; + + self.render_multi_line_end_single( + f, + first, + label.style, + LabelRenderMode::MultiLineFirst, + )?; + for label_line in rest { + // gutter _again_ + self.render_highlight_gutter( + f, + max_gutter, + line, + labels, + LabelRenderMode::MultiLineRest, + )?; + self.render_multi_line_end_single( + f, + label_line, + label.style, + LabelRenderMode::MultiLineRest, + )?; + } + } + } else { + // gutter _again_ + self.render_highlight_gutter(f, max_gutter, line, labels, LabelRenderMode::SingleLine)?; + // has no label + writeln!(f, "{}", self.theme.characters.hbar.style(label.style))?; + } + + Ok(()) + } + + fn render_line_gutter( + &self, + f: &mut impl fmt::Write, + max_gutter: usize, + line: &Line, + highlights: &[FancySpan], + ) -> fmt::Result { + if max_gutter == 0 { + return Ok(()); + } + let chars = &self.theme.characters; + let mut gutter = String::new(); + let applicable = highlights.iter().filter(|hl| line.span_applies_gutter(hl)); + let mut arrow = false; + for (i, hl) in applicable.enumerate() { + if line.span_starts(hl) { + gutter.push_str(&chars.ltop.style(hl.style).to_string()); + gutter.push_str( + &chars + .hbar + .to_string() + .repeat(max_gutter.saturating_sub(i)) + .style(hl.style) + .to_string(), + ); + gutter.push_str(&chars.rarrow.style(hl.style).to_string()); + arrow = true; + break; + } else if line.span_ends(hl) { + if hl.label().is_some() { + gutter.push_str(&chars.lcross.style(hl.style).to_string()); + } else { + gutter.push_str(&chars.lbot.style(hl.style).to_string()); + } + gutter.push_str( + &chars + .hbar + .to_string() + .repeat(max_gutter.saturating_sub(i)) + .style(hl.style) + .to_string(), + ); + gutter.push_str(&chars.rarrow.style(hl.style).to_string()); + arrow = true; + break; + } else if line.span_flyby(hl) { + gutter.push_str(&chars.vbar.style(hl.style).to_string()); + } else { + gutter.push(' '); + } + } + write!( + f, + "{}{}", + gutter, + " ".repeat( + if arrow { 1 } else { 3 } + max_gutter.saturating_sub(gutter.chars().count()) + ) + )?; + Ok(()) + } + + fn render_highlight_gutter( + &self, + f: &mut impl fmt::Write, + max_gutter: usize, + line: &Line, + highlights: &[FancySpan], + render_mode: LabelRenderMode, + ) -> fmt::Result { + if max_gutter == 0 { + return Ok(()); + } + + // keeps track of how many columns wide the gutter is + // important for ansi since simply measuring the size of the final string + // gives the wrong result when the string contains ansi codes. + let mut gutter_cols = 0; + + let chars = &self.theme.characters; + let mut gutter = String::new(); + let applicable = highlights.iter().filter(|hl| line.span_applies_gutter(hl)); + for (i, hl) in applicable.enumerate() { + if !line.span_line_only(hl) && line.span_ends(hl) { + if render_mode == LabelRenderMode::MultiLineRest { + // this is to make multiline labels work. We want to make the right amount + // of horizontal space for them, but not actually draw the lines + let horizontal_space = max_gutter.saturating_sub(i) + 2; + for _ in 0..horizontal_space { + gutter.push(' '); + } + // account for one more horizontal space, since in multiline mode + // we also add in the vertical line before the label like this: + // 2 │ ╭─▶ text + // 3 │ ├─▶ here + // · ╰──┤ these two lines + // · │ are the problem + // ^this + gutter_cols += horizontal_space + 1; + } else { + let num_repeat = max_gutter.saturating_sub(i) + 2; + + gutter.push_str(&chars.lbot.style(hl.style).to_string()); + + gutter.push_str( + &chars + .hbar + .to_string() + .repeat( + num_repeat + // if we are rendering a multiline label, then leave a bit of space for the + // rcross character + - if render_mode == LabelRenderMode::MultiLineFirst { + 1 + } else { + 0 + }, + ) + .style(hl.style) + .to_string(), + ); + + // we count 1 for the lbot char, and then a few more, the same number + // as we just repeated for. For each repeat we only add 1, even though + // due to ansi escape codes the number of bytes in the string could grow + // a lot each time. + gutter_cols += num_repeat + 1; + } + break; + } else { + gutter.push_str(&chars.vbar.style(hl.style).to_string()); + + // we may push many bytes for the ansi escape codes style adds, + // but we still only add a single character-width to the string in a terminal + gutter_cols += 1; + } + } + + // now calculate how many spaces to add based on how many columns we just + // created. it's the max width of the gutter, minus how many + // character-widths we just generated capped at 0 (though this should + // never go below in reality), and then we add 3 to account for + // arrowheads when a gutter line ends + let num_spaces = (max_gutter + 3).saturating_sub(gutter_cols); + // we then write the gutter and as many spaces as we need + write!(f, "{}{:width$}", gutter, "", width = num_spaces)?; + Ok(()) + } + + /// Returns an iterator over the visual width of each character in a line. + fn line_visual_char_width<'a>(&self, text: &'a str) -> impl Iterator + 'a { + let mut column = 0; + let mut escaped = false; + let tab_width = self.tab_width; + text.chars().map(move |c| { + let width = match (escaped, c) { + // Round up to the next multiple of tab_width + (false, '\t') => tab_width - column % tab_width, + // start of ANSI escape + (false, '\x1b') => { + escaped = true; + 0 + } + // use Unicode width for all other characters + (false, c) => c.width().unwrap_or(0), + // end of ANSI escape + (true, 'm') => { + escaped = false; + 0 + } + // characters are zero width within escape sequence + (true, _) => 0, + }; + column += width; + width + }) + } + + /// Returns the visual column position of a byte offset on a specific line. + /// + /// If the offset occurs in the middle of a character, the returned column + /// corresponds to that character's first column in `start` is true, or its + /// last column if `start` is false. + fn visual_offset(&self, line: &Line, offset: usize, start: bool) -> usize { + let line_range = line.offset..=(line.offset + line.length); + assert!(line_range.contains(&offset)); + + let mut text_index = offset - line.offset; + while text_index <= line.text.len() && !line.text.is_char_boundary(text_index) { + if start { + text_index -= 1; + } else { + text_index += 1; + } + } + let text = &line.text[..text_index.min(line.text.len())]; + let text_width = self.line_visual_char_width(text).sum(); + if text_index > line.text.len() { + // Spans extending past the end of the line are always rendered as + // one column past the end of the visible line. + // + // This doesn't necessarily correspond to a specific byte-offset, + // since a span extending past the end of the line could contain: + // - an actual \n character (1 byte) + // - a CRLF (2 bytes) + // - EOF (0 bytes) + text_width + 1 + } else { + text_width + } + } + + /// Renders a line to the output formatter, replacing tabs with spaces. + fn render_line_text(&self, f: &mut impl fmt::Write, text: &str) -> fmt::Result { + for (c, width) in text.chars().zip(self.line_visual_char_width(text)) { + if c == '\t' { + for _ in 0..width { + f.write_char(' ')?; + } + } else { + f.write_char(c)?; + } + } + f.write_char('\n')?; + Ok(()) + } + + fn render_single_line_highlights( + &self, + f: &mut impl fmt::Write, + line: &Line, + max_gutter: usize, + single_liners: &[&FancySpan], + all_highlights: &[FancySpan], + ) -> fmt::Result { + let mut underlines = String::new(); + let mut highest = 0; + + let chars = &self.theme.characters; + let vbar_offsets: Vec<_> = single_liners + .iter() + .map(|hl| { + let byte_start = hl.offset(); + let byte_end = hl.offset() + hl.len(); + let start = self.visual_offset(line, byte_start, true).max(highest); + let end = if hl.len() == 0 { + start + 1 + } else { + self.visual_offset(line, byte_end, false).max(start + 1) + }; + + let vbar_offset = (start + end) / 2; + let num_left = vbar_offset - start; + let num_right = end - vbar_offset - 1; + underlines.push_str( + &format!( + "{:width$}{}{}{}", + "", + chars.underline.to_string().repeat(num_left), + if hl.len() == 0 { + chars.uarrow + } else if hl.label().is_some() { + chars.underbar + } else { + chars.underline + }, + chars.underline.to_string().repeat(num_right), + width = start.saturating_sub(highest), + ) + .style(hl.style) + .to_string(), + ); + highest = std::cmp::max(highest, end); + + (hl, vbar_offset) + }) + .collect(); + writeln!(f, "{underlines}")?; + + for hl in single_liners.iter().rev() { + if let Some(label) = hl.label_parts() { + if label.len() == 1 { + self.write_label_text( + f, + line, + max_gutter, + all_highlights, + chars, + &vbar_offsets, + hl, + &label[0], + LabelRenderMode::SingleLine, + )?; + } else { + let mut first = true; + for label_line in &label { + self.write_label_text( + f, + line, + max_gutter, + all_highlights, + chars, + &vbar_offsets, + hl, + label_line, + if first { + LabelRenderMode::MultiLineFirst + } else { + LabelRenderMode::MultiLineRest + }, + )?; + first = false; + } + } + } + } + Ok(()) + } + + // I know it's not good practice, but making this a function makes a lot of + // sense and making a struct for this does not... + #[allow(clippy::too_many_arguments)] + fn write_label_text( + &self, + f: &mut impl fmt::Write, + line: &Line, + max_gutter: usize, + all_highlights: &[FancySpan], + chars: &ThemeCharacters, + vbar_offsets: &[(&&FancySpan, usize)], + hl: &&FancySpan, + label: &str, + render_mode: LabelRenderMode, + ) -> fmt::Result { + self.render_highlight_gutter( + f, + max_gutter, + line, + all_highlights, + LabelRenderMode::SingleLine, + )?; + let mut curr_offset = 1usize; + for (offset_hl, vbar_offset) in vbar_offsets { + while curr_offset < *vbar_offset + 1 { + write!(f, " ")?; + curr_offset += 1; + } + if *offset_hl != hl { + write!(f, "{}", chars.vbar.to_string().style(offset_hl.style))?; + curr_offset += 1; + } else { + let lines = match render_mode { + LabelRenderMode::SingleLine => format!( + "{}{} {}", + chars.lbot, + chars.hbar.to_string().repeat(2), + label, + ), + LabelRenderMode::MultiLineFirst => { + format!("{}{}{} {}", chars.lbot, chars.hbar, chars.rcross, label,) + } + LabelRenderMode::MultiLineRest => { + format!(" {} {}", chars.vbar, label,) + } + }; + writeln!(f, "{}", lines.style(hl.style))?; + break; + } + } + Ok(()) + } + + fn render_multi_line_end_single( + &self, + f: &mut impl fmt::Write, + label: &str, + style: Style, + render_mode: LabelRenderMode, + ) -> fmt::Result { + match render_mode { + LabelRenderMode::SingleLine => { + writeln!(f, "{} {}", self.theme.characters.hbar.style(style), label)?; + } + LabelRenderMode::MultiLineFirst => { + writeln!(f, "{} {}", self.theme.characters.rcross.style(style), label)?; + } + LabelRenderMode::MultiLineRest => { + writeln!(f, "{} {}", self.theme.characters.vbar.style(style), label)?; + } + } + + Ok(()) + } + + fn get_lines<'a>( + &'a self, + source: &'a dyn SourceCode, + context_span: &'a SourceSpan, + ) -> Result, fmt::Error> { + let context_data = source + .read_span(context_span, self.context_lines, self.context_lines) + .map_err(|_| fmt::Error)?; + let context = String::from_utf8_lossy(context_data.data()); + let mut column = context_data.column(); + let mut offset = context_data.span().offset(); + let mut line_offset = offset; + let mut line_str = String::with_capacity(context.len()); + let mut lines = Vec::with_capacity(1); + let mut iter = context.chars().peekable(); + while let Some(ch) = iter.next() { + offset += ch.len_utf8(); + match ch { + '\r' if iter.next_if_eq(&'\n').is_some() => { + offset += 1; + column = 0; + } + '\r' => { + line_str.push(ch); + column += 1; + } + '\n' => { + column = 0; + } + _ => { + line_str.push(ch); + column += 1; + } + } + + if column == 0 || iter.peek().is_none() { + lines.push(Line { + offset: line_offset, + length: offset - line_offset, + text: line_str.clone(), + }); + line_str.clear(); + line_offset = offset; + } + } + Ok(lines) + } +} + +impl ReportHandler for SwcReportHandler { + fn debug(&self, diagnostic: &dyn Diagnostic, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.alternate() { + return fmt::Debug::fmt(diagnostic, f); + } + + self.render_report(f, diagnostic) + } +} + +/* +Support types +*/ + +#[derive(PartialEq, Debug)] +enum LabelRenderMode { + /// we're rendering a single line label (or not rendering in any special + /// way) + SingleLine, + /// we're rendering a multiline label + MultiLineFirst, + /// we're rendering the rest of a multiline label + MultiLineRest, +} + +#[derive(Debug)] +struct Line { + offset: usize, + length: usize, + text: String, +} + +impl Line { + fn span_line_only(&self, span: &FancySpan) -> bool { + span.offset() >= self.offset && span.offset() + span.len() <= self.offset + self.length + } + + /// Returns whether `span` should be visible on this line, either in the + /// gutter or under the text on this line + fn span_applies(&self, span: &FancySpan) -> bool { + let spanlen = if span.len() == 0 { 1 } else { span.len() }; + // Span starts in this line + + (span.offset() >= self.offset && span.offset() < self.offset + self.length) + // Span passes through this line + || (span.offset() < self.offset && span.offset() + spanlen > self.offset + self.length) //todo + // Span ends on this line + || (span.offset() + spanlen > self.offset && span.offset() + spanlen <= self.offset + self.length) + } + + /// Returns whether `span` should be visible on this line in the gutter (so + /// this excludes spans that are only visible on this line and do not + /// span multiple lines) + fn span_applies_gutter(&self, span: &FancySpan) -> bool { + let spanlen = if span.len() == 0 { 1 } else { span.len() }; + // Span starts in this line + self.span_applies(span) + && !( + // as long as it doesn't start *and* end on this line + (span.offset() >= self.offset && span.offset() < self.offset + self.length) + && (span.offset() + spanlen > self.offset + && span.offset() + spanlen <= self.offset + self.length) + ) + } + + // A 'flyby' is a multi-line span that technically covers this line, but + // does not begin or end within the line itself. This method is used to + // calculate gutters. + fn span_flyby(&self, span: &FancySpan) -> bool { + // The span itself starts before this line's starting offset (so, in a + // prev line). + span.offset() < self.offset + // ...and it stops after this line's end. + && span.offset() + span.len() > self.offset + self.length + } + + // Does this line contain the *beginning* of this multiline span? + // This assumes self.span_applies() is true already. + fn span_starts(&self, span: &FancySpan) -> bool { + span.offset() >= self.offset + } + + // Does this line contain the *end* of this multiline span? + // This assumes self.span_applies() is true already. + fn span_ends(&self, span: &FancySpan) -> bool { + span.offset() + span.len() >= self.offset + && span.offset() + span.len() <= self.offset + self.length + } +} + +#[derive(Debug, Clone)] +struct FancySpan { + /// this is deliberately an option of a vec because I wanted to be very + /// explicit that there can also be *no* label. If there is a label, it + /// can have multiple lines which is what the vec is for. + label: Option>, + span: SourceSpan, + style: Style, +} + +impl PartialEq for FancySpan { + fn eq(&self, other: &Self) -> bool { + self.label == other.label && self.span == other.span + } +} + +fn split_label(v: String) -> Vec { + v.split('\n').map(|i| i.to_string()).collect() +} + +impl FancySpan { + fn new(label: Option, span: SourceSpan, style: Style) -> Self { + FancySpan { + label: label.map(split_label), + span, + style, + } + } + + fn style(&self) -> Style { + self.style + } + + fn label(&self) -> Option { + self.label + .as_ref() + .map(|l| l.join("\n").style(self.style()).to_string()) + } + + fn label_parts(&self) -> Option> { + self.label.as_ref().map(|l| { + l.iter() + .map(|i| i.style(self.style()).to_string()) + .collect() + }) + } + + fn offset(&self) -> usize { + self.span.offset() + } + + fn len(&self) -> usize { + self.span.len() + } +} diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/src/lib.rs b/deps/swc/bindings/binding_nodejs_support_wasm/src/lib.rs new file mode 100644 index 000000000..e971058ac --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/src/lib.rs @@ -0,0 +1,308 @@ +use std::{ + iter::once, + mem::take, + sync::{Arc, Mutex}, +}; + +use anyhow::Error; +use error_reporter::SwcReportHandler; +use js_sys::Uint8Array; +use miette::{GraphicalTheme, LabeledSpan, ThemeCharacters, ThemeStyles}; +use serde::Serialize; +use swc_common::{ + errors::{DiagnosticBuilder, DiagnosticId, Emitter, Handler, HANDLER}, + sync::Lrc, + SourceMap, Span, GLOBALS, +}; +use swc_error_reporters::{convert_span, to_pretty_source_code}; +use swc_ts_fast_strip::{Options, TransformOutput}; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::{future_to_promise, js_sys::Promise}; + +mod error_reporter; +mod nodejs; + +/// Custom interface definitions for `@swc/nodejs-support-wasm`. +#[wasm_bindgen(typescript_custom_section)] +const INTERFACE_DEFINITIONS: &'static str = r#" +export declare function transform(src: string | Uint8Array, opts?: Options): Promise; +export declare function transformSync(src: string | Uint8Array, opts?: Options): TransformOutput; +export declare function transformModuleSyntax(src: string | Uint8Array): ModuleSyntaxTransformOutput; +export declare function getFirstExpression(src: string | Uint8Array, startColumn: number): string; +export declare function isValidSyntax(src: string | Uint8Array): boolean; +export declare function isRecoverableError(src: string | Uint8Array): boolean; +export type { Options, TransformOutput }; + +export interface ModuleSyntaxTransformOutput { + code: string; + hadModuleSyntax: boolean; +} +"#; + +#[wasm_bindgen(skip_typescript)] +pub fn transform(input: JsValue, options: JsValue) -> Promise { + future_to_promise(async move { transform_sync(input, options) }) +} + +#[wasm_bindgen(js_name = "transformSync", skip_typescript)] +pub fn transform_sync(input: JsValue, options: JsValue) -> Result { + let options: Options = if options.is_falsy() { + Default::default() + } else { + serde_wasm_bindgen::from_value(options)? + }; + + let input = coerce_input(input)?; + + let result = GLOBALS.set(&Default::default(), || operate(input, options)); + + match result { + Ok(v) => Ok(serde_wasm_bindgen::to_value(&v)?), + Err(errors) => Err(serde_wasm_bindgen::to_value(&errors[0])?), + } +} + +#[wasm_bindgen(js_name = "transformModuleSyntax", skip_typescript)] +pub fn transform_module_syntax(input: JsValue) -> Result { + let input = coerce_input(input)?; + let output = nodejs::transform_module_syntax(input); + + Ok(serde_wasm_bindgen::to_value(&output)?) +} + +#[wasm_bindgen(js_name = "getFirstExpression", skip_typescript)] +pub fn get_first_expression(input: JsValue, start_column: u32) -> Result { + let input = coerce_input(input)?; + + Ok(nodejs::get_first_expression(input, start_column)) +} + +#[wasm_bindgen(js_name = "isValidSyntax", skip_typescript)] +pub fn is_valid_syntax(input: JsValue) -> Result { + let input = coerce_input(input)?; + + Ok(nodejs::is_valid_syntax(input)) +} + +#[wasm_bindgen(js_name = "isRecoverableError", skip_typescript)] +pub fn is_recoverable_error(input: JsValue) -> Result { + let input = coerce_input(input)?; + + Ok(nodejs::is_recoverable_error(input)) +} + +fn coerce_input(input: JsValue) -> Result { + match input.as_string() { + Some(input) => Ok(input), + None => { + if input.is_instance_of::() { + let input = input.unchecked_into::(); + + String::from_utf8(input.to_vec()) + .map_err(|_| JsValue::from_str("Input Uint8Array is not valid utf-8")) + } else { + Err(JsValue::from_str("Input is not a string or Uint8Array")) + } + } + } +} + +fn operate(input: String, options: Options) -> Result> { + let cm = Lrc::new(SourceMap::default()); + + try_with_json_handler(cm.clone(), |handler| { + swc_ts_fast_strip::operate(&cm, handler, input, options).map_err(anyhow::Error::new) + }) +} + +#[derive(Clone)] +struct JsonErrorWriter { + errors: Arc>>, + /// Successful transforms never need the graphical diagnostic reporter. + reporter: Option, + cm: Lrc, +} + +fn try_with_json_handler(cm: Lrc, op: F) -> Result> +where + F: FnOnce(&Handler) -> Result, +{ + let wr = JsonErrorWriter { + errors: Default::default(), + reporter: None, + cm, + }; + let emitter: Box = Box::new(wr.clone()); + + let handler = Handler::with_emitter(true, false, emitter); + + let ret = HANDLER.set(&handler, || op(&handler)); + + if handler.has_errors() { + let mut lock = wr.errors.lock().unwrap(); + let error = take(&mut *lock); + + Err(error) + } else { + Ok(ret.expect("it should not fail without emitting errors to handler")) + } +} + +impl Emitter for JsonErrorWriter { + fn emit(&mut self, db: &mut DiagnosticBuilder) { + let d = &**db; + + let snippet = d.span.primary_span().and_then(|span| { + let mut snippet = String::new(); + let reporter = self.reporter.get_or_insert_with(json_reporter); + match reporter.render_report( + &mut snippet, + &Snippet { + source_code: &to_pretty_source_code(&self.cm, true), + span, + }, + ) { + Ok(()) => Some(snippet), + Err(_) => None, + } + }); + + let children = d + .children + .iter() + .map(|d| todo!("json subdiagnostic: {d:?}")) + .collect::>(); + + let error_code = match &d.code { + Some(DiagnosticId::Error(s)) => Some(&**s), + Some(DiagnosticId::Lint(s)) => Some(&**s), + None => None, + }; + + let start = d + .span + .primary_span() + .and_then(|span| self.cm.try_lookup_char_pos(span.lo()).ok()); + + let end = d + .span + .primary_span() + .and_then(|span| self.cm.try_lookup_char_pos(span.hi()).ok()); + + let filename = start.as_ref().map(|loc| loc.file.name.to_string()); + + let error = JsonDiagnostic { + code: error_code.map(|s| s.to_string()), + message: d.message[0].0.to_string(), + snippet, + filename, + start_line: start.as_ref().map(|loc| loc.line), + start_column: start.as_ref().map(|loc| loc.col_display), + end_line: end.as_ref().map(|loc| loc.line), + end_column: end.as_ref().map(|loc| loc.col_display), + children, + }; + + self.errors.lock().unwrap().push(error); + } + + fn take_diagnostics(&mut self) -> Vec { + Default::default() + } +} + +fn json_reporter() -> SwcReportHandler { + SwcReportHandler::default().with_theme(GraphicalTheme { + characters: ThemeCharacters { + hbar: ' ', + vbar: ' ', + xbar: ' ', + vbar_break: ' ', + ltop: ' ', + rtop: ' ', + mtop: ' ', + lbot: ' ', + rbot: ' ', + mbot: ' ', + error: "".into(), + warning: "".into(), + advice: "".into(), + ..ThemeCharacters::ascii() + }, + styles: ThemeStyles::none(), + }) +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonDiagnostic { + /// Error code + #[serde(skip_serializing_if = "Option::is_none")] + code: Option, + message: String, + + #[serde(skip_serializing_if = "Option::is_none")] + snippet: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + filename: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + start_line: Option, + #[serde(skip_serializing_if = "Option::is_none")] + start_column: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + end_line: Option, + #[serde(skip_serializing_if = "Option::is_none")] + end_column: Option, + + #[serde(skip_serializing_if = "Vec::is_empty")] + children: Vec, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonSubdiagnostic { + message: String, + #[serde(skip_serializing_if = "Option::is_none")] + snippet: Option, + filename: String, + line: usize, +} + +struct Snippet<'a> { + source_code: &'a dyn miette::SourceCode, + span: Span, +} + +impl miette::Diagnostic for Snippet<'_> { + fn source_code(&self) -> Option<&dyn miette::SourceCode> { + if self.span.lo().is_dummy() || self.span.hi().is_dummy() { + return None; + } + + Some(self.source_code) + } + + fn labels(&self) -> Option + '_>> { + Some(Box::new(once(LabeledSpan::new_with_span( + None, + convert_span(self.span), + )))) + } +} + +impl std::error::Error for Snippet<'_> {} + +impl std::fmt::Display for Snippet<'_> { + fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Ok(()) + } +} + +impl std::fmt::Debug for Snippet<'_> { + fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Ok(()) + } +} diff --git a/deps/swc/bindings/binding_nodejs_support_wasm/src/nodejs.rs b/deps/swc/bindings/binding_nodejs_support_wasm/src/nodejs.rs new file mode 100644 index 000000000..50bcd7c1e --- /dev/null +++ b/deps/swc/bindings/binding_nodejs_support_wasm/src/nodejs.rs @@ -0,0 +1,1750 @@ +//! Node.js-specific helpers for `@swc/nodejs-support-wasm`. +//! +//! These functions intentionally expose only the compact operations Node needs +//! from Rust and avoid serializing SWC ASTs into JavaScript. + +use serde::Serialize; +use swc_common::{comments::SingleThreadedComments, sync::Lrc, FileName, SourceMap, Span, Spanned}; +use swc_ecma_ast::{ + ArrowExpr, ArrowFunctionBody, AssignExpr, AssignTarget, AssignTargetPat, BindingIdent, + BlockStmt, CallExpr, Callee, CatchClause, Class, ClassDecl, Decl, DefaultDecl, EsVersion, + ExportSpecifier, Expr, FnDecl, Function, FunctionBody, ImportDecl, ImportSpecifier, + MetaPropExpr, MetaPropKind, Module, ModuleDecl, ModuleExportName, ModuleItem, NamedExport, + ObjectLit, ObjectPatProp, Pat, Prop, SimpleAssignTarget, Stmt, UpdateExpr, VarDecl, + VarDeclKind, +}; +use swc_ecma_parser::{ + error::{Error as ParseError, SyntaxError}, + lexer::Lexer, + unstable::{Token, TokenAndSpan}, + EsSyntax, Parser, StringInput, Syntax, TsSyntax, +}; +use swc_ecma_visit::{Visit, VisitWith}; + +const DYNAMIC_IMPORT_NAME: &str = "__nodeREPLDynamicImport"; + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ModuleSyntaxTransformOutput { + pub code: String, + pub had_module_syntax: bool, +} + +/// Rewrites Node REPL module syntax into script syntax. +/// +/// The transform follows Node's edit-list approach: static imports become +/// awaited dynamic imports, dynamic `import(...)` is routed through Node's REPL +/// helper, and exports are unwrapped or dropped depending on whether they have +/// runtime declarations. +pub fn transform_module_syntax(code: String) -> ModuleSyntaxTransformOutput { + if !code.contains("import") && !code.contains("export") { + return ModuleSyntaxTransformOutput { + code, + had_module_syntax: false, + }; + } + + let Some(module) = parse_module(&code) else { + return ModuleSyntaxTransformOutput { + code, + had_module_syntax: false, + }; + }; + + let (edits, hoisted) = { + let mut transform = ModuleSyntaxTransform::new(&code); + + for item in &module.body { + transform.collect_module_item_edit(item); + } + + let replaced_ranges = transform + .edits + .iter() + .map(|edit| (edit.start, edit.end)) + .collect::>(); + module.visit_with(&mut ModuleFeatureCollector { + code: &code, + edits: &mut transform.edits, + replaced_ranges: &replaced_ranges, + }); + module.visit_with(&mut ImportBindingReferenceCollector { + code: &code, + edits: &mut transform.edits, + replaced_ranges: &replaced_ranges, + bindings: &transform.import_bindings, + scopes: vec![Vec::new()], + }); + + if transform.edits.is_empty() && transform.hoisted.is_empty() { + return ModuleSyntaxTransformOutput { + code, + had_module_syntax: false, + }; + } + + (transform.edits, transform.hoisted) + }; + + ModuleSyntaxTransformOutput { + code: prepend_hoisted_imports(apply_edits(code, edits), hoisted), + had_module_syntax: true, + } +} + +/// Extracts the first source expression associated with a V8 error column. +/// +/// `start_column` is interpreted as a JavaScript UTF-16 code-unit column to +/// match Node/V8 source locations. The implementation uses only lexer tokens +/// because the source line can be incomplete JavaScript. +pub fn get_first_expression(code: String, start_column: u32) -> String { + let start_byte = utf16_column_to_byte_pos(&code, start_column); + let mut last_token = None; + let mut potential_expression_start_token = None; + let mut first_member_access_name_token = None; + let mut pending_optional_chain_name_token = None; + let mut terminating_byte = None; + let mut paren_level = 0u32; + let mut member_bracket_depth = 0u32; + + for token in tokenize(&code) { + if token.token == Token::Eof { + break; + } + + let Some((token_start, token_end)) = span_range(token.span) else { + continue; + }; + if token_start < start_byte { + if token.token == Token::Semi { + potential_expression_start_token = None; + first_member_access_name_token = None; + pending_optional_chain_name_token = None; + member_bracket_depth = 0; + last_token = None; + continue; + } + + if member_bracket_depth > 0 { + match token.token { + Token::LBracket => member_bracket_depth += 1, + Token::RBracket => { + member_bracket_depth = member_bracket_depth.saturating_sub(1); + } + _ => {} + } + last_token = Some(token); + continue; + } + + if is_member_identifier_token(&code, &token) + && first_member_access_name_token.is_none() + && potential_expression_start_token.is_none() + { + potential_expression_start_token = Some(token); + } + + if token.token == Token::QuestionMark + && last_token + .as_ref() + .is_some_and(|last: &TokenAndSpan| is_member_identifier_token(&code, last)) + { + pending_optional_chain_name_token = last_token; + last_token = Some(token); + continue; + } + + if token.token == Token::Dot + && last_token + .as_ref() + .is_some_and(|last: &TokenAndSpan| last.token == Token::QuestionMark) + { + if let Some(name_token) = pending_optional_chain_name_token.take() { + first_member_access_name_token.get_or_insert(name_token); + last_token = Some(token); + continue; + } + } else if pending_optional_chain_name_token.take().is_some() { + first_member_access_name_token = None; + } + + if token.token == Token::LBracket + && last_token + .as_ref() + .is_some_and(|last: &TokenAndSpan| is_member_identifier_token(&code, last)) + { + first_member_access_name_token + .get_or_insert(potential_expression_start_token.unwrap_or(last_token.unwrap())); + member_bracket_depth = 1; + last_token = Some(token); + continue; + } + + if is_member_access_token(token.token) { + if last_token + .as_ref() + .is_some_and(|last: &TokenAndSpan| is_member_identifier_token(&code, last)) + { + first_member_access_name_token.get_or_insert( + potential_expression_start_token.unwrap_or(last_token.unwrap()), + ); + last_token = Some(token); + continue; + } + } else if token.token != Token::LParen && !is_member_name_token(&code, &token) { + potential_expression_start_token = None; + first_member_access_name_token = None; + } + + if token.token == Token::LParen && first_member_access_name_token.is_some() { + paren_level += 1; + last_token = Some(token); + continue; + } + + if token.token == Token::LParen + && last_token + .as_ref() + .is_some_and(|last: &TokenAndSpan| is_member_identifier_token(&code, last)) + { + first_member_access_name_token + .get_or_insert(potential_expression_start_token.unwrap_or(last_token.unwrap())); + paren_level += 1; + last_token = Some(token); + continue; + } + + last_token = Some(token); + continue; + } + + if token.token == Token::LParen + && last_token + .as_ref() + .is_some_and(|last: &TokenAndSpan| is_member_identifier_token(&code, last)) + { + first_member_access_name_token + .get_or_insert(potential_expression_start_token.unwrap_or(last_token.unwrap())); + } + + match token.token { + Token::LParen => { + paren_level += 1; + } + Token::RParen => { + paren_level = paren_level.saturating_sub(1); + if paren_level == 0 { + terminating_byte = Some(token_end); + break; + } + } + Token::Semi => { + terminating_byte = Some(token_start); + break; + } + _ => {} + } + } + + let start = first_member_access_name_token + .and_then(|token| span_range(token.span).map(|(start, _)| start)) + .unwrap_or(start_byte); + let end = terminating_byte.unwrap_or(code.len()); + + if start >= code.len() + || start > end + || !code.is_char_boundary(start) + || !code.is_char_boundary(end) + { + return String::new(); + } + + code[start..end].to_string() +} + +/// Returns true when the source parses as a program or expression. +pub fn is_valid_syntax(code: String) -> bool { + parses_as_program(&code) || parses_as_program(&format!("_={code}")) +} + +/// Returns true for parser errors that should keep a Node REPL input open. +pub fn is_recoverable_error(code: String) -> bool { + match parse_program_result(&code) { + ParseOutcome::Valid => false, + ParseOutcome::Invalid(errors) => { + if errors + .iter() + .any(|error| is_recoverable_parse_error(&code, error)) + { + return true; + } + + code.trim_start().starts_with('{') && is_recoverable_error(format!("({code}")) + } + } +} + +struct ModuleSyntaxTransform<'a> { + code: &'a str, + edits: Vec, + hoisted: Vec, + import_bindings: Vec, + import_namespace_count: u32, +} + +impl<'a> ModuleSyntaxTransform<'a> { + fn new(code: &'a str) -> Self { + Self { + code, + edits: Vec::new(), + hoisted: Vec::new(), + import_bindings: Vec::new(), + import_namespace_count: 0, + } + } + + fn collect_module_item_edit(&mut self, item: &ModuleItem) { + let ModuleItem::ModuleDecl(decl) = item else { + return; + }; + + match decl { + ModuleDecl::Import(import) => { + self.delete_span(import.span); + if !import.type_only { + if let Some(script) = self.import_decl_to_script(import) { + self.hoisted.push(script); + } + } + } + ModuleDecl::ExportDecl(export) => { + if is_type_only_decl(&export.decl) { + self.delete_span(export.span); + } else if let (Some((start, _)), Some((decl_start, _))) = + (span_range(export.span), span_range(export.decl.span())) + { + push_range_edit(&mut self.edits, self.code, start, decl_start, String::new()); + } + } + ModuleDecl::ExportNamed(export) => { + self.delete_span(export.span); + if let Some(src) = &export.src { + if let Some(required_exports) = named_export_source_imports(export) { + self.hoist_validated_import( + &src.value.to_string_lossy(), + export.with.as_deref(), + &required_exports, + ); + } + } + } + ModuleDecl::ExportDefaultDecl(export) => { + self.unwrap_default_declaration(export.span, export.decl.span(), &export.decl); + } + ModuleDecl::ExportDefaultExpr(export) => { + self.unwrap_default_expression( + export.span, + export.expr.span(), + matches!(&*export.expr, Expr::Object(..)), + ); + } + ModuleDecl::ExportAll(export) => { + self.delete_span(export.span); + if !export.type_only { + self.hoist_import(&export.src.value.to_string_lossy(), export.with.as_deref()); + } + } + ModuleDecl::TsImportEquals(import) => { + if import.is_type_only { + self.delete_span(import.span); + } + } + ModuleDecl::TsNamespaceExport(export) => { + self.delete_span(export.span); + } + ModuleDecl::TsExportAssignment(..) => {} + } + } + + fn delete_span(&mut self, span: Span) { + let replacement = if needs_statement_separator(self.code, span) { + ";" + } else { + "" + }; + self.replace_span(span, replacement.to_string()); + } + + fn replace_span(&mut self, span: Span, text: String) { + push_span_edit(&mut self.edits, self.code, span, text); + } + + fn hoist_import(&mut self, specifier: &str, with: Option<&ObjectLit>) { + self.hoisted.push(format!( + "await {};", + await_import(self.code, specifier, with, &[]) + )); + } + + fn hoist_validated_import( + &mut self, + specifier: &str, + with: Option<&ObjectLit>, + required_exports: &[String], + ) { + self.hoisted.push(format!( + "await {};", + await_import(self.code, specifier, with, required_exports) + )); + } + + fn import_decl_to_script(&mut self, node: &ImportDecl) -> Option { + let specifier = node.src.value.to_string_lossy(); + let with = node.with.as_deref(); + + if node.specifiers.is_empty() { + return Some(format!( + "await {};", + await_import(self.code, &specifier, with, &[]) + )); + } + + let mut namespace_name = None; + let mut default_name = None; + let mut named = Vec::new(); + let mut required_exports = Vec::new(); + + for specifier in &node.specifiers { + match specifier { + ImportSpecifier::Namespace(specifier) => { + namespace_name = Some(specifier.local.sym.to_string()); + } + ImportSpecifier::Default(specifier) => { + default_name = Some(specifier.local.sym.to_string()); + push_required_export(&mut required_exports, "default".to_string()); + } + ImportSpecifier::Named(specifier) => { + if specifier.is_type_only { + continue; + } + + let local = specifier.local.sym.to_string(); + let imported = specifier + .imported + .as_ref() + .map(module_export_name) + .unwrap_or_else(|| local.clone()); + push_required_export(&mut required_exports, imported.clone()); + named.push((local, imported)); + } + } + } + + if namespace_name.is_none() && default_name.is_none() && named.is_empty() { + return None; + } + + let namespace_name = namespace_name.unwrap_or_else(|| self.fresh_import_namespace_name()); + let out = format!( + "const {namespace_name} = await {};", + await_import(self.code, &specifier, with, &required_exports) + ); + + if let Some(default_name) = default_name { + self.import_bindings.push(ImportBinding { + local: default_name, + namespace: namespace_name.clone(), + export_name: "default".to_string(), + }); + } + + for (local, export_name) in named { + self.import_bindings.push(ImportBinding { + local, + namespace: namespace_name.clone(), + export_name, + }); + } + + Some(out) + } + + fn fresh_import_namespace_name(&mut self) -> String { + loop { + let candidate = format!("__nodeREPLImport{}", self.import_namespace_count); + self.import_namespace_count += 1; + + if !self.code.contains(&candidate) { + return candidate; + } + } + } + + fn unwrap_default_declaration( + &mut self, + export_span: Span, + decl_span: Span, + decl: &DefaultDecl, + ) { + if matches!(decl, DefaultDecl::TsInterfaceDecl(..)) { + self.delete_span(export_span); + return; + } + + let (Some((export_start, _)), Some((decl_start, decl_end))) = + (span_range(export_span), span_range(decl_span)) + else { + return; + }; + + push_range_edit( + &mut self.edits, + self.code, + export_start, + decl_start, + String::new(), + ); + + if default_declaration_needs_parentheses(decl) { + push_range_edit( + &mut self.edits, + self.code, + decl_start, + decl_start, + "(".to_string(), + ); + push_range_edit( + &mut self.edits, + self.code, + decl_end, + decl_end, + ");".to_string(), + ); + } + } + + fn unwrap_default_expression( + &mut self, + export_span: Span, + expr_span: Span, + needs_parentheses: bool, + ) { + let (Some((export_start, export_end)), Some((expr_start, expr_end))) = + (span_range(export_span), span_range(expr_span)) + else { + return; + }; + + push_range_edit( + &mut self.edits, + self.code, + export_start, + expr_start, + String::new(), + ); + + if needs_parentheses { + push_range_edit( + &mut self.edits, + self.code, + expr_start, + expr_start, + "(".to_string(), + ); + } + + let has_separator = self + .code + .get(expr_end..export_end) + .is_some_and(|tail| tail.contains(';')); + if needs_parentheses || !has_separator { + let mut suffix = String::new(); + if needs_parentheses { + suffix.push(')'); + } + if !has_separator { + suffix.push(';'); + } + push_range_edit(&mut self.edits, self.code, expr_end, expr_end, suffix); + } + } +} + +fn await_import( + code: &str, + specifier: &str, + with: Option<&ObjectLit>, + required_exports: &[String], +) -> String { + let mut out = format!("{DYNAMIC_IMPORT_NAME}({}", json_string(specifier)); + if let Some(options) = import_options_to_dynamic_options(code, with) { + out.push_str(", "); + out.push_str(&options); + } + out.push(')'); + if !required_exports.is_empty() { + out.push_str(".then((m) => { "); + for export_name in required_exports { + out.push_str("if (!("); + out.push_str(&json_string(export_name)); + out.push_str(" in m)) throw new SyntaxError("); + out.push_str(&json_string(&format!( + "The requested module '{specifier}' does not provide an export named \ + '{export_name}'" + ))); + out.push_str("); "); + } + out.push_str("return m; })"); + } + out +} + +fn import_options_to_dynamic_options(code: &str, with: Option<&ObjectLit>) -> Option { + let attributes = slice_span(code, with?.span)?; + Some(format!("{{ with: {attributes} }}")) +} + +fn default_declaration_needs_parentheses(decl: &DefaultDecl) -> bool { + matches!(decl, DefaultDecl::Class(class) if class.ident.is_none()) + || matches!(decl, DefaultDecl::Fn(function) if function.ident.is_none()) +} + +fn is_type_only_decl(decl: &Decl) -> bool { + matches!(decl, Decl::TsInterface(..) | Decl::TsTypeAlias(..)) +} + +fn named_export_source_imports(export: &NamedExport) -> Option> { + if export.type_only { + return None; + } + + let mut loads_source = export.specifiers.is_empty(); + let mut required_exports = Vec::new(); + + for specifier in &export.specifiers { + match specifier { + ExportSpecifier::Named(named) => { + if named.is_type_only { + continue; + } + + loads_source = true; + push_required_export(&mut required_exports, module_export_name(&named.orig)); + } + ExportSpecifier::Default(..) => { + loads_source = true; + push_required_export(&mut required_exports, "default".to_string()); + } + ExportSpecifier::Namespace(..) => { + loads_source = true; + } + } + } + + loads_source.then_some(required_exports) +} + +fn push_required_export(required_exports: &mut Vec, export_name: String) { + if !required_exports + .iter() + .any(|required| required == &export_name) + { + required_exports.push(export_name); + } +} + +fn module_export_name(name: &ModuleExportName) -> String { + match name { + ModuleExportName::Ident(ident) => ident.sym.to_string(), + ModuleExportName::Str(string) => string.value.to_string_lossy().into_owned(), + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +struct Edit { + start: usize, + end: usize, + text: String, +} + +#[derive(Debug)] +struct ImportBinding { + local: String, + namespace: String, + export_name: String, +} + +fn push_span_edit(edits: &mut Vec, code: &str, span: Span, text: String) { + if let Some((start, end)) = span_range(span) { + push_range_edit(edits, code, start, end, text); + } +} + +fn push_range_edit(edits: &mut Vec, code: &str, start: usize, end: usize, text: String) { + if start <= end && end <= code.len() { + edits.push(Edit { start, end, text }); + } +} + +fn apply_edits(mut code: String, mut edits: Vec) -> String { + edits.sort_by(|a, b| b.start.cmp(&a.start).then_with(|| b.end.cmp(&a.end))); + + for edit in edits { + if edit.start <= edit.end + && edit.end <= code.len() + && code.is_char_boundary(edit.start) + && code.is_char_boundary(edit.end) + { + code.replace_range(edit.start..edit.end, &edit.text); + } + } + + code +} + +fn needs_statement_separator(code: &str, span: Span) -> bool { + let Some((start, end)) = span_range(span) else { + return false; + }; + + code[..start].chars().any(|ch| !ch.is_whitespace()) + && code[end..].chars().any(|ch| !ch.is_whitespace()) +} + +fn prepend_hoisted_imports(code: String, hoisted: Vec) -> String { + if hoisted.is_empty() { + return code; + } + + let imports = hoisted.join("\n"); + if code.starts_with("#!") { + if let Some(line_end) = code.find('\n') { + let insert_at = line_end + 1; + let (hashbang, rest) = code.split_at(insert_at); + if rest.is_empty() || rest.starts_with('\n') { + format!("{hashbang}{imports}{rest}") + } else { + format!("{hashbang}{imports}\n{rest}") + } + } else { + format!("{code}\n{imports}") + } + } else if code.is_empty() { + imports + } else if code.starts_with('\n') || code.starts_with("\r\n") { + format!("{imports}{code}") + } else { + format!("{imports}\n{code}") + } +} + +struct ModuleFeatureCollector<'a, 'b> { + code: &'a str, + edits: &'b mut Vec, + replaced_ranges: &'b [(usize, usize)], +} + +impl Visit for ModuleFeatureCollector<'_, '_> { + fn visit_call_expr(&mut self, node: &CallExpr) { + if matches!(node.callee, Callee::Import(..)) { + if let Some((start, end)) = span_range(node.span) { + if !range_is_replaced(self.replaced_ranges, start, end) { + let original = &self.code[start..end]; + if original.starts_with("import") { + self.edits.push(Edit { + start, + end: start + "import".len(), + text: DYNAMIC_IMPORT_NAME.to_string(), + }); + } + } + } + } + + node.visit_children_with(self); + } + + fn visit_meta_prop_expr(&mut self, node: &MetaPropExpr) { + if node.kind == MetaPropKind::ImportMeta { + if let Some((start, end)) = span_range(node.span) { + if !range_is_replaced(self.replaced_ranges, start, end) { + self.edits.push(Edit { + start, + end, + text: import_meta_error_expression(), + }); + } + } + } + } +} + +struct ImportBindingReferenceCollector<'a, 'b> { + code: &'a str, + edits: &'b mut Vec, + replaced_ranges: &'b [(usize, usize)], + bindings: &'b [ImportBinding], + scopes: Vec>, +} + +impl Visit for ImportBindingReferenceCollector<'_, '_> { + fn visit_assign_expr(&mut self, node: &AssignExpr) { + if self.import_binding_for_assign_target(&node.left).is_some() { + self.replace_expression_with_import_assignment_error(node.span); + return; + } + + node.visit_children_with(self); + } + + fn visit_update_expr(&mut self, node: &UpdateExpr) { + if let Expr::Ident(ident) = &*node.arg { + if self.binding_for_unshadowed(ident.sym.as_ref()).is_some() { + self.replace_expression_with_import_assignment_error(node.span); + return; + } + } + + node.visit_children_with(self); + } + + fn visit_function(&mut self, node: &Function) { + let shadowed = function_scope_shadowed_bindings(node, self.bindings); + self.with_scope(shadowed, |this| node.visit_children_with(this)); + } + + fn visit_arrow_expr(&mut self, node: &ArrowExpr) { + let shadowed = arrow_scope_shadowed_bindings(node, self.bindings); + self.with_scope(shadowed, |this| node.visit_children_with(this)); + } + + fn visit_block_stmt(&mut self, node: &BlockStmt) { + let shadowed = direct_block_shadowed_bindings(node, self.bindings); + self.with_scope(shadowed, |this| node.visit_children_with(this)); + } + + fn visit_catch_clause(&mut self, node: &CatchClause) { + let mut shadowed = Vec::new(); + if let Some(param) = &node.param { + collect_shadowed_pat_bindings(&mut shadowed, param, self.bindings); + } + + self.with_scope(shadowed, |this| node.visit_children_with(this)); + } + + fn visit_expr(&mut self, node: &Expr) { + if let Expr::Ident(ident) = node { + self.replace_identifier(ident.span, ident.sym.as_ref()); + return; + } + + node.visit_children_with(self); + } + + fn visit_prop(&mut self, node: &Prop) { + if let Prop::Shorthand(ident) = node { + if let Some(binding) = self.binding_for_unshadowed(ident.sym.as_ref()) { + if let Some((start, end)) = span_range(ident.span) { + if !range_is_replaced(self.replaced_ranges, start, end) { + let access = import_binding_access(binding); + self.edits.push(Edit { + start, + end, + text: format!("{}: {access}", ident.sym), + }); + } + } + } + return; + } + + node.visit_children_with(self); + } +} + +impl ImportBindingReferenceCollector<'_, '_> { + fn replace_identifier(&mut self, span: Span, local: &str) { + let Some(binding) = self.binding_for_unshadowed(local) else { + return; + }; + + let Some((start, end)) = span_range(span) else { + return; + }; + + if range_is_replaced(self.replaced_ranges, start, end) { + return; + } + + if !self.code.get(start..end).is_some_and(|text| text == local) { + return; + } + + self.edits.push(Edit { + start, + end, + text: import_binding_access(binding), + }); + } + + fn binding_for(&self, local: &str) -> Option<&ImportBinding> { + self.bindings.iter().find(|binding| binding.local == local) + } + + fn binding_for_unshadowed(&self, local: &str) -> Option<&ImportBinding> { + if self.is_shadowed(local) { + return None; + } + + self.binding_for(local) + } + + fn import_binding_for_assign_target(&self, target: &AssignTarget) -> Option<&ImportBinding> { + match target { + AssignTarget::Simple(SimpleAssignTarget::Ident(ident)) => { + self.binding_for_unshadowed(ident.id.sym.as_ref()) + } + AssignTarget::Pat(pat) => self.import_binding_for_assign_target_pat(pat), + _ => None, + } + } + + fn import_binding_for_assign_target_pat( + &self, + target: &AssignTargetPat, + ) -> Option<&ImportBinding> { + match target { + AssignTargetPat::Array(array) => array + .elems + .iter() + .flatten() + .find_map(|pat| self.import_binding_for_pat(pat)), + AssignTargetPat::Object(object) => object.props.iter().find_map(|prop| match prop { + ObjectPatProp::KeyValue(prop) => self.import_binding_for_pat(&prop.value), + ObjectPatProp::Assign(prop) => { + self.binding_for_unshadowed(prop.key.id.sym.as_ref()) + } + ObjectPatProp::Rest(prop) => self.import_binding_for_pat(&prop.arg), + }), + AssignTargetPat::Invalid(..) => None, + } + } + + fn import_binding_for_pat(&self, pat: &Pat) -> Option<&ImportBinding> { + match pat { + Pat::Ident(ident) => self.binding_for_unshadowed(ident.id.sym.as_ref()), + Pat::Array(array) => array + .elems + .iter() + .flatten() + .find_map(|pat| self.import_binding_for_pat(pat)), + Pat::Rest(rest) => self.import_binding_for_pat(&rest.arg), + Pat::Object(object) => object.props.iter().find_map(|prop| match prop { + ObjectPatProp::KeyValue(prop) => self.import_binding_for_pat(&prop.value), + ObjectPatProp::Assign(prop) => { + self.binding_for_unshadowed(prop.key.id.sym.as_ref()) + } + ObjectPatProp::Rest(prop) => self.import_binding_for_pat(&prop.arg), + }), + Pat::Assign(assign) => self.import_binding_for_pat(&assign.left), + Pat::Invalid(..) | Pat::Expr(..) => None, + } + } + + fn replace_expression_with_import_assignment_error(&mut self, span: Span) { + let Some((start, end)) = span_range(span) else { + return; + }; + + if range_is_replaced(self.replaced_ranges, start, end) { + return; + } + + self.edits.push(Edit { + start, + end, + text: import_assignment_error_expression(), + }); + } + + fn with_scope(&mut self, shadowed: Vec, op: impl FnOnce(&mut Self)) { + self.scopes.push(shadowed); + op(self); + self.scopes.pop(); + } + + fn is_shadowed(&self, local: &str) -> bool { + self.scopes + .iter() + .rev() + .any(|scope| scope.iter().any(|name| name == local)) + } +} + +fn function_scope_shadowed_bindings(node: &Function, bindings: &[ImportBinding]) -> Vec { + let mut shadowed = Vec::new(); + for param in &node.params { + collect_shadowed_pat_bindings(&mut shadowed, ¶m.pat, bindings); + } + if let Some(body) = &node.body { + collect_function_var_shadowed_bindings(&mut shadowed, body, bindings); + } + shadowed +} + +fn arrow_scope_shadowed_bindings(node: &ArrowExpr, bindings: &[ImportBinding]) -> Vec { + let mut shadowed = Vec::new(); + for param in &node.params { + collect_shadowed_pat_bindings(&mut shadowed, param, bindings); + } + if let ArrowFunctionBody::FunctionBody(body) = &*node.body { + collect_function_var_shadowed_bindings(&mut shadowed, body, bindings); + } + shadowed +} + +fn collect_function_var_shadowed_bindings( + out: &mut Vec, + body: &FunctionBody, + bindings: &[ImportBinding], +) { + let mut collector = FunctionScopedVarCollector { + bindings, + shadowed: out, + }; + body.visit_with(&mut collector); +} + +struct FunctionScopedVarCollector<'a, 'b> { + bindings: &'a [ImportBinding], + shadowed: &'b mut Vec, +} + +impl Visit for FunctionScopedVarCollector<'_, '_> { + fn visit_var_decl(&mut self, node: &VarDecl) { + if node.kind == VarDeclKind::Var { + collect_shadowed_var_decl_bindings(self.shadowed, node, self.bindings); + } + } + + fn visit_function(&mut self, _: &Function) {} + + fn visit_arrow_expr(&mut self, _: &ArrowExpr) {} + + fn visit_class(&mut self, _: &Class) {} +} + +fn direct_block_shadowed_bindings(node: &BlockStmt, bindings: &[ImportBinding]) -> Vec { + let mut shadowed = Vec::new(); + + for stmt in &node.stmts { + if let Stmt::Decl(decl) = stmt { + collect_shadowed_decl_bindings(&mut shadowed, decl, bindings); + } + } + + shadowed +} + +fn collect_shadowed_decl_bindings(out: &mut Vec, decl: &Decl, bindings: &[ImportBinding]) { + match decl { + Decl::Class(ClassDecl { ident, .. }) | Decl::Fn(FnDecl { ident, .. }) => { + push_shadowed_ident_binding(out, ident.sym.as_ref(), bindings); + } + Decl::Var(var) => { + collect_shadowed_var_decl_bindings(out, var, bindings); + } + Decl::Using(using) => { + for declarator in &using.decls { + collect_shadowed_pat_bindings(out, &declarator.name, bindings); + } + } + Decl::TsInterface(..) | Decl::TsTypeAlias(..) | Decl::TsEnum(..) | Decl::TsModule(..) => {} + } +} + +fn collect_shadowed_var_decl_bindings( + out: &mut Vec, + decl: &VarDecl, + bindings: &[ImportBinding], +) { + for declarator in &decl.decls { + collect_shadowed_pat_bindings(out, &declarator.name, bindings); + } +} + +fn collect_shadowed_pat_bindings(out: &mut Vec, pat: &Pat, bindings: &[ImportBinding]) { + match pat { + Pat::Ident(ident) => push_shadowed_binding_ident(out, ident, bindings), + Pat::Array(array) => { + for elem in array.elems.iter().flatten() { + collect_shadowed_pat_bindings(out, elem, bindings); + } + } + Pat::Rest(rest) => collect_shadowed_pat_bindings(out, &rest.arg, bindings), + Pat::Object(object) => { + for prop in &object.props { + match prop { + ObjectPatProp::KeyValue(prop) => { + collect_shadowed_pat_bindings(out, &prop.value, bindings); + } + ObjectPatProp::Assign(prop) => { + push_shadowed_binding_ident(out, &prop.key, bindings); + } + ObjectPatProp::Rest(prop) => { + collect_shadowed_pat_bindings(out, &prop.arg, bindings); + } + } + } + } + Pat::Assign(assign) => collect_shadowed_pat_bindings(out, &assign.left, bindings), + Pat::Invalid(..) | Pat::Expr(..) => {} + } +} + +fn push_shadowed_binding_ident( + out: &mut Vec, + ident: &BindingIdent, + bindings: &[ImportBinding], +) { + push_shadowed_ident_binding(out, ident.id.sym.as_ref(), bindings); +} + +fn push_shadowed_ident_binding(out: &mut Vec, local: &str, bindings: &[ImportBinding]) { + if bindings.iter().any(|binding| binding.local == local) + && !out.iter().any(|name| name == local) + { + out.push(local.to_string()); + } +} + +fn range_is_replaced(replaced_ranges: &[(usize, usize)], start: usize, end: usize) -> bool { + replaced_ranges + .iter() + .any(|(replace_start, replace_end)| start >= *replace_start && end <= *replace_end) +} + +fn import_binding_access(binding: &ImportBinding) -> String { + format!( + "{}{}", + binding.namespace, + export_property_access(&binding.export_name) + ) +} + +fn export_property_access(export_name: &str) -> String { + if is_identifier_name(export_name) { + format!(".{export_name}") + } else { + format!("[{}]", json_string(export_name)) + } +} + +fn import_meta_error_expression() -> String { + "(() => { throw new SyntaxError(\"Cannot use import.meta outside a module\"); })()".to_string() +} + +fn import_assignment_error_expression() -> String { + "(() => { throw new TypeError(\"Assignment to constant variable.\"); })()".to_string() +} + +fn is_identifier_name(value: &str) -> bool { + let mut chars = value.chars(); + let Some(first) = chars.next() else { + return false; + }; + + if !(first == '_' || first == '$' || first.is_ascii_alphabetic()) { + return false; + } + + chars.all(|ch| ch == '_' || ch == '$' || ch.is_ascii_alphanumeric()) +} + +enum ParseOutcome { + Valid, + Invalid(Vec), +} + +fn parse_program_result(code: &str) -> ParseOutcome { + let es = parse_program_result_with_syntax(code, Syntax::Es(es_syntax())); + if matches!(es, ParseOutcome::Valid) { + return es; + } + + parse_program_result_with_syntax(code, Syntax::Typescript(ts_syntax())) +} + +fn parse_program_result_with_syntax(code: &str, syntax: Syntax) -> ParseOutcome { + let cm = Lrc::new(SourceMap::default()); + let fm = cm.new_source_file(FileName::Anon.into(), code.to_string()); + let comments = SingleThreadedComments::default(); + let lexer = Lexer::new( + syntax, + EsVersion::latest(), + StringInput::from(&*fm), + Some(&comments), + ); + let mut parser = Parser::new_from(lexer); + + match parser.parse_program() { + Ok(..) => { + let errors = parser.take_errors(); + if errors.is_empty() { + ParseOutcome::Valid + } else { + ParseOutcome::Invalid(errors) + } + } + Err(error) => { + let mut errors = vec![error]; + errors.extend(parser.take_errors()); + ParseOutcome::Invalid(errors) + } + } +} + +fn parse_module(code: &str) -> Option { + parse_module_with_syntax(code, Syntax::Es(es_syntax())) + .or_else(|| parse_module_with_syntax(code, Syntax::Typescript(ts_syntax()))) +} + +fn parse_module_with_syntax(code: &str, syntax: Syntax) -> Option { + let cm = Lrc::new(SourceMap::default()); + let fm = cm.new_source_file(FileName::Anon.into(), code.to_string()); + let comments = SingleThreadedComments::default(); + let lexer = Lexer::new( + syntax, + EsVersion::latest(), + StringInput::from(&*fm), + Some(&comments), + ); + let mut parser = Parser::new_from(lexer); + let module = parser.parse_module().ok()?; + + if parser.take_errors().is_empty() { + Some(module) + } else { + None + } +} + +fn parses_as_program(code: &str) -> bool { + matches!(parse_program_result(code), ParseOutcome::Valid) +} + +fn tokenize(code: &str) -> Vec { + let cm = Lrc::new(SourceMap::default()); + let fm = cm.new_source_file(FileName::Anon.into(), code.to_string()); + let comments = SingleThreadedComments::default(); + Lexer::new( + Syntax::Es(es_syntax()), + EsVersion::latest(), + StringInput::from(&*fm), + Some(&comments), + ) + .collect() +} + +fn es_syntax() -> EsSyntax { + EsSyntax { + auto_accessors: true, + explicit_resource_management: true, + import_attributes: true, + ..Default::default() + } +} + +fn ts_syntax() -> TsSyntax { + TsSyntax { + decorators: true, + ..Default::default() + } +} + +fn is_recoverable_parse_error(code: &str, error: &ParseError) -> bool { + match error.kind() { + SyntaxError::Eof | SyntaxError::UnterminatedTpl | SyntaxError::UnterminatedBlockComment => { + true + } + SyntaxError::UnterminatedStrLit => has_trailing_line_continuation(code), + SyntaxError::Expected(_, got) => got == "", + _ => false, + } +} + +fn has_trailing_line_continuation(code: &str) -> bool { + code.ends_with("\\\n") + || code.ends_with("\\\r") + || code.ends_with("\\\r\n") + || code.ends_with("\\\u{2028}") + || code.ends_with("\\\u{2029}") +} + +fn is_member_access_token(token: Token) -> bool { + matches!( + token, + Token::Dot | Token::OptionalChain | Token::LBracket | Token::RBracket + ) +} + +fn is_member_name_token(code: &str, token: &TokenAndSpan) -> bool { + matches!(token.token, Token::Ident | Token::Str | Token::Num) + || token.token.is_known_ident() + || token_text_is_identifier(code, token) +} + +fn is_member_identifier_token(code: &str, token: &TokenAndSpan) -> bool { + token.token == Token::Ident + || token.token.is_known_ident() + || token_text_is_identifier(code, token) +} + +fn token_text_is_identifier(code: &str, token: &TokenAndSpan) -> bool { + slice_span(code, token.span).is_some_and(is_identifier_name) +} + +fn slice_span(code: &str, span: Span) -> Option<&str> { + let (start, end) = span_range(span)?; + code.get(start..end) +} + +fn span_range(span: Span) -> Option<(usize, usize)> { + if span.lo.is_dummy() || span.hi.is_dummy() { + return None; + } + + let start = span.lo.0.checked_sub(1)? as usize; + let end = span.hi.0.checked_sub(1)? as usize; + Some((start, end)) +} + +fn utf16_column_to_byte_pos(code: &str, column: u32) -> usize { + let mut utf16_pos = 0u32; + + for (byte_pos, ch) in code.char_indices() { + if utf16_pos >= column { + return byte_pos; + } + + utf16_pos += ch.len_utf16() as u32; + if utf16_pos > column { + return byte_pos; + } + } + + code.len() +} + +fn json_string(value: &str) -> String { + serde_json::to_string(value).expect("serializing a string should not fail") +} + +#[cfg(test)] +mod tests { + use super::*; + + fn validated_import(specifier: &str, required_exports: &[&str]) -> String { + validated_import_with_options(specifier, None, required_exports) + } + + fn validated_import_with_options( + specifier: &str, + options: Option<&str>, + required_exports: &[&str], + ) -> String { + let mut out = format!("{DYNAMIC_IMPORT_NAME}({}", json_string(specifier)); + if let Some(options) = options { + out.push_str(", "); + out.push_str(options); + } + out.push(')'); + + if !required_exports.is_empty() { + out.push_str(".then((m) => { "); + for export_name in required_exports { + out.push_str("if (!("); + out.push_str(&json_string(export_name)); + out.push_str(" in m)) throw new SyntaxError("); + out.push_str(&json_string(&format!( + "The requested module '{specifier}' does not provide an export named \ + '{export_name}'" + ))); + out.push_str("); "); + } + out.push_str("return m; })"); + } + + out + } + + #[test] + fn transform_import_forms() { + assert_eq!( + transform_module_syntax("import \"node:fs\";".into()).code, + "await __nodeREPLDynamicImport(\"node:fs\");" + ); + assert_eq!( + transform_module_syntax("import fs from \"node:fs\";".into()).code, + format!( + "const __nodeREPLImport0 = await {};", + validated_import("node:fs", &["default"]) + ) + ); + assert_eq!( + transform_module_syntax("import { readFile as rf } from \"node:fs\";".into()).code, + format!( + "const __nodeREPLImport0 = await {};", + validated_import("node:fs", &["readFile"]) + ) + ); + assert_eq!( + transform_module_syntax("import { readFile as rf } from \"node:fs\";\nrf();".into()) + .code, + format!( + "const __nodeREPLImport0 = await {};\n__nodeREPLImport0.readFile();", + validated_import("node:fs", &["readFile"]) + ) + ); + assert_eq!( + transform_module_syntax("import def, * as ns from \"mod\";".into()).code, + format!( + "const ns = await {};", + validated_import("mod", &["default"]) + ) + ); + assert_eq!( + transform_module_syntax("import def, * as ns from \"mod\";\ndef; ns;".into()).code, + format!( + "const ns = await {};\nns.default; ns;", + validated_import("mod", &["default"]) + ) + ); + assert_eq!( + transform_module_syntax("import { \"a-b\" as c } from \"mod\";".into()).code, + format!( + "const __nodeREPLImport0 = await {};", + validated_import("mod", &["a-b"]) + ) + ); + assert_eq!( + transform_module_syntax("import { \"a-b\" as c } from \"mod\";\nc;".into()).code, + format!( + "const __nodeREPLImport0 = await {};\n__nodeREPLImport0[\"a-b\"];", + validated_import("mod", &["a-b"]) + ) + ); + assert_eq!( + transform_module_syntax( + "import data from \"./data.json\" with { type: \"json\" };".into() + ) + .code, + format!( + "const __nodeREPLImport0 = await {};", + validated_import_with_options( + "./data.json", + Some("{ with: { type: \"json\" } }"), + &["default"] + ) + ) + ); + assert_eq!( + transform_module_syntax("console.log(typeof fs);\nimport fs from \"node:fs\";".into()) + .code, + format!( + "const __nodeREPLImport0 = await {};\nconsole.log(typeof \ + __nodeREPLImport0.default);\n", + validated_import("node:fs", &["default"]) + ) + ); + } + + #[test] + fn transform_export_forms() { + assert_eq!( + transform_module_syntax("export const x = 1;".into()).code, + "const x = 1;" + ); + assert_eq!( + transform_module_syntax("export default value;".into()).code, + "value;" + ); + assert_eq!( + transform_module_syntax("export default foo; doSomething();".into()).code, + "foo; doSomething();" + ); + assert_eq!( + transform_module_syntax("export default { ...config };".into()).code, + "({ ...config });" + ); + assert_eq!( + transform_module_syntax("export default function () {}".into()).code, + "(function () {});" + ); + assert_eq!( + transform_module_syntax( + "export default function f() { return import(\"node:fs\"); }".into() + ) + .code, + "function f() { return __nodeREPLDynamicImport(\"node:fs\"); }" + ); + assert_eq!( + transform_module_syntax( + "export default function () { return import(\"node:fs\"); }".into() + ) + .code, + "(function () { return __nodeREPLDynamicImport(\"node:fs\"); });" + ); + assert_eq!( + transform_module_syntax("export default class {}".into()).code, + "(class {});" + ); + assert_eq!(transform_module_syntax("export { x };".into()).code, ""); + assert_eq!( + transform_module_syntax("export * from \"mod\";".into()).code, + "await __nodeREPLDynamicImport(\"mod\");" + ); + assert_eq!( + transform_module_syntax("console.log(1);\nexport { value } from \"mod\";".into()).code, + format!( + "await {};\nconsole.log(1);\n", + validated_import("mod", &["value"]) + ) + ); + } + + #[test] + fn transform_preserves_missing_export_failures() { + let missing_default = transform_module_syntax("import missing from \"mod\";".into()); + assert!(missing_default.code.contains("\"default\" in m")); + assert!(missing_default.code.contains("export named 'default'")); + + let missing_named = transform_module_syntax("import { missing, ok } from \"mod\";".into()); + assert!(missing_named.code.contains("\"missing\" in m")); + assert!(missing_named.code.contains("\"ok\" in m")); + + let re_export = transform_module_syntax("export { missing } from \"mod\";".into()); + assert!(re_export.code.contains("\"missing\" in m")); + } + + #[test] + fn transform_preserves_import_binding_semantics() { + assert_eq!( + transform_module_syntax("import { spec } from \"m\";\nimport(spec);".into()).code, + format!( + "const __nodeREPLImport0 = await \ + {};\n__nodeREPLDynamicImport(__nodeREPLImport0.spec);", + validated_import("m", &["spec"]) + ) + ); + + assert_eq!( + transform_module_syntax( + "import { x } from \"m\";\nfunction f(x) { return x; }\nx;".into() + ) + .code, + format!( + "const __nodeREPLImport0 = await {};\nfunction f(x) {{ return x; \ + }}\n__nodeREPLImport0.x;", + validated_import("m", &["x"]) + ) + ); + + assert_eq!( + transform_module_syntax("import { x } from \"m\";\n{ const x = 1; x; }\nx;".into()) + .code, + format!( + "const __nodeREPLImport0 = await {};\n{{ const x = 1; x; }}\n__nodeREPLImport0.x;", + validated_import("m", &["x"]) + ) + ); + + assert_eq!( + transform_module_syntax("import { x } from \"m\";\ntry {} catch (x) { x; }\nx;".into()) + .code, + format!( + "const __nodeREPLImport0 = await {};\ntry {{}} catch (x) {{ x; \ + }}\n__nodeREPLImport0.x;", + validated_import("m", &["x"]) + ) + ); + + assert_eq!( + transform_module_syntax( + "import { x } from \"m\";\nfunction f(){ if (ok) { var x = 1; } return x; }\nx;" + .into() + ) + .code, + format!( + "const __nodeREPLImport0 = await {};\nfunction f(){{ if (ok) {{ var x = 1; }} \ + return x; }}\n__nodeREPLImport0.x;", + validated_import("m", &["x"]) + ) + ); + + assert_eq!( + transform_module_syntax("import { readFile } from \"node:fs\";\nreadFile = 1;".into()) + .code, + format!( + "const __nodeREPLImport0 = await {};\n(() => {{ throw new TypeError(\"Assignment \ + to constant variable.\"); }})();", + validated_import("node:fs", &["readFile"]) + ) + ); + + assert_eq!( + transform_module_syntax( + "import { readFile } from \"node:fs\";\n({ readFile } = obj);".into() + ) + .code, + format!( + "const __nodeREPLImport0 = await {};\n((() => {{ throw new TypeError(\"Assignment \ + to constant variable.\"); }})());", + validated_import("node:fs", &["readFile"]) + ) + ); + + assert_eq!( + transform_module_syntax("import { readFile } from \"node:fs\";\nreadFile++;".into()) + .code, + format!( + "const __nodeREPLImport0 = await {};\n(() => {{ throw new TypeError(\"Assignment \ + to constant variable.\"); }})();", + validated_import("node:fs", &["readFile"]) + ) + ); + } + + #[test] + fn transform_dynamic_import_and_noops() { + assert_eq!( + transform_module_syntax("const mod = import(\"node:fs\");".into()).code, + "const mod = __nodeREPLDynamicImport(\"node:fs\");" + ); + + let no_module_syntax = transform_module_syntax("const importName = \"import\";".into()); + assert!(!no_module_syntax.had_module_syntax); + assert_eq!(no_module_syntax.code, "const importName = \"import\";"); + + let incomplete = transform_module_syntax("import {".into()); + assert!(!incomplete.had_module_syntax); + assert_eq!(incomplete.code, "import {"); + + let import_meta = transform_module_syntax("console.log(import.meta.url);".into()); + assert!(import_meta.had_module_syntax); + assert!(import_meta + .code + .contains("Cannot use import.meta outside a module")); + } + + #[test] + fn transform_preserves_statement_boundaries() { + let hashbang = transform_module_syntax( + "#!/usr/bin/env node\nimport fs from \"node:fs\";\nfs.readFile;".into(), + ) + .code; + assert!(hashbang.starts_with("#!/usr/bin/env node\nconst __nodeREPLImport0 = await ")); + assert!(hashbang.contains("\n__nodeREPLImport0.default.readFile;")); + + assert_eq!( + transform_module_syntax("foo()\nimport \"x\";\n[1].forEach(bar)".into()).code, + "await __nodeREPLDynamicImport(\"x\");\nfoo()\n;\n[1].forEach(bar)" + ); + } + + #[test] + fn transform_typescript_module_syntax() { + assert_eq!( + transform_module_syntax("import fs from \"node:fs\";\nconst x: number = 1;".into()) + .code, + format!( + "const __nodeREPLImport0 = await {};\nconst x: number = 1;", + validated_import("node:fs", &["default"]) + ) + ); + + let type_only = transform_module_syntax( + "import type { Foo } from \"types\";\nexport type { Foo };\nconst x: number = 1;" + .into(), + ); + assert!(type_only.had_module_syntax); + assert!(!type_only.code.contains("__nodeREPLDynamicImport")); + assert!(!type_only.code.contains("import type")); + assert!(!type_only.code.contains("export type")); + + let re_export_type = + transform_module_syntax("export { type Foo } from \"types\";\nconst x = 1;".into()); + assert!(!re_export_type.code.contains("__nodeREPLDynamicImport")); + assert_eq!(re_export_type.code, "\nconst x = 1;"); + + let import_equals = + transform_module_syntax("import type Foo = require(\"foo\");\nconst x = 1;".into()); + assert!(import_equals.had_module_syntax); + assert_eq!(import_equals.code, "\nconst x = 1;"); + + let namespace_export = + transform_module_syntax("export as namespace Foo;\nconst x = 1;".into()); + assert!(namespace_export.had_module_syntax); + assert_eq!(namespace_export.code, "\nconst x = 1;"); + } + + #[test] + fn first_expression_from_error_column() { + assert_eq!( + get_first_expression("assert(value)".into(), 6), + "assert(value)" + ); + assert_eq!(get_first_expression("ok(value)".into(), 3), "ok(value)"); + assert_eq!( + get_first_expression("assert.ok(value)".into(), 9), + "assert.ok(value)" + ); + assert_eq!( + get_first_expression("assert['ok'](value)".into(), 12), + "assert['ok'](value)" + ); + assert_eq!( + get_first_expression("assert[method + suffix](value)".into(), 23), + "assert[method + suffix](value)" + ); + assert_eq!( + get_first_expression("assert.deepEqual(foo(), 1)".into(), 17), + "assert.deepEqual(foo(), 1)" + ); + assert_eq!( + get_first_expression("assert?.ok(value)".into(), 10), + "assert?.ok(value)" + ); + assert_eq!( + get_first_expression("a(); assert.ok(value); b()".into(), 13), + "assert.ok(value)" + ); + assert_eq!( + get_first_expression("const 🍣 = 1; assert.ok(🍣)".into(), 23), + "assert.ok(🍣)" + ); + } + + #[test] + fn valid_syntax_checks() { + assert!(is_valid_syntax("await foo".into())); + assert!(is_valid_syntax("{ value: 1 }".into())); + assert!(is_valid_syntax("foo + bar".into())); + assert!(is_valid_syntax("const x: number = 1".into())); + assert!(!is_valid_syntax("function foo(".into())); + } + + #[test] + fn recoverable_syntax_checks() { + assert!(is_recoverable_error("function foo() {".into())); + assert!(is_recoverable_error("{".into())); + assert!(is_recoverable_error("`template".into())); + assert!(is_recoverable_error("/* comment".into())); + assert!(is_recoverable_error("\"continued\\\n".into())); + assert!(!is_recoverable_error("const x: number = 1".into())); + assert!(!is_recoverable_error("{ value: 1 }".into())); + assert!(!is_recoverable_error("{}".into())); + assert!(!is_recoverable_error("2e".into())); + assert!(!is_recoverable_error("\"unterminated".into())); + } +} diff --git a/deps/swc/bindings/binding_react_compiler_node/Cargo.toml b/deps/swc/bindings/binding_react_compiler_node/Cargo.toml index 64f37cf09..552b0fa61 100644 --- a/deps/swc/bindings/binding_react_compiler_node/Cargo.toml +++ b/deps/swc/bindings/binding_react_compiler_node/Cargo.toml @@ -20,6 +20,7 @@ backtrace = { workspace = true } napi = { workspace = true, features = ["napi3", "serde-json"] } napi-derive = { workspace = true, features = ["type-def"] } serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } tracing = { workspace = true, features = ["release_max_level_info"] } diff --git a/deps/swc/bindings/binding_react_compiler_node/src/diagnostics.rs b/deps/swc/bindings/binding_react_compiler_node/src/diagnostics.rs new file mode 100644 index 000000000..7cc1a3c18 --- /dev/null +++ b/deps/swc/bindings/binding_react_compiler_node/src/diagnostics.rs @@ -0,0 +1,281 @@ +use swc_ecma_react_compiler::diagnostics::{ + DiagnosticDetail as CoreDiagnosticDetail, DiagnosticLocation as CoreDiagnosticLocation, + DiagnosticMessage, DiagnosticPosition as CoreDiagnosticPosition, Severity, +}; + +// `#[napi]` resolves via the crate-wide `#[macro_use] extern crate +// napi_derive;` in `lib.rs` — matches the convention already used in +// `support.rs`. +#[napi(object)] +#[derive(Debug, Clone)] +pub struct Diagnostic { + pub severity: String, + pub message: String, + #[napi(js_name = "ruleId")] + pub rule_id: Option, + pub category: Option, + pub reason: Option, + pub description: Option, + pub loc: Option, + pub details: Vec, +} + +#[napi(object)] +#[derive(Debug, Clone)] +pub struct DiagnosticLocation { + pub start: DiagnosticPosition, + pub end: DiagnosticPosition, + pub filename: Option, + #[napi(js_name = "identifierName")] + pub identifier_name: Option, +} + +#[napi(object)] +#[derive(Debug, Clone)] +pub struct DiagnosticPosition { + pub line: u32, + pub column: u32, + pub index: Option, +} + +#[napi(object)] +#[derive(Debug, Clone)] +pub struct DiagnosticDetail { + pub kind: String, + pub loc: Option, + pub message: Option, +} + +/// Converts a lint result's diagnostics into their napi-facing shape. +/// +/// `source_text` is the same source that was linted — needed to convert +/// `CoreDiagnosticPosition`'s byte-based `column`/`index` into the UTF-16 +/// code-unit-based positions JS/ESLint consumers expect. See +/// [`diagnostic_position_from`] for why this conversion can't happen +/// upstream in `swc_ecma_react_compiler` itself. +pub fn diagnostic_from_message(source_text: &str, value: &DiagnosticMessage) -> Diagnostic { + Diagnostic { + severity: match value.severity { + Severity::Error => "error".to_string(), + Severity::Warning => "warning".to_string(), + }, + message: value.message.clone(), + rule_id: value.rule_id.clone(), + category: value.category.clone(), + reason: value.reason.clone(), + description: value.description.clone(), + loc: value + .loc + .as_ref() + .map(|loc| diagnostic_location_from(source_text, loc)), + details: value + .details + .iter() + .map(|detail| diagnostic_detail_from(source_text, detail)) + .collect(), + } +} + +fn diagnostic_location_from( + source_text: &str, + value: &CoreDiagnosticLocation, +) -> DiagnosticLocation { + DiagnosticLocation { + start: diagnostic_position_from(source_text, &value.start), + end: diagnostic_position_from(source_text, &value.end), + filename: value.filename.clone(), + identifier_name: value.identifier_name.clone(), + } +} + +/// Converts a byte-offset-based position into a UTF-16 code-unit-based one. +/// +/// `swc_ecma_react_compiler`'s `DiagnosticPosition` (and the upstream +/// `Position` it's built from) is deliberately byte-based: it also feeds +/// `DiagnosticMessage.span`, which `@swc/core`'s existing react-compiler +/// transform-error path turns into a real `swc_common::Span`/`BytePos` for +/// terminal error rendering — that consumer genuinely needs byte offsets. +/// This napi package's `lint`/`lintSync` are a different consumer exposing +/// positions to JS/ESLint, whose string indexing is UTF-16-based. Rather +/// than changing the shared byte-based representation (and breaking the +/// unrelated transform-error consumer for any non-ASCII source), the +/// conversion happens here, at this package's own boundary. +/// +/// For ASCII-only source text this is a no-op (byte count == UTF-16 code +/// unit count for ASCII); they diverge for any non-ASCII character +/// appearing before the position being converted. +fn diagnostic_position_from( + source_text: &str, + value: &CoreDiagnosticPosition, +) -> DiagnosticPosition { + let line_text = source_text + .split('\n') + .nth(value.line.saturating_sub(1) as usize) + .unwrap_or_default(); + let byte_column = value.column as usize; + let column = line_text + .get(..byte_column) + .unwrap_or(line_text) + .encode_utf16() + .count() as u32; + + let index = value.index.map(|byte_index| { + source_text + .get(..byte_index as usize) + .unwrap_or(source_text) + .encode_utf16() + .count() as u32 + }); + + DiagnosticPosition { + line: value.line, + column, + index, + } +} + +fn diagnostic_detail_from(source_text: &str, value: &CoreDiagnosticDetail) -> DiagnosticDetail { + DiagnosticDetail { + kind: value.kind.clone(), + loc: value + .loc + .as_ref() + .map(|loc| diagnostic_location_from(source_text, loc)), + message: value.message.clone(), + } +} + +#[cfg(test)] +mod tests { + use swc_ecma_react_compiler::diagnostics::{ + DiagnosticDetail as CoreDiagnosticDetail, DiagnosticLocation as CoreDiagnosticLocation, + DiagnosticMessage, DiagnosticPosition as CoreDiagnosticPosition, Severity, + }; + + use super::diagnostic_from_message; + + // Line 3 (1-indexed) is `👋 const value = 1;` — a 4-byte emoji followed + // by a space, so byte offsets and UTF-16 offsets diverge from column 0 + // onward on this line, and `index` (absolute, from file start) diverges + // for every position after it. + const SOURCE: &str = "line one\nline two\n👋 const value = 1;\n"; + + fn sample_message() -> DiagnosticMessage { + DiagnosticMessage { + severity: Severity::Error, + message: "[ReactCompiler] Refs: invalid ref access".into(), + span: Some((1, 2)), + rule_id: Some("refs".into()), + category: Some("Refs".into()), + reason: Some("invalid ref access".into()), + description: Some("description".into()), + // All of these are the BYTE-based values `swc_ecma_react_compiler` + // would actually produce (what `diagnostic_from_message` takes as + // input) — `value` on line 3 starts after "👋 const ", which is + // 4 (the emoji, a 4-byte UTF-8 sequence) + 1 (space) + 6 + // ("const ") = 11 bytes. Lines 1-2 ("line one"/"line two") plus + // their newlines are 8 + 1 + 8 + 1 = 18 bytes, so `value`'s + // absolute byte index is 18 + 11 = 29. + loc: Some(CoreDiagnosticLocation { + start: CoreDiagnosticPosition { + line: 3, + column: 11, + index: Some(29), + }, + end: CoreDiagnosticPosition { + line: 3, + column: 16, // 11 + "value".len() + index: Some(34), + }, + filename: Some("input.tsx".into()), + identifier_name: Some("value".into()), + }), + details: vec![CoreDiagnosticDetail { + kind: "error".into(), + loc: None, + message: Some("detail".into()), + }], + } + } + + #[test] + fn converts_diagnostic_message_to_napi_shape() { + let diagnostic = diagnostic_from_message(SOURCE, &sample_message()); + + assert_eq!(diagnostic.severity, "error"); + assert_eq!( + diagnostic.message, + "[ReactCompiler] Refs: invalid ref access" + ); + assert_eq!(diagnostic.rule_id.as_deref(), Some("refs")); + assert_eq!(diagnostic.category.as_deref(), Some("Refs")); + + let loc = diagnostic.loc.expect("expected loc"); + assert_eq!(loc.start.line, 3); + assert_eq!(loc.identifier_name.as_deref(), Some("value")); + + assert_eq!(diagnostic.details.len(), 1); + assert_eq!(diagnostic.details[0].kind, "error"); + } + + #[test] + fn converts_warning_severity() { + let mut message = sample_message(); + message.severity = Severity::Warning; + + let diagnostic = diagnostic_from_message(SOURCE, &message); + + assert_eq!(diagnostic.severity, "warning"); + } + + #[test] + fn converts_byte_offsets_to_utf16_code_units_across_non_ascii_text() { + let diagnostic = diagnostic_from_message(SOURCE, &sample_message()); + let loc = diagnostic.loc.expect("expected loc"); + + // Byte column (11) counts the 4-byte emoji as 4 bytes; UTF-16 column + // counts it as 2 code units ('👋' is outside the BMP, so it's a + // surrogate pair): "👋"(2) + " "(1) + "const "(6) = 9. + assert_eq!(loc.start.column, 9); + assert_eq!(loc.end.column, 9 + 5); // + "value".len() + + // Same divergence propagated into the absolute `index`. Lines 1-2 + // and their newlines are ASCII, so their UTF-16 length equals their + // byte length (18); only line 3's emoji prefix diverges (9 UTF-16 + // units vs. 11 bytes), giving 18 + 9 = 27 instead of the byte-based + // 29. + assert_eq!(loc.start.index, Some(18 + 9)); + assert_eq!(loc.end.index, Some(18 + 9 + 5)); + } + + #[test] + fn ascii_only_source_leaves_positions_unchanged() { + let source = "line one\nfunction App() {\n const value = 1;\n}\n"; + let message = DiagnosticMessage { + loc: Some(CoreDiagnosticLocation { + start: CoreDiagnosticPosition { + line: 3, + column: 10, + index: Some(9 + 17 + 10), + }, + end: CoreDiagnosticPosition { + line: 3, + column: 15, + index: Some(9 + 17 + 15), + }, + filename: None, + identifier_name: None, + }), + ..sample_message() + }; + + let diagnostic = diagnostic_from_message(source, &message); + let loc = diagnostic.loc.expect("expected loc"); + + // For ASCII-only source, byte offsets and UTF-16 offsets coincide. + assert_eq!(loc.start.column, 10); + assert_eq!(loc.start.index, Some(9 + 17 + 10)); + assert_eq!(loc.end.column, 15); + assert_eq!(loc.end.index, Some(9 + 17 + 15)); + } +} diff --git a/deps/swc/bindings/binding_react_compiler_node/src/lib.rs b/deps/swc/bindings/binding_react_compiler_node/src/lib.rs index 12ae4f151..11460014d 100644 --- a/deps/swc/bindings/binding_react_compiler_node/src/lib.rs +++ b/deps/swc/bindings/binding_react_compiler_node/src/lib.rs @@ -10,6 +10,8 @@ use std::{env, panic::set_hook}; use backtrace::Backtrace; +mod diagnostics; +mod lint; mod support; #[napi_derive::module_init] diff --git a/deps/swc/bindings/binding_react_compiler_node/src/lint.rs b/deps/swc/bindings/binding_react_compiler_node/src/lint.rs new file mode 100644 index 000000000..c91c4d310 --- /dev/null +++ b/deps/swc/bindings/binding_react_compiler_node/src/lint.rs @@ -0,0 +1,257 @@ +use napi::bindgen_prelude::*; +use swc_core::ecma::parser::Syntax; + +use crate::diagnostics::{diagnostic_from_message, Diagnostic}; + +/// Matches `swc_ecma_parser::Syntax`'s own `Default` impl +/// (`Es(EsSyntax::default())` — plain ECMAScript, no JSX/TSX/decorators) rather +/// than any particular consumer's build settings. This package is +/// general-purpose; it must not silently assume one caller's parser +/// configuration for everyone else. +fn default_syntax() -> Syntax { + Syntax::default() +} + +/// Pure JSON decode, no napi types involved — this is the only part of +/// syntax parsing that unit tests may call directly. A `napi::Error` has a +/// non-trivial `Drop`/`ToNapiValue` impl that references live N-API C +/// functions (`napi_throw`, `napi_create_error`, ...), which only exist once +/// this cdylib is `dlopen`'d by a running Node process. If ANY function that +/// tests call constructs a `napi::Error` anywhere in its body — even in a +/// branch that specific test never executes — the whole function's compiled +/// object code references those unresolved symbols, and a standalone +/// `cargo test` binary (never loaded by Node) fails to link. Keep this +/// function's signature free of `napi::Error`/`napi::Result` so tests can +/// call it safely. +fn decode_syntax(bytes: &[u8]) -> std::result::Result { + serde_json::from_slice(bytes) +} + +/// Thin napi-facing wrapper — not unit tested (see `decode_syntax`'s doc +/// comment), matching this crate's existing convention of only testing the +/// pure logic behind a `#[napi]` function, never the function itself (see +/// `support.rs`'s `is_react_compiler_required(_sync)`, which have no tests +/// at all). +fn parse_syntax_option(syntax: Option) -> napi::Result { + match syntax { + Some(buf) => decode_syntax(buf.as_ref()).map_err(|err| { + napi::Error::new(napi::Status::InvalidArg, format!("invalid `syntax`: {err}")) + }), + None => Ok(default_syntax()), + } +} + +fn lint_inner(code: &str, syntax: Syntax) -> Vec { + let result = swc_ecma_react_compiler::lint_source( + code, + syntax, + swc_ecma_react_compiler::default_plugin_options(), + ); + + result + .diagnostics + .iter() + .map(|d| diagnostic_from_message(code, d)) + .collect() +} + +struct LintTask { + code: String, + syntax: Syntax, +} + +#[napi] +impl Task for LintTask { + type JsValue = Vec; + type Output = Vec; + + fn compute(&mut self) -> napi::Result { + Ok(lint_inner(&self.code, self.syntax)) + } + + fn resolve(&mut self, _env: napi::Env, output: Self::Output) -> napi::Result { + Ok(output) + } +} + +#[napi] +fn lint( + code: String, + syntax: Option, + signal: Option, +) -> napi::Result> { + let syntax = parse_syntax_option(syntax)?; + + Ok(AsyncTask::with_optional_signal( + LintTask { code, syntax }, + signal, + )) +} + +#[napi] +pub fn lint_sync(code: String, syntax: Option) -> napi::Result> { + let syntax = parse_syntax_option(syntax)?; + + Ok(lint_inner(&code, syntax)) +} + +#[cfg(test)] +mod tests { + use swc_core::ecma::parser::{EsSyntax, Syntax, TsSyntax}; + + use super::{decode_syntax, default_syntax, lint_inner}; + + /// Several documented React Compiler lint rules + /// (https://react.dev/reference/eslint-plugin-react-hooks) only surface + /// on JSX-bearing source, which `default_syntax()` (plain ECMAScript, no + /// JSX) can't parse. Tests exercising those rules use this instead. + fn tsx_syntax() -> Syntax { + Syntax::Typescript(TsSyntax { + tsx: true, + decorators: true, + ..Default::default() + }) + } + + #[test] + fn reports_ref_access_error_with_default_syntax() { + let source = r#" + import { useRef } from 'react'; + + function App() { + const ref = useRef(1); + return ref.current; + } + "#; + + let diagnostics = lint_inner(source, default_syntax()); + + assert_eq!(diagnostics.len(), 1); + assert_eq!(diagnostics[0].severity, "error"); + assert_eq!(diagnostics[0].rule_id.as_deref(), Some("refs")); + assert_eq!(diagnostics[0].category.as_deref(), Some("Refs")); + } + + #[test] + fn returns_empty_for_non_react_code() { + let diagnostics = lint_inner("const x = 1;", default_syntax()); + + assert!(diagnostics.is_empty()); + } + + /// One test per documented React Compiler lint rule + /// (https://react.dev/reference/eslint-plugin-react-hooks) that a + /// hand-written source snippet can reliably trigger. Every trigger + /// condition here was verified empirically against the actual compiled + /// binary before being written as a test — not guessed. Rules not + /// covered below either require configuration this crate deliberately + /// doesn't expose (`config`, `gating`: need explicit gating directives; + /// `purity`: `validate_no_impure_functions_in_render` defaults to + /// `false` upstream) or need more investigation to find a reliable + /// trigger (`error-boundaries`, `static-components`, + /// `set-state-in-effect`, `incompatible-library`). + mod documented_rule_coverage { + use super::{lint_inner, tsx_syntax}; + + fn assert_fires(source: &str, expected_rule_id: &str) { + let diagnostics = lint_inner(source, tsx_syntax()); + + assert!( + diagnostics + .iter() + .any(|d| d.rule_id.as_deref() == Some(expected_rule_id)), + "expected a `{expected_rule_id}` diagnostic, got: {diagnostics:#?}" + ); + } + + #[test] + fn globals() { + assert_fires( + r#" + let count = 0; + function App() { + const [x] = useState(0); + count = count + 1; + return
{count}{x}
; + } + "#, + "globals", + ); + } + + #[test] + fn immutability() { + assert_fires( + r#" + function App(props) { + const [x, setX] = useState(0); + props.value = 1; + return
setX(x + 1)}>{x}
; + } + "#, + "immutability", + ); + } + + #[test] + fn use_memo() { + assert_fires( + r#" + function App() { + const value = useMemo((extra) => extra, [1]); + return
{value}
; + } + "#, + "use-memo", + ); + } + + #[test] + fn set_state_in_render() { + assert_fires( + r#" + function App() { + const [state, setState] = useState(0); + setState(state + 1); + return
{state}
; + } + "#, + "set-state-in-render", + ); + } + + #[test] + fn unsupported_syntax() { + assert_fires( + r#" + function App() { + eval('1'); + return
; + } + "#, + "unsupported-syntax", + ); + } + } + + #[test] + fn decode_syntax_decodes_ecmascript_json() { + let syntax = decode_syntax(br#"{"syntax":"ecmascript","jsx":true}"#) + .expect("valid ecmascript syntax JSON should decode"); + + assert_eq!( + syntax, + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + }) + ); + } + + #[test] + fn decode_syntax_rejects_invalid_json() { + let result = decode_syntax(b"not json"); + + assert!(result.is_err()); + } +} diff --git a/deps/swc/bindings/binding_react_compiler_node/src/support.rs b/deps/swc/bindings/binding_react_compiler_node/src/support.rs index 9d3e2f2b3..730372efe 100644 --- a/deps/swc/bindings/binding_react_compiler_node/src/support.rs +++ b/deps/swc/bindings/binding_react_compiler_node/src/support.rs @@ -26,6 +26,7 @@ fn is_react_compiler_required_inner(code: &str) -> bool { let cm = Lrc::new(SourceMap::default()); let fm = cm.new_source_file(FileName::Anon.into(), code.to_string()); + let mut recovered_errors = Vec::new(); let program = swc_core::ecma::parser::parse_file_as_program( &fm, Syntax::Typescript(swc_core::ecma::parser::TsSyntax { @@ -35,13 +36,17 @@ fn is_react_compiler_required_inner(code: &str) -> bool { }), EsVersion::latest(), None, - &mut vec![], + &mut recovered_errors, ); let Ok(program) = program else { - return false; + return true; }; + if !recovered_errors.is_empty() { + return true; + } + swc_ecma_react_compiler::fast_check::is_required(&program) } @@ -63,3 +68,37 @@ pub fn is_react_compiler_required_sync(code: Buffer) -> napi::Result { Ok(is_react_compiler_required_inner(&code)) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn recovered_parse_errors_are_conservative() { + let code = "return 1;"; + let cm = Lrc::new(SourceMap::default()); + let fm = cm.new_source_file(FileName::Anon.into(), code.to_string()); + let mut recovered_errors = Vec::new(); + let program = swc_core::ecma::parser::parse_file_as_program( + &fm, + Syntax::Typescript(swc_core::ecma::parser::TsSyntax { + decorators: true, + tsx: true, + ..Default::default() + }), + EsVersion::latest(), + None, + &mut recovered_errors, + ); + + assert!( + program.is_ok(), + "the regression requires a recovered rather than fatal parse error" + ); + assert!( + !recovered_errors.is_empty(), + "the regression requires at least one recovered parse error" + ); + assert!(is_react_compiler_required_inner(code)); + } +} diff --git a/deps/swc/bindings/binding_typescript_wasm/Cargo.toml b/deps/swc/bindings/binding_typescript_wasm/Cargo.toml index 922980b92..617a021c8 100644 --- a/deps/swc/bindings/binding_typescript_wasm/Cargo.toml +++ b/deps/swc/bindings/binding_typescript_wasm/Cargo.toml @@ -6,7 +6,7 @@ license = { workspace = true } name = "binding_typescript_wasm" publish = false repository = { workspace = true } -version = "1.15.43" +version = "1.16.0" [lib] bench = false diff --git a/deps/swc/bindings/binding_typescript_wasm/src/lib.rs b/deps/swc/bindings/binding_typescript_wasm/src/lib.rs index ffc93e641..8d0ab76c8 100644 --- a/deps/swc/bindings/binding_typescript_wasm/src/lib.rs +++ b/deps/swc/bindings/binding_typescript_wasm/src/lib.rs @@ -77,7 +77,8 @@ fn operate(input: String, options: Options) -> Result>>, - reporter: SwcReportHandler, + /// Successful transforms never need the graphical diagnostic reporter. + reporter: Option, cm: Lrc, } @@ -87,25 +88,7 @@ where { let wr = JsonErrorWriter { errors: Default::default(), - reporter: SwcReportHandler::default().with_theme(GraphicalTheme { - characters: ThemeCharacters { - hbar: ' ', - vbar: ' ', - xbar: ' ', - vbar_break: ' ', - ltop: ' ', - rtop: ' ', - mtop: ' ', - lbot: ' ', - rbot: ' ', - mbot: ' ', - error: "".into(), - warning: "".into(), - advice: "".into(), - ..ThemeCharacters::ascii() - }, - styles: ThemeStyles::none(), - }), + reporter: None, cm, }; let emitter: Box = Box::new(wr.clone()); @@ -130,7 +113,8 @@ impl Emitter for JsonErrorWriter { let snippet = d.span.primary_span().and_then(|span| { let mut snippet = String::new(); - match self.reporter.render_report( + let reporter = self.reporter.get_or_insert_with(json_reporter); + match reporter.render_report( &mut snippet, &Snippet { source_code: &to_pretty_source_code(&self.cm, true), @@ -186,6 +170,28 @@ impl Emitter for JsonErrorWriter { } } +fn json_reporter() -> SwcReportHandler { + SwcReportHandler::default().with_theme(GraphicalTheme { + characters: ThemeCharacters { + hbar: ' ', + vbar: ' ', + xbar: ' ', + vbar_break: ' ', + ltop: ' ', + rtop: ' ', + mtop: ' ', + lbot: ' ', + rbot: ' ', + mbot: ' ', + error: "".into(), + warning: "".into(), + advice: "".into(), + ..ThemeCharacters::ascii() + }, + styles: ThemeStyles::none(), + }) +} + #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct JsonDiagnostic { diff --git a/deps/swc/bindings/swc_cli/Cargo.toml b/deps/swc/bindings/swc_cli/Cargo.toml index 0447ac4eb..cab8d90c5 100644 --- a/deps/swc/bindings/swc_cli/Cargo.toml +++ b/deps/swc/bindings/swc_cli/Cargo.toml @@ -6,7 +6,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_cli" repository = { workspace = true } -version = "0.116.3" +version = "0.122.2" [[bin]] bench = false @@ -20,4 +20,4 @@ plugin = ["swc_cli_impl/plugin"] [dependencies] anyhow = { workspace = true } par-core = { workspace = true, features = ["chili"] } -swc_cli_impl = { version = "71.0.0", path = "../../crates/swc_cli_impl" } +swc_cli_impl = { version = "77.0.0", path = "../../crates/swc_cli_impl" } diff --git a/deps/swc/crates/ast_node/Cargo.toml b/deps/swc/crates/ast_node/Cargo.toml index bb4d94aba..dbf0d099b 100644 --- a/deps/swc/crates/ast_node/Cargo.toml +++ b/deps/swc/crates/ast_node/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "ast_node" repository = { workspace = true } -version = "5.0.0" +version = "7.0.0" [lib] bench = false diff --git a/deps/swc/crates/ast_node/src/ast_node_macro.rs b/deps/swc/crates/ast_node/src/ast_node_macro.rs index 1b76b3dfa..faabde72d 100644 --- a/deps/swc/crates/ast_node/src/ast_node_macro.rs +++ b/deps/swc/crates/ast_node/src/ast_node_macro.rs @@ -7,11 +7,29 @@ use syn::{ #[derive(Clone)] pub struct Args { pub ty: Literal, + pub no_partial_eq: bool, } impl Parse for Args { fn parse(i: ParseStream<'_>) -> syn::Result { - Ok(Args { ty: i.parse()? }) + let ty = i.parse()?; + let mut no_partial_eq = false; + + if i.parse::>()?.is_some() { + let option: Ident = i.parse()?; + + if option == "no_partial_eq" { + no_partial_eq = true; + } else { + return Err(Error::new(option.span(), "unknown ast_node option")); + } + } + + if !i.is_empty() { + return Err(i.error("unexpected ast_node arguments")); + } + + Ok(Args { ty, no_partial_eq }) } } diff --git a/deps/swc/crates/ast_node/src/encoding/decode.rs b/deps/swc/crates/ast_node/src/encoding/decode.rs index e67ee3022..61b404bac 100644 --- a/deps/swc/crates/ast_node/src/encoding/decode.rs +++ b/deps/swc/crates/ast_node/src/encoding/decode.rs @@ -40,7 +40,11 @@ pub fn expand(DeriveInput { ident, data, .. }: DeriveInput) -> syn::ItemImpl { syn::parse_quote! { #ident ( #(#names),* ) } }; - let count = data.fields.len(); + let count = data + .fields + .iter() + .filter(|field| !is_ignore(&field.attrs)) + .count(); let head: Option = (count != 1).then(|| { syn::parse_quote! { let len = >::len(reader)?.unwrap(); @@ -193,7 +197,7 @@ pub fn expand(DeriveInput { ident, data, .. }: DeriveInput) -> syn::ItemImpl { } }) .collect::>(); - let count = field.fields.len(); + let count = names.len(); let stmt = field.fields.iter() .zip(names.iter()) diff --git a/deps/swc/crates/ast_node/src/encoding/encode.rs b/deps/swc/crates/ast_node/src/encoding/encode.rs index e4485f743..107f69982 100644 --- a/deps/swc/crates/ast_node/src/encoding/encode.rs +++ b/deps/swc/crates/ast_node/src/encoding/encode.rs @@ -28,8 +28,9 @@ pub fn expand(DeriveInput { ident, data, .. }: DeriveInput) -> syn::ItemImpl { cbor4ii::core::enc::Encode::encode(&#fieldpath, writer)?; }, } - }); - let count = data.fields.len(); + }) + .collect::>(); + let count = fields.len(); let head: Option = (count != 1).then(|| { syn::parse_quote! { >::bounded(#count, writer)?; diff --git a/deps/swc/crates/ast_node/src/lib.rs b/deps/swc/crates/ast_node/src/lib.rs index 351afe17e..f2177dba0 100644 --- a/deps/swc/crates/ast_node/src/lib.rs +++ b/deps/swc/crates/ast_node/src/lib.rs @@ -5,7 +5,7 @@ extern crate proc_macro; use quote::quote; use swc_macros_common::prelude::*; -use syn::{visit_mut::VisitMut, *}; +use syn::*; mod ast_node_macro; mod encoding; @@ -151,19 +151,11 @@ pub fn ast_serde( print("ast_serde", item) } -struct AddAttr; - -impl VisitMut for AddAttr { - fn visit_field_mut(&mut self, f: &mut Field) { - f.attrs - .push(parse_quote!(#[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))])); - } -} - -/// Alias for -/// `#[derive(Spanned, Fold, Clone, Debug, PartialEq)]` for a struct and -/// `#[derive(Spanned, Fold, Clone, Debug, PartialEq, FromVariant)]` for an -/// enum. +/// Adds the standard AST node derives and serialization metadata. +/// +/// Structs derive `PartialEq` by default. Pass `no_partial_eq` after the node +/// tag when the type provides a manual implementation: +/// `#[ast_node("CustomNode", no_partial_eq)]`. #[proc_macro_attribute] pub fn ast_node( args: proc_macro::TokenStream, @@ -171,8 +163,6 @@ pub fn ast_node( ) -> proc_macro::TokenStream { let mut input: DeriveInput = parse(input).expect("failed to parse input as a DeriveInput"); - AddAttr.visit_data_mut(&mut input.data); - // we should use call_site let mut item = TokenStream::new(); match &input.data { @@ -252,27 +242,6 @@ pub fn ast_node( )] #clone #non_exhaustive - #[cfg_attr( - feature = "rkyv-impl", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) - )] - #[cfg_attr( - feature = "rkyv-impl", - rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source)) - )] - #[cfg_attr(feature = "rkyv-impl", repr(u32))] - #[cfg_attr( - feature = "rkyv-impl", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) - )] - #[cfg_attr( - feature = "rkyv-impl", - rkyv(bytecheck(bounds( - __C: rkyv::validation::ArchiveContext, - __C::Error: rkyv::rancor::Source - ))) - )] #[cfg_attr( feature = "serde-impl", serde(untagged) @@ -321,34 +290,18 @@ pub fn ast_node( .as_ref() .map(|args| ast_node_macro::expand_struct(args.clone(), input.clone())); + let partial_eq = match &args { + Some(args) if args.no_partial_eq => None, + _ => Some(quote!(PartialEq,)), + }; + item.extend(quote!( #[allow(clippy::derive_partial_eq_without_eq)] - #[derive(::swc_common::Spanned, Clone, Debug, PartialEq)] + #[derive(::swc_common::Spanned, Clone, Debug, #partial_eq)] #[cfg_attr( feature = "serde-impl", derive(::serde::Serialize, ::serde::Deserialize) )] - #[cfg_attr( - feature = "rkyv-impl", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) - )] - #[cfg_attr( - feature = "rkyv-impl", - rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source)) - )] - #[cfg_attr( - feature = "rkyv-impl", - rkyv(bytecheck(bounds( - __C: rkyv::validation::ArchiveContext, - __C::Error: rkyv::rancor::Source - ))) - )] - #[cfg_attr(feature = "rkyv-impl", repr(C))] - #[cfg_attr( - feature = "rkyv-impl", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) - )] #serde_tag #[cfg_attr( feature = "serde-impl", diff --git a/deps/swc/crates/binding_macros/Cargo.toml b/deps/swc/crates/binding_macros/Cargo.toml index bae521da1..9a149465b 100644 --- a/deps/swc/crates/binding_macros/Cargo.toml +++ b/deps/swc/crates/binding_macros/Cargo.toml @@ -5,7 +5,7 @@ edition = { workspace = true } license = { workspace = true } name = "binding_macros" repository = { workspace = true } -version = "69.0.0" +version = "75.0.0" [lib] bench = false @@ -33,11 +33,11 @@ binding_wasm = [ [dependencies] # Common deps for the SWC imports -swc = { optional = true, version = "69.0.0", path = "../swc", default-features = false } -swc_common = { optional = true, version = "23.0.2", path = "../swc_common", default-features = false } -swc_ecma_ast = { optional = true, version = "25.0.0", path = "../swc_ecma_ast", default-features = false } -swc_ecma_transforms = { optional = true, version = "56.0.0", path = "../swc_ecma_transforms", default-features = false } -swc_ecma_visit = { optional = true, version = "25.0.0", path = "../swc_ecma_visit", default-features = false } +swc = { optional = true, version = "75.0.0", path = "../swc", default-features = false } +swc_common = { optional = true, version = "26.0.0", path = "../swc_common", default-features = false } +swc_ecma_ast = { optional = true, version = "29.0.0", path = "../swc_ecma_ast", default-features = false } +swc_ecma_transforms = { optional = true, version = "62.0.0", path = "../swc_ecma_transforms", default-features = false } +swc_ecma_visit = { optional = true, version = "29.0.0", path = "../swc_ecma_visit", default-features = false } # Optional deps for the wasm binding macro anyhow = { workspace = true, optional = true } diff --git a/deps/swc/crates/dbg-swc/Cargo.toml b/deps/swc/crates/dbg-swc/Cargo.toml index 98ed5e53e..4d0bec596 100644 --- a/deps/swc/crates/dbg-swc/Cargo.toml +++ b/deps/swc/crates/dbg-swc/Cargo.toml @@ -5,7 +5,7 @@ edition = { workspace = true } license = { workspace = true } name = "dbg-swc" repository = { workspace = true } -version = "57.0.0" +version = "62.0.0" [[bin]] bench = false @@ -22,22 +22,22 @@ rayon = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } sha1 = { workspace = true } -swc_common = { version = "23.0.2", features = [ +swc_common = { version = "26.0.0", features = [ "concurrent", "tty-emitter", ], path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_minifier = { version = "56.0.1", path = "../swc_ecma_minifier", features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_minifier = { version = "61.0.0", path = "../swc_ecma_minifier", features = [ "concurrent", ] } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", features = [ +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", features = [ "flow", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_typescript = { version = "50.0.0", path = "../swc_ecma_transforms_typescript" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } -swc_error_reporters = { version = "25.0.0", path = "../swc_error_reporters" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_typescript = { version = "55.0.0", path = "../swc_ecma_transforms_typescript" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } +swc_error_reporters = { version = "28.0.0", path = "../swc_error_reporters" } tempfile = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["fmt", "env-filter"] } diff --git a/deps/swc/crates/hstr/Cargo.toml b/deps/swc/crates/hstr/Cargo.toml index ef9b3e381..64c9afcca 100644 --- a/deps/swc/crates/hstr/Cargo.toml +++ b/deps/swc/crates/hstr/Cargo.toml @@ -5,7 +5,7 @@ edition = { workspace = true } license = { workspace = true } name = "hstr" repository = { workspace = true } -version = "3.0.6" +version = "4.0.1" [lib] bench = false @@ -14,14 +14,12 @@ bench = false [features] atom_size_128 = [] atom_size_64 = [] -rkyv = ["dep:rkyv"] serde = ["dep:serde"] [dependencies] hashbrown = { workspace = true } new_debug_unreachable = { workspace = true } once_cell = { workspace = true } -rkyv = { workspace = true, optional = true } rustc-hash = { workspace = true } serde = { workspace = true, optional = true } triomphe = { workspace = true } @@ -35,7 +33,6 @@ num_cpus = { workspace = true } par-iter = { workspace = true } rand = { workspace = true } serde_json = { workspace = true } -smartstring = { workspace = true } smol_str = { workspace = true } string_cache = { workspace = true } diff --git a/deps/swc/crates/hstr/benches/libs.rs b/deps/swc/crates/hstr/benches/libs.rs index f5ca6621c..2d781e3de 100644 --- a/deps/swc/crates/hstr/benches/libs.rs +++ b/deps/swc/crates/hstr/benches/libs.rs @@ -11,7 +11,6 @@ use criterion::{black_box, BatchSize, BenchmarkId, Criterion}; use par_iter::prelude::*; use rand::distributions::{Alphanumeric, DistString}; use rustc_hash::FxHashSet; -use smartstring::{LazyCompact, SmartString}; macro_rules! string_creation { ($group:expr, $len:expr, $setup:expr) => {{ @@ -62,16 +61,6 @@ macro_rules! string_creation { ); }); - group.bench_with_input(BenchmarkId::new("smartstring", len), &len, |b, _| { - b.iter_batched( - $setup(len), - |text| { - black_box(SmartString::::from(text)); - }, - BatchSize::SmallInput, - ); - }); - group.bench_with_input(BenchmarkId::new("smol_str", len), &len, |b, _| { b.iter_batched( $setup(len), @@ -214,17 +203,6 @@ fn bench_hash_operation(c: &mut Criterion) { BatchSize::SmallInput, ); }); - group.bench_with_input(BenchmarkId::new("smartstring", len), &len, |b, _| { - b.iter_batched( - || prepare(len, &mut SmartString::::from), - |(map, keys)| { - for key in keys { - black_box(map.contains(&key)); - } - }, - BatchSize::SmallInput, - ); - }); group.bench_with_input(BenchmarkId::new("smol_str", len), &len, |b, _| { b.iter_batched( || prepare(len, &mut smol_str::SmolStr::from), diff --git a/deps/swc/crates/hstr/src/lib.rs b/deps/swc/crates/hstr/src/lib.rs index c643dd181..66dbb043f 100644 --- a/deps/swc/crates/hstr/src/lib.rs +++ b/deps/swc/crates/hstr/src/lib.rs @@ -6,7 +6,7 @@ use std::{ borrow::Borrow, fmt::{Debug, Display}, hash::Hash, - mem::{self, forget, transmute, ManuallyDrop}, + mem::{forget, transmute, ManuallyDrop}, num::NonZeroU8, ops::Deref, str::from_utf8_unchecked, @@ -221,11 +221,12 @@ impl Atom { impl Atom { fn from_mutated_str(s: &str, f: F) -> Self { - let mut buffer = mem::MaybeUninit::<[u8; 64]>::uninit(); - let buffer = unsafe { &mut *buffer.as_mut_ptr() }; + let mut buffer = [0u8; 64]; if let Some(buffer_prefix) = buffer.get_mut(..s.len()) { buffer_prefix.copy_from_slice(s.as_bytes()); + // SAFETY: `buffer_prefix` was just initialized from `s`, which is + // valid UTF-8. `f` receives a `str`, so it must preserve UTF-8. let as_str = unsafe { ::std::str::from_utf8_unchecked_mut(buffer_prefix) }; f(as_str); Atom::from(&*as_str) @@ -408,39 +409,6 @@ impl Borrow for Atom { } } -/// NOT A PUBLIC API -#[cfg(feature = "rkyv")] -impl rkyv::Archive for Atom { - type Archived = rkyv::string::ArchivedString; - type Resolver = rkyv::string::StringResolver; - - #[allow(clippy::unit_arg)] - unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) { - rkyv::string::ArchivedString::resolve_from_str(self, pos, resolver, out) - } -} - -/// NOT A PUBLIC API -#[cfg(feature = "rkyv")] -impl rkyv::Serialize for Atom { - fn serialize(&self, serializer: &mut S) -> Result { - String::serialize(&self.to_string(), serializer) - } -} - -/// NOT A PUBLIC API -#[cfg(feature = "rkyv")] -impl rkyv::Deserialize for rkyv::string::ArchivedString -where - D: ?Sized + rkyv::Fallible, -{ - fn deserialize(&self, deserializer: &mut D) -> Result::Error> { - let s: String = self.deserialize(deserializer)?; - - Ok(Atom::new(s)) - } -} - impl Atom { /// Converts a WTF-8 encoded [Wtf8Atom] to a regular UTF-8 [Atom] without /// validation. diff --git a/deps/swc/crates/hstr/src/wtf8/mod.rs b/deps/swc/crates/hstr/src/wtf8/mod.rs index 020408973..12bca81a5 100644 --- a/deps/swc/crates/hstr/src/wtf8/mod.rs +++ b/deps/swc/crates/hstr/src/wtf8/mod.rs @@ -1081,6 +1081,33 @@ mod tests { assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); } + #[test] + fn wtf8buf_push_code_points_of_each_encoded_width() { + fn code_point(value: u32) -> CodePoint { + CodePoint::from_u32(value).unwrap() + } + + let mut string = Wtf8Buf::new(); + + string.push(code_point(0x7f)); + assert_eq!(string.bytes, b"\x7f"); + + string.push(code_point(0x80)); + assert_eq!(string.bytes, b"\x7f\xc2\x80"); + + string.push(code_point(0x800)); + assert_eq!(string.bytes, b"\x7f\xc2\x80\xe0\xa0\x80"); + + string.push(code_point(0xd800)); + assert_eq!(string.bytes, b"\x7f\xc2\x80\xe0\xa0\x80\xed\xa0\x80"); + + string.push(code_point(0x10000)); + assert_eq!( + string.bytes, + b"\x7f\xc2\x80\xe0\xa0\x80\xed\xa0\x80\xf0\x90\x80\x80" + ); + } + #[test] fn wtf8buf_push() { let mut string = Wtf8Buf::from_str("aé "); diff --git a/deps/swc/crates/hstr/src/wtf8/not_quite_std.rs b/deps/swc/crates/hstr/src/wtf8/not_quite_std.rs index d8e701241..3aa5c7e3f 100644 --- a/deps/swc/crates/hstr/src/wtf8/not_quite_std.rs +++ b/deps/swc/crates/hstr/src/wtf8/not_quite_std.rs @@ -13,7 +13,11 @@ //! Maybe by having private generic code that is monomorphized to UTF-8 and //! WTF-8? -use core::{char, mem, slice}; +use core::{ + char, + mem::{self, MaybeUninit}, + slice, +}; use super::{CodePoint, IllFormedUtf16CodeUnits, Wtf8, Wtf8Buf}; @@ -27,27 +31,31 @@ const MAX_ONE_B: u32 = 0x80; const MAX_TWO_B: u32 = 0x800; const MAX_THREE_B: u32 = 0x10000; -/// Copied from 48d5fe9ec560b53b1f5069219b0d62015e1de5ba^:src/libcore/char.rs +/// Encode a code point into potentially uninitialized storage. +/// +/// On success, exactly the first returned number of elements in `dst` are +/// initialized. Copied from +/// 48d5fe9ec560b53b1f5069219b0d62015e1de5ba^:src/libcore/char.rs. #[inline] -fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> Option { +fn encode_utf8_raw(code: u32, dst: &mut [MaybeUninit]) -> Option { // Marked #[inline] to allow llvm optimizing it away if code < MAX_ONE_B && !dst.is_empty() { - dst[0] = code as u8; + dst[0].write(code as u8); Some(1) } else if code < MAX_TWO_B && dst.len() >= 2 { - dst[0] = (code >> 6 & 0x1f) as u8 | TAG_TWO_B; - dst[1] = (code & 0x3f) as u8 | TAG_CONT; + dst[0].write((code >> 6 & 0x1f) as u8 | TAG_TWO_B); + dst[1].write((code & 0x3f) as u8 | TAG_CONT); Some(2) } else if code < MAX_THREE_B && dst.len() >= 3 { - dst[0] = (code >> 12 & 0x0f) as u8 | TAG_THREE_B; - dst[1] = (code >> 6 & 0x3f) as u8 | TAG_CONT; - dst[2] = (code & 0x3f) as u8 | TAG_CONT; + dst[0].write((code >> 12 & 0x0f) as u8 | TAG_THREE_B); + dst[1].write((code >> 6 & 0x3f) as u8 | TAG_CONT); + dst[2].write((code & 0x3f) as u8 | TAG_CONT); Some(3) } else if dst.len() >= 4 { - dst[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - dst[1] = (code >> 12 & 0x3f) as u8 | TAG_CONT; - dst[2] = (code >> 6 & 0x3f) as u8 | TAG_CONT; - dst[3] = (code & 0x3f) as u8 | TAG_CONT; + dst[0].write((code >> 18 & 0x07) as u8 | TAG_FOUR_B); + dst[1].write((code >> 12 & 0x3f) as u8 | TAG_CONT); + dst[2].write((code >> 6 & 0x3f) as u8 | TAG_CONT); + dst[3].write((code & 0x3f) as u8 | TAG_CONT); Some(4) } else { None @@ -136,11 +144,15 @@ pub fn push_code_point(string: &mut Wtf8Buf, code_point: CodePoint) { // This may use up to 4 bytes. string.reserve(4); + let used = { + let spare = string.bytes.spare_capacity_mut(); + encode_utf8_raw(code_point.to_u32(), &mut spare[..4]) + .expect("four bytes are sufficient to encode any code point") + }; + + // SAFETY: `reserve(4)` guarantees capacity for `cur_len + 4`, and + // `encode_utf8_raw` initialized exactly the first `used` spare bytes. unsafe { - // Attempt to not use an intermediate buffer by just pushing bytes - // directly onto this string. - let slice = slice::from_raw_parts_mut(string.bytes.as_mut_ptr().add(cur_len), 4); - let used = encode_utf8_raw(code_point.to_u32(), slice).unwrap_or(0); string.bytes.set_len(cur_len + used); } } diff --git a/deps/swc/crates/jsdoc/Cargo.toml b/deps/swc/crates/jsdoc/Cargo.toml index 6020feb31..5ba75bd78 100644 --- a/deps/swc/crates/jsdoc/Cargo.toml +++ b/deps/swc/crates/jsdoc/Cargo.toml @@ -7,19 +7,17 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "jsdoc" repository = { workspace = true } -version = "23.0.0" +version = "26.0.0" [lib] bench = false [features] -__rkyv = [] encoding-impl = [ "cbor4ii", "swc_atoms/encoding-impl", "swc_common/encoding-impl", ] -rkyv-impl = [] serde-impl = ["serde"] [lints.rust] @@ -30,10 +28,10 @@ cbor4ii = { workspace = true, features = ["use_std"], optional = true } nom = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } [dev-dependencies] dashmap = { workspace = true } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/preset_env_base/Cargo.toml b/deps/swc/crates/preset_env_base/Cargo.toml index 9577fd8eb..eeb0dbe1c 100644 --- a/deps/swc/crates/preset_env_base/Cargo.toml +++ b/deps/swc/crates/preset_env_base/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "preset_env_base" repository = { workspace = true } -version = "8.0.1" +version = "9.0.0" [lib] bench = false diff --git a/deps/swc/crates/swc-ast-explorer/Cargo.toml b/deps/swc/crates/swc-ast-explorer/Cargo.toml index 35ca42b8c..db5d91d39 100644 --- a/deps/swc/crates/swc-ast-explorer/Cargo.toml +++ b/deps/swc/crates/swc-ast-explorer/Cargo.toml @@ -18,10 +18,10 @@ anyhow = { workspace = true } clap = { version = "3", features = ["derive"] } owo-colors = { workspace = true } regex = { workspace = true } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_error_reporters = { version = "25.0.0", path = "../swc_error_reporters" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_error_reporters = { version = "28.0.0", path = "../swc_error_reporters" } [dev-dependencies] assert_cmd = { workspace = true } diff --git a/deps/swc/crates/swc/Cargo.toml b/deps/swc/crates/swc/Cargo.toml index d3517a76a..ea7fb7ad6 100644 --- a/deps/swc/crates/swc/Cargo.toml +++ b/deps/swc/crates/swc/Cargo.toml @@ -9,7 +9,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc" repository = { workspace = true } -version = "69.0.0" +version = "75.0.0" [lib] bench = false @@ -87,50 +87,50 @@ tracing = { workspace = true } url = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "sourcemap", "parking_lot", ] } -swc_compiler_base = { version = "59.0.0", path = "../swc_compiler_base" } -swc_config = { version = "5.0.0", path = "../swc_config" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_ext_transforms = { version = "31.0.0", path = "../swc_ecma_ext_transforms" } -swc_ecma_lints = { version = "33.0.0", path = "../swc_ecma_lints", optional = true } -swc_ecma_loader = { version = "24.0.1", path = "../swc_ecma_loader", features = [ +swc_compiler_base = { version = "64.0.0", path = "../swc_compiler_base" } +swc_config = { version = "6.0.0", path = "../swc_config" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_ext_transforms = { version = "35.0.0", path = "../swc_ecma_ext_transforms" } +swc_ecma_lints = { version = "37.0.0", path = "../swc_ecma_lints", optional = true } +swc_ecma_loader = { version = "27.0.0", path = "../swc_ecma_loader", features = [ "cache", "node", "tsc", ] } -swc_ecma_minifier = { version = "56.0.1", path = "../swc_ecma_minifier" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_ecma_minifier = { version = "61.0.0", path = "../swc_ecma_minifier" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_preset_env = { version = "57.0.0", path = "../swc_ecma_preset_env", default-features = false, features = [ +swc_ecma_preset_env = { version = "63.0.0", path = "../swc_ecma_preset_env", default-features = false, features = [ "serde-impl", ] } -swc_ecma_react_compiler = { version = "20.0.2", path = "../swc_ecma_react_compiler", optional = true } -swc_ecma_transforms = { version = "56.0.0", path = "../swc_ecma_transforms", features = [ +swc_ecma_react_compiler = { version = "24.0.0", path = "../swc_ecma_react_compiler", optional = true } +swc_ecma_transforms = { version = "62.0.0", path = "../swc_ecma_transforms", features = [ "compat", "optimization", "proposal", "react", "typescript", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_compat = { version = "52.0.1", path = "../swc_ecma_transforms_compat", default-features = false } -swc_ecma_transforms_module = { version = "49.0.1", path = "../swc_ecma_transforms_module", optional = true } -swc_ecma_transforms_optimization = { version = "47.0.1", path = "../swc_ecma_transforms_optimization" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } -swc_error_reporters = { version = "25.0.0", path = "../swc_error_reporters" } -swc_node_comments = { version = "24.0.0", path = "../swc_node_comments" } -swc_plugin_backend_wasmer = { version = "13.0.0", path = "../swc_plugin_backend_wasmer", optional = true, default-features = false } -swc_plugin_proxy = { version = "26.0.0", path = "../swc_plugin_proxy", optional = true } -swc_plugin_runner = { version = "30.0.0", path = "../swc_plugin_runner", optional = true, default-features = false } -swc_transform_common = { version = "17.0.0", path = "../swc_transform_common" } -swc_typescript = { version = "30.0.1", path = "../swc_typescript", optional = true } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_compat = { version = "57.0.0", path = "../swc_ecma_transforms_compat", default-features = false } +swc_ecma_transforms_module = { version = "55.0.0", path = "../swc_ecma_transforms_module", optional = true } +swc_ecma_transforms_optimization = { version = "52.0.0", path = "../swc_ecma_transforms_optimization" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } +swc_error_reporters = { version = "28.0.0", path = "../swc_error_reporters" } +swc_node_comments = { version = "27.0.0", path = "../swc_node_comments" } +swc_plugin_backend_wasmer = { version = "17.0.0", path = "../swc_plugin_backend_wasmer", optional = true, default-features = false } +swc_plugin_proxy = { version = "30.0.0", path = "../swc_plugin_proxy", optional = true } +swc_plugin_runner = { version = "34.0.0", path = "../swc_plugin_runner", optional = true, default-features = false } +swc_transform_common = { version = "20.0.0", path = "../swc_transform_common" } +swc_typescript = { version = "34.0.0", path = "../swc_typescript", optional = true } swc_visit = { version = "2.0.1", path = "../swc_visit" } [dependencies.tokio] @@ -156,24 +156,24 @@ par-core = { workspace = true, features = ["chili"] } tempfile = { workspace = true } walkdir = { workspace = true } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast", features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast", features = [ "serde-impl", ] } -swc_ecma_lints = { version = "33.0.0", path = "../swc_ecma_lints", features = [ +swc_ecma_lints = { version = "37.0.0", path = "../swc_ecma_lints", features = [ "non_critical_lints", ] } -swc_ecma_preset_env = { version = "57.0.0", path = "../swc_ecma_preset_env", features = [ +swc_ecma_preset_env = { version = "63.0.0", path = "../swc_ecma_preset_env", features = [ "es3", ] } -swc_ecma_testing = { version = "24.0.1", path = "../swc_ecma_testing" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base", features = [ +swc_ecma_testing = { version = "27.0.0", path = "../swc_ecma_testing" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base", features = [ "inline-helpers", ] } -swc_ecma_transforms_compat = { version = "52.0.1", path = "../swc_ecma_transforms_compat", features = [ +swc_ecma_transforms_compat = { version = "57.0.0", path = "../swc_ecma_transforms_compat", features = [ "es3", ] } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } [[example]] name = "transform" diff --git a/deps/swc/crates/swc/examples/node_counter.rs b/deps/swc/crates/swc/examples/node_counter.rs index 4210b2709..51c757e71 100644 --- a/deps/swc/crates/swc/examples/node_counter.rs +++ b/deps/swc/crates/swc/examples/node_counter.rs @@ -43,7 +43,7 @@ macro_rules! node_ref_variants { BinaryOp, BindingIdent, BlockStmt, - BlockStmtOrExpr, + ArrowFunctionBody, Bool, BreakStmt, CallExpr, @@ -83,6 +83,7 @@ macro_rules! node_ref_variants { ForOfStmt, ForStmt, Function, + FunctionBody, GetterProp, Ident, IdentName, @@ -227,6 +228,7 @@ macro_rules! node_ref_variants { TsRestType, TsSatisfiesExpr, TsSetterSignature, + TsThisParam, TsThisType, TsThisTypeOrIdent, TsTplLitType, diff --git a/deps/swc/crates/swc/src/builder.rs b/deps/swc/crates/swc/src/builder.rs index 0cd9866db..653661239 100644 --- a/deps/swc/crates/swc/src/builder.rs +++ b/deps/swc/crates/swc/src/builder.rs @@ -55,7 +55,7 @@ impl Pass for MinifierPass<'_> { n.visit_mut_with(&mut hygiene_with_config( swc_ecma_transforms_base::hygiene::Config { top_level_mark: self.top_level_mark, - ..Default::default() + ..swc_ecma_transforms_base::hygiene::Config::hygiene_default() }, )); diff --git a/deps/swc/crates/swc/src/config/mod.rs b/deps/swc/crates/swc/src/config/mod.rs index 7ad7a71ac..3a0a6d616 100644 --- a/deps/swc/crates/swc/src/config/mod.rs +++ b/deps/swc/crates/swc/src/config/mod.rs @@ -603,9 +603,9 @@ impl Options { Some(ModuleConfig::Es6(..)) => TsImportExportAssignConfig::EsNext, Some(ModuleConfig::CommonJs(..)) | Some(ModuleConfig::Amd(..)) - | Some(ModuleConfig::Umd(..)) => TsImportExportAssignConfig::Preserve, + | Some(ModuleConfig::Umd(..)) + | Some(ModuleConfig::SystemJs(..)) => TsImportExportAssignConfig::Preserve, Some(ModuleConfig::NodeNext(..)) => TsImportExportAssignConfig::NodeNext, - // TODO: should Preserve for SystemJS _ => TsImportExportAssignConfig::Classic, }; @@ -652,7 +652,7 @@ impl Options { } else { Some(hygiene::Config { keep_class_names, - ..Default::default() + ..hygiene::Config::hygiene_default() }) }; let env = cfg.env.map(Into::into); @@ -702,6 +702,8 @@ impl Options { .map(|v| v.mangle.is_obj() || v.mangle.is_true()) .unwrap_or(false); + let jsx_preserve = transform.react.runtime == Some(react::Runtime::Preserve); + #[cfg(feature = "module")] let rewrite_import_pass: Box = { let swc_import_rewriter: Box = match resolver.clone() { @@ -715,7 +717,7 @@ impl Options { }; let typescript_import_rewriter = Optional::new( - modules::rewriter::typescript_import_rewriter(), + modules::rewriter::typescript_import_rewriter(jsx_preserve), rewrite_relative_import_extensions.into_bool(), ); @@ -791,7 +793,9 @@ impl Options { Optional::new( hygiene_with_config(swc_ecma_transforms_base::hygiene::Config { top_level_mark, - ..hygiene_config.clone().unwrap_or_default() + ..hygiene_config + .clone() + .unwrap_or_else(hygiene::Config::hygiene_default) }), hygiene_config.is_some() && !is_mangler_enabled, ), @@ -878,8 +882,7 @@ impl Options { { plugin_transforms.unwrap() } else { - let jsx_enabled = - syntax.jsx() && transform.react.runtime != Some(react::Runtime::Preserve); + let jsx_enabled = syntax.jsx() && !jsx_preserve; let decorator_pass: Box = match transform.decorator_version.unwrap_or_default() { @@ -1727,8 +1730,8 @@ impl ModuleConfig { Some(ModuleConfig::SystemJs(config)) => build_resolver( base_url, paths, - config.config.resolve_fully, - &config.config.out_file_extension, + config.resolve_fully, + &config.out_file_extension, preserve_symlinks, ), }; @@ -1813,8 +1816,8 @@ pub struct TransformConfig { /// Public `.swcrc` configuration for React Compiler. /// /// This intentionally mirrors only a curated subset of upstream -/// `PluginOptions`; the deep `environment` configuration is kept internal for -/// the first SWC integration. +/// `PluginOptions`. The nested `environment` object likewise exposes only a +/// curated subset of the compiler's environment configuration. #[derive(Debug, Default, Clone, Serialize, Deserialize, Merge)] #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct ReactCompilerConfig { @@ -1856,6 +1859,9 @@ pub struct ReactCompilerConfig { #[serde(default)] pub dynamic_gating: Option, + + #[serde(default)] + pub environment: Option, } #[cfg(feature = "react-compiler")] @@ -1907,6 +1913,9 @@ impl ReactCompilerConfig { if let Some(dynamic_gating) = self.dynamic_gating { options.dynamic_gating = Some(dynamic_gating.into()); } + if let Some(environment) = self.environment { + environment.apply_to(&mut options); + } options } @@ -2031,6 +2040,38 @@ impl From for swc_ecma_react_compiler::Dynamic } } +/// Curated subset of the React Compiler `environment` options exposed through +/// the SWC config, mirroring Babel's `reactCompiler.environment` object. +/// +/// Only fields wired end-to-end into the compiler are exposed here. A field +/// left unset (`None`) leaves the compiler default untouched, so a partial +/// object such as `{ "enableFunctionOutlining": false }` overrides only that +/// setting. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields, rename_all = "camelCase")] +pub struct ReactCompilerEnvironmentConfig { + /// Extract anonymous functions that do not close over local variables into + /// top-level helper functions. Maps to the compiler's + /// `environment.enable_function_outlining` (default `true`). + #[serde(default)] + pub enable_function_outlining: Option, +} + +#[cfg(feature = "react-compiler")] +impl ReactCompilerEnvironmentConfig { + /// Apply the set (`Some`) overrides onto the compiler options' environment, + /// leaving unset fields at their existing (default) values. + /// + /// This mutates the public `environment` field in place rather than naming + /// the upstream `EnvironmentConfig` type, so the config layer does not + /// require that type to be re-exported. + fn apply_to(self, options: &mut swc_ecma_react_compiler::PluginOptions) { + if let Some(enable_function_outlining) = self.enable_function_outlining { + options.environment.enable_function_outlining = enable_function_outlining; + } + } +} + #[cfg(feature = "react-compiler")] fn react_compiler_options( config: BoolOrDataConfig, diff --git a/deps/swc/crates/swc_allocator/Cargo.toml b/deps/swc/crates/swc_allocator/Cargo.toml index dfed6c906..55ea3b94c 100644 --- a/deps/swc/crates/swc_allocator/Cargo.toml +++ b/deps/swc/crates/swc_allocator/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_allocator" repository = { workspace = true } -version = "4.0.1" +version = "5.0.0" [package.metadata.docs.rs] all-features = true @@ -21,8 +21,7 @@ nightly = [ # The latest pinned nightly rejects the bumpalo/hashbrown/allocator-api2 # nightly-only allocator paths. Stable allocator-api2 support is sufficient # for our usage here. -# This two features are actually useless -rkyv = [] +# This feature is actually useless. serde = [] # This feature is used to suppress warnings about slowness caused by stable rustc. # It's recommended to use nightly rustc until the allocator APIs are stabilized. diff --git a/deps/swc/crates/swc_atoms/Cargo.toml b/deps/swc/crates/swc_atoms/Cargo.toml index 254a714bd..1bac4407b 100644 --- a/deps/swc/crates/swc_atoms/Cargo.toml +++ b/deps/swc/crates/swc_atoms/Cargo.toml @@ -6,26 +6,20 @@ edition = { workspace = true } license = { workspace = true } name = "swc_atoms" repository = { workspace = true } -version = "9.0.3" +version = "10.0.0" [lib] bench = false [features] -__rkyv = [] encoding-impl = ["cbor4ii"] -rkyv-impl = ["__rkyv", "rkyv", "bytecheck", "rancor"] shrink-to-fit = ["dep:shrink-to-fit"] [dependencies] -# bytecheck version should be in sync with rkyv version. Do not bump individually. arbitrary = { workspace = true, optional = true } -bytecheck = { workspace = true, optional = true } cbor4ii = { workspace = true, features = ["use_std"], optional = true } once_cell = { workspace = true } -rancor = { workspace = true, optional = true } -rkyv = { workspace = true, optional = true } serde = { workspace = true } shrink-to-fit = { workspace = true, optional = true } -hstr = { version = "3.0.6", path = "../hstr", features = ["serde"] } +hstr = { version = "4.0.1", path = "../hstr", features = ["serde"] } diff --git a/deps/swc/crates/swc_atoms/src/lib.rs b/deps/swc/crates/swc_atoms/src/lib.rs index 4d2391352..fa8f36caf 100644 --- a/deps/swc/crates/swc_atoms/src/lib.rs +++ b/deps/swc/crates/swc_atoms/src/lib.rs @@ -34,7 +34,6 @@ mod wtf8_atom; /// /// See [tendril] for more details. #[derive(Clone, Default)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] #[repr(transparent)] pub struct Atom(hstr::Atom); @@ -284,40 +283,6 @@ impl PartialEq for str { } } -/// NOT A PUBLIC API -#[cfg(feature = "rkyv-impl")] -impl rkyv::Archive for Atom { - type Archived = rkyv::string::ArchivedString; - type Resolver = rkyv::string::StringResolver; - - #[allow(clippy::unit_arg)] - fn resolve(&self, resolver: Self::Resolver, out: rkyv::Place) { - rkyv::string::ArchivedString::resolve_from_str(self, resolver, out) - } -} - -/// NOT A PUBLIC API -#[cfg(feature = "rkyv-impl")] -impl rkyv::Serialize for Atom -where - ::Error: rancor::Source, -{ - fn serialize(&self, serializer: &mut S) -> Result { - rkyv::string::ArchivedString::serialize_from_str(self.as_str(), serializer) - } -} - -/// NOT A PUBLIC API -#[cfg(feature = "rkyv-impl")] -impl rkyv::Deserialize for rkyv::string::ArchivedString -where - D: ?Sized + rancor::Fallible, -{ - fn deserialize(&self, _: &mut D) -> Result::Error> { - Ok(Atom::new(self.as_str())) - } -} - #[doc(hidden)] pub type CahcedAtom = Lazy; diff --git a/deps/swc/crates/swc_atoms/src/wtf8_atom.rs b/deps/swc/crates/swc_atoms/src/wtf8_atom.rs index 47898822b..ddd08f2e4 100644 --- a/deps/swc/crates/swc_atoms/src/wtf8_atom.rs +++ b/deps/swc/crates/swc_atoms/src/wtf8_atom.rs @@ -14,7 +14,6 @@ use crate::Atom; /// /// See [tendril] for more details. #[derive(Clone, Default, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] #[repr(transparent)] pub struct Wtf8Atom(pub(super) hstr::Wtf8Atom); @@ -192,46 +191,6 @@ impl<'de> serde::de::Deserialize<'de> for Wtf8Atom { } } -/// NOT A PUBLIC API -#[cfg(feature = "rkyv-impl")] -impl rkyv::Archive for Wtf8Atom { - type Archived = rkyv::vec::ArchivedVec; - type Resolver = rkyv::vec::VecResolver; - - #[allow(clippy::unit_arg)] - fn resolve(&self, resolver: Self::Resolver, out: rkyv::Place) { - rkyv::vec::ArchivedVec::::resolve_from_slice(self.as_bytes(), resolver, out) - } -} - -/// NOT A PUBLIC API -#[cfg(feature = "rkyv-impl")] -impl rkyv::Serialize - for Wtf8Atom -where - ::Error: rancor::Source, -{ - fn serialize(&self, serializer: &mut S) -> Result { - rkyv::vec::ArchivedVec::::serialize_from_slice(self.as_bytes(), serializer) - } -} - -/// NOT A PUBLIC API -#[cfg(feature = "rkyv-impl")] -impl rkyv::Deserialize for rkyv::vec::ArchivedVec -where - D: ?Sized + rancor::Fallible, - ::Error: rancor::Source, -{ - fn deserialize(&self, _: &mut D) -> Result::Error> { - Ok(Wtf8Atom::new( - // SAFETY: `ArchivedVec` is guaranteed to be serialized with `Wtf8Atom` byte - // sequence. `Wtf8Atom` byte sequence is identical to `Wtf8` byte sequence. - unsafe { Wtf8::from_bytes_unchecked(self.as_slice()) }, - )) - } -} - /// noop #[cfg(feature = "shrink-to-fit")] impl shrink_to_fit::ShrinkToFit for Wtf8Atom { diff --git a/deps/swc/crates/swc_bundler/Cargo.toml b/deps/swc/crates/swc_bundler/Cargo.toml index 41be17431..b4b45e411 100644 --- a/deps/swc/crates/swc_bundler/Cargo.toml +++ b/deps/swc/crates/swc_bundler/Cargo.toml @@ -9,7 +9,7 @@ include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/**/*.js"] license = { workspace = true } name = "swc_bundler" repository = { workspace = true } -version = "51.0.1" +version = "56.0.0" [package.metadata.docs.rs] all-features = true @@ -40,18 +40,18 @@ relative-path = { workspace = true } rustc-hash = { workspace = true } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_loader = { version = "24.0.1", path = "../swc_ecma_loader" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_loader = { version = "27.0.0", path = "../swc_ecma_loader" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_optimization = { version = "47.0.1", path = "../swc_ecma_transforms_optimization" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_optimization = { version = "52.0.0", path = "../swc_ecma_transforms_optimization" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } swc_graph_analyzer = { version = "14.0.2", path = "../swc_graph_analyzer/" } [dev-dependencies] @@ -63,18 +63,18 @@ reqwest = { workspace = true, features = ["blocking"] } sha1 = { workspace = true } tempfile = { workspace = true } -swc_ecma_loader = { version = "24.0.1", path = "../swc_ecma_loader", features = [ +swc_ecma_loader = { version = "27.0.0", path = "../swc_ecma_loader", features = [ "node", "cache", ] } -swc_ecma_minifier = { version = "56.0.1", path = "../swc_ecma_minifier", features = [ +swc_ecma_minifier = { version = "61.0.0", path = "../swc_ecma_minifier", features = [ "concurrent", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base", features = [ +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base", features = [ "inline-helpers", ] } -swc_ecma_transforms_proposal = { version = "44.0.1", path = "../swc_ecma_transforms_proposal" } -swc_ecma_transforms_react = { version = "50.0.0", path = "../swc_ecma_transforms_react" } -swc_ecma_transforms_typescript = { version = "50.0.0", path = "../swc_ecma_transforms_typescript" } +swc_ecma_transforms_proposal = { version = "49.0.0", path = "../swc_ecma_transforms_proposal" } +swc_ecma_transforms_react = { version = "55.0.0", path = "../swc_ecma_transforms_react" } +swc_ecma_transforms_typescript = { version = "55.0.0", path = "../swc_ecma_transforms_typescript" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_bundler/src/bundler/chunk/cjs.rs b/deps/swc/crates/swc_bundler/src/bundler/chunk/cjs.rs index e91938ec8..8635f2328 100644 --- a/deps/swc/crates/swc_bundler/src/bundler/chunk/cjs.rs +++ b/deps/swc/crates/swc_bundler/src/bundler/chunk/cjs.rs @@ -132,7 +132,7 @@ fn wrap_module( ], decorators: Vec::new(), span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: dep.span, stmts: dep .body @@ -146,7 +146,6 @@ fn wrap_module( _ => panic!("unable to access unknown nodes"), }) .collect(), - ..Default::default() }), is_generator: false, is_async: false, diff --git a/deps/swc/crates/swc_bundler/src/bundler/chunk/computed_key.rs b/deps/swc/crates/swc_bundler/src/bundler/chunk/computed_key.rs index f64dfde3a..f9034da5d 100644 --- a/deps/swc/crates/swc_bundler/src/bundler/chunk/computed_key.rs +++ b/deps/swc/crates/swc_bundler/src/bundler/chunk/computed_key.rs @@ -142,10 +142,9 @@ where let module_fn: Expr = FnExpr { function: Box::new(Function { params: Default::default(), - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![return_stmt], - ..Default::default() }), is_generator: false, is_async, diff --git a/deps/swc/crates/swc_bundler/src/bundler/finalize.rs b/deps/swc/crates/swc_bundler/src/bundler/finalize.rs index abe38dce8..2c1527dc1 100644 --- a/deps/swc/crates/swc_bundler/src/bundler/finalize.rs +++ b/deps/swc/crates/swc_bundler/src/bundler/finalize.rs @@ -156,7 +156,7 @@ where // Properties of returned object let mut props = Vec::new(); - let mut body = BlockStmt { + let mut body = FunctionBody { span: module.span, stmts: module .body @@ -347,7 +347,6 @@ where } }) .collect(), - ..Default::default() }; body.stmts.push( ReturnStmt { diff --git a/deps/swc/crates/swc_cli_impl/Cargo.toml b/deps/swc/crates/swc_cli_impl/Cargo.toml index 944554b72..6de229fb8 100644 --- a/deps/swc/crates/swc_cli_impl/Cargo.toml +++ b/deps/swc/crates/swc_cli_impl/Cargo.toml @@ -6,7 +6,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_cli_impl" repository = { workspace = true } -version = "71.0.0" +version = "77.0.0" [[bin]] name = "swc" @@ -37,7 +37,7 @@ serde_json = { workspace = true, features = ["unbounded_depth"] } tracing = { workspace = true } walkdir = { workspace = true } -swc_core = { version = "71.0.3", features = [ +swc_core = { version = "77.0.0", features = [ "common_concurrent", "base_concurrent", "base_flow", diff --git a/deps/swc/crates/swc_common/Cargo.toml b/deps/swc/crates/swc_common/Cargo.toml index 467031a6c..1e5f67010 100644 --- a/deps/swc/crates/swc_common/Cargo.toml +++ b/deps/swc/crates/swc_common/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_common" repository = { workspace = true } -version = "23.0.2" +version = "26.0.0" [package.metadata.docs.rs] all-features = true @@ -26,7 +26,7 @@ concurrent = ["parking_lot"] debug = [] default = [] diagnostic-serde = [] -plugin-base = ["__plugin", "rkyv-impl", "diagnostic-serde"] +plugin-base = ["__plugin", "diagnostic-serde"] plugin-mode = ["__plugin_mode", "plugin-base"] plugin-rt = ["__plugin_rt", "plugin-base"] sourcemap = ["dep:swc_sourcemap"] @@ -36,16 +36,7 @@ plugin_transform_schema_vtest = [] tty-emitter = ["termcolor"] -__rkyv = [] encoding-impl = ["cbor4ii", "swc_atoms/encoding-impl"] -rkyv-impl = [ - "__rkyv", - "rkyv", - "swc_atoms/rkyv-impl", - "bytes-str/rkyv", - "bytecheck", - "rancor", -] shrink-to-fit = ["dep:shrink-to-fit", "swc_atoms/shrink-to-fit"] @@ -53,15 +44,12 @@ shrink-to-fit = ["dep:shrink-to-fit", "swc_atoms/shrink-to-fit"] [dependencies] anyhow = { workspace = true } arbitrary = { workspace = true, features = ["derive"], optional = true } -bytecheck = { workspace = true, optional = true } bytes-str = { workspace = true, features = ["serde"] } cbor4ii = { workspace = true, features = ["use_std"], optional = true } either = { workspace = true } num-bigint = { workspace = true } once_cell = { workspace = true } parking_lot = { workspace = true, optional = true } -rancor = { workspace = true, optional = true } -rkyv = { workspace = true, optional = true } rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } shrink-to-fit = { workspace = true, optional = true } @@ -72,10 +60,10 @@ tracing = { workspace = true } unicode-width = { workspace = true } url = { workspace = true } -ast_node = { version = "5.0.0", path = "../ast_node" } +ast_node = { version = "7.0.0", path = "../ast_node" } better_scoped_tls = { version = "1.0.1", path = "../better_scoped_tls" } from_variant = { version = "3.0.0", path = "../from_variant" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } swc_eq_ignore_macros = { version = "1.0.1", path = "../swc_eq_ignore_macros" } swc_visit = { version = "2.0.1", path = "../swc_visit" } diff --git a/deps/swc/crates/swc_common/src/cache.rs b/deps/swc/crates/swc_common/src/cache.rs index d943cb347..b2221f445 100644 --- a/deps/swc/crates/swc_common/src/cache.rs +++ b/deps/swc/crates/swc_common/src/cache.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use once_cell::sync::OnceCell; -/// Wrapper for [OnceCell] with support for [rkyv]. +/// Wrapper for [OnceCell]. #[derive(Clone, Debug)] pub struct CacheCell(OnceCell); @@ -31,86 +31,3 @@ impl Default for CacheCell { Self::new() } } - -#[cfg(feature = "rkyv-impl")] -mod rkyv_impl { - use std::hint::unreachable_unchecked; - - use rancor::Fallible; - use rkyv::{ - munge::munge, option::ArchivedOption, traits::NoUndef, Archive, Deserialize, Place, - Serialize, - }; - - use super::*; - - #[allow(dead_code)] - #[repr(u8)] - enum ArchivedOptionTag { - None, - Some, - } - - // SAFETY: `ArchivedOptionTag` is `repr(u8)` and so always consists of a single - // well-defined byte. - unsafe impl NoUndef for ArchivedOptionTag {} - - #[repr(C)] - struct ArchivedOptionVariantNone(ArchivedOptionTag); - - #[repr(C)] - struct ArchivedOptionVariantSome(ArchivedOptionTag, T); - - impl Archive for CacheCell { - type Archived = ArchivedOption; - type Resolver = Option; - - fn resolve(&self, resolver: Self::Resolver, out: Place) { - match resolver { - None => { - let out = unsafe { out.cast_unchecked::() }; - munge!(let ArchivedOptionVariantNone(tag) = out); - tag.write(ArchivedOptionTag::None); - } - Some(resolver) => { - let out = - unsafe { out.cast_unchecked::>() }; - munge!(let ArchivedOptionVariantSome(tag, out_value) = out); - tag.write(ArchivedOptionTag::Some); - - let value = if let Some(value) = self.get() { - value - } else { - unsafe { - unreachable_unchecked(); - } - }; - - value.resolve(resolver, out_value); - } - } - } - } - - impl, S: Fallible + ?Sized> Serialize for CacheCell { - fn serialize(&self, serializer: &mut S) -> Result { - self.get() - .map(|value| value.serialize(serializer)) - .transpose() - } - } - - impl Deserialize, D> for ArchivedOption - where - T: Archive, - T::Archived: Deserialize, - D: Fallible + ?Sized, - { - fn deserialize(&self, deserializer: &mut D) -> Result, D::Error> { - Ok(match self { - ArchivedOption::Some(value) => CacheCell::from(value.deserialize(deserializer)?), - ArchivedOption::None => CacheCell::new(), - }) - } - } -} diff --git a/deps/swc/crates/swc_common/src/comments.rs b/deps/swc/crates/swc_common/src/comments.rs index df39f7fa0..69e3d57ad 100644 --- a/deps/swc/crates/swc_common/src/comments.rs +++ b/deps/swc/crates/swc_common/src/comments.rs @@ -630,12 +630,6 @@ impl SingleThreadedComments { } #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr(feature = "encoding-impl", derive(crate::Encode, crate::Decode))] pub struct Comment { pub kind: CommentKind, @@ -651,12 +645,6 @@ impl Spanned for Comment { } #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr(feature = "encoding-impl", derive(crate::Encode, crate::Decode))] pub enum CommentKind { Line = 0, diff --git a/deps/swc/crates/swc_common/src/errors/diagnostic.rs b/deps/swc/crates/swc_common/src/errors/diagnostic.rs index f96c749ba..5f84b0d65 100644 --- a/deps/swc/crates/swc_common/src/errors/diagnostic.rs +++ b/deps/swc/crates/swc_common/src/errors/diagnostic.rs @@ -18,12 +18,6 @@ use crate::syntax_pos::{MultiSpan, Span}; feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -36,12 +30,6 @@ pub struct Message(pub String, pub Style); feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -73,12 +61,6 @@ pub struct Diagnostic { feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -94,12 +76,6 @@ pub enum DiagnosticId { feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) diff --git a/deps/swc/crates/swc_common/src/errors/mod.rs b/deps/swc/crates/swc_common/src/errors/mod.rs index bd9a7d50c..ecfffb0b1 100644 --- a/deps/swc/crates/swc_common/src/errors/mod.rs +++ b/deps/swc/crates/swc_common/src/errors/mod.rs @@ -48,12 +48,6 @@ mod styled_buffer; feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -70,12 +64,6 @@ pub enum Applicability { feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -127,12 +115,6 @@ pub struct CodeSuggestion { feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -146,12 +128,6 @@ pub struct Substitution { feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -919,12 +895,6 @@ impl Handler { feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) diff --git a/deps/swc/crates/swc_common/src/errors/snippet.rs b/deps/swc/crates/swc_common/src/errors/snippet.rs index e72539912..a8c3a6ce4 100644 --- a/deps/swc/crates/swc_common/src/errors/snippet.rs +++ b/deps/swc/crates/swc_common/src/errors/snippet.rs @@ -176,12 +176,6 @@ pub struct StyledString { feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) diff --git a/deps/swc/crates/swc_common/src/lib.rs b/deps/swc/crates/swc_common/src/lib.rs index 6dadc449c..500e9197d 100644 --- a/deps/swc/crates/swc_common/src/lib.rs +++ b/deps/swc/crates/swc_common/src/lib.rs @@ -76,18 +76,6 @@ pub mod util; #[cfg(all(not(debug_assertions), feature = "plugin-rt", feature = "plugin-mode"))] compile_error!("You can't enable `plugin-rt` and `plugin-mode` at the same time"); -/// Warning: The particular implementation of serialization and deserialization -/// of the ast nodes may change in the future, and so these types would be -/// removed. It's safe to say they will be serializable in some form or another, -/// but not necessarily with these specific types underlying the implementation. -/// As such, *use these types at your own risk*. -#[cfg(feature = "rkyv-impl")] -#[doc(hidden)] -pub use self::syntax_pos::{ - ArchivedBytePos, ArchivedCharPos, ArchivedFileName, ArchivedMultiSpan, ArchivedSourceFile, - ArchivedSourceFileAndBytePos, ArchivedSpan, ArchivedSpanLinesError, ArchivedSpanSnippetError, -}; - #[cfg(swc_ast_unknown)] #[track_caller] pub fn unknown_impl() -> std::convert::Infallible { diff --git a/deps/swc/crates/swc_common/src/plugin/diagnostics.rs b/deps/swc/crates/swc_common/src/plugin/diagnostics.rs index 985ff3db2..0eab07447 100644 --- a/deps/swc/crates/swc_common/src/plugin/diagnostics.rs +++ b/deps/swc/crates/swc_common/src/plugin/diagnostics.rs @@ -1,14 +1,8 @@ /// A serializable, wrapped struct for the diagnostics information /// included in plugin binaries. -/// TODO: Must implement bytecheck with forward-compatible schema changes to +/// TODO: Must implement forward-compatible validation for schema changes to /// prevent handshake failure. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) diff --git a/deps/swc/crates/swc_common/src/plugin/serialized.rs b/deps/swc/crates/swc_common/src/plugin/serialized.rs index dac996dea..0b73b7a04 100644 --- a/deps/swc/crates/swc_common/src/plugin/serialized.rs +++ b/deps/swc/crates/swc_common/src/plugin/serialized.rs @@ -4,11 +4,6 @@ use anyhow::Error; #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] -#[cfg_attr( - feature = "__plugin", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "__plugin", derive(bytecheck::CheckBytes))] #[cfg_attr(feature = "__plugin", repr(u32))] /// Enum for possible errors while running transform via plugin. /// @@ -58,25 +53,6 @@ impl PluginSerializedBytes { * This is sort of mimic TryFrom behavior, since we can't use generic * to implement TryFrom trait */ - /* - #[cfg_attr(debug_assertions, tracing::instrument(level = "info", skip_all))] - pub fn try_serialize(t: &VersionedSerializable) -> Result - where - W: rkyv::Serialize>, - { - rkyv::to_bytes::<_, 512>(t) - .map(|field| PluginSerializedBytes { field }) - .map_err(|err| match err { - rkyv::ser::serializers::CompositeSerializerError::SerializerError(e) => e.into(), - rkyv::ser::serializers::CompositeSerializerError::ScratchSpaceError(_e) => { - Error::msg("AllocScratchError") - } - rkyv::ser::serializers::CompositeSerializerError::SharedError(_e) => { - Error::msg("SharedSerializeMapError") - } - }) - } - */ #[cfg_attr(debug_assertions, tracing::instrument(level = "info", skip_all))] pub fn try_serialize(t: &VersionedSerializable) -> Result @@ -90,15 +66,29 @@ impl PluginSerializedBytes { }) } - /* - * Internal fn to constructs an instance from raw bytes ptr. - */ + /// Constructs an instance by copying serialized bytes from a raw pointer. + /// + /// ```compile_fail + /// # use swc_common::plugin::serialized::PluginSerializedBytes; + /// let bytes = [0_u8; 1]; + /// PluginSerializedBytes::from_raw_ptr(bytes.as_ptr(), bytes.len()); + /// ``` + /// + /// # Safety + /// + /// `raw_allocated_ptr` must be non-null and properly aligned, including + /// when `raw_allocated_ptr_len` is zero. It must point to + /// `raw_allocated_ptr_len` initialized bytes of readable memory in a single + /// allocation, and that memory must remain valid for reads for the duration + /// of this function call. The byte range must not exceed `isize::MAX` or + /// wrap around the address space. #[cfg_attr(debug_assertions, tracing::instrument(level = "info", skip_all))] - #[allow(clippy::not_unsafe_ptr_arg_deref)] - pub fn from_raw_ptr( + pub unsafe fn from_raw_ptr( raw_allocated_ptr: *const u8, raw_allocated_ptr_len: usize, ) -> PluginSerializedBytes { + // SAFETY: The caller guarantees all requirements of `from_raw_parts` + // for this pointer and length for the duration of the copy below. let raw_ptr_bytes = unsafe { std::slice::from_raw_parts(raw_allocated_ptr, raw_allocated_ptr_len) }; @@ -125,26 +115,6 @@ impl PluginSerializedBytes { .with_context(|| format!("failed to deserialize `{}`", type_name::()))?; Ok(VersionedSerializable(deserialized)) } - - /* - #[cfg_attr(debug_assertions, tracing::instrument(level = "info", skip_all))] - pub fn deserialize(&self) -> Result, Error> - where - W: rkyv::Archive, - W::Archived: rkyv::Deserialize - + for<'a> rkyv::CheckBytes>, - { - use anyhow::Context; - - let archived = rkyv::check_archived_root::>(&self.field[..]) - .map_err(|err| { - anyhow::format_err!("wasm plugin bytecheck failed {:?}", err.to_string()) - })?; - - archived - .deserialize(&mut rkyv::de::deserializers::SharedDeserializeMap::new()) - .with_context(|| format!("failed to deserialize `{}`", type_name::())) - } */ } /// A wrapper type for the structures to be passed into plugins @@ -154,18 +124,9 @@ impl PluginSerializedBytes { /// First field indicate version of struct type (schema). Any consumers like /// swc_plugin_macro can use this to validate compatiblility before attempt to /// serialize. -#[cfg_attr( - feature = "__plugin", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] #[repr(transparent)] -#[cfg_attr(feature = "__plugin", derive(bytecheck::CheckBytes))] #[derive(Debug)] -pub struct VersionedSerializable( - // [NOTE]: https://github.com/rkyv/rkyv/issues/373#issuecomment-1546360897 - //#[cfg_attr(feature = "__plugin", with(rkyv::with::AsBox))] - pub T, -); +pub struct VersionedSerializable(pub T); impl VersionedSerializable { pub fn new(value: T) -> Self { @@ -224,3 +185,25 @@ where } } } + +#[cfg(all(test, feature = "__plugin"))] +mod tests { + use super::{PluginSerializedBytes, VersionedSerializable}; + + #[test] + fn copies_initialized_bytes_from_raw_pointer() { + let serialized = PluginSerializedBytes::try_serialize(&VersionedSerializable::new(42_u32)) + .expect("u32 should be serializable"); + let (ptr, len) = serialized.as_ptr(); + + // SAFETY: `ptr` and `len` describe the initialized allocation owned by + // `serialized`, which remains alive until after `from_raw_ptr` copies it. + let copied = unsafe { PluginSerializedBytes::from_raw_ptr(ptr, len) }; + let value: u32 = copied + .deserialize() + .expect("copied bytes should deserialize") + .into_inner(); + + assert_eq!(value, 42); + } +} diff --git a/deps/swc/crates/swc_common/src/syntax_pos.rs b/deps/swc/crates/swc_common/src/syntax_pos.rs index 51bca32b6..d46f15b40 100644 --- a/deps/swc/crates/swc_common/src/syntax_pos.rs +++ b/deps/swc/crates/swc_common/src/syntax_pos.rs @@ -29,12 +29,6 @@ pub mod hygiene; /// assume that the length of the `span = hi - lo`; there may be space in the /// `BytePos` range between files. #[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -42,10 +36,8 @@ pub mod hygiene; #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct Span { #[serde(rename = "start")] - #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] pub lo: BytePos, #[serde(rename = "end")] - #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] pub hi: BytePos, } @@ -167,21 +159,9 @@ better_scoped_tls::scoped_tls!( pub static GLOBALS: Globals ); -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)] pub enum FileName { - Real( - #[cfg_attr( - any(feature = "rkyv-impl"), - rkyv(with = crate::source_map::EncodePathBuf) - )] - PathBuf, - ), + Real(PathBuf), /// A macro. This includes the full name of the macro, so that there are no /// clashes. Macros(String), @@ -192,7 +172,7 @@ pub enum FileName { /// Hack in src/libsyntax/parse.rs MacroExpansion, ProcMacroSourceCode, - Url(#[cfg_attr(any(feature = "rkyv-impl"), rkyv(with = crate::source_map::EncodeUrl))] Url), + Url(Url), Internal(String), /// Custom sources for explicit parser calls from plugins and drivers Custom(String), @@ -296,103 +276,6 @@ impl<'de> cbor4ii::core::dec::Decode<'de> for FileName { } } -/// A wrapper that attempts to convert a type to and from UTF-8. -/// -/// Types like `OsString` and `PathBuf` aren't guaranteed to be encoded as -/// UTF-8, but they usually are anyway. Using this wrapper will archive them as -/// if they were regular `String`s. -/// -/// There is built-in `AsString` supports PathBuf but it requires custom -/// serializer wrapper to handle conversion errors. This wrapper is simplified -/// version accepts errors -#[cfg(feature = "rkyv-impl")] -#[derive(Debug, Clone, Copy)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] -pub struct EncodePathBuf; - -#[cfg(feature = "rkyv-impl")] -impl rkyv::with::ArchiveWith for EncodePathBuf { - type Archived = rkyv::string::ArchivedString; - type Resolver = rkyv::string::StringResolver; - - #[inline] - fn resolve_with(field: &PathBuf, resolver: Self::Resolver, out: rkyv::Place) { - // It's safe to unwrap here because if the OsString wasn't valid UTF-8 it would - // have failed to serialize - rkyv::string::ArchivedString::resolve_from_str(field.to_str().unwrap(), resolver, out); - } -} - -#[cfg(feature = "rkyv-impl")] -impl rkyv::with::SerializeWith for EncodePathBuf -where - S: ?Sized + rancor::Fallible + rkyv::ser::Writer, - S::Error: rancor::Source, -{ - #[inline] - fn serialize_with(field: &PathBuf, serializer: &mut S) -> Result { - let s = field.to_str().unwrap_or_default(); - rkyv::string::ArchivedString::serialize_from_str(s, serializer) - } -} - -#[cfg(feature = "rkyv-impl")] -impl rkyv::with::DeserializeWith for EncodePathBuf -where - D: ?Sized + rancor::Fallible, -{ - #[inline] - fn deserialize_with( - field: &rkyv::string::ArchivedString, - _: &mut D, - ) -> Result { - Ok(::from_str(field.as_str()).unwrap()) - } -} - -/// A wrapper that attempts to convert a Url to and from String. -#[cfg(feature = "rkyv-impl")] -#[derive(Debug, Clone, Copy)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] -pub struct EncodeUrl; - -#[cfg(feature = "rkyv-impl")] -impl rkyv::with::ArchiveWith for EncodeUrl { - type Archived = rkyv::string::ArchivedString; - type Resolver = rkyv::string::StringResolver; - - #[inline] - fn resolve_with(field: &Url, resolver: Self::Resolver, out: rkyv::Place) { - rkyv::string::ArchivedString::resolve_from_str(field.as_str(), resolver, out); - } -} - -#[cfg(feature = "rkyv-impl")] -impl rkyv::with::SerializeWith for EncodeUrl -where - S: ?Sized + rancor::Fallible + rkyv::ser::Writer, - S::Error: rancor::Source, -{ - #[inline] - fn serialize_with(field: &Url, serializer: &mut S) -> Result { - let field = field.as_str(); - rkyv::string::ArchivedString::serialize_from_str(field, serializer) - } -} - -#[cfg(feature = "rkyv-impl")] -impl rkyv::with::DeserializeWith, Url, D> for EncodeUrl -where - D: ?Sized + rancor::Fallible, -{ - #[inline] - fn deserialize_with(field: &rkyv::string::ArchivedString, _: &mut D) -> Result { - Ok(Url::parse(field.as_str()).unwrap()) - } -} - impl std::fmt::Display for FileName { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match *self { @@ -459,12 +342,6 @@ impl FileName { feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -482,12 +359,6 @@ pub struct PrimarySpanLabel(pub Span, pub String); feature = "diagnostic-serde", derive(serde::Serialize, serde::Deserialize) )] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -795,12 +666,6 @@ impl From> for MultiSpan { pub const NO_EXPANSION: SyntaxContext = SyntaxContext::empty(); /// Identifies an offset of a multi-byte character in a SourceFile -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub struct MultiByteChar { /// The absolute offset of the character in the SourceMap @@ -825,12 +690,6 @@ impl MultiByteChar { } /// Identifies an offset of a non-narrow character in a SourceFile -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum NonNarrowChar { /// Represents a zero-width character @@ -893,12 +752,6 @@ impl Sub for NonNarrowChar { } /// A single source in the SourceMap. -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[derive(Clone)] pub struct SourceFile { /// The name of the file that the source came from. Source that doesn't @@ -923,12 +776,6 @@ pub struct SourceFile { lazy: CacheCell, } -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[derive(Clone)] pub struct SourceFileAnalysis { /// Stable hash of the source code. @@ -1203,14 +1050,8 @@ pub trait SmallPos { )] #[serde(transparent)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -pub struct BytePos(#[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] pub u32); +pub struct BytePos(pub u32); #[cfg(feature = "encoding-impl")] impl cbor4ii::core::enc::Encode for BytePos { @@ -1273,12 +1114,6 @@ impl BytePos { /// A character offset. Because of multibyte utf8 characters, a byte offset /// is not equivalent to a character offset. The SourceMap will convert BytePos /// values to CharPos values as necessary. -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr(feature = "encoding-impl", derive(crate::Encode, crate::Decode))] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub struct CharPos( @@ -1374,7 +1209,7 @@ impl Sub for CharPos { /// A source code location used for error reporting. /// -/// Note: This struct intentionally does not implement rkyv's archieve +/// Note: This struct intentionally does not implement an archive format /// to avoid redundant data copy (https://github.com/swc-project/swc/issues/5471) /// source_map_proxy constructs plugin-side Loc instead with shared SourceFile /// instance. @@ -1392,12 +1227,6 @@ pub struct Loc { /// A struct to exchange `Loc` with omitting SourceFile as needed. /// This is internal struct between plugins to the host, not a public interface. -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Debug, Clone) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr(feature = "encoding-impl", derive(crate::Encode, crate::Decode))] pub struct PartialLoc { #[cfg_attr( @@ -1431,12 +1260,6 @@ pub struct SourceFileAndLine { pub line: usize, } -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -1452,12 +1275,6 @@ pub struct SourceFileAndBytePos { } #[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr(feature = "encoding-impl", derive(crate::Encode, crate::Decode))] pub struct LineInfo { /// Index of line, starting from 0. @@ -1483,7 +1300,7 @@ pub struct LineCol { /// A struct to represent lines of a source file. /// -/// Note: This struct intentionally does not implement rkyv's archieve +/// Note: This struct intentionally does not implement an archive format /// to avoid redundant data copy (https://github.com/swc-project/swc/issues/5471) /// source_map_proxy constructs plugin-side Loc instead with shared SourceFile /// instance. @@ -1494,12 +1311,6 @@ pub struct FileLines { /// A struct to exchange `FileLines` with omitting SourceFile as needed. /// This is internal struct between plugins to the host, not a public interface. -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Debug, Clone) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -1523,12 +1334,6 @@ pub type FileLinesResult = Result>; pub type PartialFileLinesResult = Result>; #[derive(Clone, PartialEq, Eq, Debug)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -1539,12 +1344,6 @@ pub enum SpanLinesError { } #[derive(Clone, PartialEq, Eq, Debug)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] pub enum SpanSnippetError { DummyBytePos, IllFormedSpan(Span), @@ -1612,12 +1411,6 @@ impl<'de> cbor4ii::core::dec::Decode<'de> for SpanSnippetError { /// /// This type is small. #[derive(Clone, PartialEq, Eq, Debug)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -1627,12 +1420,6 @@ pub enum SourceMapLookupError { } #[derive(Clone, PartialEq, Eq, Debug)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -1647,12 +1434,6 @@ pub struct FilePos( ); #[derive(Clone, PartialEq, Eq, Debug)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -1663,12 +1444,6 @@ pub struct DistinctSources { } #[derive(Clone, PartialEq, Eq, Debug)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) diff --git a/deps/swc/crates/swc_common/src/syntax_pos/hygiene.rs b/deps/swc/crates/swc_common/src/syntax_pos/hygiene.rs index 448166db5..f0a76198f 100644 --- a/deps/swc/crates/swc_common/src/syntax_pos/hygiene.rs +++ b/deps/swc/crates/swc_common/src/syntax_pos/hygiene.rs @@ -31,14 +31,8 @@ use crate::EqIgnoreSpan; /// marks). #[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash, Serialize, Deserialize)] #[serde(transparent)] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -pub struct SyntaxContext(#[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] u32); +pub struct SyntaxContext(u32); #[cfg(feature = "encoding-impl")] impl cbor4ii::core::enc::Encode for SyntaxContext { @@ -104,12 +98,6 @@ pub(crate) struct MarkData { pub(crate) parent: Mark, } -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::ast_node::Encode, ::ast_node::Decode) @@ -207,11 +195,17 @@ impl Mark { } // Deserialize result, assign / return values as needed. - let context: MutableMarkContext = + // SAFETY: `ptr` and `len` come from `serialized`'s initialized byte + // allocation, which remains alive through this copy. The host proxy ABI + // writes its result into that allocation before returning and may not + // access memory outside it. + let serialized_context = unsafe { crate::plugin::serialized::PluginSerializedBytes::from_raw_ptr( ptr, len.try_into().expect("Should able to convert ptr length"), ) + }; + let context: MutableMarkContext = serialized_context .deserialize() .expect("Should able to deserialize") .into_inner(); @@ -249,11 +243,17 @@ impl Mark { __mark_least_ancestor(a.0, b.0, ptr as _); } - let context: MutableMarkContext = + // SAFETY: `ptr` and `len` come from `serialized`'s initialized byte + // allocation, which remains alive through this copy. The host proxy ABI + // writes its result into that allocation before returning and may not + // access memory outside it. + let serialized_context = unsafe { crate::plugin::serialized::PluginSerializedBytes::from_raw_ptr( ptr, len.try_into().expect("Should able to convert ptr length"), ) + }; + let context: MutableMarkContext = serialized_context .deserialize() .expect("Should able to deserialize") .into_inner(); @@ -417,11 +417,17 @@ impl SyntaxContext { __syntax_context_remove_mark_proxy(self.0, ptr as _); } - let context: MutableMarkContext = + // SAFETY: `ptr` and `len` come from `serialized`'s initialized byte + // allocation, which remains alive through this copy. The host proxy ABI + // writes its result into that allocation before returning and may not + // access memory outside it. + let serialized_context = unsafe { crate::plugin::serialized::PluginSerializedBytes::from_raw_ptr( ptr, len.try_into().expect("Should able to convert ptr length"), ) + }; + let context: MutableMarkContext = serialized_context .deserialize() .expect("Should able to deserialize") .into_inner(); diff --git a/deps/swc/crates/swc_common/src/unknown.rs b/deps/swc/crates/swc_common/src/unknown.rs index 3a4166439..92452bde1 100644 --- a/deps/swc/crates/swc_common/src/unknown.rs +++ b/deps/swc/crates/swc_common/src/unknown.rs @@ -37,57 +37,6 @@ impl std::hash::Hash for Unknown { } } -#[cfg(feature = "rkyv-impl")] -#[derive(Debug)] -struct UnknownError; - -#[cfg(feature = "rkyv-impl")] -impl std::error::Error for UnknownError {} - -#[cfg(feature = "rkyv-impl")] -impl std::fmt::Display for UnknownError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "cannot access unknown type") - } -} - -#[cfg(feature = "rkyv-impl")] -impl rkyv::Archive for Unknown { - type Archived = std::marker::PhantomData; - type Resolver = (); - - fn resolve(&self, _resolver: Self::Resolver, _out: rkyv::Place) { - // - } -} - -/// NOT A PUBLIC API -#[cfg(feature = "rkyv-impl")] -impl rkyv::Serialize for Unknown -where - S: rancor::Fallible + rkyv::ser::Writer + ?Sized, - S::Error: rancor::Source, -{ - fn serialize(&self, _serializer: &mut S) -> Result { - Err(::new(UnknownError)) - } -} - -/// NOT A PUBLIC API -#[cfg(feature = "rkyv-impl")] -impl rkyv::Deserialize for std::marker::PhantomData -where - D: ?Sized + rancor::Fallible, - D::Error: rancor::Source, -{ - fn deserialize( - &self, - _deserializer: &mut D, - ) -> Result::Error> { - Err(::new(UnknownError)) - } -} - impl std::fmt::Debug for Unknown { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Unknown") diff --git a/deps/swc/crates/swc_compiler_base/Cargo.toml b/deps/swc/crates/swc_compiler_base/Cargo.toml index e68be15ad..7d1859e12 100644 --- a/deps/swc/crates/swc_compiler_base/Cargo.toml +++ b/deps/swc/crates/swc_compiler_base/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_compiler_base" repository = { workspace = true } -version = "59.0.0" +version = "64.0.0" [features] node = ["napi", "napi-derive"] @@ -23,18 +23,18 @@ serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } swc_sourcemap = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "sourcemap", ] } -swc_config = { version = "5.0.0", path = "../swc_config" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_minifier = { version = "56.0.1", path = "../swc_ecma_minifier" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_config = { version = "6.0.0", path = "../swc_config" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_minifier = { version = "61.0.0", path = "../swc_ecma_minifier" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dependencies.napi-derive] default-features = false diff --git a/deps/swc/crates/swc_config/Cargo.toml b/deps/swc/crates/swc_config/Cargo.toml index dbeb0fc11..ad4d24161 100644 --- a/deps/swc/crates/swc_config/Cargo.toml +++ b/deps/swc/crates/swc_config/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_config" repository = { workspace = true } -version = "5.0.0" +version = "6.0.0" [package.metadata.docs.rs] diff --git a/deps/swc/crates/swc_core/Cargo.toml b/deps/swc/crates/swc_core/Cargo.toml index 522e119c2..06500c601 100644 --- a/deps/swc/crates/swc_core/Cargo.toml +++ b/deps/swc/crates/swc_core/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_core" repository = { workspace = true } -version = "71.0.3" +version = "77.0.0" [package.metadata.docs.rs] features = [ "allocator_node", @@ -332,55 +332,52 @@ __visit = ["__ecma", "swc_ecma_visit"] par-core = { workspace = true, optional = true } # swc_* dependencies -binding_macros = { optional = true, version = "69.0.0", path = "../binding_macros" } -swc = { optional = true, version = "69.0.0", path = "../swc", default-features = false } -swc_allocator = { version = "4.0.1", path = "../swc_allocator", default-features = false } -swc_atoms = { optional = true, version = "9.0.3", path = "../swc_atoms" } -swc_bundler = { optional = true, version = "51.0.1", path = "../swc_bundler" } -swc_common = { optional = true, version = "23.0.2", path = "../swc_common" } -swc_config = { optional = true, version = "5.0.0", path = "../swc_config" } -swc_css_ast = { optional = true, version = "23.0.0", path = "../swc_css_ast" } -swc_css_codegen = { optional = true, version = "23.0.0", path = "../swc_css_codegen" } -swc_css_compat = { optional = true, version = "23.0.0", path = "../swc_css_compat" } -swc_css_minifier = { optional = true, version = "23.0.0", path = "../swc_css_minifier" } -swc_css_modules = { optional = true, version = "23.0.0", path = "../swc_css_modules" } -swc_css_parser = { optional = true, version = "23.0.0", path = "../swc_css_parser" } -swc_css_prefixer = { optional = true, version = "28.0.0", path = "../swc_css_prefixer" } -swc_css_utils = { optional = true, version = "23.0.0", path = "../swc_css_utils/" } -swc_css_visit = { optional = true, version = "23.0.0", path = "../swc_css_visit" } -swc_ecma_ast = { optional = true, version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { optional = true, version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_lints = { optional = true, version = "33.0.0", path = "../swc_ecma_lints" } -swc_ecma_loader = { optional = true, version = "24.0.1", path = "../swc_ecma_loader" } -swc_ecma_minifier = { optional = true, version = "56.0.1", path = "../swc_ecma_minifier" } -swc_ecma_parser = { optional = true, version = "41.1.2", path = "../swc_ecma_parser", default-features = false } -swc_ecma_preset_env = { optional = true, version = "57.0.0", path = "../swc_ecma_preset_env" } -swc_ecma_quote_macros = { optional = true, version = "41.0.0", path = "../swc_ecma_quote_macros" } -swc_ecma_react_compiler = { optional = true, version = "20.0.2", path = "../swc_ecma_react_compiler" } -swc_ecma_transforms_base = { optional = true, version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_compat = { optional = true, version = "52.0.1", path = "../swc_ecma_transforms_compat" } -swc_ecma_transforms_module = { optional = true, version = "49.0.1", path = "../swc_ecma_transforms_module" } -swc_ecma_transforms_optimization = { optional = true, version = "47.0.1", path = "../swc_ecma_transforms_optimization" } -swc_ecma_transforms_proposal = { optional = true, version = "44.0.1", path = "../swc_ecma_transforms_proposal" } -swc_ecma_transforms_react = { optional = true, version = "50.0.0", path = "../swc_ecma_transforms_react" } -swc_ecma_transforms_testing = { optional = true, version = "48.0.0", path = "../swc_ecma_transforms_testing" } -swc_ecma_transforms_typescript = { optional = true, version = "50.0.0", path = "../swc_ecma_transforms_typescript" } -swc_ecma_utils = { optional = true, version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { optional = true, version = "25.0.0", path = "../swc_ecma_visit" } +binding_macros = { optional = true, version = "75.0.0", path = "../binding_macros" } +swc = { optional = true, version = "75.0.0", path = "../swc", default-features = false } +swc_allocator = { version = "5.0.0", path = "../swc_allocator", default-features = false } +swc_atoms = { optional = true, version = "10.0.0", path = "../swc_atoms" } +swc_bundler = { optional = true, version = "56.0.0", path = "../swc_bundler" } +swc_common = { optional = true, version = "26.0.0", path = "../swc_common" } +swc_config = { optional = true, version = "6.0.0", path = "../swc_config" } +swc_css_ast = { optional = true, version = "26.0.0", path = "../swc_css_ast" } +swc_css_codegen = { optional = true, version = "26.0.0", path = "../swc_css_codegen" } +swc_css_compat = { optional = true, version = "26.0.0", path = "../swc_css_compat" } +swc_css_minifier = { optional = true, version = "26.0.0", path = "../swc_css_minifier" } +swc_css_modules = { optional = true, version = "26.0.0", path = "../swc_css_modules" } +swc_css_parser = { optional = true, version = "26.0.0", path = "../swc_css_parser" } +swc_css_prefixer = { optional = true, version = "31.0.0", path = "../swc_css_prefixer" } +swc_css_utils = { optional = true, version = "26.0.0", path = "../swc_css_utils/" } +swc_css_visit = { optional = true, version = "26.0.0", path = "../swc_css_visit" } +swc_ecma_ast = { optional = true, version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { optional = true, version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_lints = { optional = true, version = "37.0.0", path = "../swc_ecma_lints" } +swc_ecma_loader = { optional = true, version = "27.0.0", path = "../swc_ecma_loader" } +swc_ecma_minifier = { optional = true, version = "61.0.0", path = "../swc_ecma_minifier" } +swc_ecma_parser = { optional = true, version = "45.0.0", path = "../swc_ecma_parser", default-features = false } +swc_ecma_preset_env = { optional = true, version = "63.0.0", path = "../swc_ecma_preset_env" } +swc_ecma_quote_macros = { optional = true, version = "45.0.0", path = "../swc_ecma_quote_macros" } +swc_ecma_react_compiler = { optional = true, version = "24.0.0", path = "../swc_ecma_react_compiler" } +swc_ecma_transforms_base = { optional = true, version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_compat = { optional = true, version = "57.0.0", path = "../swc_ecma_transforms_compat" } +swc_ecma_transforms_module = { optional = true, version = "55.0.0", path = "../swc_ecma_transforms_module" } +swc_ecma_transforms_optimization = { optional = true, version = "52.0.0", path = "../swc_ecma_transforms_optimization" } +swc_ecma_transforms_proposal = { optional = true, version = "49.0.0", path = "../swc_ecma_transforms_proposal" } +swc_ecma_transforms_react = { optional = true, version = "55.0.0", path = "../swc_ecma_transforms_react" } +swc_ecma_transforms_testing = { optional = true, version = "53.0.0", path = "../swc_ecma_transforms_testing" } +swc_ecma_transforms_typescript = { optional = true, version = "55.0.0", path = "../swc_ecma_transforms_typescript" } +swc_ecma_utils = { optional = true, version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { optional = true, version = "29.0.0", path = "../swc_ecma_visit" } swc_malloc = { optional = true, version = "1.2.5", path = "../swc_malloc" } -swc_node_bundler = { optional = true, version = "70.0.0", path = "../swc_node_bundler" } +swc_node_bundler = { optional = true, version = "76.0.0", path = "../swc_node_bundler" } swc_nodejs_common = { optional = true, version = "1.0.3", path = "../swc_nodejs_common" } swc_plugin = { optional = true, version = "1.0.1", path = "../swc_plugin" } -swc_plugin_macro = { optional = true, version = "1.1.1", path = "../swc_plugin_macro" } -swc_plugin_proxy = { optional = true, version = "26.0.0", path = "../swc_plugin_proxy" } -swc_plugin_runner = { optional = true, version = "30.0.0", path = "../swc_plugin_runner", default-features = false } -swc_transform_common = { optional = true, version = "17.0.0", path = "../swc_transform_common" } -swc_typescript = { optional = true, version = "30.0.1", path = "../swc_typescript" } -testing = { optional = true, version = "24.0.1", path = "../testing" } - -[build-dependencies] -vergen = { workspace = true, features = ["cargo"] } +swc_plugin_macro = { optional = true, version = "2.0.0", path = "../swc_plugin_macro" } +swc_plugin_proxy = { optional = true, version = "30.0.0", path = "../swc_plugin_proxy" } +swc_plugin_runner = { optional = true, version = "34.0.0", path = "../swc_plugin_runner", default-features = false } +swc_transform_common = { optional = true, version = "20.0.0", path = "../swc_transform_common" } +swc_typescript = { optional = true, version = "34.0.0", path = "../swc_typescript" } +testing = { optional = true, version = "27.0.0", path = "../testing" } [dev-dependencies] anyhow = { workspace = true } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_core/build.rs b/deps/swc/crates/swc_core/build.rs index f3a1c9a5f..1da24415e 100644 --- a/deps/swc/crates/swc_core/build.rs +++ b/deps/swc/crates/swc_core/build.rs @@ -1,11 +1,4 @@ -use std::{ - env, - fs::File, - io::{BufWriter, Write}, - path::Path, -}; - -use vergen::{CargoBuilder, Emitter}; +use std::{env, fs, path::Path}; // Validate conflict between host / plugin features #[cfg(all( @@ -22,23 +15,25 @@ compile_error!( ); fn main() { - let cargo = CargoBuilder::all_cargo().unwrap(); - - // Creates a static compile time constants for the version of swc_core. + // Keep these generated files deterministic so sccache can reuse builds. let pkg_version = env::var("CARGO_PKG_VERSION").unwrap(); let out_dir = env::var("OUT_DIR").expect("Outdir should exist"); - let dest_path = Path::new(&out_dir).join("core_pkg_version.txt"); - let mut f = BufWriter::new( - File::create(dest_path).expect("Failed to create swc_core version constant"), - ); - write!(f, "{pkg_version}").expect("Failed to write swc_core version constant"); + let out_dir = Path::new(&out_dir); + + fs::write(out_dir.join("core_pkg_version.txt"), pkg_version) + .expect("Failed to write swc_core version constant"); + fs::write(out_dir.join("cargo_features.txt"), cargo_features()) + .expect("Failed to write swc_core feature list"); +} - // Attempt to collect some build time env values but will skip if there are any - // errors. +fn cargo_features() -> String { + let mut features = env::vars() + .filter_map(|(key, _)| { + key.strip_prefix("CARGO_FEATURE_") + .map(|feature| feature.to_ascii_lowercase()) + }) + .collect::>(); - Emitter::default() - .add_instructions(&cargo) - .unwrap() - .emit() - .unwrap(); + features.sort_unstable(); + features.join(",") } diff --git a/deps/swc/crates/swc_core/src/lib.rs b/deps/swc/crates/swc_core/src/lib.rs index c16fcd63f..8bfed50ea 100644 --- a/deps/swc/crates/swc_core/src/lib.rs +++ b/deps/swc/crates/swc_core/src/lib.rs @@ -307,12 +307,9 @@ pub mod diagnostics { /// Returns metadata about the swc_core engine that was built against. pub fn get_core_engine_diagnostics() -> CoreEngineDiagnostics { CoreEngineDiagnostics { - package_semver: option_env!("VERGEN_BUILD_SEMVER") - .unwrap_or_else(|| PKG_SEMVER_FALLBACK) - .to_string(), + package_semver: PKG_SEMVER_FALLBACK.to_string(), git_sha: GIT_SHA.to_string(), - cargo_features: option_env!("VERGEN_CARGO_FEATURES") - .unwrap_or_else(|| "Unavailable to query") + cargo_features: include_str!(concat!(env!("OUT_DIR"), "/cargo_features.txt")) .to_string(), } } diff --git a/deps/swc/crates/swc_css/Cargo.toml b/deps/swc/crates/swc_css/Cargo.toml index 216a0c4b9..006b63575 100644 --- a/deps/swc/crates/swc_css/Cargo.toml +++ b/deps/swc/crates/swc_css/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_css" repository = { workspace = true } -version = "28.0.0" +version = "31.0.0" [package.metadata.docs.rs] all-features = true @@ -22,12 +22,12 @@ modules = ["swc_css_modules"] prefixer = ["swc_css_prefixer"] [dependencies] -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } -swc_css_codegen = { version = "23.0.0", path = "../swc_css_codegen" } -swc_css_compat = { version = "23.0.0", path = "../swc_css_compat", optional = true } -swc_css_minifier = { version = "23.0.0", path = "../swc_css_minifier", optional = true } -swc_css_modules = { version = "23.0.0", path = "../swc_css_modules", optional = true } -swc_css_parser = { version = "23.0.0", path = "../swc_css_parser" } -swc_css_prefixer = { version = "28.0.0", path = "../swc_css_prefixer", optional = true } -swc_css_utils = { version = "23.0.0", path = "../swc_css_utils/" } -swc_css_visit = { version = "23.0.0", path = "../swc_css_visit" } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } +swc_css_codegen = { version = "26.0.0", path = "../swc_css_codegen" } +swc_css_compat = { version = "26.0.0", path = "../swc_css_compat", optional = true } +swc_css_minifier = { version = "26.0.0", path = "../swc_css_minifier", optional = true } +swc_css_modules = { version = "26.0.0", path = "../swc_css_modules", optional = true } +swc_css_parser = { version = "26.0.0", path = "../swc_css_parser" } +swc_css_prefixer = { version = "31.0.0", path = "../swc_css_prefixer", optional = true } +swc_css_utils = { version = "26.0.0", path = "../swc_css_utils/" } +swc_css_visit = { version = "26.0.0", path = "../swc_css_visit" } diff --git a/deps/swc/crates/swc_css_ast/Cargo.toml b/deps/swc/crates/swc_css_ast/Cargo.toml index 805857230..e8058767e 100644 --- a/deps/swc/crates/swc_css_ast/Cargo.toml +++ b/deps/swc/crates/swc_css_ast/Cargo.toml @@ -6,36 +6,26 @@ edition = { workspace = true } license = { workspace = true } name = "swc_css_ast" repository = { workspace = true } -version = "23.0.0" +version = "26.0.0" [lib] bench = false [features] -__rkyv = [] default = [] encoding-impl = [ "cbor4ii", "swc_atoms/encoding-impl", "swc_common/encoding-impl", ] -rkyv-impl = [ - "__rkyv", - "rkyv", - "swc_atoms/rkyv-impl", - "swc_common/rkyv-impl", - "bytecheck", -] serde-impl = ["serde"] [dependencies] -bytecheck = { workspace = true, optional = true } is-macro = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } string_enum = { version = "1.0.2", path = "../string_enum/" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } cbor4ii = { workspace = true, features = ["use_std"], optional = true } -rkyv = { workspace = true, optional = true } diff --git a/deps/swc/crates/swc_css_ast/src/at_rule.rs b/deps/swc/crates/swc_css_ast/src/at_rule.rs index b986304de..b764f6afe 100644 --- a/deps/swc/crates/swc_css_ast/src/at_rule.rs +++ b/deps/swc/crates/swc_css_ast/src/at_rule.rs @@ -509,21 +509,10 @@ pub struct MediaFeatureBoolean { } #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) )] -//#[cfg_attr( -// feature = "rkyv", -// archive(bound(serialize = "__S: rkyv::ser::ScratchSpace + -// rkyv::ser::Serializer")) -//)] pub enum MediaFeatureRangeComparison { /// `<` Lt, @@ -876,17 +865,6 @@ pub struct SizeFeatureBoolean { } #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] -//#[cfg_attr( -// feature = "rkyv", -// archive(bound(serialize = "__S: rkyv::ser::ScratchSpace + -// rkyv::ser::Serializer")) -//)] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) diff --git a/deps/swc/crates/swc_css_ast/src/selector.rs b/deps/swc/crates/swc_css_ast/src/selector.rs index aa2a56f67..4225b9ed6 100644 --- a/deps/swc/crates/swc_css_ast/src/selector.rs +++ b/deps/swc/crates/swc_css_ast/src/selector.rs @@ -131,17 +131,6 @@ pub struct Combinator { } #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr( - feature = "rkyv", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -299,17 +288,6 @@ pub struct AttributeSelector { } #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] -//#[cfg_attr( -// feature = "rkyv", -// archive(bound(serialize = "__S: rkyv::ser::ScratchSpace + -// rkyv::ser::Serializer")) -//)] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) diff --git a/deps/swc/crates/swc_css_ast/src/token.rs b/deps/swc/crates/swc_css_ast/src/token.rs index a741ecf39..021a87b42 100644 --- a/deps/swc/crates/swc_css_ast/src/token.rs +++ b/deps/swc/crates/swc_css_ast/src/token.rs @@ -24,12 +24,6 @@ impl Take for TokenAndSpan { #[derive(Debug, Clone, PartialEq, EqIgnoreSpan, Hash)] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -37,17 +31,6 @@ impl Take for TokenAndSpan { pub struct UrlKeyValue(pub Atom, pub Atom); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Is, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] -#[cfg_attr( - feature = "rkyv", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] #[cfg_attr(feature = "serde-impl", derive(Serialize, Deserialize))] #[cfg_attr( feature = "encoding-impl", @@ -61,12 +44,6 @@ pub enum NumberType { } #[derive(Debug, Clone, PartialEq, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(C))] #[cfg_attr(feature = "serde-impl", derive(Serialize, Deserialize))] #[cfg_attr( feature = "encoding-impl", @@ -84,17 +61,6 @@ pub struct DimensionToken { } #[derive(Debug, Clone, PartialEq, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] -#[cfg_attr( - feature = "rkyv", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr( feature = "encoding-impl", diff --git a/deps/swc/crates/swc_css_ast/src/value.rs b/deps/swc/crates/swc_css_ast/src/value.rs index 5a0bfce39..4e19dfcac 100644 --- a/deps/swc/crates/swc_css_ast/src/value.rs +++ b/deps/swc/crates/swc_css_ast/src/value.rs @@ -132,17 +132,6 @@ impl EqIgnoreSpan for Str { } #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr( - feature = "rkyv", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -429,17 +418,6 @@ pub struct Ratio { } #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr( - feature = "rkyv", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -560,17 +538,6 @@ pub struct CalcOperator { } #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr( - feature = "rkyv", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) diff --git a/deps/swc/crates/swc_css_codegen/Cargo.toml b/deps/swc/crates/swc_css_codegen/Cargo.toml index d6816218c..bfd292608 100644 --- a/deps/swc/crates/swc_css_codegen/Cargo.toml +++ b/deps/swc/crates/swc_css_codegen/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_css_codegen" repository = { workspace = true } -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -18,16 +18,16 @@ bitflags = { workspace = true } rustc-hash = { workspace = true } serde = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } swc_css_codegen_macros = { version = "1.0.2", path = "../swc_css_codegen_macros" } -swc_css_utils = { version = "23.0.0", path = "../swc_css_utils" } +swc_css_utils = { version = "26.0.0", path = "../swc_css_utils" } [dev-dependencies] -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "sourcemap", ] } -swc_css_parser = { version = "23.0.0", path = "../swc_css_parser" } -swc_css_visit = { version = "23.0.0", path = "../swc_css_visit" } -testing = { version = "24.0.1", path = "../testing" } +swc_css_parser = { version = "26.0.0", path = "../swc_css_parser" } +swc_css_visit = { version = "26.0.0", path = "../swc_css_visit" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_css_compat/Cargo.toml b/deps/swc/crates/swc_css_compat/Cargo.toml index 9202ed4c3..3d45bcf1f 100644 --- a/deps/swc/crates/swc_css_compat/Cargo.toml +++ b/deps/swc/crates/swc_css_compat/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/**/*.json", "data/**/*.json"] license = { workspace = true } name = "swc_css_compat" repository = { workspace = true } -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -16,13 +16,13 @@ bench = false bitflags = { workspace = true } serde = { workspace = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } -swc_css_utils = { version = "23.0.0", path = "../swc_css_utils/" } -swc_css_visit = { version = "23.0.0", path = "../swc_css_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } +swc_css_utils = { version = "26.0.0", path = "../swc_css_utils/" } +swc_css_visit = { version = "26.0.0", path = "../swc_css_visit" } [dev-dependencies] -swc_css_codegen = { version = "23.0.0", path = "../swc_css_codegen" } -swc_css_parser = { version = "23.0.0", path = "../swc_css_parser" } -testing = { version = "24.0.1", path = "../testing" } +swc_css_codegen = { version = "26.0.0", path = "../swc_css_codegen" } +swc_css_parser = { version = "26.0.0", path = "../swc_css_parser" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_css_lints/Cargo.toml b/deps/swc/crates/swc_css_lints/Cargo.toml index f1c10eb6c..63f3e2e60 100644 --- a/deps/swc/crates/swc_css_lints/Cargo.toml +++ b/deps/swc/crates/swc_css_lints/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_css_lints" repository = { workspace = true } -version = "25.0.0" +version = "29.0.0" [lib] bench = false @@ -21,14 +21,14 @@ rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } thiserror = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_config = { version = "5.0.0", path = "../swc_config", features = ["regex"] } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } -swc_css_visit = { version = "23.0.0", path = "../swc_css_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_config = { version = "6.0.0", path = "../swc_config", features = ["regex"] } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } +swc_css_visit = { version = "26.0.0", path = "../swc_css_visit" } [dev-dependencies] serde_json = { workspace = true } -swc_css_parser = { version = "23.0.0", path = "../swc_css_parser" } -testing = { version = "24.0.1", path = "../testing" } +swc_css_parser = { version = "26.0.0", path = "../swc_css_parser" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_css_minifier/Cargo.toml b/deps/swc/crates/swc_css_minifier/Cargo.toml index c9c969450..5d3360bb0 100644 --- a/deps/swc/crates/swc_css_minifier/Cargo.toml +++ b/deps/swc/crates/swc_css_minifier/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_css_minifier" repository = { workspace = true } -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -16,14 +16,14 @@ bench = false rustc-hash = { workspace = true } serde = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } -swc_css_utils = { version = "23.0.0", path = "../swc_css_utils/" } -swc_css_visit = { version = "23.0.0", path = "../swc_css_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } +swc_css_utils = { version = "26.0.0", path = "../swc_css_utils/" } +swc_css_visit = { version = "26.0.0", path = "../swc_css_visit" } [dev-dependencies] -swc_css_codegen = { version = "23.0.0", path = "../swc_css_codegen" } -swc_css_parser = { version = "23.0.0", path = "../swc_css_parser" } -testing = { version = "24.0.1", path = "../testing" } +swc_css_codegen = { version = "26.0.0", path = "../swc_css_codegen" } +swc_css_parser = { version = "26.0.0", path = "../swc_css_parser" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_css_modules/Cargo.toml b/deps/swc/crates/swc_css_modules/Cargo.toml index d41f853ad..5267a28b1 100644 --- a/deps/swc/crates/swc_css_modules/Cargo.toml +++ b/deps/swc/crates/swc_css_modules/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_css_modules" repository = { workspace = true } -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -18,15 +18,15 @@ bench = false rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } -swc_css_codegen = { version = "23.0.0", path = "../swc_css_codegen" } -swc_css_parser = { version = "23.0.0", path = "../swc_css_parser" } -swc_css_visit = { version = "23.0.0", path = "../swc_css_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } +swc_css_codegen = { version = "26.0.0", path = "../swc_css_codegen" } +swc_css_parser = { version = "26.0.0", path = "../swc_css_parser" } +swc_css_visit = { version = "26.0.0", path = "../swc_css_visit" } [dev-dependencies] indexmap = { workspace = true, features = ["serde"] } -swc_css_compat = { version = "23.0.0", path = "../swc_css_compat" } -testing = { version = "24.0.1", path = "../testing" } +swc_css_compat = { version = "26.0.0", path = "../swc_css_compat" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_css_parser/Cargo.toml b/deps/swc/crates/swc_css_parser/Cargo.toml index 118705309..6f902fbd7 100644 --- a/deps/swc/crates/swc_css_parser/Cargo.toml +++ b/deps/swc/crates/swc_css_parser/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_css_parser" repository = { workspace = true } -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -19,20 +19,20 @@ debug = [] lexical = { workspace = true } serde = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } [dev-dependencies] codspeed-criterion-compat = { workspace = true } serde_json = { workspace = true } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast", features = [ +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast", features = [ "serde-impl", ] } -swc_css_visit = { version = "23.0.0", path = "../swc_css_visit" } +swc_css_visit = { version = "26.0.0", path = "../swc_css_visit" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } [[bench]] harness = false diff --git a/deps/swc/crates/swc_css_prefixer/Cargo.toml b/deps/swc/crates/swc_css_prefixer/Cargo.toml index f0c704557..77a5cd55d 100644 --- a/deps/swc/crates/swc_css_prefixer/Cargo.toml +++ b/deps/swc/crates/swc_css_prefixer/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/**/*.json", "data/**/*.json"] license = { workspace = true } name = "swc_css_prefixer" repository = { workspace = true } -version = "28.0.0" +version = "31.0.0" [lib] bench = false @@ -18,14 +18,14 @@ rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -preset_env_base = { version = "8.0.1", path = "../preset_env_base" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } -swc_css_utils = { version = "23.0.0", path = "../swc_css_utils/" } -swc_css_visit = { version = "23.0.0", path = "../swc_css_visit" } +preset_env_base = { version = "9.0.0", path = "../preset_env_base" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } +swc_css_utils = { version = "26.0.0", path = "../swc_css_utils/" } +swc_css_visit = { version = "26.0.0", path = "../swc_css_visit" } [dev-dependencies] -swc_css_codegen = { version = "23.0.0", path = "../swc_css_codegen" } -swc_css_parser = { version = "23.0.0", path = "../swc_css_parser" } -testing = { version = "24.0.1", path = "../testing" } +swc_css_codegen = { version = "26.0.0", path = "../swc_css_codegen" } +swc_css_parser = { version = "26.0.0", path = "../swc_css_parser" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_css_utils/Cargo.toml b/deps/swc/crates/swc_css_utils/Cargo.toml index 1fc26037e..84e430bdc 100644 --- a/deps/swc/crates/swc_css_utils/Cargo.toml +++ b/deps/swc/crates/swc_css_utils/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/**/*.json"] license = { workspace = true } name = "swc_css_utils" repository = { workspace = true } -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -18,6 +18,6 @@ rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } -swc_css_visit = { version = "23.0.0", path = "../swc_css_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } +swc_css_visit = { version = "26.0.0", path = "../swc_css_visit" } diff --git a/deps/swc/crates/swc_css_visit/Cargo.toml b/deps/swc/crates/swc_css_visit/Cargo.toml index 3e61eba9f..590e184af 100644 --- a/deps/swc/crates/swc_css_visit/Cargo.toml +++ b/deps/swc/crates/swc_css_visit/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_css_visit" repository = { workspace = true } -version = "23.0.0" +version = "26.0.0" [package.metadata.docs.rs] all-features = true @@ -23,7 +23,7 @@ serde-impl = ["serde"] [dependencies] serde = { workspace = true, optional = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast" } swc_visit = { version = "2.0.1", path = "../swc_visit" } diff --git a/deps/swc/crates/swc_ecma_ast/Cargo.toml b/deps/swc/crates/swc_ecma_ast/Cargo.toml index 1815d32e8..5c6fde883 100644 --- a/deps/swc/crates/swc_ecma_ast/Cargo.toml +++ b/deps/swc/crates/swc_ecma_ast/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_ast" repository = { workspace = true } -version = "25.0.0" +version = "29.0.0" [package.metadata.docs.rs] all-features = true @@ -19,7 +19,6 @@ bench = false unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [features] -__rkyv = [] default = [] encoding-impl = [ "cbor4ii", @@ -27,14 +26,6 @@ encoding-impl = [ "swc_common/encoding-impl", ] fuzzing = ["arbitrary", "swc_atoms/arbitrary", "swc_common/arbitrary"] -rkyv-impl = [ - "__rkyv", - "rkyv", - "bytecheck", - "rancor", - "swc_atoms/rkyv-impl", - "swc_common/rkyv-impl", -] serde-impl = ["serde"] shrink-to-fit = [ "dep:shrink-to-fit", @@ -45,21 +36,18 @@ shrink-to-fit = [ [dependencies] arbitrary = { workspace = true, features = ["derive"], optional = true } bitflags = { workspace = true } -bytecheck = { workspace = true, optional = true } is-macro = { workspace = true } num-bigint = { workspace = true, features = ["serde"] } once_cell = { workspace = true } phf = { workspace = true, features = ["macros"] } -rancor = { workspace = true, optional = true } -rkyv = { workspace = true, optional = true } rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } shrink-to-fit = { workspace = true, optional = true } unicode-id-start = { workspace = true } string_enum = { version = "1.0.2", path = "../string_enum" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } swc_visit = { version = "2.0.1", path = "../swc_visit" } cbor4ii = { workspace = true, features = ["use_std"], optional = true } diff --git a/deps/swc/crates/swc_ecma_ast/src/class.rs b/deps/swc/crates/swc_ecma_ast/src/class.rs index b3591a11e..3a9d0db17 100644 --- a/deps/swc/crates/swc_ecma_ast/src/class.rs +++ b/deps/swc/crates/swc_ecma_ast/src/class.rs @@ -3,7 +3,7 @@ use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, SyntaxContext, use crate::{ expr::Expr, - function::{Function, ParamOrTsParamProp}, + function::{Function, FunctionBody, ParamOrTsParamProp}, ident::PrivateName, prop::PropName, stmt::BlockStmt, @@ -289,7 +289,7 @@ pub struct Constructor { feature = "encoding-impl", encoding(with = "cbor4ii::core::types::Maybe") )] - pub body: Option, + pub body: Option, #[cfg_attr(feature = "serde-impl", serde(default))] #[cfg_attr( @@ -315,12 +315,6 @@ pub struct Decorator { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EqIgnoreSpan, Default)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] #[cfg_attr( diff --git a/deps/swc/crates/swc_ecma_ast/src/decl.rs b/deps/swc/crates/swc_ecma_ast/src/decl.rs index 8e8ecfd40..0b8a9e10f 100644 --- a/deps/swc/crates/swc_ecma_ast/src/decl.rs +++ b/deps/swc/crates/swc_ecma_ast/src/decl.rs @@ -172,12 +172,6 @@ impl Take for VarDecl { #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] #[cfg_attr( feature = "encoding-impl", diff --git a/deps/swc/crates/swc_ecma_ast/src/expr.rs b/deps/swc/crates/swc_ecma_ast/src/expr.rs index 56ff932ef..eae495eb6 100644 --- a/deps/swc/crates/swc_ecma_ast/src/expr.rs +++ b/deps/swc/crates/swc_ecma_ast/src/expr.rs @@ -1,5 +1,4 @@ #![allow(clippy::vec_box)] -use std::mem::transmute; use is_macro::Is; use string_enum::StringEnum; @@ -10,14 +9,13 @@ use swc_common::{ use crate::{ class::Class, - function::Function, + function::{Function, FunctionBody}, ident::{Ident, PrivateName}, jsx::{JSXElement, JSXEmptyExpr, JSXFragment, JSXMemberExpr, JSXNamespacedName}, lit::Lit, operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp}, pat::Pat, prop::Prop, - stmt::BlockStmt, typescript::{ TsAsExpr, TsConstAssertion, TsInstantiation, TsNonNullExpr, TsSatisfiesExpr, TsTypeAnn, TsTypeAssertion, TsTypeParamDecl, TsTypeParamInstantiation, @@ -239,19 +237,61 @@ impl Expr { /// If the provided function returns [Some], the function is called again /// with the returned value. If the provided functions returns [None], /// the last expression is returned. - pub fn unwrap_mut_with<'a, F>(&'a mut self, mut op: F) -> &'a mut Expr + /// + /// The function receives a fresh mutable reborrow on each invocation. It + /// can return a nested expression borrowed from its argument, but it cannot + /// retain that argument after the invocation. + /// + /// # Source compatibility + /// + /// The higher-ranked callback bound rejects functions that retain the + /// argument outside the callback. Such functions were accepted by older + /// versions of this method, but could create aliased mutable references. + /// Callbacks that only return an expression nested within the argument + /// remain supported. + /// + /// ```compile_fail + /// use swc_ecma_ast::Expr; + /// + /// fn stash_callback_argument(expr: &mut Expr) { + /// let mut stashed: Option<&mut Expr> = None; + /// + /// let returned = expr.unwrap_mut_with(|current| { + /// stashed = Some(current); + /// None + /// }); + /// + /// let _aliases = (returned, stashed.unwrap()); + /// } + /// ``` + pub fn unwrap_mut_with<'root, F>(&'root mut self, mut op: F) -> &'root mut Expr where - F: FnMut(&'a mut Expr) -> Option<&'a mut Expr>, + F: for<'call> FnMut(&'call mut Expr) -> Option<&'call mut Expr>, { - let mut cur = self; + // Stable borrow checking cannot yet express that the callback's borrow + // ends in the `None` branch, so keep the cursor raw between calls. + let mut cur: *mut Expr = self; + loop { - match unsafe { - // Safety: Polonius is not yet stable - op(transmute::<&mut _, &mut _>(cur)) - } { + // SAFETY: + // - `cur` starts as the pointer behind the exclusive `'root` borrow, and is + // only replaced with a pointer obtained from the callback's exclusive return + // value. + // - The higher-ranked bound gives every call its own lifetime, so safe callback + // code cannot retain this reborrow in captured state. While `op` runs, no + // other reference is created from `cur`. + // - A returned reference is consumed into `cur` before the next iteration. Safe + // code cannot return a reference whose storage expires at the end of the + // call. + match unsafe { op(&mut *cur) } { Some(next) => cur = next, None => { - return cur; + // SAFETY: `None` contains no reference from the last + // reborrow, and the higher-ranked callback cannot have + // retained it. Thus `cur` is still valid and exclusively + // borrowed, and its reference can be returned for the + // remainder of `'root`. + return unsafe { &mut *cur }; } } } @@ -1084,7 +1124,7 @@ pub struct ArrowExpr { pub params: Vec, /// This is boxed to reduce the type size of [Expr]. - pub body: Box, + pub body: Box, #[cfg_attr(feature = "serde-impl", serde(default, rename = "async"))] pub is_async: bool, @@ -1154,12 +1194,6 @@ pub struct MetaPropExpr { #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] #[cfg_attr( feature = "encoding-impl", @@ -1369,27 +1403,6 @@ impl Take for Import { #[derive(Clone, Debug, PartialEq, Eq, Hash, EqIgnoreSpan)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr( - feature = "rkyv", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] -#[cfg_attr( - feature = "rkyv-impl", - rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source)) -)] -#[cfg_attr( - feature = "rkyv-impl", - rkyv(bytecheck(bounds( - __C: rkyv::validation::ArchiveContext, - __C::Error: rkyv::rancor::Source - ))) - )] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr( feature = "encoding-impl", @@ -1397,7 +1410,6 @@ impl Take for Import { )] pub struct ExprOrSpread { #[cfg_attr(feature = "serde-impl", serde(default))] - #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] #[cfg_attr( feature = "encoding-impl", encoding(with = "cbor4ii::core::types::Maybe") @@ -1405,7 +1417,6 @@ pub struct ExprOrSpread { pub spread: Option, #[cfg_attr(feature = "serde-impl", serde(rename = "expression"))] - #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] pub expr: Box, } @@ -1446,20 +1457,30 @@ bridge_from!(ExprOrSpread, Box, Expr); #[allow(variant_size_differences)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -pub enum BlockStmtOrExpr { - #[tag("BlockStatement")] - BlockStmt(BlockStmt), +pub enum ArrowFunctionBody { + #[tag("FunctionBody")] + FunctionBody(FunctionBody), #[tag("*")] Expr(Box), } -impl Default for BlockStmtOrExpr { +/// Deprecated alias for [`ArrowFunctionBody`]. +/// +/// This alias preserves only the former type name. The former +/// `BlockStmtOrExpr::BlockStmt` variant has been replaced by +/// [`ArrowFunctionBody::FunctionBody`]. +#[deprecated( + note = "Use `ArrowFunctionBody`; its block variant is `ArrowFunctionBody::FunctionBody`" +)] +pub type BlockStmtOrExpr = ArrowFunctionBody; + +impl Default for ArrowFunctionBody { fn default() -> Self { - BlockStmtOrExpr::BlockStmt(Default::default()) + ArrowFunctionBody::FunctionBody(Default::default()) } } -impl From for BlockStmtOrExpr +impl From for ArrowFunctionBody where T: Into, { @@ -1468,9 +1489,9 @@ where } } -impl Take for BlockStmtOrExpr { +impl Take for ArrowFunctionBody { fn dummy() -> Self { - BlockStmtOrExpr::Expr(Take::dummy()) + ArrowFunctionBody::Expr(Take::dummy()) } } diff --git a/deps/swc/crates/swc_ecma_ast/src/function.rs b/deps/swc/crates/swc_ecma_ast/src/function.rs index 3d0747b3a..079a499db 100644 --- a/deps/swc/crates/swc_ecma_ast/src/function.rs +++ b/deps/swc/crates/swc_ecma_ast/src/function.rs @@ -4,8 +4,8 @@ use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, SyntaxContext, use crate::{ class::Decorator, pat::Pat, - stmt::BlockStmt, - typescript::{TsParamProp, TsTypeAnn, TsTypeParamDecl}, + stmt::Stmt, + typescript::{TsParamProp, TsThisParam, TsTypeAnn, TsTypeParamDecl}, }; /// Common parts of function and method. @@ -14,6 +14,18 @@ use crate::{ #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct Function { + /// TypeScript or Flow `this` parameter, which is not part of the runtime + /// parameter list. + #[cfg_attr( + feature = "serde-impl", + serde(default, rename = "thisParam", skip_serializing_if = "Option::is_none") + )] + #[cfg_attr( + feature = "encoding-impl", + encoding(with = "cbor4ii::core::types::Maybe") + )] + pub this_param: Option>, + pub params: Vec, #[cfg_attr(feature = "serde-impl", serde(default))] @@ -28,7 +40,7 @@ pub struct Function { feature = "encoding-impl", encoding(with = "cbor4ii::core::types::Maybe") )] - pub body: Option, + pub body: Option, /// if it's a generator. #[cfg_attr(feature = "serde-impl", serde(default, rename = "generator"))] @@ -61,6 +73,32 @@ impl Take for Function { } } +/// The braced body of a function, method, constructor, or block-bodied arrow +/// function. +/// +/// Unlike [`crate::BlockStmt`], a function body does not introduce an +/// additional block scope. Its statements are evaluated in the scope created +/// by the owning function-like node. +#[ast_node("FunctionBody")] +#[derive(Eq, Hash, EqIgnoreSpan, Default)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] +pub struct FunctionBody { + /// Span including the braces. + pub span: Span, + + pub stmts: Vec, +} + +impl Take for FunctionBody { + fn dummy() -> Self { + FunctionBody { + span: DUMMY_SP, + stmts: Vec::new(), + } + } +} + #[ast_node("Parameter")] #[derive(Eq, Hash, EqIgnoreSpan)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] diff --git a/deps/swc/crates/swc_ecma_ast/src/ident.rs b/deps/swc/crates/swc_ecma_ast/src/ident.rs index 38a68175f..afe9f25ae 100644 --- a/deps/swc/crates/swc_ecma_ast/src/ident.rs +++ b/deps/swc/crates/swc_ecma_ast/src/ident.rs @@ -17,27 +17,6 @@ use crate::{typescript::TsTypeAnn, Expr}; /// Identifier used as a pattern. #[derive(Clone, Debug, PartialEq, Eq, Hash, EqIgnoreSpan, Default)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr( - feature = "rkyv-impl", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] -#[cfg_attr( - feature = "rkyv-impl", - rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source)) -)] -#[cfg_attr( - feature = "rkyv-impl", - rkyv(bytecheck(bounds( - __C: rkyv::validation::ArchiveContext, - __C::Error: rkyv::rancor::Source - ))) -)] -#[cfg_attr(feature = "rkyv-impl", repr(C))] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] #[cfg_attr( @@ -46,11 +25,9 @@ use crate::{typescript::TsTypeAnn, Expr}; )] pub struct BindingIdent { #[cfg_attr(feature = "serde-impl", serde(flatten))] - #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] pub id: Ident, #[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))] - #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] #[cfg_attr( feature = "encoding-impl", encoding(with = "cbor4ii::core::types::Maybe") @@ -181,10 +158,8 @@ bridge_from!(BindingIdent, Ident, Id); #[derive(Eq, Hash, Default)] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct Ident { - #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] pub span: Span, - #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] pub ctxt: SyntaxContext, #[cfg_attr(feature = "serde-impl", serde(rename = "value"))] @@ -420,7 +395,6 @@ impl Ident { #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct IdentName { - #[cfg_attr(feature = "__rkyv", rkyv(omit_bounds))] pub span: Span, #[cfg_attr(feature = "serde-impl", serde(rename = "value"))] diff --git a/deps/swc/crates/swc_ecma_ast/src/jsx.rs b/deps/swc/crates/swc_ecma_ast/src/jsx.rs index 9fe62b375..75cc49a8b 100644 --- a/deps/swc/crates/swc_ecma_ast/src/jsx.rs +++ b/deps/swc/crates/swc_ecma_ast/src/jsx.rs @@ -1,5 +1,5 @@ use is_macro::Is; -use swc_atoms::Atom; +use swc_atoms::{Atom, Wtf8Atom}; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP}; use crate::{ @@ -214,7 +214,7 @@ pub enum JSXAttrValue { #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct JSXText { pub span: Span, - pub value: Atom, + pub value: Wtf8Atom, pub raw: Atom, } @@ -223,7 +223,7 @@ pub struct JSXText { impl<'a> arbitrary::Arbitrary<'a> for JSXText { fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result { let span = u.arbitrary()?; - let value = u.arbitrary::()?.into(); + let value = u.arbitrary::()?.into(); let raw = u.arbitrary::()?.into(); Ok(Self { span, value, raw }) diff --git a/deps/swc/crates/swc_ecma_ast/src/lib.rs b/deps/swc/crates/swc_ecma_ast/src/lib.rs index faed62d44..c499a1de7 100644 --- a/deps/swc/crates/swc_ecma_ast/src/lib.rs +++ b/deps/swc/crates/swc_ecma_ast/src/lib.rs @@ -21,7 +21,7 @@ pub use self::{ }, decl::{ClassDecl, Decl, FnDecl, UsingDecl, VarDecl, VarDeclKind, VarDeclarator}, expr::*, - function::{Function, Param, ParamOrTsParamProp}, + function::{Function, FunctionBody, Param, ParamOrTsParamProp}, ident::{ unsafe_id, unsafe_id_from_ident, BindingIdent, EsReserved, Id, Ident, IdentName, PrivateName, UnsafeId, @@ -66,11 +66,11 @@ pub use self::{ TsMethodSignature, TsModuleBlock, TsModuleDecl, TsModuleName, TsModuleRef, TsNamespaceBody, TsNamespaceDecl, TsNamespaceExportDecl, TsNonNullExpr, TsOptionalType, TsParamProp, TsParamPropParam, TsParenthesizedType, TsPropertySignature, TsQualifiedName, TsRestType, - TsSatisfiesExpr, TsSetterSignature, TsThisType, TsThisTypeOrIdent, TsTplLitType, - TsTupleElement, TsTupleType, TsType, TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, - TsTypeElement, TsTypeLit, TsTypeOperator, TsTypeOperatorOp, TsTypeParam, TsTypeParamDecl, - TsTypeParamInstantiation, TsTypePredicate, TsTypeQuery, TsTypeQueryExpr, TsTypeRef, - TsUnionOrIntersectionType, TsUnionType, + TsSatisfiesExpr, TsSetterSignature, TsThisParam, TsThisType, TsThisTypeOrIdent, + TsTplLitType, TsTupleElement, TsTupleType, TsType, TsTypeAliasDecl, TsTypeAnn, + TsTypeAssertion, TsTypeElement, TsTypeLit, TsTypeOperator, TsTypeOperatorOp, TsTypeParam, + TsTypeParamDecl, TsTypeParamInstantiation, TsTypePredicate, TsTypeQuery, TsTypeQueryExpr, + TsTypeRef, TsUnionOrIntersectionType, TsUnionType, }, }; @@ -400,367 +400,3 @@ impl EsVersion { EsVersion::EsNext } } - -/// Warning: The particular implementation of serialization and deserialization -/// of the ast nodes may change in the future, and so these types would be -/// removed. It's safe to say they will be serializable in some form or another, -/// but not necessarily with these specific types underlying the implementation. -/// As such, *use these types at your own risk*. -#[cfg(feature = "rkyv-impl")] -#[doc(hidden)] -pub use self::{ - class::{ - ArchivedAutoAccessor, ArchivedClass, ArchivedClassMember, ArchivedClassMethod, - ArchivedClassProp, ArchivedConstructor, ArchivedDecorator, ArchivedKey, ArchivedMethodKind, - ArchivedPrivateMethod, ArchivedPrivateProp, ArchivedStaticBlock, - }, - decl::{ - ArchivedClassDecl, ArchivedDecl, ArchivedFnDecl, ArchivedUsingDecl, ArchivedVarDecl, - ArchivedVarDeclKind, ArchivedVarDeclarator, - }, - expr::{ - ArchivedArrayLit, ArchivedArrowExpr, ArchivedAssignExpr, ArchivedAssignTarget, - ArchivedAwaitExpr, ArchivedBinExpr, ArchivedBlockStmtOrExpr, ArchivedCallExpr, - ArchivedCallee, ArchivedClassExpr, ArchivedCondExpr, ArchivedExpr, ArchivedExprOrSpread, - ArchivedFnExpr, ArchivedImport, ArchivedMemberExpr, ArchivedMemberProp, - ArchivedMetaPropExpr, ArchivedMetaPropKind, ArchivedNewExpr, ArchivedObjectLit, - ArchivedOptCall, ArchivedOptChainBase, ArchivedOptChainExpr, ArchivedParenExpr, - ArchivedPropOrSpread, ArchivedSeqExpr, ArchivedSpreadElement, ArchivedSuper, - ArchivedSuperProp, ArchivedSuperPropExpr, ArchivedTaggedTpl, ArchivedThisExpr, ArchivedTpl, - ArchivedTplElement, ArchivedUnaryExpr, ArchivedUpdateExpr, ArchivedYieldExpr, - }, - function::{ArchivedFunction, ArchivedParam, ArchivedParamOrTsParamProp}, - ident::{ArchivedBindingIdent, ArchivedIdent, ArchivedIdentName, ArchivedPrivateName}, - jsx::{ - ArchivedJSXAttr, ArchivedJSXAttrName, ArchivedJSXAttrOrSpread, ArchivedJSXAttrValue, - ArchivedJSXClosingElement, ArchivedJSXClosingFragment, ArchivedJSXElement, - ArchivedJSXElementChild, ArchivedJSXElementName, ArchivedJSXEmptyExpr, ArchivedJSXExpr, - ArchivedJSXExprContainer, ArchivedJSXFragment, ArchivedJSXMemberExpr, - ArchivedJSXNamespacedName, ArchivedJSXObject, ArchivedJSXOpeningElement, - ArchivedJSXOpeningFragment, ArchivedJSXSpreadChild, ArchivedJSXText, - }, - lit::{ - ArchivedBigInt, ArchivedBool, ArchivedLit, ArchivedNull, ArchivedNumber, ArchivedRegex, - ArchivedStr, - }, - module::{ArchivedModule, ArchivedModuleItem, ArchivedProgram, ArchivedScript}, - module_decl::{ - ArchivedDefaultDecl, ArchivedExportAll, ArchivedExportDecl, ArchivedExportDefaultDecl, - ArchivedExportDefaultExpr, ArchivedExportDefaultSpecifier, ArchivedExportNamedSpecifier, - ArchivedExportNamespaceSpecifier, ArchivedExportSpecifier, ArchivedImportDecl, - ArchivedImportDefaultSpecifier, ArchivedImportNamedSpecifier, ArchivedImportSpecifier, - ArchivedImportStarAsSpecifier, ArchivedModuleDecl, ArchivedModuleExportName, - ArchivedNamedExport, - }, - operators::{ArchivedAssignOp, ArchivedBinaryOp, ArchivedUnaryOp, ArchivedUpdateOp}, - pat::{ - ArchivedArrayPat, ArchivedAssignPat, ArchivedAssignPatProp, ArchivedKeyValuePatProp, - ArchivedObjectPat, ArchivedObjectPatProp, ArchivedPat, ArchivedRestPat, - }, - prop::{ - ArchivedAssignProp, ArchivedComputedPropName, ArchivedGetterProp, ArchivedKeyValueProp, - ArchivedMethodProp, ArchivedProp, ArchivedPropName, ArchivedSetterProp, - }, - stmt::{ - ArchivedBlockStmt, ArchivedBreakStmt, ArchivedCatchClause, ArchivedContinueStmt, - ArchivedDebuggerStmt, ArchivedDoWhileStmt, ArchivedEmptyStmt, ArchivedExprStmt, - ArchivedForHead, ArchivedForInStmt, ArchivedForOfStmt, ArchivedForStmt, ArchivedIfStmt, - ArchivedLabeledStmt, ArchivedReturnStmt, ArchivedStmt, ArchivedSwitchCase, - ArchivedSwitchStmt, ArchivedThrowStmt, ArchivedTryStmt, ArchivedVarDeclOrExpr, - ArchivedWhileStmt, ArchivedWithStmt, - }, - typescript::{ - ArchivedAccessibility, ArchivedTruePlusMinus, ArchivedTsArrayType, ArchivedTsAsExpr, - ArchivedTsCallSignatureDecl, ArchivedTsConditionalType, ArchivedTsConstAssertion, - ArchivedTsConstructSignatureDecl, ArchivedTsConstructorType, ArchivedTsEntityName, - ArchivedTsEnumDecl, ArchivedTsEnumMember, ArchivedTsEnumMemberId, - ArchivedTsExportAssignment, ArchivedTsExprWithTypeArgs, ArchivedTsExternalModuleRef, - ArchivedTsFnOrConstructorType, ArchivedTsFnParam, ArchivedTsFnType, - ArchivedTsGetterSignature, ArchivedTsImportEqualsDecl, ArchivedTsImportType, - ArchivedTsIndexSignature, ArchivedTsIndexedAccessType, ArchivedTsInferType, - ArchivedTsInstantiation, ArchivedTsInterfaceBody, ArchivedTsInterfaceDecl, - ArchivedTsIntersectionType, ArchivedTsKeywordType, ArchivedTsKeywordTypeKind, - ArchivedTsLit, ArchivedTsLitType, ArchivedTsMappedType, ArchivedTsMethodSignature, - ArchivedTsModuleBlock, ArchivedTsModuleDecl, ArchivedTsModuleName, ArchivedTsModuleRef, - ArchivedTsNamespaceBody, ArchivedTsNamespaceDecl, ArchivedTsNamespaceExportDecl, - ArchivedTsNonNullExpr, ArchivedTsOptionalType, ArchivedTsParamProp, - ArchivedTsParamPropParam, ArchivedTsParenthesizedType, ArchivedTsPropertySignature, - ArchivedTsQualifiedName, ArchivedTsRestType, ArchivedTsSatisfiesExpr, - ArchivedTsSetterSignature, ArchivedTsThisType, ArchivedTsThisTypeOrIdent, - ArchivedTsTplLitType, ArchivedTsTupleElement, ArchivedTsTupleType, ArchivedTsType, - ArchivedTsTypeAliasDecl, ArchivedTsTypeAnn, ArchivedTsTypeAssertion, ArchivedTsTypeElement, - ArchivedTsTypeLit, ArchivedTsTypeOperator, ArchivedTsTypeOperatorOp, ArchivedTsTypeParam, - ArchivedTsTypeParamDecl, ArchivedTsTypeParamInstantiation, ArchivedTsTypePredicate, - ArchivedTsTypeQuery, ArchivedTsTypeQueryExpr, ArchivedTsTypeRef, - ArchivedTsUnionOrIntersectionType, ArchivedTsUnionType, - }, -}; - -#[cfg(feature = "rkyv-impl")] -mod rkyv_layout_assert { - use crate::*; - - macro_rules! assert_size { - ($T:ty, $size:expr) => { - const _: fn() = || { - let _ = std::mem::transmute::<$T, [u8; $size]>; - }; - }; - } - - assert_size!(ArchivedProgram, 32); - assert_size!(ArchivedModule, 28); - assert_size!(ArchivedScript, 28); - assert_size!(ArchivedModuleItem, 52); - - // Class types - assert_size!(ArchivedAutoAccessor, 96); - assert_size!(ArchivedClass, 64); - assert_size!(ArchivedClassMember, 104); - assert_size!(ArchivedClassMethod, 64); - assert_size!(ArchivedClassProp, 88); - assert_size!(ArchivedConstructor, 96); - assert_size!(ArchivedDecorator, 12); - assert_size!(ArchivedKey, 48); - assert_size!(ArchivedMethodKind, 1); - assert_size!(ArchivedPrivateMethod, 36); - assert_size!(ArchivedPrivateProp, 64); - assert_size!(ArchivedStaticBlock, 28); - - // Declaration types - assert_size!(ArchivedClassDecl, 32); - assert_size!(ArchivedDecl, 36); - assert_size!(ArchivedFnDecl, 32); - assert_size!(ArchivedUsingDecl, 20); - assert_size!(ArchivedVarDecl, 24); - assert_size!(ArchivedVarDeclKind, 1); - assert_size!(ArchivedVarDeclarator, 56); - - // Expression types - assert_size!(ArchivedArrayLit, 16); - assert_size!(ArchivedArrowExpr, 44); - assert_size!(ArchivedAssignExpr, 60); - assert_size!(ArchivedAssignTarget, 44); - assert_size!(ArchivedAwaitExpr, 12); - assert_size!(ArchivedBinExpr, 20); - assert_size!(ArchivedBlockStmtOrExpr, 24); - assert_size!(ArchivedCallExpr, 44); - assert_size!(ArchivedCallee, 16); - assert_size!(ArchivedClassExpr, 32); - assert_size!(ArchivedCondExpr, 20); - assert_size!(ArchivedExpr, 64); - assert_size!(ArchivedExprOrSpread, 16); - assert_size!(ArchivedFnExpr, 32); - assert_size!(ArchivedImport, 12); - assert_size!(ArchivedMemberExpr, 32); - assert_size!(ArchivedMemberProp, 20); - assert_size!(ArchivedMetaPropExpr, 12); - assert_size!(ArchivedMetaPropKind, 1); - assert_size!(ArchivedNewExpr, 36); - assert_size!(ArchivedObjectLit, 16); - assert_size!(ArchivedOptCall, 32); - assert_size!(ArchivedOptChainBase, 36); - assert_size!(ArchivedOptChainExpr, 16); - assert_size!(ArchivedParenExpr, 12); - assert_size!(ArchivedPropOrSpread, 16); - assert_size!(ArchivedSeqExpr, 16); - assert_size!(ArchivedSpreadElement, 12); - assert_size!(ArchivedSuper, 8); - assert_size!(ArchivedSuperProp, 20); - assert_size!(ArchivedSuperPropExpr, 36); - assert_size!(ArchivedTaggedTpl, 28); - assert_size!(ArchivedThisExpr, 8); - assert_size!(ArchivedTpl, 24); - assert_size!(ArchivedTplElement, 32); - assert_size!(ArchivedUnaryExpr, 16); - assert_size!(ArchivedUpdateExpr, 16); - assert_size!(ArchivedYieldExpr, 20); - - // Function types - assert_size!(ArchivedFunction, 72); - assert_size!(ArchivedParam, 52); - assert_size!(ArchivedParamOrTsParamProp, 60); - - // Identifier types - assert_size!(ArchivedBindingIdent, 32); - assert_size!(ArchivedIdent, 24); - assert_size!(ArchivedIdentName, 16); - assert_size!(ArchivedPrivateName, 16); - - // JSX types - assert_size!(ArchivedJSXAttr, 92); - assert_size!(ArchivedJSXAttrName, 44); - assert_size!(ArchivedJSXAttrOrSpread, 96); - assert_size!(ArchivedJSXAttrValue, 36); - assert_size!(ArchivedJSXClosingElement, 64); - assert_size!(ArchivedJSXClosingFragment, 8); - assert_size!(ArchivedJSXElement, 168); - assert_size!(ArchivedJSXElementChild, 36); - assert_size!(ArchivedJSXElementName, 56); - assert_size!(ArchivedJSXEmptyExpr, 8); - assert_size!(ArchivedJSXExpr, 12); - assert_size!(ArchivedJSXExprContainer, 20); - assert_size!(ArchivedJSXFragment, 32); - assert_size!(ArchivedJSXMemberExpr, 52); - assert_size!(ArchivedJSXNamespacedName, 40); - assert_size!(ArchivedJSXObject, 28); - assert_size!(ArchivedJSXOpeningElement, 84); - assert_size!(ArchivedJSXOpeningFragment, 8); - assert_size!(ArchivedJSXSpreadChild, 12); - assert_size!(ArchivedJSXText, 24); - - // Literal types - assert_size!(ArchivedBigInt, 28); - assert_size!(ArchivedBool, 12); - assert_size!(ArchivedLit, 40); - assert_size!(ArchivedNull, 8); - assert_size!(ArchivedNumber, 32); - assert_size!(ArchivedRegex, 24); - assert_size!(ArchivedStr, 28); - - // Module declaration types - assert_size!(ArchivedDefaultDecl, 36); - assert_size!(ArchivedExportAll, 24); - assert_size!(ArchivedExportDecl, 44); - assert_size!(ArchivedExportDefaultDecl, 44); - assert_size!(ArchivedExportDefaultExpr, 12); - assert_size!(ArchivedExportDefaultSpecifier, 24); - assert_size!(ArchivedExportNamedSpecifier, 80); - assert_size!(ArchivedExportNamespaceSpecifier, 40); - assert_size!(ArchivedExportSpecifier, 84); - assert_size!(ArchivedImportDecl, 36); - assert_size!(ArchivedImportDefaultSpecifier, 32); - assert_size!(ArchivedImportNamedSpecifier, 72); - assert_size!(ArchivedImportSpecifier, 76); - assert_size!(ArchivedImportStarAsSpecifier, 32); - assert_size!(ArchivedModuleDecl, 48); - assert_size!(ArchivedModuleExportName, 32); - assert_size!(ArchivedNamedExport, 36); - - // Operator types - assert_size!(ArchivedAssignOp, 1); - assert_size!(ArchivedBinaryOp, 1); - assert_size!(ArchivedUnaryOp, 1); - assert_size!(ArchivedUpdateOp, 1); - - // Pattern types - assert_size!(ArchivedArrayPat, 28); - assert_size!(ArchivedAssignPat, 16); - assert_size!(ArchivedAssignPatProp, 48); - assert_size!(ArchivedKeyValuePatProp, 48); - assert_size!(ArchivedObjectPat, 28); - assert_size!(ArchivedObjectPatProp, 56); - assert_size!(ArchivedPat, 36); - assert_size!(ArchivedRestPat, 28); - - // Property types - assert_size!(ArchivedAssignProp, 36); - assert_size!(ArchivedComputedPropName, 12); - assert_size!(ArchivedGetterProp, 80); - assert_size!(ArchivedKeyValueProp, 48); - assert_size!(ArchivedMethodProp, 48); - assert_size!(ArchivedProp, 128); - assert_size!(ArchivedPropName, 40); - assert_size!(ArchivedSetterProp, 120); - - // Statement types - assert_size!(ArchivedBlockStmt, 20); - assert_size!(ArchivedBreakStmt, 36); - assert_size!(ArchivedCatchClause, 68); - assert_size!(ArchivedContinueStmt, 36); - assert_size!(ArchivedDebuggerStmt, 8); - assert_size!(ArchivedDoWhileStmt, 16); - assert_size!(ArchivedEmptyStmt, 8); - assert_size!(ArchivedExprStmt, 12); - assert_size!(ArchivedForHead, 8); - assert_size!(ArchivedForInStmt, 24); - assert_size!(ArchivedForOfStmt, 28); - assert_size!(ArchivedForStmt, 40); - assert_size!(ArchivedIfStmt, 24); - assert_size!(ArchivedLabeledStmt, 36); - assert_size!(ArchivedReturnStmt, 16); - assert_size!(ArchivedStmt, 44); - assert_size!(ArchivedSwitchCase, 24); - assert_size!(ArchivedSwitchStmt, 20); - assert_size!(ArchivedThrowStmt, 12); - assert_size!(ArchivedTryStmt, 124); - assert_size!(ArchivedVarDeclOrExpr, 8); - assert_size!(ArchivedWhileStmt, 16); - assert_size!(ArchivedWithStmt, 16); - - // TypeScript types - assert_size!(ArchivedAccessibility, 1); - assert_size!(ArchivedTruePlusMinus, 1); - assert_size!(ArchivedTsArrayType, 12); - assert_size!(ArchivedTsAsExpr, 16); - assert_size!(ArchivedTsCallSignatureDecl, 32); - assert_size!(ArchivedTsConditionalType, 24); - assert_size!(ArchivedTsConstAssertion, 12); - assert_size!(ArchivedTsConstructSignatureDecl, 32); - assert_size!(ArchivedTsConstructorType, 32); - assert_size!(ArchivedTsEntityName, 28); - assert_size!(ArchivedTsEnumDecl, 44); - assert_size!(ArchivedTsEnumMember, 48); - assert_size!(ArchivedTsEnumMemberId, 32); - assert_size!(ArchivedTsExportAssignment, 12); - assert_size!(ArchivedTsExprWithTypeArgs, 20); - assert_size!(ArchivedTsExternalModuleRef, 36); - assert_size!(ArchivedTsFnOrConstructorType, 36); - assert_size!(ArchivedTsFnParam, 36); - assert_size!(ArchivedTsFnType, 28); - assert_size!(ArchivedTsGetterSignature, 24); - assert_size!(ArchivedTsImportEqualsDecl, 76); - assert_size!(ArchivedTsImportType, 92); - assert_size!(ArchivedTsIndexSignature, 28); - assert_size!(ArchivedTsIndexedAccessType, 20); - assert_size!(ArchivedTsInferType, 60); - assert_size!(ArchivedTsInstantiation, 16); - assert_size!(ArchivedTsInterfaceBody, 16); - assert_size!(ArchivedTsInterfaceDecl, 68); - assert_size!(ArchivedTsIntersectionType, 16); - assert_size!(ArchivedTsKeywordType, 12); - assert_size!(ArchivedTsKeywordTypeKind, 1); - assert_size!(ArchivedTsLit, 40); - assert_size!(ArchivedTsLitType, 48); - assert_size!(ArchivedTsMappedType, 84); - assert_size!(ArchivedTsMethodSignature, 40); - assert_size!(ArchivedTsModuleBlock, 16); - assert_size!(ArchivedTsModuleDecl, 92); - assert_size!(ArchivedTsModuleName, 32); - assert_size!(ArchivedTsModuleRef, 40); - assert_size!(ArchivedTsNamespaceBody, 44); - assert_size!(ArchivedTsNamespaceDecl, 40); - assert_size!(ArchivedTsNamespaceExportDecl, 32); - assert_size!(ArchivedTsNonNullExpr, 12); - assert_size!(ArchivedTsOptionalType, 12); - assert_size!(ArchivedTsParamProp, 56); - assert_size!(ArchivedTsParamPropParam, 36); - assert_size!(ArchivedTsParenthesizedType, 12); - assert_size!(ArchivedTsPropertySignature, 28); - assert_size!(ArchivedTsQualifiedName, 52); - assert_size!(ArchivedTsRestType, 12); - assert_size!(ArchivedTsSatisfiesExpr, 16); - assert_size!(ArchivedTsSetterSignature, 52); - assert_size!(ArchivedTsThisType, 8); - assert_size!(ArchivedTsThisTypeOrIdent, 28); - assert_size!(ArchivedTsTplLitType, 24); - assert_size!(ArchivedTsTupleElement, 52); - assert_size!(ArchivedTsTupleType, 16); - assert_size!(ArchivedTsType, 120); - assert_size!(ArchivedTsTypeAliasDecl, 48); - assert_size!(ArchivedTsTypeAnn, 12); - assert_size!(ArchivedTsTypeAssertion, 16); - assert_size!(ArchivedTsTypeElement, 56); - assert_size!(ArchivedTsTypeLit, 16); - assert_size!(ArchivedTsTypeOperator, 16); - assert_size!(ArchivedTsTypeOperatorOp, 1); - assert_size!(ArchivedTsTypeParam, 52); - assert_size!(ArchivedTsTypeParamDecl, 16); - assert_size!(ArchivedTsTypeParamInstantiation, 16); - assert_size!(ArchivedTsTypePredicate, 48); - assert_size!(ArchivedTsTypeQuery, 112); - assert_size!(ArchivedTsTypeQueryExpr, 96); - assert_size!(ArchivedTsTypeRef, 44); - assert_size!(ArchivedTsUnionOrIntersectionType, 20); - assert_size!(ArchivedTsUnionType, 16); -} diff --git a/deps/swc/crates/swc_ecma_ast/src/lit.rs b/deps/swc/crates/swc_ecma_ast/src/lit.rs index 904430f22..307198057 100644 --- a/deps/swc/crates/swc_ecma_ast/src/lit.rs +++ b/deps/swc/crates/swc_ecma_ast/src/lit.rs @@ -86,7 +86,6 @@ impl Lit { #[derive(Eq, Hash)] pub struct BigInt { pub span: Span, - #[cfg_attr(any(feature = "rkyv-impl"), rkyv(with = EncodeBigInt))] #[cfg_attr(feature = "encoding-impl", encoding(with = "EncodeBigInt2"))] pub value: Box, @@ -138,61 +137,6 @@ impl<'de> cbor4ii::core::dec::Decode<'de> for EncodeBigInt2> { } } -#[cfg(feature = "rkyv-impl")] -#[derive(Debug, Clone, Copy)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(C))] -pub struct EncodeBigInt; - -#[cfg(feature = "rkyv-impl")] -impl rkyv::with::ArchiveWith> for EncodeBigInt { - type Archived = rkyv::Archived; - type Resolver = rkyv::Resolver; - - fn resolve_with( - field: &Box, - resolver: Self::Resolver, - out: rkyv::Place, - ) { - use rkyv::Archive; - - let s = field.to_string(); - s.resolve(resolver, out); - } -} - -#[cfg(feature = "rkyv-impl")] -impl rkyv::with::SerializeWith, S> for EncodeBigInt -where - S: ?Sized + rancor::Fallible + rkyv::ser::Writer, - S::Error: rancor::Source, -{ - fn serialize_with( - field: &Box, - serializer: &mut S, - ) -> Result { - let field = field.to_string(); - rkyv::string::ArchivedString::serialize_from_str(&field, serializer) - } -} - -#[cfg(feature = "rkyv-impl")] -impl rkyv::with::DeserializeWith, Box, D> for EncodeBigInt -where - D: ?Sized + rancor::Fallible, -{ - fn deserialize_with( - field: &rkyv::Archived, - deserializer: &mut D, - ) -> Result, D::Error> { - use rkyv::Deserialize; - - let s: String = field.deserialize(deserializer)?; - - Ok(Box::new(s.parse().unwrap())) - } -} - #[cfg(feature = "arbitrary")] #[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))] impl<'a> arbitrary::Arbitrary<'a> for BigInt { @@ -578,13 +522,14 @@ impl<'a> arbitrary::Arbitrary<'a> for Regex { /// All of `Box`, `Expr`, `Lit`, `Number` implements `From<64>` and /// `From`. -#[ast_node("NumericLiteral")] +#[ast_node("NumericLiteral", no_partial_eq)] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct Number { pub span: Span, - /// **Note**: This should not be `NaN`. Use [crate::Ident] to represent NaN. + /// The numeric value, including `NaN` and positive or negative infinity. /// - /// If you store `NaN` in this field, a hash map will behave strangely. + /// Equality treats all `NaN` representations as equal and distinguishes + /// positive and negative zero. pub value: f64, /// Use `None` value only for transformations to avoid recalculate @@ -596,38 +541,52 @@ pub struct Number { pub raw: Option, } +impl PartialEq for Number { + fn eq(&self, other: &Self) -> bool { + self.span == other.span && number_value_eq(self.value, other.value) && self.raw == other.raw + } +} + impl Eq for Number {} impl EqIgnoreSpan for Number { fn eq_ignore_span(&self, other: &Self) -> bool { - self.value == other.value && self.value.is_sign_positive() == other.value.is_sign_positive() + number_value_eq(self.value, other.value) } } -#[allow(clippy::derived_hash_with_manual_eq)] -#[allow(unnecessary_transmutes)] impl Hash for Number { fn hash(&self, state: &mut H) { - fn integer_decode(val: f64) -> (u64, i16, i8) { - let bits: u64 = val.to_bits(); - let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 }; - let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16; - let mantissa = if exponent == 0 { - (bits & 0xfffffffffffff) << 1 - } else { - (bits & 0xfffffffffffff) | 0x10000000000000 - }; - - exponent -= 1023 + 52; - (mantissa, exponent, sign) - } - self.span.hash(state); - integer_decode(self.value).hash(state); + canonical_number_bits(self.value).hash(state); self.raw.hash(state); } } +/// Compares numeric values using the equality semantics required by `Number`. +/// +/// NaN payloads are not observable in ECMAScript, while the sign of zero is. +#[inline] +fn number_value_eq(left: f64, right: f64) -> bool { + // Compare bits so positive and negative zero remain distinct. + left.to_bits() == right.to_bits() || (left.is_nan() && right.is_nan()) +} + +/// Returns bits consistent with [`number_value_eq`]. +/// +/// This follows the NaN canonicalization used by `ordered-float`, but retains +/// the sign bit of zero. +#[inline] +fn canonical_number_bits(value: f64) -> u64 { + const CANONICAL_NAN_BITS: u64 = 0x7ff8_0000_0000_0000; + + if value.is_nan() { + CANONICAL_NAN_BITS + } else { + value.to_bits() + } +} + impl Display for Number { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { if self.value.is_infinite() { diff --git a/deps/swc/crates/swc_ecma_ast/src/module_decl.rs b/deps/swc/crates/swc_ecma_ast/src/module_decl.rs index 6e0fe1477..1cd9d8fe1 100644 --- a/deps/swc/crates/swc_ecma_ast/src/module_decl.rs +++ b/deps/swc/crates/swc_ecma_ast/src/module_decl.rs @@ -145,12 +145,6 @@ pub struct ImportDecl { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, EqIgnoreSpan)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr( feature = "encoding-impl", diff --git a/deps/swc/crates/swc_ecma_ast/src/operators.rs b/deps/swc/crates/swc_ecma_ast/src/operators.rs index 27c4b0b43..eb37349d2 100644 --- a/deps/swc/crates/swc_ecma_ast/src/operators.rs +++ b/deps/swc/crates/swc_ecma_ast/src/operators.rs @@ -4,12 +4,6 @@ use swc_common::EqIgnoreSpan; #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -122,12 +116,6 @@ impl BinaryOp { #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -204,12 +192,6 @@ impl AssignOp { #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -226,12 +208,6 @@ pub enum UpdateOp { #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) diff --git a/deps/swc/crates/swc_ecma_ast/src/prop.rs b/deps/swc/crates/swc_ecma_ast/src/prop.rs index 94c09cc92..63e325183 100644 --- a/deps/swc/crates/swc_ecma_ast/src/prop.rs +++ b/deps/swc/crates/swc_ecma_ast/src/prop.rs @@ -6,9 +6,7 @@ use crate::{ function::Function, ident::Ident, lit::{BigInt, Number, Str}, - stmt::BlockStmt, - typescript::TsTypeAnn, - Id, IdentName, MemberProp, Pat, + Id, IdentName, MemberProp, }; #[ast_node] @@ -69,18 +67,8 @@ pub struct AssignProp { pub struct GetterProp { pub span: Span, pub key: PropName, - #[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))] - #[cfg_attr( - feature = "encoding-impl", - encoding(with = "cbor4ii::core::types::Maybe") - )] - pub type_ann: Option>, - #[cfg_attr(feature = "serde-impl", serde(default))] - #[cfg_attr( - feature = "encoding-impl", - encoding(with = "cbor4ii::core::types::Maybe") - )] - pub body: Option, + /// Function backing the getter. + pub function: Box, } #[ast_node("SetterProperty")] #[derive(Eq, Hash, EqIgnoreSpan, Default)] @@ -89,18 +77,8 @@ pub struct GetterProp { pub struct SetterProp { pub span: Span, pub key: PropName, - #[cfg_attr( - feature = "encoding-impl", - encoding(with = "cbor4ii::core::types::Maybe") - )] - pub this_param: Option, - pub param: Box, - #[cfg_attr(feature = "serde-impl", serde(default))] - #[cfg_attr( - feature = "encoding-impl", - encoding(with = "cbor4ii::core::types::Maybe") - )] - pub body: Option, + /// Function backing the setter. + pub function: Box, } #[ast_node("MethodProperty")] #[derive(Eq, Hash, EqIgnoreSpan)] diff --git a/deps/swc/crates/swc_ecma_ast/src/stmt.rs b/deps/swc/crates/swc_ecma_ast/src/stmt.rs index 328308aec..cbca076ec 100644 --- a/deps/swc/crates/swc_ecma_ast/src/stmt.rs +++ b/deps/swc/crates/swc_ecma_ast/src/stmt.rs @@ -328,6 +328,7 @@ pub struct IfStmt { #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] pub struct SwitchStmt { pub span: Span, + pub body_ctxt: SyntaxContext, pub discriminant: Box, pub cases: Vec, } diff --git a/deps/swc/crates/swc_ecma_ast/src/typescript.rs b/deps/swc/crates/swc_ecma_ast/src/typescript.rs index c3d9b3333..450758124 100644 --- a/deps/swc/crates/swc_ecma_ast/src/typescript.rs +++ b/deps/swc/crates/swc_ecma_ast/src/typescript.rs @@ -33,6 +33,26 @@ pub struct TsTypeAnn { pub type_ann: Box, } +/// TypeScript or Flow `this` parameter of a function. +/// +/// This parameter describes the type of `this` inside the function and is not +/// emitted as a JavaScript runtime parameter. +#[ast_node("TsThisParameter")] +#[derive(Eq, Hash, EqIgnoreSpan)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] +pub struct TsThisParam { + pub span: Span, + #[cfg_attr(feature = "serde-impl", serde(rename = "thisSpan"))] + pub this_span: Span, + #[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))] + #[cfg_attr( + feature = "encoding-impl", + encoding(with = "cbor4ii::core::types::Maybe") + )] + pub type_ann: Option>, +} + #[ast_node("TsTypeParameterDeclaration")] #[derive(Eq, Hash, EqIgnoreSpan)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] @@ -452,12 +472,6 @@ pub struct TsKeywordType { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, EqIgnoreSpan)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr( feature = "encoding-impl", @@ -813,12 +827,6 @@ pub struct TsTypeOperator { #[derive(StringEnum, Clone, Copy, PartialEq, Eq, Hash, EqIgnoreSpan)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -848,12 +856,6 @@ pub struct TsIndexedAccessType { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EqIgnoreSpan)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -1281,12 +1283,6 @@ pub struct TsSatisfiesExpr { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EqIgnoreSpan)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[cfg_attr( - any(feature = "rkyv-impl"), - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv-impl", repr(u32))] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))] #[cfg_attr( diff --git a/deps/swc/crates/swc_ecma_codegen/Cargo.toml b/deps/swc/crates/swc_ecma_codegen/Cargo.toml index b8f9e87f7..61fab61f8 100644 --- a/deps/swc/crates/swc_ecma_codegen/Cargo.toml +++ b/deps/swc/crates/swc_ecma_codegen/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_codegen" repository = { workspace = true } -version = "28.0.2" +version = "32.0.0" [features] # This does not enable serde for ast nodes. @@ -20,39 +20,40 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } bench = false [dependencies] -ascii = { workspace = true } -compact_str = { workspace = true } -dragonbox_ecma = { workspace = true } -memchr = { workspace = true } -num-bigint = { workspace = true, features = ["serde"] } -once_cell = { workspace = true } -regex = { workspace = true } -rustc-hash = { workspace = true } -serde = { workspace = true } -tracing = { workspace = true } - -swc_allocator = { version = "4.0.1", path = "../swc_allocator", default-features = false, features = [ +ascii = { workspace = true } +compact_str = { workspace = true } +dragonbox_ecma = { workspace = true } +memchr = { workspace = true } +num-bigint = { workspace = true, features = ["serde"] } +once_cell = { workspace = true } +regex = { workspace = true } +rustc-hash = { workspace = true } +serde = { workspace = true } +tracing = { workspace = true } + +swc_allocator = { version = "5.0.0", path = "../swc_allocator", default-features = false, features = [ "hashbrown", ] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } swc_ecma_codegen_macros = { version = "2.0.2", path = "../swc_ecma_codegen_macros" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } [dev-dependencies] base64 = { workspace = true } codspeed-criterion-compat = { workspace = true } serde_json = { workspace = true } -swc_allocator = { version = "4.0.1", path = "../swc_allocator" } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_allocator = { version = "5.0.0", path = "../swc_allocator" } +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "sourcemap", ] } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_testing = { version = "24.0.1", path = "../swc_ecma_testing" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_testing = { version = "27.0.0", path = "../swc_ecma_testing" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } swc_sourcemap = { workspace = true } +testing = { version = "27.0.0", path = "../testing" } [[bench]] harness = false diff --git a/deps/swc/crates/swc_ecma_codegen/src/class.rs b/deps/swc/crates/swc_ecma_codegen/src/class.rs index 1936da0b2..3b0c4c398 100644 --- a/deps/swc/crates/swc_ecma_codegen/src/class.rs +++ b/deps/swc/crates/swc_ecma_codegen/src/class.rs @@ -8,7 +8,7 @@ use crate::{ scope_helpers::{for_each_constructor_param_binding, for_each_param_binding}, text_writer::{BindingStorage, ScopeKind, WriteJs}, util::StartsWithAlphaNum, - Emitter, ListFormat, Result, SourceMapperExt, + Emitter, ExprPrecedence, ListFormat, Result, SourceMapperExt, }; impl Emitter<'_, W, S> @@ -21,13 +21,13 @@ where space!(self); keyword!(self, "extends"); - if super_class.starts_with_alpha_num() { + if self.expr_starts_with_alpha_num_after_codegen(super_class, ExprPrecedence::POSTFIX) { space!(self); } else { formatting_space!(self) } - emit!(self, node.super_class); + self.emit_expr_with_precedence(super_class, ExprPrecedence::POSTFIX)?; emit!(self, node.super_type_params); } @@ -94,13 +94,15 @@ impl MacroNode for Class { space!(emitter); keyword!(emitter, "extends"); - if super_class.starts_with_alpha_num() { + if emitter + .expr_starts_with_alpha_num_after_codegen(super_class, ExprPrecedence::POSTFIX) + { space!(emitter); } else { formatting_space!(emitter) } - emit!(self.super_class); + emitter.emit_expr_with_precedence(super_class, ExprPrecedence::POSTFIX)?; emit!(self.super_type_params); } @@ -389,14 +391,7 @@ impl MacroNode for ClassMethod { emit!(type_params); } - punct!(emitter, "("); - emitter.emit_list( - self.function.span, - Some(&self.function.params), - ListFormat::CommaListElements, - )?; - - punct!(emitter, ")"); + emitter.emit_fn_params(&self.function)?; if let Some(ty) = &self.function.return_type { punct!(emitter, ":"); diff --git a/deps/swc/crates/swc_ecma_codegen/src/lib.rs b/deps/swc/crates/swc_ecma_codegen/src/lib.rs index db788f1de..2dee0e203 100644 --- a/deps/swc/crates/swc_ecma_codegen/src/lib.rs +++ b/deps/swc/crates/swc_ecma_codegen/src/lib.rs @@ -119,6 +119,41 @@ where pub wr: W, } +/// The minimum precedence required by an expression's parent. +/// +/// Most expressions are already parenthesized by the fixer, but non-finite +/// numeric literals can expand into division expressions while being emitted. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub(crate) struct ExprPrecedence(u8); + +impl ExprPrecedence { + const EXPONENTIATION: Self = Self(11); + const LOWEST: Self = Self(0); + const MULTIPLICATIVE: Self = Self(10); + const POSTFIX: Self = Self(13); + const PREFIX: Self = Self(12); + + #[inline] + fn for_binary_left(op: BinaryOp) -> Self { + if op == op!("**") { + // Exponentiation cannot have an unparenthesized unary expression on + // the left-hand side. + Self::PREFIX + } else { + Self(op.precedence() - 1) + } + } + + #[inline] + fn for_binary_right(op: BinaryOp) -> Self { + if op == op!("**") { + Self::MULTIPLICATIVE + } else { + Self(op.precedence()) + } + } +} + enum CowStr<'a> { Borrowed(&'a str), Owned(CompactString), @@ -154,6 +189,43 @@ where node.emit_with(self) } + /// Emits an expression with the precedence required by its parent. + /// + /// This only changes non-finite numeric literals. All other expressions + /// continue through their existing emitters. + #[inline] + fn emit_expr_with_precedence(&mut self, expr: &Expr, precedence: ExprPrecedence) -> Result { + if let Expr::Lit(Lit::Num(num)) = expr { + if !num.value.is_finite() { + self.emit_num_lit_expr(num, precedence, false)?; + + if self.comments.is_some() { + self.emit_trailing_comments_of_pos(expr.span().hi, true, true)?; + } + + return Ok(()); + } + } + + expr.emit_with(self) + } + + /// Returns whether an expression starts with an alphanumeric token after + /// applying code-generation-only rewrites. + #[inline] + fn expr_starts_with_alpha_num_after_codegen( + &self, + expr: &Expr, + precedence: ExprPrecedence, + ) -> bool { + match expr { + Expr::Lit(Lit::Num(num)) if !num.value.is_finite() => { + self.non_finite_expr_starts_with_alpha_num(num, precedence) + } + _ => expr.starts_with_alpha_num(), + } + } + #[inline(always)] fn scope_tracking_enabled(&self) -> bool { self.wr.has_scope_tracking() @@ -208,14 +280,15 @@ where keyword!(self, "new"); - let starts_with_alpha_num = node.callee.starts_with_alpha_num(); + let starts_with_alpha_num = + self.expr_starts_with_alpha_num_after_codegen(&node.callee, ExprPrecedence::POSTFIX); if starts_with_alpha_num { space!(self); } else { formatting_space!(self); } - emit!(self, node.callee); + self.emit_expr_with_precedence(&node.callee, ExprPrecedence::POSTFIX)?; if let Some(type_args) = &node.type_args { emit!(self, type_args); @@ -320,7 +393,7 @@ where span.is_pure() || self .comments - .is_some_and(|comments| comments.has_leading(node.right.span().lo)) + .is_some_and(|comments| comments.has_leading(span.lo)) } else { require_space_before_rhs(&node.right, &node.op) } @@ -336,7 +409,22 @@ where } else { formatting_space!(self); } - emit!(self, node.right); + self.emit_expr_with_precedence(&node.right, ExprPrecedence::for_binary_right(node.op))?; + + Ok(()) + } + + fn emit_fn_params(&mut self, node: &Function) -> Result { + punct!(self, "("); + if let Some(this_param) = &node.this_param { + emit!(self, this_param); + if !node.params.is_empty() { + punct!(self, ","); + formatting_space!(self); + } + } + self.emit_list(node.span, Some(&node.params), ListFormat::CommaListElements)?; + punct!(self, ")"); Ok(()) } @@ -347,9 +435,7 @@ where emit!(self, type_params); } - punct!(self, "("); - self.emit_list(node.span, Some(&node.params), ListFormat::CommaListElements)?; - punct!(self, ")"); + self.emit_fn_params(node)?; if let Some(ty) = &node.return_type { punct!(self, ":"); @@ -359,7 +445,7 @@ where if let Some(body) = &node.body { formatting_space!(self); - self.emit_block_stmt_inner(body, true)?; + self.emit_function_body_inner(body, true)?; } else { semi!(self); } @@ -774,14 +860,34 @@ where self.emit_leading_comments_of_span(node.span(), false)?; self.start_scope(None, ScopeKind::Block, false, false, Some(node.span))?; + self.emit_braced_stmts(node.span, &node.stmts, skip_first_src_map)?; + self.end_scope()?; + Ok(()) + } + + fn emit_function_body_inner( + &mut self, + node: &FunctionBody, + skip_first_src_map: bool, + ) -> Result { + self.emit_leading_comments_of_span(node.span(), false)?; + self.emit_braced_stmts(node.span, &node.stmts, skip_first_src_map) + } + + fn emit_braced_stmts( + &mut self, + span: Span, + stmts: &[Stmt], + skip_first_src_map: bool, + ) -> Result { if !skip_first_src_map { - srcmap!(self, node, true); + srcmap!(self, span, true); } punct!(self, "{"); - let emit_new_line = !self.cfg.minify - && !(node.stmts.is_empty() && is_empty_comments(&node.span(), &self.comments)); + let emit_new_line = + !self.cfg.minify && !(stmts.is_empty() && is_empty_comments(&span, &self.comments)); let mut list_format = ListFormat::MultiLineBlockStatements; @@ -789,13 +895,12 @@ where list_format -= ListFormat::MultiLine | ListFormat::Indented; } - self.emit_list(node.span(), Some(&node.stmts), list_format)?; + self.emit_list(span, Some(stmts), list_format)?; - self.emit_leading_comments_of_span(node.span(), true)?; + self.emit_leading_comments_of_span(span, true)?; - srcmap!(self, node, false, true); + srcmap!(self, span, false, true); punct!(self, "}"); - self.end_scope()?; Ok(()) } @@ -1574,7 +1679,7 @@ impl MacroNode for Callee { if let Expr::New(new) = &**e { emitter.emit_new(new, false)?; } else { - emit!(e); + emitter.emit_expr_with_precedence(e, ExprPrecedence::POSTFIX)?; } } Callee::Super(n) => emit!(n), @@ -1684,7 +1789,7 @@ impl MacroNode for OptChainExpr { if let Expr::New(new) = &*e.obj { emitter.emit_new(new, false)?; } else { - emit!(e.obj); + emitter.emit_expr_with_precedence(&e.obj, ExprPrecedence::POSTFIX)?; } if self.optional { punct!(emitter, "?."); @@ -1702,7 +1807,7 @@ impl MacroNode for OptChainExpr { } OptChainBase::Call(e) => { debug_assert!(!e.callee.is_new()); - emit!(e.callee); + emitter.emit_expr_with_precedence(&e.callee, ExprPrecedence::POSTFIX)?; if self.optional { punct!(emitter, "?."); @@ -1787,7 +1892,8 @@ impl MacroNode for MemberExpr { emitter.emit_new(new, false)?; } Expr::Lit(Lit::Num(num)) => { - needs_2dots_for_property_access = emitter.emit_num_lit_internal(num, true)?; + needs_2dots_for_property_access = + emitter.emit_num_lit_expr(num, ExprPrecedence::POSTFIX, true)?; } _ => { emit!(self.obj); @@ -2012,7 +2118,10 @@ impl MacroNode for BinExpr { for (i, left) in lefts.into_iter().rev().enumerate() { if i == 0 { - emit!(left.left); + emitter.emit_expr_with_precedence( + &left.left, + ExprPrecedence::for_binary_left(left.op), + )?; } // Check if it's last if i + 1 != len { @@ -2114,13 +2223,13 @@ impl MacroNode for FnExpr { } #[node_impl] -impl MacroNode for BlockStmtOrExpr { +impl MacroNode for ArrowFunctionBody { fn emit(&mut self, emitter: &mut Macro) -> Result { match self { - BlockStmtOrExpr::BlockStmt(block) => { - emitter.emit_block_stmt_inner(block, true)?; + ArrowFunctionBody::FunctionBody(body) => { + emitter.emit_function_body_inner(body, true)?; } - BlockStmtOrExpr::Expr(expr) => { + ArrowFunctionBody::Expr(expr) => { emitter.wr.increase_indent()?; emit!(expr); emitter.wr.decrease_indent()?; @@ -2228,7 +2337,7 @@ impl MacroNode for TaggedTpl { if let Expr::New(new) = &*self.tag { emitter.emit_new(new, false)?; } else { - emit!(self.tag); + emitter.emit_expr_with_precedence(&self.tag, ExprPrecedence::POSTFIX)?; } emit!(self.type_params); @@ -2267,7 +2376,7 @@ impl MacroNode for UnaryExpr { formatting_space!(emitter); } - emit!(self.arg); + emitter.emit_expr_with_precedence(&self.arg, ExprPrecedence::EXPONENTIATION)?; Ok(()) } @@ -2354,7 +2463,7 @@ impl MacroNode for AwaitExpr { keyword!(emitter, "await"); space!(emitter); - emit!(self.arg); + emitter.emit_expr_with_precedence(&self.arg, ExprPrecedence::EXPONENTIATION)?; Ok(()) } diff --git a/deps/swc/crates/swc_ecma_codegen/src/lit.rs b/deps/swc/crates/swc_ecma_codegen/src/lit.rs index fa4f81336..a932f44d1 100644 --- a/deps/swc/crates/swc_ecma_codegen/src/lit.rs +++ b/deps/swc/crates/swc_ecma_codegen/src/lit.rs @@ -6,10 +6,45 @@ use swc_atoms::wtf8::{CodePoint, Wtf8}; use swc_common::{Spanned, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_codegen_macros::node_impl; +use swc_ecma_utils::number::minify_number; #[cfg(swc_ast_unknown)] use crate::unknown_error; -use crate::{text_writer::WriteJs, CowStr, Emitter, SourceMapperExt}; +use crate::{text_writer::WriteJs, CowStr, Emitter, ExprPrecedence, SourceMapperExt}; + +#[derive(Clone, Copy)] +enum NonFiniteNumber { + NaN, + PositiveInfinity, + NegativeInfinity, +} + +impl NonFiniteNumber { + #[inline] + fn from_value(value: f64) -> Self { + debug_assert!(!value.is_finite()); + + if value.is_nan() { + Self::NaN + } else if value.is_sign_positive() { + Self::PositiveInfinity + } else { + Self::NegativeInfinity + } + } + + #[inline] + fn division_text(self, minify: bool) -> &'static str { + match (self, minify) { + (Self::NaN, false) => "0 / 0", + (Self::PositiveInfinity, false) => "1 / 0", + (Self::NegativeInfinity, false) => "-1 / 0", + (Self::NaN, true) => "0/0", + (Self::PositiveInfinity, true) => "1/0", + (Self::NegativeInfinity, true) => "-1/0", + } + } +} #[node_impl] impl MacroNode for Lit { @@ -29,7 +64,9 @@ impl MacroNode for Lit { Lit::Null(Null { .. }) => keyword!(emitter, "null"), Lit::Str(ref s) => emit!(s), Lit::BigInt(ref s) => emit!(s), - Lit::Num(ref n) => emit!(n), + Lit::Num(ref n) => { + emitter.emit_num_lit_expr(n, ExprPrecedence::LOWEST, false)?; + } Lit::Regex(ref n) => { punct!(emitter, "/"); // Encode non-ASCII characters in regex pattern when ascii_only is enabled @@ -218,6 +255,77 @@ where W: WriteJs, S: SourceMapperExt, { + /// Emits a numeric literal in expression position. + /// + /// Readable output preserves a non-finite value's raw text when present. + /// Otherwise, non-finite values use division expressions, with spaces + /// omitted in minified output. Positive infinity uses an overflow literal + /// when division would require parentheses, avoiding an opening + /// parenthesis that could interact with automatic semicolon insertion. + /// Other generated expressions are parenthesized here because the fixer + /// cannot see code-generation-only expressions. + pub(crate) fn emit_num_lit_expr( + &mut self, + num: &Number, + precedence: ExprPrecedence, + detect_dot: bool, + ) -> std::result::Result { + if num.value.is_finite() { + return self.emit_num_lit_internal(num, detect_dot); + } + + if !self.cfg.minify && num.raw.is_some() { + return self.emit_num_lit_internal(num, detect_dot); + } + + self.wr.commit_pending_semi()?; + self.emit_leading_comments_of_span(num.span(), false)?; + + srcmap!(self, num, true); + + let kind = NonFiniteNumber::from_value(num.value); + let requires_parentheses = precedence >= ExprPrecedence::MULTIPLICATIVE; + let (text, wrap) = + if requires_parentheses && matches!(kind, NonFiniteNumber::PositiveInfinity) { + ("2e308", false) + } else { + (kind.division_text(self.cfg.minify), requires_parentheses) + }; + + if wrap { + punct!(self, "("); + } + self.wr.write_str_lit(num.span, text)?; + if wrap { + punct!(self, ")"); + } + + Ok(false) + } + + pub(crate) fn non_finite_expr_starts_with_alpha_num( + &self, + num: &Number, + precedence: ExprPrecedence, + ) -> bool { + debug_assert!(!num.value.is_finite()); + + if !self.cfg.minify { + if let Some(raw) = &num.raw { + return raw + .as_bytes() + .first() + .is_some_and(u8::is_ascii_alphanumeric); + } + } + + if precedence >= ExprPrecedence::MULTIPLICATIVE { + return num.value == f64::INFINITY; + } + + !num.value.is_sign_negative() || num.value.is_nan() + } + /// `1.toString` is an invalid property access, /// should emit a dot after the literal if return true pub fn emit_num_lit_internal( @@ -559,78 +667,6 @@ pub fn get_quoted_utf16(v: &Wtf8, ascii_only: bool, target: EsVersion) -> (Ascii (quote_char, CowStr::Owned(buf)) } -pub fn minify_number(num: f64, detect_dot: &mut bool) -> String { - // ddddd -> 0xhhhh - // len(0xhhhh) == len(ddddd) - // 10000000 <= num <= 0xffffff - 'hex: { - if num.fract() == 0.0 && num.abs() <= u64::MAX as f64 { - let int = num.abs() as u64; - - if int < 10000000 { - break 'hex; - } - - // use scientific notation - if int % 1000 == 0 { - break 'hex; - } - - *detect_dot = false; - return format!( - "{}{:#x}", - if num.is_sign_negative() { "-" } else { "" }, - int - ); - } - } - - let mut num = num.to_string(); - - if num.contains(".") { - *detect_dot = false; - } - - if let Some(num) = num.strip_prefix("0.") { - let cnt = clz(num); - if cnt > 2 { - return format!("{}e-{}", &num[cnt..], num.len()); - } - return format!(".{num}"); - } - - if let Some(num) = num.strip_prefix("-0.") { - let cnt = clz(num); - if cnt > 2 { - return format!("-{}e-{}", &num[cnt..], num.len()); - } - return format!("-.{num}"); - } - - if num.ends_with("000") { - *detect_dot = false; - - let cnt = num - .as_bytes() - .iter() - .rev() - .skip(3) - .take_while(|&&c| c == b'0') - .count() - + 3; - - num.truncate(num.len() - cnt); - num.push('e'); - num.push_str(&cnt.to_string()); - } - - num -} - -fn clz(s: &str) -> usize { - s.as_bytes().iter().take_while(|&&c| c == b'0').count() -} - pub trait Print { fn print(&self) -> String; } diff --git a/deps/swc/crates/swc_ecma_codegen/src/object.rs b/deps/swc/crates/swc_ecma_codegen/src/object.rs index 38f4aa4cf..a863a64fb 100644 --- a/deps/swc/crates/swc_ecma_codegen/src/object.rs +++ b/deps/swc/crates/swc_ecma_codegen/src/object.rs @@ -6,7 +6,7 @@ use swc_ecma_codegen_macros::node_impl; use crate::unknown_error; use crate::{ is_empty_comments, - scope_helpers::{for_each_param_binding, for_each_pat_binding}, + scope_helpers::for_each_param_binding, text_writer::{BindingStorage, ScopeKind}, ListFormat, }; @@ -110,7 +110,13 @@ impl MacroNode for GetterProp { emitter.emit_leading_comments_of_span(self.span(), false)?; srcmap!(emitter, self, true); - emitter.start_scope(None, ScopeKind::Function, true, false, Some(self.span()))?; + emitter.start_scope( + None, + ScopeKind::Function, + true, + false, + Some(self.function.span), + )?; keyword!(emitter, "get"); @@ -125,10 +131,7 @@ impl MacroNode for GetterProp { } emit!(self.key); formatting_space!(emitter); - punct!(emitter, "("); - punct!(emitter, ")"); - formatting_space!(emitter); - emit!(self.body); + emitter.emit_fn_trailing(&self.function)?; emitter.end_scope()?; Ok(()) @@ -141,10 +144,18 @@ impl MacroNode for SetterProp { emitter.emit_leading_comments_of_span(self.span(), false)?; srcmap!(emitter, self, true); - emitter.start_scope(None, ScopeKind::Function, true, false, Some(self.span()))?; + emitter.start_scope( + None, + ScopeKind::Function, + true, + false, + Some(self.function.span), + )?; if emitter.scope_tracking_enabled() { let mut names = vec![]; - for_each_pat_binding(&self.param, &mut |name| names.push(name.to_string())); + for_each_param_binding(&self.function.params, &mut |name| { + names.push(name.to_string()) + }); for name in names { emitter.add_scope_variable(&name, Some(&name), BindingStorage::Lexical)?; } @@ -166,19 +177,23 @@ impl MacroNode for SetterProp { emit!(self.key); formatting_space!(emitter); - punct!(emitter, "("); - if let Some(this) = &self.this_param { - emit!(this); - punct!(emitter, ","); - - formatting_space!(emitter); + if let Some(type_params) = &self.function.type_params { + emit!(type_params); } - emit!(self.param); + emitter.emit_fn_params(&self.function)?; - punct!(emitter, ")"); + if let Some(return_type) = &self.function.return_type { + punct!(emitter, ":"); + formatting_space!(emitter); + emit!(return_type); + } - emit!(self.body); + if let Some(body) = &self.function.body { + emit!(body); + } else { + semi!(emitter); + } emitter.end_scope()?; Ok(()) diff --git a/deps/swc/crates/swc_ecma_codegen/src/stmt.rs b/deps/swc/crates/swc_ecma_codegen/src/stmt.rs index 8c484aaf4..e635ab198 100644 --- a/deps/swc/crates/swc_ecma_codegen/src/stmt.rs +++ b/deps/swc/crates/swc_ecma_codegen/src/stmt.rs @@ -79,6 +79,15 @@ impl MacroNode for BlockStmt { } } +#[node_impl] +impl MacroNode for FunctionBody { + fn emit(&mut self, emitter: &mut Macro) -> Result { + emitter.emit_function_body_inner(self, false)?; + + Ok(()) + } +} + #[node_impl] impl MacroNode for ExprStmt { fn emit(&mut self, emitter: &mut Macro) -> Result { diff --git a/deps/swc/crates/swc_ecma_codegen/src/typescript.rs b/deps/swc/crates/swc_ecma_codegen/src/typescript.rs index b51d0b470..ef57f9499 100644 --- a/deps/swc/crates/swc_ecma_codegen/src/typescript.rs +++ b/deps/swc/crates/swc_ecma_codegen/src/typescript.rs @@ -4,6 +4,7 @@ use swc_ecma_codegen_macros::node_impl; #[cfg(swc_ast_unknown)] use crate::unknown_error; +use crate::ExprPrecedence; #[node_impl] impl MacroNode for ParamOrTsParamProp { @@ -311,6 +312,30 @@ impl MacroNode for TsFnParam { } } +#[node_impl] +impl MacroNode for TsThisParam { + fn emit(&mut self, emitter: &mut Macro) -> Result { + emitter.emit_leading_comments_of_span(self.span(), false)?; + + srcmap!(emitter, self.this_span, true); + keyword!(emitter, "this"); + + if let Some(type_ann) = &self.type_ann { + punct!(emitter, ":"); + formatting_space!(emitter); + emit!(type_ann); + } + + srcmap!(emitter, self, false); + + if emitter.comments.is_some() { + emitter.emit_trailing_comments_of_pos(self.span.hi, true, true)?; + } + + Ok(()) + } +} + #[node_impl] impl MacroNode for TsFnType { fn emit(&mut self, emitter: &mut Macro) -> Result { @@ -819,7 +844,7 @@ impl MacroNode for TsNonNullExpr { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.expr); + emitter.emit_expr_with_precedence(&self.expr, ExprPrecedence::POSTFIX)?; punct!(emitter, "!"); Ok(()) } @@ -1135,7 +1160,7 @@ impl MacroNode for TsTypeAssertion { punct!(emitter, "<"); emit!(self.type_ann); punct!(emitter, ">"); - emit!(self.expr); + emitter.emit_expr_with_precedence(&self.expr, ExprPrecedence::EXPONENTIATION)?; Ok(()) } } @@ -1422,7 +1447,7 @@ impl MacroNode for TsInstantiation { fn emit(&mut self, emitter: &mut Macro) -> Result { emitter.emit_leading_comments_of_span(self.span(), false)?; - emit!(self.expr); + emitter.emit_expr_with_precedence(&self.expr, ExprPrecedence::POSTFIX)?; emit!(self.type_args); Ok(()) diff --git a/deps/swc/crates/swc_ecma_compat_bugfixes/Cargo.toml b/deps/swc/crates/swc_ecma_compat_bugfixes/Cargo.toml index f5491ebff..334b61fac 100644 --- a/deps/swc/crates/swc_ecma_compat_bugfixes/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_bugfixes/Cargo.toml @@ -7,21 +7,21 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_bugfixes" repository = { workspace = true } -version = "51.0.0" +version = "56.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rustc-hash = { workspace = true } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_compat_es2015 = { version = "50.0.0", path = "../swc_ecma_compat_es2015" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_compat_es2015 = { version = "55.0.0", path = "../swc_ecma_compat_es2015" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } diff --git a/deps/swc/crates/swc_ecma_compat_bugfixes/src/edge_default_param.rs b/deps/swc/crates/swc_ecma_compat_bugfixes/src/edge_default_param.rs index 1bb6e5a00..27dcdf9a5 100644 --- a/deps/swc/crates/swc_ecma_compat_bugfixes/src/edge_default_param.rs +++ b/deps/swc/crates/swc_ecma_compat_bugfixes/src/edge_default_param.rs @@ -23,7 +23,7 @@ impl VisitMut for EdgeDefaultParam { n.params.visit_mut_children_with(self); self.in_arrow = false; - n.body.visit_mut_children_with(self); + n.body.visit_mut_with(self); } fn visit_mut_object_pat(&mut self, n: &mut ObjectPat) { diff --git a/deps/swc/crates/swc_ecma_compat_bugfixes/src/safari_id_destructuring_collision_in_function_expression.rs b/deps/swc/crates/swc_ecma_compat_bugfixes/src/safari_id_destructuring_collision_in_function_expression.rs index ca4d98860..f15979696 100644 --- a/deps/swc/crates/swc_ecma_compat_bugfixes/src/safari_id_destructuring_collision_in_function_expression.rs +++ b/deps/swc/crates/swc_ecma_compat_bugfixes/src/safari_id_destructuring_collision_in_function_expression.rs @@ -52,7 +52,7 @@ impl VisitMut for SafariIdDestructuringCollisionInFunctionExpression { self.in_body = false; n.function.params.visit_mut_children_with(self); self.in_body = true; - n.function.body.visit_mut_children_with(self); + n.function.body.visit_mut_with(self); if let Some(id_ctxt) = self.destructured_id_span.take() { let mut rename_map = HashMap::default(); @@ -80,7 +80,7 @@ impl VisitMut for SafariIdDestructuringCollisionInFunctionExpression { self.in_body = false; n.function.params.visit_mut_children_with(self); self.in_body = true; - n.function.body.visit_mut_children_with(self); + n.function.body.visit_mut_with(self); } self.in_body = old_in_body; } diff --git a/deps/swc/crates/swc_ecma_compat_bugfixes/src/template_literal_caching.rs b/deps/swc/crates/swc_ecma_compat_bugfixes/src/template_literal_caching.rs index 874daffcd..473baed00 100644 --- a/deps/swc/crates/swc_ecma_compat_bugfixes/src/template_literal_caching.rs +++ b/deps/swc/crates/swc_ecma_compat_bugfixes/src/template_literal_caching.rs @@ -75,7 +75,7 @@ impl Fold for TemplateLiteralCaching { ArrowExpr { span: DUMMY_SP, params: vec![t.clone().into()], - body: Box::new(BlockStmtOrExpr::Expr(t.into())), + body: Box::new(ArrowFunctionBody::Expr(t.into())), is_async: false, is_generator: false, ..Default::default() diff --git a/deps/swc/crates/swc_ecma_compat_common/Cargo.toml b/deps/swc/crates/swc_ecma_compat_common/Cargo.toml index e4b675a86..6ba9930c3 100644 --- a/deps/swc/crates/swc_ecma_compat_common/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_common/Cargo.toml @@ -7,12 +7,12 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_common" repository = { workspace = true } -version = "40.0.1" +version = "45.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } diff --git a/deps/swc/crates/swc_ecma_compat_common/src/macros.rs b/deps/swc/crates/swc_ecma_compat_common/src/macros.rs index 0ac0b5891..19671f15d 100644 --- a/deps/swc/crates/swc_ecma_compat_common/src/macros.rs +++ b/deps/swc/crates/swc_ecma_compat_common/src/macros.rs @@ -9,10 +9,11 @@ macro_rules! impl_visit_mut_fn { f.visit_mut_children_with(self); - let (params, body) = self.visit_mut_fn_like(&mut f.params, &mut f.body.take().unwrap()); + let body = f.body.as_mut().unwrap(); + let (params, stmts) = self.visit_mut_fn_like(&mut f.params, &mut body.stmts); f.params = params; - f.body = Some(body); + body.stmts = stmts; } fn visit_mut_arrow_expr(&mut self, f: &mut ArrowExpr) { @@ -21,10 +22,22 @@ macro_rules! impl_visit_mut_fn { f.visit_mut_children_with(self); let was_expr = match *f.body { - BlockStmtOrExpr::Expr(..) => true, + ArrowFunctionBody::Expr(..) => true, _ => false, }; - let (params, mut body) = self.visit_mut_fn_like( + let mut body = match &mut *f.body { + ArrowFunctionBody::FunctionBody(body) => body.take(), + ArrowFunctionBody::Expr(expr) => FunctionBody { + span: DUMMY_SP, + stmts: vec![Stmt::Return(ReturnStmt { + span: DUMMY_SP, + arg: Some(expr.take()), + })], + }, + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + }; + let (params, stmts) = self.visit_mut_fn_like( &mut f .params .take() @@ -35,18 +48,9 @@ macro_rules! impl_visit_mut_fn { pat, }) .collect(), - &mut match &mut *f.body { - BlockStmtOrExpr::BlockStmt(block) => block.take(), - BlockStmtOrExpr::Expr(expr) => BlockStmt { - stmts: vec![Stmt::Return(ReturnStmt { - span: DUMMY_SP, - arg: Some(expr.take()), - })], - ..Default::default() - }, - _ => panic!("unable to access unknown nodes"), - }, + &mut body.stmts, ); + body.stmts = stmts; let body = if was_expr && body.stmts.len() == 1 @@ -56,66 +60,31 @@ macro_rules! impl_visit_mut_fn { } { match body.stmts.pop().unwrap() { Stmt::Return(ReturnStmt { arg: Some(arg), .. }) => { - Box::new(BlockStmtOrExpr::Expr(arg)) + Box::new(ArrowFunctionBody::Expr(arg)) } _ => unreachable!(), } } else { - Box::new(BlockStmtOrExpr::BlockStmt(body)) + Box::new(ArrowFunctionBody::FunctionBody(body)) }; f.params = params.into_iter().map(|param| param.pat).collect(); f.body = body; } - fn visit_mut_setter_prop(&mut self, f: &mut SetterProp) { - if f.body.is_none() { - return; - } - - f.visit_mut_children_with(self); - - let (mut params, body) = self.visit_mut_fn_like( - &mut vec![Param { - span: DUMMY_SP, - decorators: Vec::new(), - pat: *f.param.take(), - }], - &mut f.body.take().unwrap(), - ); - debug_assert!(params.len() == 1); - - f.param = Box::new(params.into_iter().next().unwrap().pat); - f.body = Some(body); - } - - fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) { - if f.body.is_none() { - return; - } - - f.visit_mut_children_with(self); - - let (params, body) = - self.visit_mut_fn_like(&mut Vec::new(), &mut f.body.take().unwrap()); - debug_assert_eq!(params, Vec::new()); - - f.body = Some(body); - } - fn visit_mut_catch_clause(&mut self, f: &mut CatchClause) { f.visit_mut_children_with(self); - let (mut params, body) = match &mut f.param { + let (mut params, stmts) = match &mut f.param { Some(pat) => self.visit_mut_fn_like( &mut vec![Param { span: DUMMY_SP, decorators: Vec::new(), pat: pat.take(), }], - &mut f.body.take(), + &mut f.body.stmts, ), - None => self.visit_mut_fn_like(&mut Vec::new(), &mut f.body.take()), + None => self.visit_mut_fn_like(&mut Vec::new(), &mut f.body.stmts), }; assert!( params.len() == 0 || params.len() == 1, @@ -129,7 +98,7 @@ macro_rules! impl_visit_mut_fn { }; f.param = param.map(|param| param.pat); - f.body = body; + f.body.stmts = stmts; } fn visit_mut_constructor(&mut self, f: &mut Constructor) { @@ -154,7 +123,8 @@ macro_rules! impl_visit_mut_fn { }) .collect(); - let (params, body) = self.visit_mut_fn_like(&mut params, &mut f.body.take().unwrap()); + let body = f.body.as_mut().unwrap(); + let (params, stmts) = self.visit_mut_fn_like(&mut params, &mut body.stmts); #[cfg(debug_assertions)] tracing::trace!( @@ -163,7 +133,7 @@ macro_rules! impl_visit_mut_fn { ); f.params = params.into_iter().map(ParamOrTsParamProp::Param).collect(); - f.body = Some(body); + body.stmts = stmts; } }; } diff --git a/deps/swc/crates/swc_ecma_compat_es2015/Cargo.toml b/deps/swc/crates/swc_ecma_compat_es2015/Cargo.toml index 19bde72f0..79bdbc2f9 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_es2015/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_es2015" repository = { workspace = true } -version = "50.0.0" +version = "55.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -23,21 +23,21 @@ rustc-hash = { workspace = true } serde = { workspace = true } serde_derive = { workspace = true } smallvec = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_config = { version = "5.0.0", path = "../swc_config" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_compat_common = { version = "40.0.1", path = "../swc_ecma_compat_common" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_classes = { version = "44.0.0", path = "../swc_ecma_transforms_classes" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_config = { version = "6.0.0", path = "../swc_config" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_compat_common = { version = "45.0.0", path = "../swc_ecma_compat_common" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_classes = { version = "49.0.0", path = "../swc_ecma_transforms_classes" } swc_ecma_transforms_macros = { version = "1.0.1", path = "../swc_ecma_transforms_macros" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } tracing = { workspace = true } [dev-dependencies] -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/arrow.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/arrow.rs index 64072c98e..b21911196 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/arrow.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/arrow.rs @@ -85,10 +85,10 @@ impl VisitMut for Arrow { fn visit_mut_constructor(&mut self, c: &mut Constructor) { c.params.visit_mut_children_with(self); - if let Some(BlockStmt { span: _, stmts, .. }) = &mut c.body { + if let Some(body) = &mut c.body { let old_rep = self.hoister.take(); - stmts.visit_mut_children_with(self); + body.visit_mut_with(self); if self.in_subclass { let (decl, this_id) = @@ -96,15 +96,15 @@ impl VisitMut for Arrow { if let Some(stmt) = decl { if let Some(this_id) = this_id { - init_this(stmts, &this_id) + init_this(&mut body.stmts, &this_id) } - prepend_stmt(stmts, stmt); + prepend_stmt(&mut body.stmts, stmt); } } else { let decl = mem::replace(&mut self.hoister, old_rep).to_stmt(); if let Some(stmt) = decl { - prepend_stmt(stmts, stmt); + prepend_stmt(&mut body.stmts, stmt); } } } @@ -151,8 +151,8 @@ impl VisitMut for Arrow { is_async: *is_async, is_generator: *is_generator, body: Some(match &mut **body { - BlockStmtOrExpr::BlockStmt(block) => block.take(), - BlockStmtOrExpr::Expr(expr) => BlockStmt { + ArrowFunctionBody::FunctionBody(body) => body.take(), + ArrowFunctionBody::Expr(expr) => FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { // this is needed so @@ -161,7 +161,6 @@ impl VisitMut for Arrow { span: DUMMY_SP, arg: Some(expr.take()), })], - ..Default::default() }, #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), @@ -190,22 +189,6 @@ impl VisitMut for Arrow { } } - fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) { - f.key.visit_mut_with(self); - - if let Some(body) = &mut f.body { - let old_rep = self.hoister.take(); - - body.visit_mut_with(self); - - let decl = mem::replace(&mut self.hoister, old_rep).to_stmt(); - - if let Some(stmt) = decl { - prepend_stmt(&mut body.stmts, stmt); - } - } - } - fn visit_mut_module_items(&mut self, stmts: &mut Vec) { stmts.visit_mut_children_with(self); @@ -225,23 +208,6 @@ impl VisitMut for Arrow { prepend_stmt(&mut script.body, stmt); } } - - fn visit_mut_setter_prop(&mut self, f: &mut SetterProp) { - f.key.visit_mut_with(self); - f.param.visit_mut_with(self); - - if let Some(body) = &mut f.body { - let old_rep = self.hoister.take(); - - body.visit_mut_with(self); - - let decl = mem::replace(&mut self.hoister, old_rep).to_stmt(); - - if let Some(stmt) = decl { - prepend_stmt(&mut body.stmts, stmt); - } - } - } } impl InjectVars for Arrow { diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoped_fn.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoped_fn.rs index 0900a0a0d..61ae4266f 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoped_fn.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoped_fn.rs @@ -13,15 +13,6 @@ struct BlockScopedFns; impl VisitMut for BlockScopedFns { noop_visit_mut_type!(fail); - fn visit_mut_function(&mut self, n: &mut Function) { - let Some(body) = &mut n.body else { return }; - - n.params.visit_mut_with(self); - - // skip function scope - body.visit_mut_children_with(self); - } - fn visit_mut_block_stmt(&mut self, n: &mut BlockStmt) { n.visit_mut_children_with(self); @@ -71,7 +62,7 @@ impl VisitMut for BlockScopedFns { #[cfg(test)] mod tests { - use swc_ecma_transforms_testing::test; + use swc_ecma_transforms_testing::{test, test_inline}; use super::*; @@ -192,4 +183,26 @@ function foo(scope) { } }" ); + + test_inline!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoped_functions(), + function_bodies_are_not_blocks, + "const arrow = () => { + function inArrow() {} + }; + class Foo { + constructor() { + function inConstructor() {} + } + }", + "const arrow = () => { + function inArrow() {} + }; + class Foo { + constructor() { + function inConstructor() {} + } + }" + ); } diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoping/mod.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoping/mod.rs index e9bfdcf81..058cbdf5f 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoping/mod.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoping/mod.rs @@ -93,6 +93,16 @@ impl BlockScoping { } } + fn visit_mut_children_with_isolated_vars(&mut self, node: &mut T) + where + T: VisitMutWith, + { + let vars = take(&mut self.vars); + node.visit_mut_children_with(self); + debug_assert!(self.vars.is_empty()); + self.vars = vars; + } + fn mark_as_used(&mut self, i: &Ident) { // Only consider the variable used in a non-ScopeKind::Loop, which means it is // captured in a closure @@ -177,11 +187,13 @@ impl BlockScoping { body_stmt.visit_mut_with(&mut flow_helper); let mut body_stmt = match &mut body_stmt.take() { - Stmt::Block(bs) => bs.take(), - body => BlockStmt { + Stmt::Block(bs) => { + let BlockStmt { span, stmts, .. } = bs.take(); + FunctionBody { span, stmts } + } + body => FunctionBody { span: DUMMY_SP, stmts: vec![body.take()], - ..Default::default() }, }; @@ -350,6 +362,7 @@ impl BlockScoping { stmts.push( SwitchStmt { span: DUMMY_SP, + body_ctxt: Default::default(), discriminant: Box::new(ret.into()), cases: flow_helper .label @@ -438,10 +451,11 @@ impl VisitMut for BlockScoping { } fn visit_mut_block_stmt(&mut self, n: &mut BlockStmt) { - let vars = take(&mut self.vars); - n.visit_mut_children_with(self); - debug_assert_eq!(self.vars, Vec::new()); - self.vars = vars; + self.visit_mut_children_with_isolated_vars(n); + } + + fn visit_mut_function_body(&mut self, n: &mut FunctionBody) { + self.visit_mut_children_with_isolated_vars(n); } fn visit_mut_constructor(&mut self, f: &mut Constructor) { @@ -539,11 +553,6 @@ impl VisitMut for BlockScoping { self.visit_mut_with_scope(ScopeKind::Fn, &mut f.body); } - fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) { - f.key.visit_mut_with(self); - self.visit_mut_with_scope(ScopeKind::Fn, &mut f.body); - } - fn visit_mut_ident(&mut self, node: &mut Ident) { self.mark_as_used(node); } @@ -552,12 +561,6 @@ impl VisitMut for BlockScoping { self.visit_mut_stmt_like(stmts); } - fn visit_mut_setter_prop(&mut self, f: &mut SetterProp) { - f.key.visit_mut_with(self); - f.param.visit_mut_with(self); - self.visit_mut_with_scope(ScopeKind::Fn, &mut f.body); - } - fn visit_mut_stmts(&mut self, n: &mut Vec) { self.visit_mut_stmt_like(n); } @@ -745,12 +748,6 @@ impl VisitMut for FlowHelper<'_> { /// noop fn visit_mut_function(&mut self, _f: &mut Function) {} - /// noop - fn visit_mut_getter_prop(&mut self, _f: &mut GetterProp) {} - - /// noop - fn visit_mut_setter_prop(&mut self, _f: &mut SetterProp) {} - fn visit_mut_labeled_stmt(&mut self, l: &mut LabeledStmt) { self.inner_label.insert(l.label.sym.clone()); diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoping/vars.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoping/vars.rs index 171754dbb..d4171b337 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoping/vars.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/block_scoping/vars.rs @@ -246,16 +246,7 @@ impl VisitMut for BlockScopedVars { n.params.visit_mut_with(v); v.is_param = old; - match &mut *n.body { - BlockStmtOrExpr::BlockStmt(b) => { - b.visit_mut_children_with(v); - } - BlockStmtOrExpr::Expr(b) => { - b.visit_mut_with(v); - } - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } + n.body.visit_mut_with(v); }); } @@ -299,10 +290,7 @@ impl VisitMut for BlockScopedVars { fn visit_mut_constructor(&mut self, n: &mut Constructor) { self.with_scope(ScopeKind::Fn, |v| { n.params.visit_mut_with(v); - - if let Some(body) = &mut n.body { - body.visit_mut_children_with(v); - } + n.body.visit_mut_with(v); }); } @@ -403,10 +391,7 @@ impl VisitMut for BlockScopedVars { self.with_scope(ScopeKind::Fn, |v| { n.params.visit_mut_with(v); - - if let Some(body) = &mut n.body { - body.visit_mut_children_with(v); - } + n.body.visit_mut_with(v); }); } diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/classes/constructor.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/classes/constructor.rs index 5addf99b4..44d10fa63 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/classes/constructor.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/classes/constructor.rs @@ -197,9 +197,9 @@ pub(super) fn fold_constructor( let function = Function { params, - body: Some(BlockStmt { + body: Some(FunctionBody { + span: DUMMY_SP, stmts, - ..Default::default() }), ..Default::default() }; @@ -243,14 +243,6 @@ impl VisitMut for ConstructorFolder { // skip } - fn visit_mut_getter_prop(&mut self, _: &mut GetterProp) { - // skip - } - - fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) { - // skip - } - fn visit_mut_if_stmt(&mut self, node: &mut IfStmt) { node.test.visit_mut_with(self); let super_found = self.super_found; diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/classes/mod.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/classes/mod.rs index 5bcdeea99..57986cc96 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/classes/mod.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/classes/mod.rs @@ -472,10 +472,9 @@ impl Classes { } } - let body = BlockStmt { + let body = FunctionBody { span: DUMMY_SP, stmts, - ..Default::default() }; let call = CallExpr { diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/classes/prop_name.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/classes/prop_name.rs index 6044c7f0a..d79ee5f9e 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/classes/prop_name.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/classes/prop_name.rs @@ -1,6 +1,7 @@ use swc_atoms::Wtf8Atom; use swc_common::{Span, Spanned}; use swc_ecma_ast::*; +use swc_ecma_utils::number::ToJsString; #[derive(Debug, PartialEq, Eq, Hash)] pub enum HashKey { @@ -14,7 +15,7 @@ impl From<&PropName> for HashKey { match p { PropName::Ident(IdentName { sym: value, .. }) => HashKey::Str(value.clone().into()), PropName::Str(Str { value, .. }) => HashKey::Str(value.clone()), - PropName::Num(Number { value, .. }) => HashKey::Str(value.to_string().into()), + PropName::Num(Number { value, .. }) => HashKey::Str(value.to_js_string().into()), PropName::BigInt(BigInt { value, .. }) => HashKey::Str(value.to_string().into()), PropName::Computed(expr) => HashKey::Computed(expr.span()), #[cfg(swc_ast_unknown)] diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/computed_props.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/computed_props.rs index 974da6514..638888573 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/computed_props.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/computed_props.rs @@ -157,36 +157,8 @@ impl VisitMut for ComputedProps { _ => None, }; let (key, function) = match prop { - Prop::Getter(GetterProp { - span, body, key, .. - }) => ( - key, - Box::new(Function { - span, - body, - is_async: false, - is_generator: false, - params: Vec::new(), - ..Default::default() - }), - ), - Prop::Setter(SetterProp { - span, - body, - param, - key, - .. - }) => ( - key, - Box::new(Function { - span, - body, - is_async: false, - is_generator: false, - params: vec![(*param).into()], - ..Default::default() - }), - ), + Prop::Getter(GetterProp { key, function, .. }) => (key, function), + Prop::Setter(SetterProp { key, function, .. }) => (key, function), _ => unreachable!(), }; diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/destructuring.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/destructuring.rs index 53483f65a..71bbeb8df 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/destructuring.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/destructuring.rs @@ -495,8 +495,8 @@ impl Destructuring { fn visit_mut_fn_like( &mut self, ps: &mut Vec, - body: &mut BlockStmt, - ) -> (Vec, BlockStmt) { + body: &mut Vec, + ) -> (Vec, Vec) { let mut params = Vec::new(); let mut decls = Vec::new(); @@ -527,7 +527,7 @@ impl Destructuring { } let stmts = if decls.is_empty() { - body.stmts.take() + body.take() } else { let mut stmt: Stmt = VarDecl { span: DUMMY_SP, @@ -540,16 +540,10 @@ impl Destructuring { stmt.visit_mut_children_with(self); - iter::once(stmt).chain(body.stmts.take()).collect() + iter::once(stmt).chain(body.take()).collect() }; - ( - params, - BlockStmt { - stmts, - ..body.take() - }, - ) + (params, stmts) } } diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/generator.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/generator.rs index d3e4dd06f..33fea581e 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/generator.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/generator.rs @@ -81,9 +81,9 @@ impl VisitMut for Wrapper { pat: Pat::Ident(v.state.clone().into()), }], decorators: Default::default(), - body: Some(BlockStmt { + body: Some(FunctionBody { + span: DUMMY_SP, stmts, - ..Default::default() }), is_generator: false, is_async: false, @@ -410,12 +410,6 @@ impl VisitMut for Generator { e.params.visit_mut_with(self); } - fn visit_mut_getter_prop(&mut self, _: &mut GetterProp) {} - - fn visit_mut_setter_prop(&mut self, e: &mut SetterProp) { - e.param.visit_mut_with(self); - } - fn visit_mut_expr(&mut self, e: &mut Expr) { match e { Expr::Yield(node) => { @@ -1360,30 +1354,12 @@ impl Generator { props: getter .map(|g| KeyValueProp { key: quote_ident!("get").into(), - value: Function { - params: Vec::new(), - span: g.span, - body: g.body, - is_generator: false, - is_async: false, - ..Default::default() - } - .into(), + value: g.function.into(), }) .into_iter() - .chain(setter.map(|s| { - KeyValueProp { - key: quote_ident!("set").into(), - value: Function { - params: vec![(*s.param).into()], - span: s.span, - body: s.body, - is_generator: false, - is_async: false, - ..Default::default() - } - .into(), - } + .chain(setter.map(|s| KeyValueProp { + key: quote_ident!("set").into(), + value: s.function.into(), })) .map(Prop::KeyValue) .map(Box::new) @@ -2111,6 +2087,7 @@ impl Generator { self.emit_stmt( SwitchStmt { span: DUMMY_SP, + body_ctxt: Default::default(), discriminant: expression.clone().into(), cases: take(&mut pending_clauses), } @@ -2987,6 +2964,7 @@ impl Generator { let label_expr = self.state.clone().make_member(quote_ident!("label")); let switch_stmt = SwitchStmt { span: DUMMY_SP, + body_ctxt: Default::default(), discriminant: label_expr.into(), cases: clauses, }; @@ -3085,7 +3063,7 @@ impl Generator { // blocks, so we surround the statements in // generated `with` blocks to create the same environment. - for (_i, with_block) in with_block_stack.iter().enumerate().rev() { + for with_block in with_block_stack.iter().rev() { let b = with_block.borrow(); let with_block = match &*b { CodeBlock::With(v) => v, diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/new_target.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/new_target.rs index 458c1ecee..5c5f58ce7 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/new_target.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/new_target.rs @@ -40,7 +40,7 @@ impl VisitMut for NewTarget { fn visit_mut_class_method(&mut self, c: &mut ClassMethod) { c.key.visit_mut_with(self); - self.visit_mut_method(&mut c.function) + self.visit_mut_method(&mut c.function); } fn visit_mut_constructor(&mut self, c: &mut Constructor) { @@ -119,19 +119,21 @@ impl VisitMut for NewTarget { self.ctx = old; } - fn visit_mut_method_prop(&mut self, m: &mut MethodProp) { + fn visit_mut_private_method(&mut self, m: &mut PrivateMethod) { m.key.visit_mut_with(self); - self.visit_mut_method(&mut m.function) + self.visit_mut_method(&mut m.function); } - fn visit_mut_getter_prop(&mut self, m: &mut GetterProp) { - m.key.visit_mut_with(self); - self.visit_mut_method(&mut m.body) - } - - fn visit_mut_setter_prop(&mut self, m: &mut SetterProp) { - m.key.visit_mut_with(self); - self.visit_mut_method(&mut m.body) + fn visit_mut_prop(&mut self, prop: &mut Prop) { + match prop { + Prop::Getter(GetterProp { key, function, .. }) + | Prop::Setter(SetterProp { key, function, .. }) + | Prop::Method(MethodProp { key, function }) => { + key.visit_mut_with(self); + self.visit_mut_method(function); + } + _ => prop.visit_mut_children_with(self), + } } } diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/object_super.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/object_super.rs index 085d8245e..6689fef90 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/object_super.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/object_super.rs @@ -85,7 +85,7 @@ impl VisitMut for ObjectSuper { if let Prop::Method(MethodProp { key: _, function }) = &mut **prop { function.visit_mut_with(&mut replacer); if !replacer.vars.is_empty() { - if let Some(BlockStmt { span: _, stmts, .. }) = &mut function.body { + if let Some(FunctionBody { span: _, stmts, .. }) = &mut function.body { prepend_stmt( stmts, VarDecl { diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/parameters.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/parameters.rs index 3a710857e..8ac476bb3 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/parameters.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/parameters.rs @@ -71,7 +71,30 @@ pub struct Config { // } impl Params { - fn visit_mut_fn_like(&mut self, ps: &mut Vec, body: &mut BlockStmt, is_setter: bool) { + /// Transforms a setter's backing function while preserving its required + /// single formal parameter. + fn visit_mut_setter_function(&mut self, f: &mut Function) { + if f.body.is_none() { + return; + } + + let old_in_subclass = self.in_subclass; + let old_in_prop = self.in_prop; + self.in_subclass = false; + self.in_prop = false; + + f.visit_mut_children_with(self); + + let mut body = f.body.take().unwrap(); + self.visit_mut_fn_like(&mut f.params, &mut body.stmts, true); + + f.body = Some(body); + + self.in_subclass = old_in_subclass; + self.in_prop = old_in_prop; + } + + fn visit_mut_fn_like(&mut self, ps: &mut Vec, stmts: &mut Vec, is_setter: bool) { let mut params = Vec::new(); let mut decls = Vec::new(); let mut loose_stmt = Vec::new(); @@ -455,9 +478,9 @@ impl Params { } if (is_setter || self.c.ignore_function_length) && !loose_stmt.is_empty() { loose_stmt.extend(iter); - prepend_stmts(&mut body.stmts, loose_stmt.into_iter()); + prepend_stmts(stmts, loose_stmt.into_iter()); } else { - prepend_stmts(&mut body.stmts, iter.into_iter()); + prepend_stmts(stmts, iter.into_iter()); }; *ps = params; @@ -473,33 +496,16 @@ impl VisitMut for Params { prop.key.visit_mut_children_with(self); let old_in_prop = self.in_prop; - self.in_prop = !prop.is_static; + // Static field initializers evaluate with the class as `this`, so they + // need the same initializer-local capture as instance fields. + self.in_prop = true; prop.value.visit_mut_with(self); self.in_prop = old_in_prop; } fn visit_mut_class_method(&mut self, m: &mut ClassMethod) { if let MethodKind::Setter = m.kind { - let f = &mut m.function; - - if f.body.is_none() { - return; - } - - let old_in_subclass = self.in_subclass; - let old_in_prop = self.in_prop; - self.in_subclass = false; - self.in_prop = false; - - f.visit_mut_children_with(self); - - let mut body = f.body.take().unwrap(); - self.visit_mut_fn_like(&mut f.params, &mut body, true); - - f.body = Some(body); - - self.in_subclass = old_in_subclass; - self.in_prop = old_in_prop; + self.visit_mut_setter_function(&mut m.function); } else { m.visit_mut_children_with(self); } @@ -508,12 +514,14 @@ impl VisitMut for Params { // same for private prop fn visit_mut_private_prop(&mut self, prop: &mut PrivateProp) { let old_in_prop = self.in_prop; - self.in_prop = !prop.is_static; + // Private static field initializers also evaluate with the class as + // `this`, and must not hoist that capture to the enclosing scope. + self.in_prop = true; prop.value.visit_mut_with(self); self.in_prop = old_in_prop; } - fn visit_mut_block_stmt_or_expr(&mut self, body: &mut BlockStmtOrExpr) { + fn visit_mut_arrow_function_body(&mut self, body: &mut ArrowFunctionBody) { let old_rep = self.hoister.take(); body.visit_mut_children_with(self); @@ -521,7 +529,7 @@ impl VisitMut for Params { let decls = mem::replace(&mut self.hoister, old_rep).to_stmt(); if let Some(decls) = decls { - if let BlockStmtOrExpr::Expr(v) = body { + if let ArrowFunctionBody::Expr(v) = body { let mut stmts = Vec::new(); prepend_stmt(&mut stmts, decls); stmts.push( @@ -531,10 +539,9 @@ impl VisitMut for Params { } .into(), ); - *body = BlockStmtOrExpr::BlockStmt(BlockStmt { + *body = ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts, - ..Default::default() }); } } @@ -552,7 +559,7 @@ impl VisitMut for Params { }); } - self.visit_mut_fn_like(&mut params, &mut f.body, false); + self.visit_mut_fn_like(&mut params, &mut f.body.stmts, false); assert!( params.is_empty() || params.len() == 1, @@ -573,7 +580,7 @@ impl VisitMut for Params { trace!("visit_mut_constructor(parmas.len() = {})", f.params.len()); f.params.visit_mut_with(self); - if let Some(BlockStmt { stmts, .. }) = &mut f.body { + if let Some(FunctionBody { stmts, .. }) = &mut f.body { let old_rep = self.hoister.take(); stmts.visit_mut_children_with(self); @@ -642,19 +649,19 @@ impl VisitMut for Params { .collect(); let mut body = match *f.body.take() { - BlockStmtOrExpr::BlockStmt(block) => block, - BlockStmtOrExpr::Expr(expr) => BlockStmt { + ArrowFunctionBody::FunctionBody(body) => body, + ArrowFunctionBody::Expr(expr) => FunctionBody { + span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, arg: Some(expr), })], - ..Default::default() }, #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), }; - self.visit_mut_fn_like(&mut params, &mut body, false); + self.visit_mut_fn_like(&mut params, &mut body.stmts, false); if need_arrow_to_function { let func: Expr = Function { @@ -673,7 +680,7 @@ impl VisitMut for Params { params: Vec::new(), is_async: false, is_generator: false, - body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt { + body: Box::new(ArrowFunctionBody::FunctionBody(FunctionBody { span: f.span, stmts: vec![ var_decl, @@ -682,7 +689,6 @@ impl VisitMut for Params { arg: Some(Box::new(func)), }), ], - ..Default::default() })), ..Default::default() } @@ -701,12 +707,12 @@ impl VisitMut for Params { ) { match body.stmts.pop().unwrap() { Stmt::Return(ReturnStmt { arg: Some(arg), .. }) => { - Box::new(BlockStmtOrExpr::Expr(arg)) + Box::new(ArrowFunctionBody::Expr(arg)) } _ => unreachable!(), } } else { - Box::new(BlockStmtOrExpr::BlockStmt(body)) + Box::new(ArrowFunctionBody::FunctionBody(body)) }; *e = ArrowExpr { @@ -738,7 +744,7 @@ impl VisitMut for Params { f.visit_mut_children_with(self); let mut body = f.body.take().unwrap(); - self.visit_mut_fn_like(&mut f.params, &mut body, false); + self.visit_mut_fn_like(&mut f.params, &mut body.stmts, false); f.body = Some(body); @@ -746,41 +752,9 @@ impl VisitMut for Params { self.in_prop = old_in_prop; } - fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) { - if f.body.is_none() { - return; - } - - f.visit_mut_children_with(self); - - let mut params = Vec::new(); - let mut body = f.body.take().unwrap(); - self.visit_mut_fn_like(&mut params, &mut body, false); - debug_assert_eq!(params, Vec::new()); - - f.body = Some(body); - } - fn visit_mut_setter_prop(&mut self, f: &mut SetterProp) { - if f.body.is_none() { - return; - } - - f.visit_mut_children_with(self); - - let mut params = vec![Param { - span: DUMMY_SP, - decorators: Default::default(), - pat: *f.param.take(), - }]; - - let mut body = f.body.take().unwrap(); - self.visit_mut_fn_like(&mut params, &mut body, true); - - debug_assert!(params.len() == 1); - - *f.param = params.pop().unwrap().pat; - f.body = Some(body); + f.key.visit_mut_with(self); + self.visit_mut_setter_function(&mut f.function); } fn visit_mut_class(&mut self, c: &mut Class) { diff --git a/deps/swc/crates/swc_ecma_compat_es2015/src/template_literal.rs b/deps/swc/crates/swc_ecma_compat_es2015/src/template_literal.rs index 9144d6aa3..eb37413c2 100644 --- a/deps/swc/crates/swc_ecma_compat_es2015/src/template_literal.rs +++ b/deps/swc/crates/swc_ecma_compat_es2015/src/template_literal.rs @@ -327,13 +327,12 @@ impl VisitMut for TemplateLiteral { is_async: false, is_generator: false, params: Vec::new(), - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, arg: Some(Box::new(quote_ident!("data").into())), })], - ..Default::default() }), ..Default::default() } @@ -342,7 +341,7 @@ impl VisitMut for TemplateLiteral { .into() }; - Some(BlockStmt { + Some(FunctionBody { span: DUMMY_SP, stmts: vec![ @@ -353,7 +352,6 @@ impl VisitMut for TemplateLiteral { arg: Some(Box::new(quote_ident!("data").into())), }), ], - ..Default::default() }) }, diff --git a/deps/swc/crates/swc_ecma_compat_es2016/Cargo.toml b/deps/swc/crates/swc_ecma_compat_es2016/Cargo.toml index 9a95a58df..63ce59543 100644 --- a/deps/swc/crates/swc_ecma_compat_es2016/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_es2016/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_es2016" repository = { workspace = true } -version = "45.0.0" +version = "50.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -16,12 +16,12 @@ version = "45.0.0" unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } tracing = { workspace = true } [dev-dependencies] -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } diff --git a/deps/swc/crates/swc_ecma_compat_es2017/Cargo.toml b/deps/swc/crates/swc_ecma_compat_es2017/Cargo.toml index 45074f4f8..4d295d278 100644 --- a/deps/swc/crates/swc_ecma_compat_es2017/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_es2017/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_es2017" repository = { workspace = true } -version = "45.0.0" +version = "50.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,11 +17,11 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] serde = { workspace = true, features = ["derive"] } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } tracing = { workspace = true } [dev-dependencies] diff --git a/deps/swc/crates/swc_ecma_compat_es2018/Cargo.toml b/deps/swc/crates/swc_ecma_compat_es2018/Cargo.toml index 2c1dacde0..01fc15234 100644 --- a/deps/swc/crates/swc_ecma_compat_es2018/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_es2018/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_es2018" repository = { workspace = true } -version = "46.0.0" +version = "51.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,10 +17,10 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] serde = { workspace = true, features = ["derive"] } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } tracing = { workspace = true } [dev-dependencies] diff --git a/deps/swc/crates/swc_ecma_compat_es2019/Cargo.toml b/deps/swc/crates/swc_ecma_compat_es2019/Cargo.toml index 2d5621420..782c10b49 100644 --- a/deps/swc/crates/swc_ecma_compat_es2019/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_es2019/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_es2019" repository = { workspace = true } -version = "45.0.0" +version = "50.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -16,13 +16,13 @@ version = "45.0.0" unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } tracing = { workspace = true } [dev-dependencies] -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } diff --git a/deps/swc/crates/swc_ecma_compat_es2020/Cargo.toml b/deps/swc/crates/swc_ecma_compat_es2020/Cargo.toml index 60f6fe6f1..4ba55cc20 100644 --- a/deps/swc/crates/swc_ecma_compat_es2020/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_es2020/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_es2020" repository = { workspace = true } -version = "48.0.0" +version = "53.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -19,12 +19,12 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } serde = { workspace = true, features = ["derive"] } tracing = { workspace = true } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_compat_es2022 = { version = "48.0.0", path = "../swc_ecma_compat_es2022" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_compat_es2022 = { version = "53.0.0", path = "../swc_ecma_compat_es2022" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] diff --git a/deps/swc/crates/swc_ecma_compat_es2021/Cargo.toml b/deps/swc/crates/swc_ecma_compat_es2021/Cargo.toml index b94ac88c3..ac41a79f1 100644 --- a/deps/swc/crates/swc_ecma_compat_es2021/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_es2021/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_es2021" repository = { workspace = true } -version = "45.0.0" +version = "50.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -18,7 +18,7 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] tracing = { workspace = true } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } diff --git a/deps/swc/crates/swc_ecma_compat_es2022/Cargo.toml b/deps/swc/crates/swc_ecma_compat_es2022/Cargo.toml index e70c3e4da..5db2e53f9 100644 --- a/deps/swc/crates/swc_ecma_compat_es2022/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_es2022/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_es2022" repository = { workspace = true } -version = "48.0.0" +version = "53.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -20,12 +20,12 @@ rustc-hash = { workspace = true } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_classes = { version = "44.0.0", path = "../swc_ecma_transforms_classes" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_classes = { version = "49.0.0", path = "../swc_ecma_transforms_classes" } swc_ecma_transforms_macros = { version = "1.0.1", path = "../swc_ecma_transforms_macros" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } diff --git a/deps/swc/crates/swc_ecma_compat_es2022/src/class_properties/mod.rs b/deps/swc/crates/swc_ecma_compat_es2022/src/class_properties/mod.rs index 6873c9d59..f59e149cf 100644 --- a/deps/swc/crates/swc_ecma_compat_es2022/src/class_properties/mod.rs +++ b/deps/swc/crates/swc_ecma_compat_es2022/src/class_properties/mod.rs @@ -155,9 +155,9 @@ impl VisitMut for ClassProperties { self.extra = old; } - fn visit_mut_block_stmt_or_expr(&mut self, body: &mut BlockStmtOrExpr) { + fn visit_mut_arrow_function_body(&mut self, body: &mut ArrowFunctionBody) { match body { - BlockStmtOrExpr::Expr(expr) if expr.is_class() => { + ArrowFunctionBody::Expr(expr) if expr.is_class() => { let ClassExpr { ident, class } = expr.take().class().unwrap(); let mut stmts = Vec::new(); @@ -174,10 +174,9 @@ impl VisitMut for ClassProperties { .into(), ); - *body = BlockStmtOrExpr::BlockStmt(BlockStmt { + *body = ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts, - ..Default::default() }); } _ => body.visit_mut_children_with(self), @@ -1177,23 +1176,6 @@ impl Visit for SuperVisitor { /// Don't recurse into fn fn visit_function(&mut self, _: &Function) {} - /// Don't recurse into fn - fn visit_getter_prop(&mut self, n: &GetterProp) { - n.key.visit_with(self); - } - - /// Don't recurse into fn - fn visit_method_prop(&mut self, n: &MethodProp) { - n.key.visit_with(self); - n.function.visit_with(self); - } - - /// Don't recurse into fn - fn visit_setter_prop(&mut self, n: &SetterProp) { - n.key.visit_with(self); - n.param.visit_with(self); - } - fn visit_super(&mut self, _: &Super) { self.found = true; } diff --git a/deps/swc/crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs b/deps/swc/crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs index 240081e79..856a7a25d 100644 --- a/deps/swc/crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs +++ b/deps/swc/crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs @@ -37,29 +37,28 @@ pub struct Config { impl VisitMut for OptionalChaining { noop_visit_mut_type!(fail); - fn visit_mut_block_stmt_or_expr(&mut self, expr: &mut BlockStmtOrExpr) { - if let BlockStmtOrExpr::Expr(e) = expr { - let mut stmt = BlockStmt { + fn visit_mut_arrow_function_body(&mut self, body: &mut ArrowFunctionBody) { + if let ArrowFunctionBody::Expr(expr) = body { + let mut function_body = FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, - arg: Some(e.take()), + arg: Some(expr.take()), })], - ..Default::default() }; - stmt.visit_mut_with(self); + function_body.visit_mut_with(self); // If there are optional chains in this expression, then the visitor will have // injected an VarDecl statement and we need to transform into a // block. If not, then we can keep the expression. - match &mut stmt.stmts[..] { - [Stmt::Return(ReturnStmt { arg: Some(e), .. })] => { - *expr = BlockStmtOrExpr::Expr(e.take()) - } - _ => *expr = BlockStmtOrExpr::BlockStmt(stmt), + match &mut function_body.stmts[..] { + [Stmt::Return(ReturnStmt { + arg: Some(expr), .. + })] => *body = ArrowFunctionBody::Expr(expr.take()), + _ => *body = ArrowFunctionBody::FunctionBody(function_body), } } else { - expr.visit_mut_children_with(self); + body.visit_mut_children_with(self); } } @@ -121,10 +120,9 @@ impl VisitMut for OptionalChaining { callee: ArrowExpr { span: DUMMY_SP, params: Vec::new(), - body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt { + body: Box::new(ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts, - ..Default::default() })), is_async: false, is_generator: false, diff --git a/deps/swc/crates/swc_ecma_compat_es3/Cargo.toml b/deps/swc/crates/swc_ecma_compat_es3/Cargo.toml index 9eccaa29c..db685a4fd 100644 --- a/deps/swc/crates/swc_ecma_compat_es3/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_es3/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_es3" repository = { workspace = true } -version = "36.0.0" +version = "41.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -16,11 +16,11 @@ version = "36.0.0" unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer", features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer", features = [ "es3", ] } [dev-dependencies] -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } diff --git a/deps/swc/crates/swc_ecma_compat_regexp/Cargo.toml b/deps/swc/crates/swc_ecma_compat_regexp/Cargo.toml index 919862831..98c79937d 100644 --- a/deps/swc/crates/swc_ecma_compat_regexp/Cargo.toml +++ b/deps/swc/crates/swc_ecma_compat_regexp/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_compat_regexp" repository = "https://github.com/swc-project/swc.git" -version = "6.0.0" +version = "9.0.0" [lib] bench = false @@ -15,8 +15,8 @@ bench = false [dependencies] icu_properties = { version = "2.0.0", default-features = false, features = ["compiled_data", "alloc"] } -swc_ecma_regexp_ast = { version = "0.12.0", path = "../swc_ecma_regexp_ast" } -swc_ecma_regexp_visit = { version = "0.12.0", path = "../swc_ecma_regexp_visit" } +swc_ecma_regexp_ast = { version = "3.0.0", path = "../swc_ecma_regexp_ast" } +swc_ecma_regexp_visit = { version = "0.15.0", path = "../swc_ecma_regexp_visit" } [dev-dependencies] -swc_ecma_regexp = { version = "0.12.0", path = "../swc_ecma_regexp" } +swc_ecma_regexp = { version = "0.15.0", path = "../swc_ecma_regexp" } diff --git a/deps/swc/crates/swc_ecma_ext_transforms/Cargo.toml b/deps/swc/crates/swc_ecma_ext_transforms/Cargo.toml index e0e3fc9cd..4899ddac9 100644 --- a/deps/swc/crates/swc_ecma_ext_transforms/Cargo.toml +++ b/deps/swc/crates/swc_ecma_ext_transforms/Cargo.toml @@ -6,14 +6,14 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_ext_transforms" repository = { workspace = true } -version = "31.0.0" +version = "35.0.0" [lib] bench = false [dependencies] phf = { workspace = true, features = ["macros"] } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } diff --git a/deps/swc/crates/swc_ecma_hooks/Cargo.toml b/deps/swc/crates/swc_ecma_hooks/Cargo.toml index 95d29467f..3bb2e2838 100644 --- a/deps/swc/crates/swc_ecma_hooks/Cargo.toml +++ b/deps/swc/crates/swc_ecma_hooks/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_hooks" repository = { workspace = true } -version = "0.9.0" +version = "1.0.0" [package.metadata.docs.rs] all-features = true @@ -16,7 +16,7 @@ rustdoc-args = ["--cfg", "docsrs"] bench = false [dependencies] -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } diff --git a/deps/swc/crates/swc_ecma_hooks/src/generated.rs b/deps/swc/crates/swc_ecma_hooks/src/generated.rs index 6d687e7fb..6086b6c97 100644 --- a/deps/swc/crates/swc_ecma_hooks/src/generated.rs +++ b/deps/swc/crates/swc_ecma_hooks/src/generated.rs @@ -41,6 +41,14 @@ pub trait VisitHook { #[inline] #[allow(unused_variables)] fn exit_arrow_expr(&mut self, node: &ArrowExpr, ctx: &mut C) {} + #[doc = "Called when entering a node of type `ArrowFunctionBody` before visiting its children."] + #[inline] + #[allow(unused_variables)] + fn enter_arrow_function_body(&mut self, node: &ArrowFunctionBody, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `ArrowFunctionBody` after visiting its children."] + #[inline] + #[allow(unused_variables)] + fn exit_arrow_function_body(&mut self, node: &ArrowFunctionBody, ctx: &mut C) {} #[doc = "Called when entering a node of type `AssignExpr` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -169,14 +177,6 @@ pub trait VisitHook { #[inline] #[allow(unused_variables)] fn exit_block_stmt(&mut self, node: &BlockStmt, ctx: &mut C) {} - #[doc = "Called when entering a node of type `BlockStmtOrExpr` before visiting its children."] - #[inline] - #[allow(unused_variables)] - fn enter_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr, ctx: &mut C) {} - #[doc = "Called when exiting a node of type `BlockStmtOrExpr` after visiting its children."] - #[inline] - #[allow(unused_variables)] - fn exit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr, ctx: &mut C) {} #[doc = "Called when entering a node of type `Bool` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -539,6 +539,14 @@ pub trait VisitHook { #[inline] #[allow(unused_variables)] fn exit_function(&mut self, node: &Function, ctx: &mut C) {} + #[doc = "Called when entering a node of type `FunctionBody` before visiting its children."] + #[inline] + #[allow(unused_variables)] + fn enter_function_body(&mut self, node: &FunctionBody, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `FunctionBody` after visiting its children."] + #[inline] + #[allow(unused_variables)] + fn exit_function_body(&mut self, node: &FunctionBody, ctx: &mut C) {} #[doc = "Called when entering a node of type `GetterProp` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -1143,6 +1151,16 @@ pub trait VisitHook { #[inline] #[allow(unused_variables)] fn exit_opt_expr_or_spreads(&mut self, node: &Option>, ctx: &mut C) {} + #[doc = "Called when entering a node of type `Option < FunctionBody >` before visiting its \ + children."] + #[inline] + #[allow(unused_variables)] + fn enter_opt_function_body(&mut self, node: &Option, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `Option < FunctionBody >` after visiting its \ + children."] + #[inline] + #[allow(unused_variables)] + fn exit_opt_function_body(&mut self, node: &Option, ctx: &mut C) {} #[doc = "Called when entering a node of type `Option < Ident >` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -1275,6 +1293,16 @@ pub trait VisitHook { #[inline] #[allow(unused_variables)] fn exit_opt_ts_namespace_body(&mut self, node: &Option, ctx: &mut C) {} + #[doc = "Called when entering a node of type `Option < Box < TsThisParam > >` before visiting \ + its children."] + #[inline] + #[allow(unused_variables)] + fn enter_opt_ts_this_param(&mut self, node: &Option>, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `Option < Box < TsThisParam > >` after visiting \ + its children."] + #[inline] + #[allow(unused_variables)] + fn exit_opt_ts_this_param(&mut self, node: &Option>, ctx: &mut C) {} #[doc = "Called when entering a node of type `Option < Box < TsType > >` before visiting its \ children."] #[inline] @@ -2161,6 +2189,14 @@ pub trait VisitHook { #[inline] #[allow(unused_variables)] fn exit_ts_setter_signature(&mut self, node: &TsSetterSignature, ctx: &mut C) {} + #[doc = "Called when entering a node of type `TsThisParam` before visiting its children."] + #[inline] + #[allow(unused_variables)] + fn enter_ts_this_param(&mut self, node: &TsThisParam, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `TsThisParam` after visiting its children."] + #[inline] + #[allow(unused_variables)] + fn exit_ts_this_param(&mut self, node: &TsThisParam, ctx: &mut C) {} #[doc = "Called when entering a node of type `TsThisType` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -2569,6 +2605,18 @@ where self.first.exit_arrow_expr(node, ctx); } + #[inline] + fn enter_arrow_function_body(&mut self, node: &ArrowFunctionBody, ctx: &mut C) { + self.first.enter_arrow_function_body(node, ctx); + self.second.enter_arrow_function_body(node, ctx); + } + + #[inline] + fn exit_arrow_function_body(&mut self, node: &ArrowFunctionBody, ctx: &mut C) { + self.second.exit_arrow_function_body(node, ctx); + self.first.exit_arrow_function_body(node, ctx); + } + #[inline] fn enter_assign_expr(&mut self, node: &AssignExpr, ctx: &mut C) { self.first.enter_assign_expr(node, ctx); @@ -2761,18 +2809,6 @@ where self.first.exit_block_stmt(node, ctx); } - #[inline] - fn enter_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr, ctx: &mut C) { - self.first.enter_block_stmt_or_expr(node, ctx); - self.second.enter_block_stmt_or_expr(node, ctx); - } - - #[inline] - fn exit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr, ctx: &mut C) { - self.second.exit_block_stmt_or_expr(node, ctx); - self.first.exit_block_stmt_or_expr(node, ctx); - } - #[inline] fn enter_bool(&mut self, node: &Bool, ctx: &mut C) { self.first.enter_bool(node, ctx); @@ -3301,6 +3337,18 @@ where self.first.exit_function(node, ctx); } + #[inline] + fn enter_function_body(&mut self, node: &FunctionBody, ctx: &mut C) { + self.first.enter_function_body(node, ctx); + self.second.enter_function_body(node, ctx); + } + + #[inline] + fn exit_function_body(&mut self, node: &FunctionBody, ctx: &mut C) { + self.second.exit_function_body(node, ctx); + self.first.exit_function_body(node, ctx); + } + #[inline] fn enter_getter_prop(&mut self, node: &GetterProp, ctx: &mut C) { self.first.enter_getter_prop(node, ctx); @@ -4165,6 +4213,18 @@ where self.first.exit_opt_expr_or_spreads(node, ctx); } + #[inline] + fn enter_opt_function_body(&mut self, node: &Option, ctx: &mut C) { + self.first.enter_opt_function_body(node, ctx); + self.second.enter_opt_function_body(node, ctx); + } + + #[inline] + fn exit_opt_function_body(&mut self, node: &Option, ctx: &mut C) { + self.second.exit_opt_function_body(node, ctx); + self.first.exit_opt_function_body(node, ctx); + } + #[inline] fn enter_opt_ident(&mut self, node: &Option, ctx: &mut C) { self.first.enter_opt_ident(node, ctx); @@ -4325,6 +4385,18 @@ where self.first.exit_opt_ts_namespace_body(node, ctx); } + #[inline] + fn enter_opt_ts_this_param(&mut self, node: &Option>, ctx: &mut C) { + self.first.enter_opt_ts_this_param(node, ctx); + self.second.enter_opt_ts_this_param(node, ctx); + } + + #[inline] + fn exit_opt_ts_this_param(&mut self, node: &Option>, ctx: &mut C) { + self.second.exit_opt_ts_this_param(node, ctx); + self.first.exit_opt_ts_this_param(node, ctx); + } + #[inline] fn enter_opt_ts_type(&mut self, node: &Option>, ctx: &mut C) { self.first.enter_opt_ts_type(node, ctx); @@ -5593,6 +5665,18 @@ where self.first.exit_ts_setter_signature(node, ctx); } + #[inline] + fn enter_ts_this_param(&mut self, node: &TsThisParam, ctx: &mut C) { + self.first.enter_ts_this_param(node, ctx); + self.second.enter_ts_this_param(node, ctx); + } + + #[inline] + fn exit_ts_this_param(&mut self, node: &TsThisParam, ctx: &mut C) { + self.second.exit_ts_this_param(node, ctx); + self.first.exit_ts_this_param(node, ctx); + } + #[inline] fn enter_ts_this_type(&mut self, node: &TsThisType, ctx: &mut C) { self.first.enter_ts_this_type(node, ctx); @@ -6150,6 +6234,22 @@ where } } + #[inline] + fn enter_arrow_function_body(&mut self, node: &ArrowFunctionBody, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_arrow_function_body(node, ctx), + Self::Right(hook) => hook.enter_arrow_function_body(node, ctx), + } + } + + #[inline] + fn exit_arrow_function_body(&mut self, node: &ArrowFunctionBody, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_arrow_function_body(node, ctx), + Self::Right(hook) => hook.exit_arrow_function_body(node, ctx), + } + } + #[inline] fn enter_assign_expr(&mut self, node: &AssignExpr, ctx: &mut C) { match self { @@ -6406,22 +6506,6 @@ where } } - #[inline] - fn enter_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr, ctx: &mut C) { - match self { - Self::Left(hook) => hook.enter_block_stmt_or_expr(node, ctx), - Self::Right(hook) => hook.enter_block_stmt_or_expr(node, ctx), - } - } - - #[inline] - fn exit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr, ctx: &mut C) { - match self { - Self::Left(hook) => hook.exit_block_stmt_or_expr(node, ctx), - Self::Right(hook) => hook.exit_block_stmt_or_expr(node, ctx), - } - } - #[inline] fn enter_bool(&mut self, node: &Bool, ctx: &mut C) { match self { @@ -7126,6 +7210,22 @@ where } } + #[inline] + fn enter_function_body(&mut self, node: &FunctionBody, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_function_body(node, ctx), + Self::Right(hook) => hook.enter_function_body(node, ctx), + } + } + + #[inline] + fn exit_function_body(&mut self, node: &FunctionBody, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_function_body(node, ctx), + Self::Right(hook) => hook.exit_function_body(node, ctx), + } + } + #[inline] fn enter_getter_prop(&mut self, node: &GetterProp, ctx: &mut C) { match self { @@ -8278,6 +8378,22 @@ where } } + #[inline] + fn enter_opt_function_body(&mut self, node: &Option, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_opt_function_body(node, ctx), + Self::Right(hook) => hook.enter_opt_function_body(node, ctx), + } + } + + #[inline] + fn exit_opt_function_body(&mut self, node: &Option, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_opt_function_body(node, ctx), + Self::Right(hook) => hook.exit_opt_function_body(node, ctx), + } + } + #[inline] fn enter_opt_ident(&mut self, node: &Option, ctx: &mut C) { match self { @@ -8490,6 +8606,22 @@ where } } + #[inline] + fn enter_opt_ts_this_param(&mut self, node: &Option>, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_opt_ts_this_param(node, ctx), + Self::Right(hook) => hook.enter_opt_ts_this_param(node, ctx), + } + } + + #[inline] + fn exit_opt_ts_this_param(&mut self, node: &Option>, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_opt_ts_this_param(node, ctx), + Self::Right(hook) => hook.exit_opt_ts_this_param(node, ctx), + } + } + #[inline] fn enter_opt_ts_type(&mut self, node: &Option>, ctx: &mut C) { match self { @@ -10178,6 +10310,22 @@ where } } + #[inline] + fn enter_ts_this_param(&mut self, node: &TsThisParam, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_ts_this_param(node, ctx), + Self::Right(hook) => hook.enter_ts_this_param(node, ctx), + } + } + + #[inline] + fn exit_ts_this_param(&mut self, node: &TsThisParam, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_ts_this_param(node, ctx), + Self::Right(hook) => hook.exit_ts_this_param(node, ctx), + } + } + #[inline] fn enter_ts_this_type(&mut self, node: &TsThisType, ctx: &mut C) { match self { @@ -10886,6 +11034,20 @@ where } } + #[inline] + fn enter_arrow_function_body(&mut self, node: &ArrowFunctionBody, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_arrow_function_body(node, ctx); + } + } + + #[inline] + fn exit_arrow_function_body(&mut self, node: &ArrowFunctionBody, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_arrow_function_body(node, ctx); + } + } + #[inline] fn enter_assign_expr(&mut self, node: &AssignExpr, ctx: &mut C) { if let Some(hook) = self { @@ -11110,20 +11272,6 @@ where } } - #[inline] - fn enter_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr, ctx: &mut C) { - if let Some(hook) = self { - hook.enter_block_stmt_or_expr(node, ctx); - } - } - - #[inline] - fn exit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr, ctx: &mut C) { - if let Some(hook) = self { - hook.exit_block_stmt_or_expr(node, ctx); - } - } - #[inline] fn enter_bool(&mut self, node: &Bool, ctx: &mut C) { if let Some(hook) = self { @@ -11740,6 +11888,20 @@ where } } + #[inline] + fn enter_function_body(&mut self, node: &FunctionBody, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_function_body(node, ctx); + } + } + + #[inline] + fn exit_function_body(&mut self, node: &FunctionBody, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_function_body(node, ctx); + } + } + #[inline] fn enter_getter_prop(&mut self, node: &GetterProp, ctx: &mut C) { if let Some(hook) = self { @@ -12748,6 +12910,20 @@ where } } + #[inline] + fn enter_opt_function_body(&mut self, node: &Option, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_opt_function_body(node, ctx); + } + } + + #[inline] + fn exit_opt_function_body(&mut self, node: &Option, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_opt_function_body(node, ctx); + } + } + #[inline] fn enter_opt_ident(&mut self, node: &Option, ctx: &mut C) { if let Some(hook) = self { @@ -12934,6 +13110,20 @@ where } } + #[inline] + fn enter_opt_ts_this_param(&mut self, node: &Option>, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_opt_ts_this_param(node, ctx); + } + } + + #[inline] + fn exit_opt_ts_this_param(&mut self, node: &Option>, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_opt_ts_this_param(node, ctx); + } + } + #[inline] fn enter_opt_ts_type(&mut self, node: &Option>, ctx: &mut C) { if let Some(hook) = self { @@ -14412,6 +14602,20 @@ where } } + #[inline] + fn enter_ts_this_param(&mut self, node: &TsThisParam, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_ts_this_param(node, ctx); + } + } + + #[inline] + fn exit_ts_this_param(&mut self, node: &TsThisParam, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_ts_this_param(node, ctx); + } + } + #[inline] fn enter_ts_this_type(&mut self, node: &TsThisType, ctx: &mut C) { if let Some(hook) = self { @@ -15022,6 +15226,14 @@ impl, C> Visit for VisitWithHook { self.hook.exit_arrow_expr(node, &mut self.context); } + #[doc = "Visits a node of type `ArrowFunctionBody` using the hook's enter and exit methods."] + #[inline] + fn visit_arrow_function_body(&mut self, node: &ArrowFunctionBody) { + self.hook.enter_arrow_function_body(node, &mut self.context); + node.visit_children_with(self); + self.hook.exit_arrow_function_body(node, &mut self.context); + } + #[doc = "Visits a node of type `AssignExpr` using the hook's enter and exit methods."] #[inline] fn visit_assign_expr(&mut self, node: &AssignExpr) { @@ -15150,14 +15362,6 @@ impl, C> Visit for VisitWithHook { self.hook.exit_block_stmt(node, &mut self.context); } - #[doc = "Visits a node of type `BlockStmtOrExpr` using the hook's enter and exit methods."] - #[inline] - fn visit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr) { - self.hook.enter_block_stmt_or_expr(node, &mut self.context); - node.visit_children_with(self); - self.hook.exit_block_stmt_or_expr(node, &mut self.context); - } - #[doc = "Visits a node of type `Bool` using the hook's enter and exit methods."] #[inline] fn visit_bool(&mut self, node: &Bool) { @@ -15519,6 +15723,14 @@ impl, C> Visit for VisitWithHook { self.hook.exit_function(node, &mut self.context); } + #[doc = "Visits a node of type `FunctionBody` using the hook's enter and exit methods."] + #[inline] + fn visit_function_body(&mut self, node: &FunctionBody) { + self.hook.enter_function_body(node, &mut self.context); + node.visit_children_with(self); + self.hook.exit_function_body(node, &mut self.context); + } + #[doc = "Visits a node of type `GetterProp` using the hook's enter and exit methods."] #[inline] fn visit_getter_prop(&mut self, node: &GetterProp) { @@ -16114,6 +16326,15 @@ impl, C> Visit for VisitWithHook { self.hook.exit_opt_expr_or_spreads(node, &mut self.context); } + #[doc = "Visits a node of type `Option < FunctionBody >` using the hook's enter and exit \ + methods."] + #[inline] + fn visit_opt_function_body(&mut self, node: &Option) { + self.hook.enter_opt_function_body(node, &mut self.context); + node.visit_children_with(self); + self.hook.exit_opt_function_body(node, &mut self.context); + } + #[doc = "Visits a node of type `Option < Ident >` using the hook's enter and exit methods."] #[inline] fn visit_opt_ident(&mut self, node: &Option) { @@ -16237,6 +16458,15 @@ impl, C> Visit for VisitWithHook { .exit_opt_ts_namespace_body(node, &mut self.context); } + #[doc = "Visits a node of type `Option < Box < TsThisParam > >` using the hook's enter and \ + exit methods."] + #[inline] + fn visit_opt_ts_this_param(&mut self, node: &Option>) { + self.hook.enter_opt_ts_this_param(node, &mut self.context); + node.visit_children_with(self); + self.hook.exit_opt_ts_this_param(node, &mut self.context); + } + #[doc = "Visits a node of type `Option < Box < TsType > >` using the hook's enter and exit \ methods."] #[inline] @@ -17131,6 +17361,14 @@ impl, C> Visit for VisitWithHook { self.hook.exit_ts_setter_signature(node, &mut self.context); } + #[doc = "Visits a node of type `TsThisParam` using the hook's enter and exit methods."] + #[inline] + fn visit_ts_this_param(&mut self, node: &TsThisParam) { + self.hook.enter_ts_this_param(node, &mut self.context); + node.visit_children_with(self); + self.hook.exit_ts_this_param(node, &mut self.context); + } + #[doc = "Visits a node of type `TsThisType` using the hook's enter and exit methods."] #[inline] fn visit_ts_this_type(&mut self, node: &TsThisType) { @@ -17499,6 +17737,14 @@ pub trait VisitMutHook { #[inline] #[allow(unused_variables)] fn exit_arrow_expr(&mut self, node: &mut ArrowExpr, ctx: &mut C) {} + #[doc = "Called when entering a node of type `ArrowFunctionBody` before visiting its children."] + #[inline] + #[allow(unused_variables)] + fn enter_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `ArrowFunctionBody` after visiting its children."] + #[inline] + #[allow(unused_variables)] + fn exit_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut C) {} #[doc = "Called when entering a node of type `AssignExpr` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -17627,14 +17873,6 @@ pub trait VisitMutHook { #[inline] #[allow(unused_variables)] fn exit_block_stmt(&mut self, node: &mut BlockStmt, ctx: &mut C) {} - #[doc = "Called when entering a node of type `BlockStmtOrExpr` before visiting its children."] - #[inline] - #[allow(unused_variables)] - fn enter_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut C) {} - #[doc = "Called when exiting a node of type `BlockStmtOrExpr` after visiting its children."] - #[inline] - #[allow(unused_variables)] - fn exit_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut C) {} #[doc = "Called when entering a node of type `Bool` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -18007,6 +18245,14 @@ pub trait VisitMutHook { #[inline] #[allow(unused_variables)] fn exit_function(&mut self, node: &mut Function, ctx: &mut C) {} + #[doc = "Called when entering a node of type `FunctionBody` before visiting its children."] + #[inline] + #[allow(unused_variables)] + fn enter_function_body(&mut self, node: &mut FunctionBody, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `FunctionBody` after visiting its children."] + #[inline] + #[allow(unused_variables)] + fn exit_function_body(&mut self, node: &mut FunctionBody, ctx: &mut C) {} #[doc = "Called when entering a node of type `GetterProp` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -18611,6 +18857,16 @@ pub trait VisitMutHook { #[inline] #[allow(unused_variables)] fn exit_opt_expr_or_spreads(&mut self, node: &mut Option>, ctx: &mut C) {} + #[doc = "Called when entering a node of type `Option < FunctionBody >` before visiting its \ + children."] + #[inline] + #[allow(unused_variables)] + fn enter_opt_function_body(&mut self, node: &mut Option, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `Option < FunctionBody >` after visiting its \ + children."] + #[inline] + #[allow(unused_variables)] + fn exit_opt_function_body(&mut self, node: &mut Option, ctx: &mut C) {} #[doc = "Called when entering a node of type `Option < Ident >` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -18748,6 +19004,16 @@ pub trait VisitMutHook { #[inline] #[allow(unused_variables)] fn exit_opt_ts_namespace_body(&mut self, node: &mut Option, ctx: &mut C) {} + #[doc = "Called when entering a node of type `Option < Box < TsThisParam > >` before visiting \ + its children."] + #[inline] + #[allow(unused_variables)] + fn enter_opt_ts_this_param(&mut self, node: &mut Option>, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `Option < Box < TsThisParam > >` after visiting \ + its children."] + #[inline] + #[allow(unused_variables)] + fn exit_opt_ts_this_param(&mut self, node: &mut Option>, ctx: &mut C) {} #[doc = "Called when entering a node of type `Option < Box < TsType > >` before visiting its \ children."] #[inline] @@ -19655,6 +19921,14 @@ pub trait VisitMutHook { #[inline] #[allow(unused_variables)] fn exit_ts_setter_signature(&mut self, node: &mut TsSetterSignature, ctx: &mut C) {} + #[doc = "Called when entering a node of type `TsThisParam` before visiting its children."] + #[inline] + #[allow(unused_variables)] + fn enter_ts_this_param(&mut self, node: &mut TsThisParam, ctx: &mut C) {} + #[doc = "Called when exiting a node of type `TsThisParam` after visiting its children."] + #[inline] + #[allow(unused_variables)] + fn exit_ts_this_param(&mut self, node: &mut TsThisParam, ctx: &mut C) {} #[doc = "Called when entering a node of type `TsThisType` before visiting its children."] #[inline] #[allow(unused_variables)] @@ -20073,6 +20347,18 @@ where self.first.exit_arrow_expr(node, ctx); } + #[inline] + fn enter_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut C) { + self.first.enter_arrow_function_body(node, ctx); + self.second.enter_arrow_function_body(node, ctx); + } + + #[inline] + fn exit_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut C) { + self.second.exit_arrow_function_body(node, ctx); + self.first.exit_arrow_function_body(node, ctx); + } + #[inline] fn enter_assign_expr(&mut self, node: &mut AssignExpr, ctx: &mut C) { self.first.enter_assign_expr(node, ctx); @@ -20265,18 +20551,6 @@ where self.first.exit_block_stmt(node, ctx); } - #[inline] - fn enter_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut C) { - self.first.enter_block_stmt_or_expr(node, ctx); - self.second.enter_block_stmt_or_expr(node, ctx); - } - - #[inline] - fn exit_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut C) { - self.second.exit_block_stmt_or_expr(node, ctx); - self.first.exit_block_stmt_or_expr(node, ctx); - } - #[inline] fn enter_bool(&mut self, node: &mut Bool, ctx: &mut C) { self.first.enter_bool(node, ctx); @@ -20813,6 +21087,18 @@ where self.first.exit_function(node, ctx); } + #[inline] + fn enter_function_body(&mut self, node: &mut FunctionBody, ctx: &mut C) { + self.first.enter_function_body(node, ctx); + self.second.enter_function_body(node, ctx); + } + + #[inline] + fn exit_function_body(&mut self, node: &mut FunctionBody, ctx: &mut C) { + self.second.exit_function_body(node, ctx); + self.first.exit_function_body(node, ctx); + } + #[inline] fn enter_getter_prop(&mut self, node: &mut GetterProp, ctx: &mut C) { self.first.enter_getter_prop(node, ctx); @@ -21677,6 +21963,18 @@ where self.first.exit_opt_expr_or_spreads(node, ctx); } + #[inline] + fn enter_opt_function_body(&mut self, node: &mut Option, ctx: &mut C) { + self.first.enter_opt_function_body(node, ctx); + self.second.enter_opt_function_body(node, ctx); + } + + #[inline] + fn exit_opt_function_body(&mut self, node: &mut Option, ctx: &mut C) { + self.second.exit_opt_function_body(node, ctx); + self.first.exit_opt_function_body(node, ctx); + } + #[inline] fn enter_opt_ident(&mut self, node: &mut Option, ctx: &mut C) { self.first.enter_opt_ident(node, ctx); @@ -21841,6 +22139,18 @@ where self.first.exit_opt_ts_namespace_body(node, ctx); } + #[inline] + fn enter_opt_ts_this_param(&mut self, node: &mut Option>, ctx: &mut C) { + self.first.enter_opt_ts_this_param(node, ctx); + self.second.enter_opt_ts_this_param(node, ctx); + } + + #[inline] + fn exit_opt_ts_this_param(&mut self, node: &mut Option>, ctx: &mut C) { + self.second.exit_opt_ts_this_param(node, ctx); + self.first.exit_opt_ts_this_param(node, ctx); + } + #[inline] fn enter_opt_ts_type(&mut self, node: &mut Option>, ctx: &mut C) { self.first.enter_opt_ts_type(node, ctx); @@ -23125,6 +23435,18 @@ where self.first.exit_ts_setter_signature(node, ctx); } + #[inline] + fn enter_ts_this_param(&mut self, node: &mut TsThisParam, ctx: &mut C) { + self.first.enter_ts_this_param(node, ctx); + self.second.enter_ts_this_param(node, ctx); + } + + #[inline] + fn exit_ts_this_param(&mut self, node: &mut TsThisParam, ctx: &mut C) { + self.second.exit_ts_this_param(node, ctx); + self.first.exit_ts_this_param(node, ctx); + } + #[inline] fn enter_ts_this_type(&mut self, node: &mut TsThisType, ctx: &mut C) { self.first.enter_ts_this_type(node, ctx); @@ -23690,6 +24012,22 @@ where } } + #[inline] + fn enter_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_arrow_function_body(node, ctx), + Self::Right(hook) => hook.enter_arrow_function_body(node, ctx), + } + } + + #[inline] + fn exit_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_arrow_function_body(node, ctx), + Self::Right(hook) => hook.exit_arrow_function_body(node, ctx), + } + } + #[inline] fn enter_assign_expr(&mut self, node: &mut AssignExpr, ctx: &mut C) { match self { @@ -23946,22 +24284,6 @@ where } } - #[inline] - fn enter_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut C) { - match self { - Self::Left(hook) => hook.enter_block_stmt_or_expr(node, ctx), - Self::Right(hook) => hook.enter_block_stmt_or_expr(node, ctx), - } - } - - #[inline] - fn exit_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut C) { - match self { - Self::Left(hook) => hook.exit_block_stmt_or_expr(node, ctx), - Self::Right(hook) => hook.exit_block_stmt_or_expr(node, ctx), - } - } - #[inline] fn enter_bool(&mut self, node: &mut Bool, ctx: &mut C) { match self { @@ -24674,6 +24996,22 @@ where } } + #[inline] + fn enter_function_body(&mut self, node: &mut FunctionBody, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_function_body(node, ctx), + Self::Right(hook) => hook.enter_function_body(node, ctx), + } + } + + #[inline] + fn exit_function_body(&mut self, node: &mut FunctionBody, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_function_body(node, ctx), + Self::Right(hook) => hook.exit_function_body(node, ctx), + } + } + #[inline] fn enter_getter_prop(&mut self, node: &mut GetterProp, ctx: &mut C) { match self { @@ -25826,6 +26164,22 @@ where } } + #[inline] + fn enter_opt_function_body(&mut self, node: &mut Option, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_opt_function_body(node, ctx), + Self::Right(hook) => hook.enter_opt_function_body(node, ctx), + } + } + + #[inline] + fn exit_opt_function_body(&mut self, node: &mut Option, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_opt_function_body(node, ctx), + Self::Right(hook) => hook.exit_opt_function_body(node, ctx), + } + } + #[inline] fn enter_opt_ident(&mut self, node: &mut Option, ctx: &mut C) { match self { @@ -26042,6 +26396,22 @@ where } } + #[inline] + fn enter_opt_ts_this_param(&mut self, node: &mut Option>, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_opt_ts_this_param(node, ctx), + Self::Right(hook) => hook.enter_opt_ts_this_param(node, ctx), + } + } + + #[inline] + fn exit_opt_ts_this_param(&mut self, node: &mut Option>, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_opt_ts_this_param(node, ctx), + Self::Right(hook) => hook.exit_opt_ts_this_param(node, ctx), + } + } + #[inline] fn enter_opt_ts_type(&mut self, node: &mut Option>, ctx: &mut C) { match self { @@ -27746,6 +28116,22 @@ where } } + #[inline] + fn enter_ts_this_param(&mut self, node: &mut TsThisParam, ctx: &mut C) { + match self { + Self::Left(hook) => hook.enter_ts_this_param(node, ctx), + Self::Right(hook) => hook.enter_ts_this_param(node, ctx), + } + } + + #[inline] + fn exit_ts_this_param(&mut self, node: &mut TsThisParam, ctx: &mut C) { + match self { + Self::Left(hook) => hook.exit_ts_this_param(node, ctx), + Self::Right(hook) => hook.exit_ts_this_param(node, ctx), + } + } + #[inline] fn enter_ts_this_type(&mut self, node: &mut TsThisType, ctx: &mut C) { match self { @@ -28462,6 +28848,20 @@ where } } + #[inline] + fn enter_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_arrow_function_body(node, ctx); + } + } + + #[inline] + fn exit_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_arrow_function_body(node, ctx); + } + } + #[inline] fn enter_assign_expr(&mut self, node: &mut AssignExpr, ctx: &mut C) { if let Some(hook) = self { @@ -28686,20 +29086,6 @@ where } } - #[inline] - fn enter_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut C) { - if let Some(hook) = self { - hook.enter_block_stmt_or_expr(node, ctx); - } - } - - #[inline] - fn exit_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut C) { - if let Some(hook) = self { - hook.exit_block_stmt_or_expr(node, ctx); - } - } - #[inline] fn enter_bool(&mut self, node: &mut Bool, ctx: &mut C) { if let Some(hook) = self { @@ -29324,6 +29710,20 @@ where } } + #[inline] + fn enter_function_body(&mut self, node: &mut FunctionBody, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_function_body(node, ctx); + } + } + + #[inline] + fn exit_function_body(&mut self, node: &mut FunctionBody, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_function_body(node, ctx); + } + } + #[inline] fn enter_getter_prop(&mut self, node: &mut GetterProp, ctx: &mut C) { if let Some(hook) = self { @@ -30332,6 +30732,20 @@ where } } + #[inline] + fn enter_opt_function_body(&mut self, node: &mut Option, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_opt_function_body(node, ctx); + } + } + + #[inline] + fn exit_opt_function_body(&mut self, node: &mut Option, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_opt_function_body(node, ctx); + } + } + #[inline] fn enter_opt_ident(&mut self, node: &mut Option, ctx: &mut C) { if let Some(hook) = self { @@ -30522,6 +30936,20 @@ where } } + #[inline] + fn enter_opt_ts_this_param(&mut self, node: &mut Option>, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_opt_ts_this_param(node, ctx); + } + } + + #[inline] + fn exit_opt_ts_this_param(&mut self, node: &mut Option>, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_opt_ts_this_param(node, ctx); + } + } + #[inline] fn enter_opt_ts_type(&mut self, node: &mut Option>, ctx: &mut C) { if let Some(hook) = self { @@ -32016,6 +32444,20 @@ where } } + #[inline] + fn enter_ts_this_param(&mut self, node: &mut TsThisParam, ctx: &mut C) { + if let Some(hook) = self { + hook.enter_ts_this_param(node, ctx); + } + } + + #[inline] + fn exit_ts_this_param(&mut self, node: &mut TsThisParam, ctx: &mut C) { + if let Some(hook) = self { + hook.exit_ts_this_param(node, ctx); + } + } + #[inline] fn enter_ts_this_type(&mut self, node: &mut TsThisType, ctx: &mut C) { if let Some(hook) = self { @@ -32634,6 +33076,14 @@ impl, C> VisitMut for VisitMutWithHook { self.hook.exit_arrow_expr(node, &mut self.context); } + #[doc = "Visits a node of type `ArrowFunctionBody` using the hook's enter and exit methods."] + #[inline] + fn visit_mut_arrow_function_body(&mut self, node: &mut ArrowFunctionBody) { + self.hook.enter_arrow_function_body(node, &mut self.context); + node.visit_mut_children_with(self); + self.hook.exit_arrow_function_body(node, &mut self.context); + } + #[doc = "Visits a node of type `AssignExpr` using the hook's enter and exit methods."] #[inline] fn visit_mut_assign_expr(&mut self, node: &mut AssignExpr) { @@ -32762,14 +33212,6 @@ impl, C> VisitMut for VisitMutWithHook { self.hook.exit_block_stmt(node, &mut self.context); } - #[doc = "Visits a node of type `BlockStmtOrExpr` using the hook's enter and exit methods."] - #[inline] - fn visit_mut_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr) { - self.hook.enter_block_stmt_or_expr(node, &mut self.context); - node.visit_mut_children_with(self); - self.hook.exit_block_stmt_or_expr(node, &mut self.context); - } - #[doc = "Visits a node of type `Bool` using the hook's enter and exit methods."] #[inline] fn visit_mut_bool(&mut self, node: &mut Bool) { @@ -33131,6 +33573,14 @@ impl, C> VisitMut for VisitMutWithHook { self.hook.exit_function(node, &mut self.context); } + #[doc = "Visits a node of type `FunctionBody` using the hook's enter and exit methods."] + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody) { + self.hook.enter_function_body(node, &mut self.context); + node.visit_mut_children_with(self); + self.hook.exit_function_body(node, &mut self.context); + } + #[doc = "Visits a node of type `GetterProp` using the hook's enter and exit methods."] #[inline] fn visit_mut_getter_prop(&mut self, node: &mut GetterProp) { @@ -33726,6 +34176,15 @@ impl, C> VisitMut for VisitMutWithHook { self.hook.exit_opt_expr_or_spreads(node, &mut self.context); } + #[doc = "Visits a node of type `Option < FunctionBody >` using the hook's enter and exit \ + methods."] + #[inline] + fn visit_mut_opt_function_body(&mut self, node: &mut Option) { + self.hook.enter_opt_function_body(node, &mut self.context); + node.visit_mut_children_with(self); + self.hook.exit_opt_function_body(node, &mut self.context); + } + #[doc = "Visits a node of type `Option < Ident >` using the hook's enter and exit methods."] #[inline] fn visit_mut_opt_ident(&mut self, node: &mut Option) { @@ -33849,6 +34308,15 @@ impl, C> VisitMut for VisitMutWithHook { .exit_opt_ts_namespace_body(node, &mut self.context); } + #[doc = "Visits a node of type `Option < Box < TsThisParam > >` using the hook's enter and \ + exit methods."] + #[inline] + fn visit_mut_opt_ts_this_param(&mut self, node: &mut Option>) { + self.hook.enter_opt_ts_this_param(node, &mut self.context); + node.visit_mut_children_with(self); + self.hook.exit_opt_ts_this_param(node, &mut self.context); + } + #[doc = "Visits a node of type `Option < Box < TsType > >` using the hook's enter and exit \ methods."] #[inline] @@ -34743,6 +35211,14 @@ impl, C> VisitMut for VisitMutWithHook { self.hook.exit_ts_setter_signature(node, &mut self.context); } + #[doc = "Visits a node of type `TsThisParam` using the hook's enter and exit methods."] + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam) { + self.hook.enter_ts_this_param(node, &mut self.context); + node.visit_mut_children_with(self); + self.hook.exit_ts_this_param(node, &mut self.context); + } + #[doc = "Visits a node of type `TsThisType` using the hook's enter and exit methods."] #[inline] fn visit_mut_ts_this_type(&mut self, node: &mut TsThisType) { diff --git a/deps/swc/crates/swc_ecma_lexer/Cargo.toml b/deps/swc/crates/swc_ecma_lexer/Cargo.toml index ae9b624f7..c1979409a 100644 --- a/deps/swc/crates/swc_ecma_lexer/Cargo.toml +++ b/deps/swc/crates/swc_ecma_lexer/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "examples/**/*.rs"] license = { workspace = true } name = "swc_ecma_lexer" repository = { workspace = true } -version = "40.0.1" +version = "44.0.0" [package.metadata.docs.rs] all-features = true @@ -29,31 +29,31 @@ verify = ["swc_ecma_visit"] [dependencies] bitflags = { workspace = true } +compact_str = { workspace = true } either = { workspace = true } num-bigint = { workspace = true } rustc-hash = { workspace = true } seq-macro = { workspace = true } serde = { workspace = true, features = ["derive"] } smallvec = { workspace = true } -smartstring = { workspace = true } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit", optional = true } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit", optional = true } [target.'cfg(not(any(target_arch = "wasm32", target_arch = "arm")))'.dependencies] stacker = { version = "0.1.15", optional = true } [dev-dependencies] -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast", features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast", features = [ "serde-impl", ] } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } +testing = { version = "27.0.0", path = "../testing" } [[example]] name = "lexer" diff --git a/deps/swc/crates/swc_ecma_lexer/src/common/lexer/mod.rs b/deps/swc/crates/swc_ecma_lexer/src/common/lexer/mod.rs index 306598781..1a2670ecd 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/common/lexer/mod.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/common/lexer/mod.rs @@ -1,9 +1,9 @@ use std::borrow::Cow; use char::CharExt; +use compact_str::CompactString; use either::Either::{self, Left, Right}; use num_bigint::BigInt as BigIntValue; -use smartstring::{LazyCompact, SmartString}; use state::State; use swc_atoms::{ wtf8::{CodePoint, Wtf8, Wtf8Buf}, @@ -1008,7 +1008,7 @@ pub trait Lexer<'a, TokenAndSpan>: Tokens + Sized { s.chars().all(|c| c.is_ascii_digit()) } - let mut s = SmartString::::default(); + let mut s = CompactString::default(); debug_assert!(self.input().cur().is_some_and(|c| c == b'&')); self.bump(); diff --git a/deps/swc/crates/swc_ecma_lexer/src/common/lexer/token.rs b/deps/swc/crates/swc_ecma_lexer/src/common/lexer/token.rs index 392d68353..367dc2ab7 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/common/lexer/token.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/common/lexer/token.rs @@ -163,9 +163,9 @@ pub trait TokenFactory<'a, TokenAndSpan, I: Tokens>: Sized + Parti fn is_template(&self) -> bool; fn take_template(self, buffer: &mut Self::Buffer) -> (LexResult, Atom); - fn jsx_text(value: Atom, raw: Atom, lexer: &mut Self::Lexer) -> Self; + fn jsx_text(value: Wtf8Atom, raw: Atom, lexer: &mut Self::Lexer) -> Self; fn is_jsx_text(&self) -> bool; - fn take_jsx_text(self, buffer: &mut Self::Buffer) -> (Atom, Atom); + fn take_jsx_text(self, buffer: &mut Self::Buffer) -> (Wtf8Atom, Atom); fn regexp(content: Atom, flags: Atom, lexer: &mut Self::Lexer) -> Self; fn is_regexp(&self) -> bool; diff --git a/deps/swc/crates/swc_ecma_lexer/src/common/parser/buffer.rs b/deps/swc/crates/swc_ecma_lexer/src/common/parser/buffer.rs index 16b8f0f51..adf79ad48 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/common/parser/buffer.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/common/parser/buffer.rs @@ -61,7 +61,7 @@ pub trait Buffer<'a> { fn expect_template_token_and_bump(&mut self) -> (LexResult, Atom); fn expect_error_token_and_bump(&mut self) -> crate::error::Error; fn expect_jsx_name_token_and_bump(&mut self) -> Atom; - fn expect_jsx_text_token_and_bump(&mut self) -> (Atom, Atom); + fn expect_jsx_text_token_and_bump(&mut self) -> (Wtf8Atom, Atom); fn expect_shebang_token_and_bump(&mut self) -> Atom; fn had_line_break_before_cur(&self) -> bool { diff --git a/deps/swc/crates/swc_ecma_lexer/src/common/parser/class_and_fn.rs b/deps/swc/crates/swc_ecma_lexer/src/common/parser/class_and_fn.rs index 11dd4ba50..839fa5342 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/common/parser/class_and_fn.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/common/parser/class_and_fn.rs @@ -22,7 +22,6 @@ use crate::{ expr::parse_subscripts, ident::parse_ident, is_invalid_class_name::IsInvalidClassName, - is_not_this, is_simple_param_list::IsSimpleParameterList, pat::{parse_constructor_params, parse_unique_formal_params}, typescript::{ @@ -49,6 +48,70 @@ struct MakeMethodArgs { is_generator: bool, } +/// Parses a leading TypeScript or Flow `this` parameter directly into its +/// dedicated AST node. Invalid optional markers and initializers are recovered +/// here so the `this` parameter never enters the ordinary parameter list. +fn parse_ts_this_param<'a, P: Parser<'a>>(p: &mut P) -> PResult>> { + if !p.syntax().typescript() || !p.input().is(&P::Token::THIS) { + return Ok(None); + } + + let start = p.cur_pos(); + let this_span = p.input().cur_span(); + let is_flow = p.syntax().flow(); + p.bump(); + + let is_optional = p.input_mut().eat(&P::Token::QUESTION); + if is_optional { + let error = if is_flow { + SyntaxError::TS1003 + } else { + SyntaxError::Expected(",".into(), "?".into()) + }; + p.emit_err(p.input().prev_span(), error); + } + + let type_ann = try_parse_ts_type_ann(p)?; + if is_flow + && type_ann.is_none() + && !p.ctx().contains(Context::InType) + && !p.ctx().contains(Context::InDeclare) + { + p.emit_err(this_span, SyntaxError::TS1003); + } + + let span = p.span(start); + if p.input_mut().eat(&P::Token::EQUAL) { + if !is_optional { + let error = if is_flow { + SyntaxError::TS1003 + } else { + SyntaxError::Expected(",".into(), "=".into()) + }; + p.emit_err(p.input().prev_span(), error); + } + p.allow_in_expr(parse_assignment_expr)?; + } + + if !p.input().is(&P::Token::RPAREN) { + expect!(p, &P::Token::COMMA); + if p.input().is(&P::Token::THIS) { + let error = if is_flow { + SyntaxError::TS1003 + } else { + SyntaxError::TS2680 + }; + p.emit_err(p.input().cur_span(), error); + } + } + + Ok(Some(Box::new(TsThisParam { + span, + this_span, + type_ann, + }))) +} + /// If `required` is `true`, this never returns `None`. pub fn parse_maybe_opt_binding_ident<'a>( p: &mut impl Parser<'a>, @@ -263,14 +326,19 @@ where expect!(p, &P::Token::LPAREN); let parse_args_with_generator_ctx = |p: &mut P| { + let parse_this_and_args = |p: &mut P| { + let this_param = parse_ts_this_param(p)?; + parse_args(p).map(|params| (this_param, params)) + }; + if is_generator { - p.do_inside_of_context(Context::InGenerator, parse_args) + p.do_inside_of_context(Context::InGenerator, parse_this_and_args) } else { - p.do_outside_of_context(Context::InGenerator, parse_args) + p.do_outside_of_context(Context::InGenerator, parse_this_and_args) } }; - let params = p.do_inside_of_context(Context::InParameters, |p| { + let (this_param, params) = p.do_inside_of_context(Context::InParameters, |p| { p.do_outside_of_context(Context::InFunction, |p| { if is_async { p.do_inside_of_context(Context::InAsync, parse_args_with_generator_ctx) @@ -315,6 +383,7 @@ where Ok(Box::new(Function { span: p.span(start), + this_param, decorators, type_params, params, @@ -531,6 +600,13 @@ where }) })?; + if p.syntax().flow() + && matches!(kind, MethodKind::Getter | MethodKind::Setter) + && function.this_param.is_some() + { + p.emit_err(key.span(), SyntaxError::TS1003); + } + match kind { MethodKind::Getter | MethodKind::Setter if p.input().syntax().typescript() && p.input().target() == EsVersion::Es3 => @@ -593,7 +669,7 @@ pub fn parse_fn_block_or_expr_body<'a, P: Parser<'a>>( is_generator: bool, is_arrow_function: bool, is_simple_parameter_list: bool, -) -> PResult> { +) -> PResult> { parse_fn_body( p, is_async, @@ -609,12 +685,12 @@ pub fn parse_fn_block_or_expr_body<'a, P: Parser<'a>>( p.emit_err(span, SyntaxError::IllegalLanguageModeDirective); } } - BlockStmtOrExpr::BlockStmt(block_stmt) + ArrowFunctionBody::FunctionBody(function_body_from_block_stmt(block_stmt)) }) .map(Box::new) } else { parse_assignment_expr(p) - .map(BlockStmtOrExpr::Expr) + .map(ArrowFunctionBody::Expr) .map(Box::new) } }, @@ -684,7 +760,7 @@ pub(super) fn parse_fn_block_body<'a, P: Parser<'a>>( is_generator: bool, is_arrow_function: bool, is_simple_parameter_list: bool, -) -> PResult> { +) -> PResult> { parse_fn_body( p, is_async, @@ -705,12 +781,18 @@ pub(super) fn parse_fn_block_body<'a, P: Parser<'a>>( p.emit_err(span, SyntaxError::IllegalLanguageModeDirective); } } - Some(block_stmt) + Some(function_body_from_block_stmt(block_stmt)) }) }, ) } +fn function_body_from_block_stmt(block_stmt: BlockStmt) -> FunctionBody { + let BlockStmt { span, stmts, .. } = block_stmt; + + FunctionBody { span, stmts } +} + fn make_property<'a, P: Parser<'a>>( p: &mut P, start: BytePos, @@ -1228,7 +1310,7 @@ fn parse_class_member_with_is_static<'a, P: Parser<'a>>( |p| { let params = parse_formal_params(p)?; - if params.iter().any(is_not_this) { + if !params.is_empty() { p.emit_err(key_span, SyntaxError::GetterParam); } @@ -1253,13 +1335,13 @@ fn parse_class_member_with_is_static<'a, P: Parser<'a>>( |p| { let params = parse_formal_params(p)?; - if params.iter().filter(|p| is_not_this(p)).count() != 1 { + if params.len() != 1 { p.emit_err(key_span, SyntaxError::SetterParam); } - if !params.is_empty() { - if let Pat::Rest(..) = params[0].pat { - p.emit_err(params[0].pat.span(), SyntaxError::RestPatInSetter); + if let Some(param) = params.first() { + if let Pat::Rest(..) = param.pat { + p.emit_err(param.pat.span(), SyntaxError::RestPatInSetter); } } diff --git a/deps/swc/crates/swc_ecma_lexer/src/common/parser/expr.rs b/deps/swc/crates/swc_ecma_lexer/src/common/parser/expr.rs index 7bcb674d7..d8b128444 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/common/parser/expr.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/common/parser/expr.rs @@ -2059,7 +2059,7 @@ fn parse_args_or_pats_inner<'a, P: Parser<'a>>( } { let params: Vec = parse_paren_items_as_params(p, items.clone(), None)?; - let body: Box = parse_fn_block_or_expr_body( + let body: Box = parse_fn_block_or_expr_body( p, false, false, @@ -2139,7 +2139,7 @@ pub fn parse_paren_expr_or_arrow_fn<'a, P: Parser<'a>>( let params: Vec = parse_paren_items_as_params(p, items_ref.clone(), trailing_comma)?; - let body: Box = parse_fn_block_or_expr_body( + let body: Box = parse_fn_block_or_expr_body( p, async_span.is_some(), false, @@ -2199,7 +2199,7 @@ pub fn parse_paren_expr_or_arrow_fn<'a, P: Parser<'a>>( let params: Vec = parse_paren_items_as_params(p, paren_items, trailing_comma)?; - let body: Box = parse_fn_block_or_expr_body( + let body: Box = parse_fn_block_or_expr_body( p, async_span.is_some(), false, @@ -2215,7 +2215,7 @@ pub fn parse_paren_expr_or_arrow_fn<'a, P: Parser<'a>>( return_type, ..Default::default() }; - if let BlockStmtOrExpr::BlockStmt(..) = &*arrow_expr.body { + if let ArrowFunctionBody::FunctionBody(..) = &*arrow_expr.body { if p.input().cur().is_bin_op() { // ) is required p.emit_err(p.input().cur_span(), SyntaxError::TS1005); diff --git a/deps/swc/crates/swc_ecma_lexer/src/common/parser/object.rs b/deps/swc/crates/swc_ecma_lexer/src/common/parser/object.rs index 1051307e5..05a04a773 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/common/parser/object.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/common/parser/object.rs @@ -1,4 +1,4 @@ -use swc_common::{Span, Spanned, DUMMY_SP}; +use swc_common::{Span, Spanned}; use swc_ecma_ast::*; use super::{ @@ -13,7 +13,6 @@ use crate::{ parser::{ buffer::Buffer, class_and_fn::parse_fn_args_body, - is_not_this, pat::{parse_formal_params, parse_unique_formal_params}, typescript::eat_any_ts_modifier, }, @@ -316,7 +315,7 @@ fn parse_expr_object_prop<'a, P: Parser<'a>>(p: &mut P) -> PResult |p| { let params = parse_formal_params(p)?; - if params.iter().any(is_not_this) { + if !params.is_empty() { p.emit_err(key_span, SyntaxError::GetterParam); } @@ -325,25 +324,19 @@ fn parse_expr_object_prop<'a, P: Parser<'a>>(p: &mut P) -> PResult false, false, ) - .map(|v| *v) - .map( - |Function { - body, return_type, .. - }| { - if parser.input().syntax().typescript() - && parser.input().target() == EsVersion::Es3 - { - parser.emit_err(key_span, SyntaxError::TS1056); - } - - PropOrSpread::Prop(Box::new(Prop::Getter(GetterProp { - span: parser.span(start), - key, - type_ann: return_type, - body, - }))) - }, - ), + .map(|function| { + if parser.input().syntax().typescript() + && parser.input().target() == EsVersion::Es3 + { + parser.emit_err(key_span, SyntaxError::TS1056); + } + + PropOrSpread::Prop(Box::new(Prop::Getter(GetterProp { + span: parser.span(start), + key, + function, + }))) + }), "set" => { parse_fn_args_body( parser, @@ -353,16 +346,13 @@ fn parse_expr_object_prop<'a, P: Parser<'a>>(p: &mut P) -> PResult |p| { let params = parse_formal_params(p)?; - if params.iter().filter(|p| is_not_this(p)).count() != 1 { + if params.len() != 1 { p.emit_err(key_span, SyntaxError::SetterParam); } - if !params.is_empty() { - if let Pat::Rest(..) = params[0].pat { - p.emit_err( - params[0].span(), - SyntaxError::RestPatInSetter, - ); + if let Some(param) = params.first() { + if let Pat::Rest(..) = param.pat { + p.emit_err(param.span(), SyntaxError::RestPatInSetter); } } @@ -377,36 +367,13 @@ fn parse_expr_object_prop<'a, P: Parser<'a>>(p: &mut P) -> PResult false, false, ) - .map(|v| *v) - .map( - |Function { - mut params, body, .. - }| { - let mut this = None; - if params.len() >= 2 { - this = Some(params.remove(0).pat); - } - - let param = Box::new( - params.into_iter().next().map(|v| v.pat).unwrap_or_else( - || { - parser.emit_err(key_span, SyntaxError::SetterParam); - - Invalid { span: DUMMY_SP }.into() - }, - ), - ); - - // debug_assert_eq!(params.len(), 1); - PropOrSpread::Prop(Box::new(Prop::Setter(SetterProp { - span: parser.span(start), - key, - body, - param, - this_param: this, - }))) - }, - ) + .map(|function| { + PropOrSpread::Prop(Box::new(Prop::Setter(SetterProp { + span: parser.span(start), + key, + function, + }))) + }) } "async" => parse_fn_args_body( parser, diff --git a/deps/swc/crates/swc_ecma_lexer/src/common/parser/pat.rs b/deps/swc/crates/swc_ecma_lexer/src/common/parser/pat.rs index 66d97a353..987f5af6e 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/common/parser/pat.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/common/parser/pat.rs @@ -22,6 +22,27 @@ use crate::{ error::SyntaxError, }; +/// Returns the identifier for a direct `this` pattern or a single assignment +/// layer whose left-hand side is a direct `this` pattern. +fn direct_ts_this_ident(pat: &Pat) -> Option<&Ident> { + let ident = match pat { + Pat::Ident(BindingIdent { id, .. }) => id, + Pat::Assign(AssignPat { left, .. }) => { + let Pat::Ident(BindingIdent { id, .. }) = &**left else { + return None; + }; + id + } + _ => return None, + }; + + if ident.sym.as_ref() != "this" { + return None; + } + + Some(ident) +} + /// argument of arrow is pattern, although idents in pattern is already /// checked if is a keyword, it should also be checked if is arguments or /// eval @@ -372,27 +393,40 @@ fn reparse_expr_as_pat_inner<'a>( } pub(super) fn parse_binding_element<'a, P: Parser<'a>>(p: &mut P) -> PResult { + parse_binding_element_with_initializer(p).map(|(pat, _)| pat) +} + +/// Returns the span of an initializer owned by this binding element. +/// Initializers nested in destructuring patterns are not propagated. +fn parse_binding_element_with_initializer<'a, P: Parser<'a>>( + p: &mut P, +) -> PResult<(Pat, Option)> { trace_cur!(p, parse_binding_element); let start = p.cur_pos(); let left = parse_binding_pat_or_ident(p, false)?; if p.input_mut().eat(&P::Token::EQUAL) { + let initializer_span = p.input().prev_span(); + let right = p.allow_in_expr(parse_assignment_expr)?; if p.ctx().contains(Context::InDeclare) { p.emit_err(p.span(start), SyntaxError::TS2371); } - return Ok(AssignPat { - span: p.span(start), - left: Box::new(left), - right, - } - .into()); + return Ok(( + AssignPat { + span: p.span(start), + left: Box::new(left), + right, + } + .into(), + Some(initializer_span), + )); } - Ok(left) + Ok((left, None)) } pub fn parse_binding_pat_or_ident<'a, P: Parser<'a>>( @@ -486,11 +520,26 @@ fn parse_formal_param_pat<'a, P: Parser<'a>>(p: &mut P) -> PResult { let has_modifier = eat_any_ts_modifier(p)?; let pat_start = p.cur_pos(); - let mut pat = parse_binding_element(p)?; + let (mut pat, initializer_span) = parse_binding_element_with_initializer(p)?; + let is_direct_ts_this_param = + p.syntax().typescript() && !p.syntax().flow() && direct_ts_this_ident(&pat).is_some(); + if let (true, Some(initializer_span)) = (is_direct_ts_this_param, initializer_span) { + p.emit_err( + initializer_span, + SyntaxError::Expected(",".into(), "=".into()), + ); + } let mut opt = false; if p.input().syntax().typescript() { if p.input_mut().eat(&P::Token::QUESTION) { + if is_direct_ts_this_param { + p.emit_err( + p.input().prev_span(), + SyntaxError::Expected(",".into(), "?".into()), + ); + } + match pat { Pat::Ident(BindingIdent { id: Ident { @@ -560,8 +609,15 @@ fn parse_formal_param_pat<'a, P: Parser<'a>>(p: &mut P) -> PResult { } let pat = if p.input_mut().eat(&P::Token::EQUAL) { + if is_direct_ts_this_param && !opt { + p.emit_err( + p.input().prev_span(), + SyntaxError::Expected(",".into(), "=".into()), + ); + } + // `=` cannot follow optional parameter. - if opt { + if opt && !is_direct_ts_this_param { p.emit_err(pat.span(), SyntaxError::TS1015); } @@ -752,6 +808,15 @@ pub fn parse_formal_params<'a, P: Parser<'a>>(p: &mut P) -> PResult> } } + if p.syntax().typescript() && !p.syntax().flow() { + for param in params.iter().skip(1) { + let Some(ident) = direct_ts_this_ident(¶m.pat) else { + continue; + }; + p.emit_err(ident.span, SyntaxError::TS2680); + } + } + Ok(params) } diff --git a/deps/swc/crates/swc_ecma_lexer/src/common/parser/stmt.rs b/deps/swc/crates/swc_ecma_lexer/src/common/parser/stmt.rs index 307e029e6..4a1ebb67d 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/common/parser/stmt.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/common/parser/stmt.rs @@ -999,6 +999,7 @@ fn parse_switch_stmt<'a, P: Parser<'a>>(p: &mut P) -> PResult { Ok(SwitchStmt { span: p.span(switch_start), + body_ctxt: Default::default(), discriminant, cases, } diff --git a/deps/swc/crates/swc_ecma_lexer/src/input.rs b/deps/swc/crates/swc_ecma_lexer/src/input.rs index 154dc9622..c550dd351 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/input.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/input.rs @@ -439,7 +439,7 @@ impl<'a, I: Tokens> crate::common::parser::buffer::Buffer<'a> for t.take_jsx_name(self) } - fn expect_jsx_text_token_and_bump(&mut self) -> (swc_atoms::Atom, swc_atoms::Atom) { + fn expect_jsx_text_token_and_bump(&mut self) -> (swc_atoms::Wtf8Atom, swc_atoms::Atom) { let t = self.bump(); t.take_jsx_text(self) } diff --git a/deps/swc/crates/swc_ecma_lexer/src/lexer/jsx.rs b/deps/swc/crates/swc_ecma_lexer/src/lexer/jsx.rs index ad5e2c009..e4195341a 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/lexer/jsx.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/lexer/jsx.rs @@ -48,10 +48,10 @@ impl Lexer<'_> { }; let value = if value.is_empty() { // Fast path: We don't need to allocate extra buffer for value - self.atoms.atom(s) + self.atoms.wtf8_atom(Wtf8::from_str(s)) } else { value.push_str(s); - self.atoms.atom(value) + self.atoms.wtf8_atom(Wtf8::from_str(&value)) }; let raw = { diff --git a/deps/swc/crates/swc_ecma_lexer/src/token.rs b/deps/swc/crates/swc_ecma_lexer/src/token.rs index e72923064..8d2565592 100644 --- a/deps/swc/crates/swc_ecma_lexer/src/token.rs +++ b/deps/swc/crates/swc_ecma_lexer/src/token.rs @@ -539,7 +539,7 @@ impl<'a, I: Tokens> crate::common::lexer::token::TokenFactory<'a, } #[inline(always)] - fn jsx_text(value: Atom, raw: Atom, _: &mut Self::Lexer) -> Self { + fn jsx_text(value: Wtf8Atom, raw: Atom, _: &mut Self::Lexer) -> Self { Self::JSXText { value, raw } } @@ -549,7 +549,7 @@ impl<'a, I: Tokens> crate::common::lexer::token::TokenFactory<'a, } #[inline(always)] - fn take_jsx_text(self, _: &mut Self::Buffer) -> (Atom, Atom) { + fn take_jsx_text(self, _: &mut Self::Buffer) -> (Wtf8Atom, Atom) { match self { Self::JSXText { value, raw } => (value, raw), _ => unreachable!(), diff --git a/deps/swc/crates/swc_ecma_lints/Cargo.toml b/deps/swc/crates/swc_ecma_lints/Cargo.toml index 2a1bedc7a..30f9e1162 100644 --- a/deps/swc/crates/swc_ecma_lints/Cargo.toml +++ b/deps/swc/crates/swc_ecma_lints/Cargo.toml @@ -6,7 +6,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_lints" repository = { workspace = true } -version = "33.0.0" +version = "37.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] @@ -24,23 +24,23 @@ regex = { workspace = true } rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "concurrent", ] } -swc_config = { version = "5.0.0", path = "../swc_config" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast", features = [ +swc_config = { version = "6.0.0", path = "../swc_config" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast", features = [ "serde", ] } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] codspeed-criterion-compat = { workspace = true } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } [features] non_critical_lints = [] diff --git a/deps/swc/crates/swc_ecma_lints/src/rules/critical_rules.rs b/deps/swc/crates/swc_ecma_lints/src/rules/critical_rules.rs index 5f3430551..b000a9e06 100644 --- a/deps/swc/crates/swc_ecma_lints/src/rules/critical_rules.rs +++ b/deps/swc/crates/swc_ecma_lints/src/rules/critical_rules.rs @@ -347,7 +347,7 @@ impl Visit for CriticalRules { let ArrowExpr { params, body, .. } = a; params.visit_with(self); - if let BlockStmtOrExpr::BlockStmt(b) = &**body { + if let ArrowFunctionBody::FunctionBody(b) = &**body { self.visit_with_stmts(&b.stmts, false) } } diff --git a/deps/swc/crates/swc_ecma_lints/src/rules/no_empty_function.rs b/deps/swc/crates/swc_ecma_lints/src/rules/no_empty_function.rs index d29e0d2b9..e24b6d1bf 100644 --- a/deps/swc/crates/swc_ecma_lints/src/rules/no_empty_function.rs +++ b/deps/swc/crates/swc_ecma_lints/src/rules/no_empty_function.rs @@ -258,13 +258,39 @@ impl NoEmptyFunction { false } + + /// Checks an object accessor while visiting the contents of its backing + /// function without classifying the accessor as a standalone function. + fn visit_object_accessor( + &mut self, + span: Span, + key: &PropName, + function: &Function, + modifier: FunctionModifiers, + ) { + if let Some(FunctionBody { + span: body_span, + stmts, + .. + }) = &function.body + { + let has_comment = self.consider_comments && self.has_comment_in_body(body_span); + + if !has_comment && stmts.is_empty() { + self.check(span, "method", self.methods.as_ref(), &[modifier]); + } + } + + key.visit_with(self); + function.visit_children_with(self); + } } impl Visit for NoEmptyFunction { noop_visit_type!(); fn visit_function(&mut self, function: &Function) { - if let Some(BlockStmt { stmts, span, .. }) = &function.body { + if let Some(FunctionBody { stmts, span, .. }) = &function.body { if self.consider_comments && self.has_comment_in_body(span) { return; } @@ -291,7 +317,7 @@ impl Visit for NoEmptyFunction { } fn visit_arrow_expr(&mut self, function: &ArrowExpr) { - if let BlockStmtOrExpr::BlockStmt(BlockStmt { stmts, span, .. }) = &*function.body { + if let ArrowFunctionBody::FunctionBody(FunctionBody { stmts, span, .. }) = &*function.body { if self.consider_comments && self.has_comment_in_body(span) { return; } @@ -318,7 +344,7 @@ impl Visit for NoEmptyFunction { } fn visit_constructor(&mut self, constructor: &Constructor) { - if let Some(BlockStmt { span, stmts, .. }) = &constructor.body { + if let Some(FunctionBody { span, stmts, .. }) = &constructor.body { if self.consider_comments && self.has_comment_in_body(span) { return; } @@ -348,7 +374,7 @@ impl Visit for NoEmptyFunction { fn visit_class_method(&mut self, class_method: &ClassMethod) { let method = &class_method.function; - if let Some(BlockStmt { span, stmts, .. }) = &method.body { + if let Some(FunctionBody { span, stmts, .. }) = &method.body { if self.consider_comments && self.has_comment_in_body(span) { return; } @@ -382,40 +408,20 @@ impl Visit for NoEmptyFunction { } fn visit_getter_prop(&mut self, getter_prop: &GetterProp) { - if self.consider_comments && self.has_comment_in_body(&getter_prop.span) { - return; - } - - if let Some(BlockStmt { stmts, .. }) = &getter_prop.body { - if stmts.is_empty() { - self.check( - getter_prop.span, - "method", - self.methods.as_ref(), - &[FunctionModifiers::Getter], - ); - } - } - - getter_prop.visit_children_with(self); + self.visit_object_accessor( + getter_prop.span, + &getter_prop.key, + &getter_prop.function, + FunctionModifiers::Getter, + ); } fn visit_setter_prop(&mut self, setter_prop: &SetterProp) { - if self.consider_comments && self.has_comment_in_body(&setter_prop.span) { - return; - } - - if let Some(BlockStmt { stmts, .. }) = &setter_prop.body { - if stmts.is_empty() { - self.check( - setter_prop.span, - "method", - self.methods.as_ref(), - &[FunctionModifiers::Setter], - ); - } - } - - setter_prop.visit_children_with(self); + self.visit_object_accessor( + setter_prop.span, + &setter_prop.key, + &setter_prop.function, + FunctionModifiers::Setter, + ); } } diff --git a/deps/swc/crates/swc_ecma_lints/src/rules/no_loop_func.rs b/deps/swc/crates/swc_ecma_lints/src/rules/no_loop_func.rs index 3fb998c0a..637f93880 100644 --- a/deps/swc/crates/swc_ecma_lints/src/rules/no_loop_func.rs +++ b/deps/swc/crates/swc_ecma_lints/src/rules/no_loop_func.rs @@ -129,20 +129,27 @@ impl NoLoopFunc { Pat::Expr(_) => {} } } + + fn visit_scope(&mut self, span: Span, op: impl FnOnce(&mut Self)) { + self.scopes.push(span); + self.scoped_unsafe_vars.insert(span, Default::default()); + + op(self); + + self.scopes.pop(); + self.scoped_unsafe_vars.remove(&span); + } } impl Visit for NoLoopFunc { noop_visit_type!(); fn visit_block_stmt(&mut self, block: &BlockStmt) { - self.scopes.push(block.span); - self.scoped_unsafe_vars - .insert(block.span, Default::default()); - - block.visit_children_with(self); + self.visit_scope(block.span, |visitor| block.visit_children_with(visitor)); + } - self.scopes.pop(); - self.scoped_unsafe_vars.remove(&block.span); + fn visit_function_body(&mut self, body: &FunctionBody) { + self.visit_scope(body.span, |visitor| body.visit_children_with(visitor)); } fn visit_for_stmt(&mut self, for_stmt: &ForStmt) { diff --git a/deps/swc/crates/swc_ecma_lints/src/rules/no_use_before_define.rs b/deps/swc/crates/swc_ecma_lints/src/rules/no_use_before_define.rs index 9adb3250f..9e9c0eac2 100644 --- a/deps/swc/crates/swc_ecma_lints/src/rules/no_use_before_define.rs +++ b/deps/swc/crates/swc_ecma_lints/src/rules/no_use_before_define.rs @@ -179,6 +179,16 @@ impl NoUseBeforeDefine { Pat::Expr(_) => {} } } + + fn visit_scope(&mut self, span: Span, op: impl FnOnce(&mut Self)) { + self.scoped_indents.insert(span, Default::default()); + self.scope.push(span); + + op(self); + + self.scoped_indents.remove(&span); + self.scope.pop(); + } } impl Visit for NoUseBeforeDefine { @@ -189,13 +199,11 @@ impl Visit for NoUseBeforeDefine { } fn visit_block_stmt(&mut self, block: &BlockStmt) { - self.scoped_indents.insert(block.span, Default::default()); - self.scope.push(block.span); - - block.visit_children_with(self); + self.visit_scope(block.span, |visitor| block.visit_children_with(visitor)); + } - self.scoped_indents.remove(&block.span); - self.scope.pop(); + fn visit_function_body(&mut self, body: &FunctionBody) { + self.visit_scope(body.span, |visitor| body.visit_children_with(visitor)); } fn visit_var_decl(&mut self, var_decl: &VarDecl) { diff --git a/deps/swc/crates/swc_ecma_lints/src/rules/prefer_const.rs b/deps/swc/crates/swc_ecma_lints/src/rules/prefer_const.rs index 689ab33f7..6003c1459 100644 --- a/deps/swc/crates/swc_ecma_lints/src/rules/prefer_const.rs +++ b/deps/swc/crates/swc_ecma_lints/src/rules/prefer_const.rs @@ -187,6 +187,12 @@ impl PreferConst { } } + fn visit_nested_scope(&mut self, op: impl FnOnce(&mut Self)) { + self.block_depth += 1; + op(self); + self.block_depth -= 1; + } + fn emit_ordered(&self) { let mut vars = self.vars_meta.iter().collect::>(); @@ -267,11 +273,11 @@ impl Visit for PreferConst { } fn visit_block_stmt(&mut self, block_stmt: &BlockStmt) { - self.block_depth += 1; - - block_stmt.visit_children_with(self); + self.visit_nested_scope(|visitor| block_stmt.visit_children_with(visitor)); + } - self.block_depth -= 1; + fn visit_function_body(&mut self, body: &FunctionBody) { + self.visit_nested_scope(|visitor| body.visit_children_with(visitor)); } fn visit_for_in_stmt(&mut self, for_in_stmt: &ForInStmt) { diff --git a/deps/swc/crates/swc_ecma_loader/Cargo.toml b/deps/swc/crates/swc_ecma_loader/Cargo.toml index ed1f9050c..2682bc732 100644 --- a/deps/swc/crates/swc_ecma_loader/Cargo.toml +++ b/deps/swc/crates/swc_ecma_loader/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_loader" repository = { workspace = true } -version = "24.0.1" +version = "27.0.0" [package.metadata.docs.rs] all-features = true @@ -37,8 +37,8 @@ serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true, optional = true } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } [dev-dependencies] lazy_static = { workspace = true } diff --git a/deps/swc/crates/swc_ecma_minifier/AGENTS.md b/deps/swc/crates/swc_ecma_minifier/AGENTS.md index 1e39e76d0..a49776bd7 100644 --- a/deps/swc/crates/swc_ecma_minifier/AGENTS.md +++ b/deps/swc/crates/swc_ecma_minifier/AGENTS.md @@ -5,6 +5,36 @@ - Always run execution tests after making changes. - You can run fixture tests by doing ./scripts/test.sh, and you can do UPDATE=1 ./scripts/test.sh to update fixtures. +### Minifier Semantic Assumptions + +The ECMAScript minifier may rely on the documented assumptions from the SWC +minification guide: + +- Calls to primitive coercion helpers such as `toString` and `valueOf` are + side-effect free, and built-in object implementations have not been + overridden. +- `undefined`, `NaN`, and `Infinity` have not been externally redefined. +- `arguments.callee`, `arguments.caller`, and `Function.prototype.caller` are + not used. +- Code does not depend on the exact contents of `Function.prototype.toString()` + or `Error.prototype.stack`. +- Getting or setting properties on a plain object does not trigger side effects + through `watch`, `Proxy`, or similar mechanisms. +- Object properties can be added, removed, and modified unless the change is + intentionally handling frozen, sealed, non-extensible, or descriptor-locked + objects. +- `document.all` is treated as not `null`. +- Assigning properties to classes is assumed to be side-effect free and + non-throwing. +- Accessing declared top-level identifiers is assumed to be side-effect free. +- TDZ violations are not preserved. +- Arithmetic expressions are treated as side-effect free, including runtime + exceptions such as mixing `bigint` and `number`. + +If a minifier change relies on an assumption beyond this list, update the +public minification documentation or leave an explicit code comment describing +the narrower local invariant. + ### Fixture Test Addition Guide - Preferred fixture roots in this crate: tests/fixture, tests/mangle, tests/pass-1, tests/pass-default, tests/full, tests/projects, benches/full. diff --git a/deps/swc/crates/swc_ecma_minifier/Cargo.toml b/deps/swc/crates/swc_ecma_minifier/Cargo.toml index c17a58c5c..d6915f0b5 100644 --- a/deps/swc/crates/swc_ecma_minifier/Cargo.toml +++ b/deps/swc/crates/swc_ecma_minifier/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/lists/*.json"] license = { workspace = true } name = "swc_ecma_minifier" repository = { workspace = true } -version = "56.0.1" +version = "61.0.0" [package.metadata.docs.rs] all-features = true @@ -51,25 +51,25 @@ rustc-hash = { workspace = true } ryu-js = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_config = { version = "5.0.0", path = "../swc_config", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_config = { version = "6.0.0", path = "../swc_config", features = [ "sourcemap", "file_pattern", "regex_js", ] } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast", features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast", features = [ "serde", ] } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_hooks = { version = "0.9.0", path = "../swc_ecma_hooks" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_hooks = { version = "1.0.0", path = "../swc_ecma_hooks" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_optimization = { version = "47.0.1", path = "../swc_ecma_transforms_optimization" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_optimization = { version = "52.0.0", path = "../swc_ecma_transforms_optimization" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } tracing = { workspace = true } [dev-dependencies] @@ -80,9 +80,9 @@ flate2 = { workspace = true } humansize = { workspace = true } par-core = { workspace = true, features = ["chili"] } pretty_assertions = { workspace = true } -swc_ecma_testing = { version = "24.0.1", path = "../swc_ecma_testing" } +swc_ecma_testing = { version = "27.0.0", path = "../swc_ecma_testing" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } walkdir = { workspace = true } [[bench]] diff --git a/deps/swc/crates/swc_ecma_minifier/fuzz/Cargo.lock b/deps/swc/crates/swc_ecma_minifier/fuzz/Cargo.lock index 44d612616..49fb4d9b0 100644 --- a/deps/swc/crates/swc_ecma_minifier/fuzz/Cargo.lock +++ b/deps/swc/crates/swc_ecma_minifier/fuzz/Cargo.lock @@ -1170,17 +1170,6 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -[[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 = "stable_deref_trait" version = "1.2.1" @@ -1236,7 +1225,7 @@ dependencies = [ [[package]] name = "swc_common" -version = "23.0.1" +version = "23.0.2" dependencies = [ "anyhow", "arbitrary", @@ -1310,7 +1299,7 @@ dependencies = [ [[package]] name = "swc_ecma_codegen" -version = "28.0.1" +version = "28.0.2" dependencies = [ "ascii", "compact_str", @@ -1350,7 +1339,7 @@ dependencies = [ [[package]] name = "swc_ecma_minifier" -version = "55.0.2" +version = "57.0.1" dependencies = [ "arrayvec", "bitflags", @@ -1399,16 +1388,16 @@ dependencies = [ [[package]] name = "swc_ecma_parser" -version = "41.1.0" +version = "41.1.2" dependencies = [ "bitflags", + "compact_str", "either", "num-bigint", "phf", "rustc-hash", "seq-macro", "serde", - "smartstring", "stacker", "swc_atoms", "swc_common", @@ -1418,7 +1407,7 @@ dependencies = [ [[package]] name = "swc_ecma_testing" -version = "24.0.0" +version = "24.0.1" dependencies = [ "anyhow", "hex", @@ -1429,7 +1418,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_base" -version = "44.0.2" +version = "45.0.0" dependencies = [ "better_scoped_tls", "indexmap", @@ -1449,7 +1438,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_optimization" -version = "47.0.0" +version = "48.0.0" dependencies = [ "bytes-str", "dashmap", @@ -1471,7 +1460,7 @@ dependencies = [ [[package]] name = "swc_ecma_utils" -version = "31.0.0" +version = "31.0.2" dependencies = [ "dragonbox_ecma", "indexmap", @@ -1592,7 +1581,7 @@ dependencies = [ [[package]] name = "testing" -version = "24.0.0" +version = "24.0.1" dependencies = [ "cargo_metadata", "difference", diff --git a/deps/swc/crates/swc_ecma_minifier/src/cli/bin.rs b/deps/swc/crates/swc_ecma_minifier/src/cli/bin.rs index c983a0dbc..1afa7705d 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/cli/bin.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/cli/bin.rs @@ -1,4 +1,5 @@ use std::{env::args, io, path::Path}; + use swc_common::{input::SourceFileInput, sync::Lrc, FilePathMapping, Mark, SourceMap}; use swc_ecma_ast::Module; use swc_ecma_codegen::text_writer::JsWriter; @@ -60,9 +61,7 @@ fn run_cli(filename: String) -> Result<(), ParseError> { &ExtraOptions { top_level_mark }, ); - let output = output - .fold_with(&mut hygiene_with_config(Default::default())) - .fold_with(&mut fixer(None)); + let output = output.fold_with(&mut hygiene()).fold_with(&mut fixer(None)); print_js(cm.clone(), &output); diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/arguments.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/arguments.rs index 1d48b0615..06c9d370f 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/arguments.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/arguments.rs @@ -2,12 +2,19 @@ use std::iter::repeat_with; use swc_common::{util::take::Take, DUMMY_SP}; use swc_ecma_ast::*; -use swc_ecma_utils::{find_pat_ids, is_valid_prop_ident, private_ident}; +use swc_ecma_utils::{ + find_pat_ids, is_valid_prop_ident, + number::{parse_canonical_index, ToJsString}, + private_ident, +}; use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith}; use super::Optimizer; use crate::compress::optimize::is_left_access_to_arguments; +/// Matches Terser's `index < argnames.length + 5` condition. +const MAX_INJECTED_PARAMS: usize = 5; + /// Methods related to the option `arguments`. impl Optimizer<'_> { /// @@ -118,7 +125,7 @@ impl Optimizer<'_> { prevent: false, }; - // We visit body two time, to use simpler logic in `inject_params_if_required` + // Visit the body twice to keep parameter injection local to each access. f.body.visit_mut_children_with(&mut v); f.body.visit_mut_children_with(&mut v); @@ -134,11 +141,19 @@ struct ArgReplacer<'a> { } impl ArgReplacer<'_> { - fn inject_params_if_required(&mut self, idx: usize) { + /// Materializes only a bounded number of missing parameters. + fn inject_params_if_within_limit(&mut self, idx: usize) { if idx < self.params.len() || self.keep_fargs { return; } - let new_args = idx + 1 - self.params.len(); + let Some(required_len) = idx.checked_add(1) else { + return; + }; + let new_args = required_len - self.params.len(); + + if new_args > MAX_INJECTED_PARAMS { + return; + } self.changed = true; report_change!("arguments: Injecting {} parameters", new_args); @@ -179,64 +194,17 @@ impl VisitMut for ArgReplacer<'_> { n.visit_mut_children_with(self); - if let Expr::Member(MemberExpr { - obj, - prop: MemberProp::Computed(c), - .. - }) = n - { - match &**obj { - Expr::Ident(Ident { sym, .. }) if &**sym == "arguments" => { - match &*c.expr { - Expr::Lit(Lit::Str(Str { value, .. })) => { - let Some(value) = value.as_str() else { - return; - }; - let idx = value.parse::(); - let idx = match idx { - Ok(v) => v, - _ => return, - }; - - self.inject_params_if_required(idx); - - if let Some(param) = self.params.get(idx) { - if let Pat::Ident(i) = ¶m.pat { - self.changed = true; - report_change!( - "arguments: Replacing access to arguments to normal \ - reference" - ); - *n = i.id.clone().into(); - } - } - } - Expr::Lit(Lit::Num(Number { value, .. })) => { - if value.fract() != 0.0 { - // We ignores non-integer values. - return; - } - - let idx = value.round() as i64 as usize; - - self.inject_params_if_required(idx); - - // - if let Some(param) = self.params.get(idx) { - if let Pat::Ident(i) = ¶m.pat { - report_change!( - "arguments: Replacing access to arguments to normal \ - reference" - ); - self.changed = true; - *n = i.id.clone().into(); - } - } - } - _ => {} - } - } - _ => (), + let Some(idx) = argument_access_index(n) else { + return; + }; + + self.inject_params_if_within_limit(idx); + + if let Some(param) = self.params.get(idx) { + if let Pat::Ident(i) = ¶m.pat { + self.changed = true; + report_change!("arguments: Replacing access to arguments to normal reference"); + *n = i.id.clone().into(); } } } @@ -266,3 +234,29 @@ impl VisitMut for ArgReplacer<'_> { } } } + +/// Returns an `arguments` index only when the property key is already in its +/// canonical non-negative integer spelling. +fn argument_access_index(expr: &Expr) -> Option { + let Expr::Member(MemberExpr { + obj, + prop: MemberProp::Computed(computed), + .. + }) = expr + else { + return None; + }; + let Expr::Ident(Ident { sym, .. }) = &**obj else { + return None; + }; + + if &**sym != "arguments" { + return None; + } + + match &*computed.expr { + Expr::Lit(Lit::Str(Str { value, .. })) => parse_canonical_index(value.as_str()?), + Expr::Lit(Lit::Num(Number { value, .. })) => parse_canonical_index(&value.to_js_string()), + _ => None, + } +} diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/evaluate.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/evaluate.rs index 09d1f5c0f..01b7ead97 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/evaluate.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/evaluate.rs @@ -1,13 +1,12 @@ -use std::num::FpCategory; - use swc_atoms::atom; -use swc_common::{util::take::Take, Spanned, SyntaxContext, DUMMY_SP}; +use swc_common::{util::take::Take, Spanned}; use swc_ecma_ast::*; -use swc_ecma_utils::{ExprExt, Value::Known}; +use swc_ecma_utils::{number::JsNumber, ExprExt, Value::Known}; use super::{BitCtx, Optimizer}; use crate::{ - compress::util::eval_as_number, program_data::VarUsageInfoFlags, DISABLE_BUGGY_PASSES, + compress::util::eval_as_number, program_data::VarUsageInfoFlags, util::make_number, + DISABLE_BUGGY_PASSES, }; /// Methods related to the option `evaluate`. @@ -111,7 +110,7 @@ impl Optimizer<'_> { enum IdentGlobal { Undefined, - Infinity, + Number(f64), } let ident_global = match e { @@ -119,8 +118,11 @@ impl Optimizer<'_> { Expr::Ident(i) if &*i.sym == "undefined" && !self.is_declared_ident(i) => { Some((i.span, IdentGlobal::Undefined)) } + Expr::Ident(i) if &*i.sym == "NaN" && !self.is_declared_ident(i) => { + Some((i.span, IdentGlobal::Number(f64::NAN))) + } Expr::Ident(i) if &*i.sym == "Infinity" && !self.is_declared_ident(i) => { - Some((i.span, IdentGlobal::Infinity)) + Some((i.span, IdentGlobal::Number(f64::INFINITY))) } _ => None, }; @@ -132,26 +134,10 @@ impl Optimizer<'_> { self.changed = true; *e = *Expr::undefined(span); } - IdentGlobal::Infinity => { - report_change!("evaluate: `Infinity` -> `1 / 0`"); + IdentGlobal::Number(value) => { + report_change!("evaluate: Global numeric constant -> numeric literal"); self.changed = true; - *e = BinExpr { - span, - op: op!("/"), - left: Lit::Num(Number { - span: DUMMY_SP, - value: 1.0, - raw: None, - }) - .into(), - right: Lit::Num(Number { - span: DUMMY_SP, - value: 0.0, - raw: None, - }) - .into(), - } - .into(); + *e = make_number(span, value); } } return; @@ -182,39 +168,19 @@ impl Optimizer<'_> { .into(); } "NaN" => { - report_change!("evaluate: `Number.NaN` -> `NaN`"); + report_change!("evaluate: `Number.NaN` -> numeric literal"); self.changed = true; - *e = Ident::new( - atom!("NaN"), - *span, - SyntaxContext::empty().apply_mark(self.marks.unresolved_mark), - ) - .into(); + *e = make_number(*span, f64::NAN); } "POSITIVE_INFINITY" => { - report_change!("evaluate: `Number.POSITIVE_INFINITY` -> `Infinity`"); + report_change!("evaluate: `Number.POSITIVE_INFINITY` -> numeric literal"); self.changed = true; - *e = Ident::new( - atom!("Infinity"), - *span, - SyntaxContext::empty().apply_mark(self.marks.unresolved_mark), - ) - .into(); + *e = make_number(*span, f64::INFINITY); } "NEGATIVE_INFINITY" => { - report_change!("evaluate: `Number.NEGATIVE_INFINITY` -> `-Infinity`"); + report_change!("evaluate: `Number.NEGATIVE_INFINITY` -> numeric literal"); self.changed = true; - *e = UnaryExpr { - span: *span, - op: op!(unary, "-"), - arg: Ident::new( - atom!("Infinity"), - *span, - SyntaxContext::empty().apply_mark(self.marks.unresolved_mark), - ) - .into(), - } - .into(); + *e = make_number(*span, f64::NEG_INFINITY); } _ => {} } @@ -334,7 +300,7 @@ impl Optimizer<'_> { } if let Known(char_code) = args[0].expr.as_pure_number(self.ctx.expr_ctx) { - let v = char_code.floor() as u32; + let v = u32::from(JsNumber::from(char_code).to_uint16()); if let Some(v) = char::from_u32(v) { if !v.is_ascii() { @@ -342,7 +308,7 @@ impl Optimizer<'_> { } self.changed = true; report_change!( - "evaluate: Evaluated `String.charCodeAt({})` as `{}`", + "evaluate: Evaluated `String.fromCharCode({})` as `{}`", char_code, v ); @@ -450,23 +416,7 @@ impl Optimizer<'_> { if let Some(value) = eval_as_number(self.ctx.expr_ctx, e) { self.changed = true; report_change!("evaluate: Evaluated an expression as `{}`", value); - - if value.is_nan() { - *e = Ident::new( - atom!("NaN"), - e.span(), - SyntaxContext::empty().apply_mark(self.marks.unresolved_mark), - ) - .into(); - return; - } - - *e = Lit::Num(Number { - span: e.span(), - value, - raw: None, - }) - .into(); + *e = make_number(e.span(), value); return; } } @@ -482,19 +432,9 @@ impl Optimizer<'_> { report_change!("evaluate: Evaluated `{:?} ** {:?}`", l, r); if l.is_nan() || r.is_nan() { - *e = Ident::new( - atom!("NaN"), - bin.span, - SyntaxContext::empty().apply_mark(self.marks.unresolved_mark), - ) - .into(); + *e = make_number(bin.span, f64::NAN); } else { - *e = Lit::Num(Number { - span: bin.span, - value: l.powf(r), - raw: None, - }) - .into(); + *e = make_number(bin.span, l.powf(r)); }; } } @@ -505,31 +445,11 @@ impl Optimizer<'_> { let rn = bin.right.as_pure_number(self.ctx.expr_ctx); if let (Known(ln), Known(rn)) = (ln, rn) { - // Prefer `0/0` over NaN. - if ln == 0.0 && rn == 0.0 { - return; - } - // Prefer `1/0` over Infinity. - if ln == 1.0 && rn == 0.0 { - return; - } - - // It's NaN - if let (FpCategory::Normal, FpCategory::Zero) = (ln.classify(), rn.classify()) { + let value = ln / rn; + if !value.is_finite() { self.changed = true; - report_change!("evaluate: `{} / 0` => `Infinity`", ln); - - // Sign does not matter for NaN - *e = if ln.is_sign_positive() == rn.is_sign_positive() { - Ident::new_no_ctxt(atom!("Infinity"), bin.span).into() - } else { - UnaryExpr { - span: bin.span, - op: op!(unary, "-"), - arg: Ident::new_no_ctxt(atom!("Infinity"), bin.span).into(), - } - .into() - }; + report_change!("evaluate: Evaluated `{} / {}`", ln, rn); + *e = make_number(bin.span, value); } } } diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/iife.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/iife.rs index cdc56c181..6626a4285 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/iife.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/iife.rs @@ -565,6 +565,12 @@ impl Optimizer<'_> { return false; } + if let Some(scope) = self.data.get_scope(f.ctxt) { + if scope.intersects(ScopeData::HAS_EVAL_CALL) { + return false; + } + } + if f.params.iter().any(|param| !param.is_ident()) { return false; } @@ -608,7 +614,13 @@ impl Optimizer<'_> { let body = f.function.body.as_ref().unwrap(); - if contains_this_expr(body) || self.data.used_arguments(f.function.ctxt) { + if let Some(scope) = self.data.get_scope(f.function.ctxt) { + if scope.intersects(ScopeData::HAS_EVAL_CALL.union(ScopeData::USED_ARGUMENTS)) { + return false; + } + } + + if contains_this_expr(body) { return false; } } @@ -661,7 +673,7 @@ impl Optimizer<'_> { let param_ids = f.params.iter().map(|p| &p.as_ident().unwrap().id); match &mut *f.body { - BlockStmtOrExpr::BlockStmt(body) => { + ArrowFunctionBody::FunctionBody(body) => { let new = self.inline_fn_like(param_ids, body, &mut call.args); if let Some(new) = new { self.changed = true; @@ -670,7 +682,7 @@ impl Optimizer<'_> { *e = new; } } - BlockStmtOrExpr::Expr(body) => { + ArrowFunctionBody::Expr(body) => { if !self.can_extract_param(param_ids.clone(), &call.args) { return; } @@ -788,8 +800,8 @@ impl Optimizer<'_> { Expr::Arrow(f) => { match &mut *f.body { // it's very likely to be processed in invoke_iife - BlockStmtOrExpr::Expr(_) => None, - BlockStmtOrExpr::BlockStmt(block_stmt) => { + ArrowFunctionBody::Expr(_) => None, + ArrowFunctionBody::FunctionBody(block_stmt) => { let param_ids = f.params.iter().map(|p| &p.as_ident().unwrap().id); self.inline_fn_like_stmt( param_ids, @@ -861,8 +873,24 @@ impl Optimizer<'_> { param_ids: impl ExactSizeIterator + Clone, args: &[ExprOrSpread], ) -> bool { - // Don't create top-level variables. + if param_ids.len() == 0 { + return true; + } + if !self.may_add_ident() { + // cannot add new ident, but sometimes inline or unused pass could remove those + // new vars + // but not when there's eval + + if self + .data + .get_scope(self.ctx.scope) + .unwrap() + .contains(ScopeData::HAS_EVAL_CALL) + { + return false; + } + for (idx, pid) in param_ids.clone().enumerate() { if let Some(usage) = self.data.vars.get(&pid.to_id()) { let arg = args.get(idx).map(|a| &*a.expr); @@ -969,7 +997,7 @@ impl Optimizer<'_> { &self, param_ids: impl ExactSizeIterator + Clone, args: &[ExprOrSpread], - body: &BlockStmt, + body: &FunctionBody, for_stmt: bool, ) -> bool { trace_op!("can_inline_fn_like"); @@ -986,17 +1014,6 @@ impl Optimizer<'_> { return false; } - // Abort on eval. - // See https://github.com/swc-project/swc/pull/6478 - // - // We completely abort on eval, because we cannot know whether a variable in - // upper scope will be afftected by eval. - // https://github.com/swc-project/swc/issues/6628 - if self.data.top.contains(ScopeData::HAS_EVAL_CALL) { - log_abort!("iife: [x] Aborting because of eval"); - return false; - } - if !self.may_add_ident() { let has_decl = if for_stmt { // we check it later @@ -1207,7 +1224,7 @@ impl Optimizer<'_> { fn inline_fn_like<'a>( &mut self, params: impl ExactSizeIterator + Clone, - body: &mut BlockStmt, + body: &mut FunctionBody, args: &mut [ExprOrSpread], ) -> Option { if !self.can_inline_fn_like(params.clone(), args, &*body, false) { @@ -1272,7 +1289,7 @@ impl Optimizer<'_> { fn inline_fn_like_stmt<'a>( &mut self, params: impl ExactSizeIterator + Clone + std::fmt::Debug, - body: &mut BlockStmt, + body: &mut FunctionBody, args: &mut [ExprOrSpread], is_return: bool, span: Span, @@ -1476,23 +1493,6 @@ impl Visit for ReturnVisitor { /// Don't recurse into fn fn visit_function(&mut self, _: &Function) {} - /// Don't recurse into fn - fn visit_getter_prop(&mut self, n: &GetterProp) { - n.key.visit_with(self); - } - - /// Don't recurse into fn - fn visit_method_prop(&mut self, n: &MethodProp) { - n.key.visit_with(self); - n.function.visit_with(self); - } - - /// Don't recurse into fn - fn visit_setter_prop(&mut self, n: &SetterProp) { - n.key.visit_with(self); - n.param.visit_with(self); - } - fn visit_expr(&mut self, _: &Expr) {} fn visit_return_stmt(&mut self, _: &ReturnStmt) { @@ -1519,23 +1519,6 @@ impl Visit for DeclVisitor { /// Don't recurse into fn fn visit_function(&mut self, _: &Function) {} - /// Don't recurse into fn - fn visit_getter_prop(&mut self, n: &GetterProp) { - n.key.visit_with(self); - } - - /// Don't recurse into fn - fn visit_method_prop(&mut self, n: &MethodProp) { - n.key.visit_with(self); - n.function.visit_with(self); - } - - /// Don't recurse into fn - fn visit_setter_prop(&mut self, n: &SetterProp) { - n.key.visit_with(self); - n.param.visit_with(self); - } - fn visit_expr(&mut self, _: &Expr) {} fn visit_decl(&mut self, d: &Decl) { @@ -1591,7 +1574,7 @@ impl Optimizer<'_> { if let Expr::Arrow(arrow) = &**callee { // For expression-style arrow functions in sequences, // we can be more aggressive with optimization - if let BlockStmtOrExpr::Expr(_body) = &*arrow.body { + if let ArrowFunctionBody::Expr(_body) = &*arrow.body { self.can_optimize_arrow_iife_in_seq(arrow, call) } else { false @@ -1614,7 +1597,7 @@ impl Optimizer<'_> { if let Expr::Call(call) = &mut **expr { if let Callee::Expr(callee) = &call.callee { if let Expr::Arrow(arrow) = &**callee { - if let BlockStmtOrExpr::Expr(_body) = &*arrow.body { + if let ArrowFunctionBody::Expr(_body) = &*arrow.body { let new_expr = self.optimize_single_arrow_iife_in_seq(arrow, call); if let Some(new_expr) = new_expr { @@ -1654,7 +1637,7 @@ impl Optimizer<'_> { } // Check if the arrow function body is simple enough for sequence optimization - if let BlockStmtOrExpr::Expr(body) = &*arrow.body { + if let ArrowFunctionBody::Expr(body) = &*arrow.body { self.is_simple_expr_for_seq_optimization(body) } else { false @@ -1683,7 +1666,7 @@ impl Optimizer<'_> { arrow: &ArrowExpr, call: &CallExpr, ) -> Option { - if let BlockStmtOrExpr::Expr(body) = &*arrow.body { + if let ArrowFunctionBody::Expr(body) = &*arrow.body { // For simple arrow functions with no parameters in sequences, // we can directly replace the IIFE with its body if arrow.params.is_empty() && call.args.is_empty() { diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/inline.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/inline.rs index da9229c7a..f4a1c282f 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/inline.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/inline.rs @@ -41,8 +41,10 @@ impl Optimizer<'_> { self.may_remove_ident(ident) ); - if self.data.top.contains(ScopeData::HAS_EVAL_CALL) { - return; + if let Some(scope) = self.data.get_scope(self.ctx.var_scope) { + if scope.intersects(ScopeData::HAS_EVAL_CALL.union(ScopeData::HAS_WITH_STMT)) { + return; + } } // We will inline if possible. @@ -65,13 +67,20 @@ impl Optimizer<'_> { return; } - if self.data.top.contains(ScopeData::USED_ARGUMENTS) + let used_arguments = self + .data + .get_scope(self.ctx.var_scope) + .unwrap() + .contains(ScopeData::USED_ARGUMENTS); + + if used_arguments && usage .flags .contains(VarUsageInfoFlags::DECLARED_AS_FN_PARAM) { return; } + if usage .flags .contains(VarUsageInfoFlags::DECLARED_AS_CATCH_PARAM) @@ -437,39 +446,7 @@ impl Optimizer<'_> { return; } - Expr::Fn(f) => { - let excluded: Vec = find_pat_ids(&f.function.params); - - for id in idents_used_by(&f.function.params) { - if excluded.contains(&id) { - continue; - } - if let Some(v_usage) = self.data.vars.get(&id) { - if v_usage.flags.contains(VarUsageInfoFlags::REASSIGNED) { - return; - } - } else { - return; - } - } - } - - Expr::Arrow(f) => { - let excluded: Vec = find_pat_ids(&f.params); - - for id in idents_used_by(&f.params) { - if excluded.contains(&id) { - continue; - } - if let Some(v_usage) = self.data.vars.get(&id) { - if v_usage.flags.contains(VarUsageInfoFlags::REASSIGNED) { - return; - } - } else { - return; - } - } - } + Expr::Fn(_) | Expr::Arrow(_) => {} Expr::Object(..) if self.options.pristine_globals => { for id in idents_used_by_ignoring_nested(init) { @@ -594,7 +571,7 @@ impl Optimizer<'_> { /// Check if the body of a function is simple enough to inline. fn is_fn_body_simple_enough_to_inline( &self, - body: &BlockStmt, + body: &FunctionBody, param_count: usize, usage: &VarUsageInfo, ) -> bool { @@ -696,16 +673,14 @@ impl Optimizer<'_> { return; } - if self - .data - .top - .intersects(ScopeData::HAS_EVAL_CALL.union(ScopeData::HAS_WITH_STMT)) - { - return; - } - let id = i.to_id(); + if let Some(scope) = self.data.get_scope(self.ctx.var_scope) { + if scope.intersects(ScopeData::HAS_EVAL_CALL.union(ScopeData::HAS_WITH_STMT)) { + return; + } + } + if let Some(usage) = self.data.vars.get(&id) { if usage .flags @@ -798,13 +773,13 @@ impl Optimizer<'_> { id.1 ); - for i in collect_infects_from( + for (i, _) in collect_infects_from( &f.function, AliasConfig::default() .marks(Some(self.marks)) .need_all(true), ) { - if let Some(usage) = self.data.vars.get_mut(&i.0) { + if let Some(usage) = self.data.vars.get_mut(&i) { usage.ref_count += 1; } } @@ -1027,8 +1002,8 @@ fn is_arrow_simple_enough_for_copy(e: &ArrowExpr) -> Option { } match &*e.body { - BlockStmtOrExpr::BlockStmt(s) => is_block_stmt_of_fn_simple_enough_for_copy(s), - BlockStmtOrExpr::Expr(e) => is_arrow_body_simple_enough_for_copy(e), + ArrowFunctionBody::FunctionBody(s) => is_block_stmt_of_fn_simple_enough_for_copy(s), + ArrowFunctionBody::Expr(e) => is_arrow_body_simple_enough_for_copy(e), #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), } @@ -1065,7 +1040,7 @@ fn is_arrow_body_simple_enough_for_copy(e: &Expr) -> Option { None } -fn is_block_stmt_of_fn_simple_enough_for_copy(b: &BlockStmt) -> Option { +fn is_block_stmt_of_fn_simple_enough_for_copy(b: &FunctionBody) -> Option { if b.stmts.len() == 1 { if let Stmt::Return(ret) = &b.stmts[0] { return ret diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/mod.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/mod.rs index ac2c94345..7fc7369d0 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/mod.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/mod.rs @@ -79,7 +79,8 @@ pub(super) fn optimizer<'a>( in_strict: options.module, remaining_depth: 6, }, - scope: SyntaxContext::default(), + scope: marks.top_level_ctxt, + var_scope: marks.top_level_ctxt, bit_ctx: BitCtx::default(), }; @@ -111,6 +112,9 @@ struct Ctx { /// Current scope. scope: SyntaxContext, + /// fn or top level scope + var_scope: SyntaxContext, + bit_ctx: BitCtx, } @@ -373,10 +377,6 @@ impl Optimizer<'_> { } fn may_add_ident(&self) -> bool { - if self.ctx.in_top_level() && self.data.top.contains(ScopeData::HAS_EVAL_CALL) { - return false; - } - // in class field if self.ctx.bit_ctx.contains(BitCtx::InClass) && !self @@ -393,7 +393,7 @@ impl Optimizer<'_> { if self .data - .get_scope(self.ctx.scope) + .get_scope(self.ctx.var_scope) .unwrap() .contains(ScopeData::HAS_EVAL_CALL) { @@ -816,8 +816,8 @@ impl Optimizer<'_> { .map(|body| body.stmts.is_empty()) .unwrap_or(false), Expr::Arrow(f) => match &*f.body { - BlockStmtOrExpr::BlockStmt(body) => body.stmts.is_empty(), - BlockStmtOrExpr::Expr(_) => false, + ArrowFunctionBody::FunctionBody(body) => body.stmts.is_empty(), + ArrowFunctionBody::Expr(_) => false, #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), }, @@ -1478,6 +1478,20 @@ impl Optimizer<'_> { } } + fn function_like_ctx(&self, scope: SyntaxContext) -> Ctx { + Ctx { + bit_ctx: self + .ctx + .bit_ctx + .with(BitCtx::InFnLike, true) + .with(BitCtx::TopLevel, false) + .with(BitCtx::InParam, false), + scope, + var_scope: scope, + ..self.ctx.clone() + } + } + fn visit_with_prepend(&mut self, n: &mut N) where N: VisitMutWith, @@ -1511,25 +1525,17 @@ impl VisitMut for Optimizer<'_> { } { - let ctx = Ctx { - bit_ctx: self - .ctx - .bit_ctx - .with(BitCtx::InFnLike, true) - .with(BitCtx::TopLevel, false), - scope: n.ctxt, - ..self.ctx.clone() - }; + let ctx = self.function_like_ctx(n.ctxt); n.body.visit_mut_with(&mut *self.with_ctx(ctx)); } if !self.prepend_stmts.is_empty() { let mut stmts = self.prepend_stmts.take().take_stmts(); match &mut *n.body { - BlockStmtOrExpr::BlockStmt(v) => { + ArrowFunctionBody::FunctionBody(v) => { prepend_stmts(&mut v.stmts, stmts.into_iter()); } - BlockStmtOrExpr::Expr(v) => { + ArrowFunctionBody::Expr(v) => { self.changed = true; report_change!("Converting a body of an arrow expression to BlockStmt"); @@ -1540,10 +1546,9 @@ impl VisitMut for Optimizer<'_> { } .into(), ); - *n.body = BlockStmtOrExpr::BlockStmt(BlockStmt { + *n.body = ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts, - ..Default::default() }); } #[cfg(swc_ast_unknown)] @@ -1553,7 +1558,7 @@ impl VisitMut for Optimizer<'_> { self.prepend_stmts = prepend; - if let BlockStmtOrExpr::BlockStmt(body) = &mut *n.body { + if let ArrowFunctionBody::FunctionBody(body) = &mut *n.body { drop_invalid_stmts(&mut body.stmts); } } @@ -1640,15 +1645,15 @@ impl VisitMut for Optimizer<'_> { n.visit_mut_children_with(&mut *self.with_ctx(ctx)); } - fn visit_mut_block_stmt_or_expr(&mut self, n: &mut BlockStmtOrExpr) { + fn visit_mut_arrow_function_body(&mut self, n: &mut ArrowFunctionBody) { n.visit_mut_children_with(self); match n { - BlockStmtOrExpr::BlockStmt(n) => { + ArrowFunctionBody::FunctionBody(n) => { self.merge_if_returns(&mut n.stmts, false, true); self.drop_else_token(&mut n.stmts); } - BlockStmtOrExpr::Expr(_) => {} + ArrowFunctionBody::Expr(_) => {} #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), } @@ -1809,12 +1814,41 @@ impl VisitMut for Optimizer<'_> { private_method.visit_mut_with(&mut *self.with_ctx(ctx)); } + ClassMember::StaticBlock(s) => { + let ctx = Ctx { + bit_ctx: self + .ctx + .bit_ctx + .with(BitCtx::TopLevel, false) + .with(BitCtx::InBlock, true) + .with(BitCtx::InParam, false), + scope: s.body.ctxt, + var_scope: s.body.ctxt, + ..self.ctx.clone() + }; + n.visit_mut_children_with(&mut *self.with_ctx(ctx)); + } + _ => { n.visit_mut_children_with(&mut *self.with_ctx(ctx)); } } } + #[cfg_attr( + all(debug_assertions, feature = "debug"), + tracing::instrument(level = "debug", skip_all) + )] + fn visit_mut_constructor(&mut self, n: &mut Constructor) { + n.key.visit_mut_with(self); + + let ctx = self.function_like_ctx(n.ctxt); + let optimizer = &mut *self.with_ctx(ctx); + + n.params.visit_mut_with(optimizer); + n.body.visit_mut_with(optimizer); + } + #[cfg_attr( all(debug_assertions, feature = "debug"), tracing::instrument(level = "debug", skip_all) @@ -2329,15 +2363,7 @@ impl VisitMut for Optimizer<'_> { let old_in_asm = self.ctx.bit_ctx.contains(BitCtx::InAsm); { - let ctx = Ctx { - bit_ctx: self - .ctx - .bit_ctx - .with(BitCtx::InFnLike, true) - .with(BitCtx::TopLevel, false), - scope: n.ctxt, - ..self.ctx.clone() - }; + let ctx = self.function_like_ctx(n.ctxt); let optimizer = &mut *self.with_ctx(ctx); n.params.visit_mut_with(optimizer); @@ -2540,6 +2566,8 @@ impl VisitMut for Optimizer<'_> { n.args.visit_mut_with(&mut *self.with_ctx(ctx)); } + self.ignore_unused_args_of_new(n); + // Try to replace global object with alias (after other transformations) if self .static_alias_state @@ -2982,7 +3010,12 @@ impl VisitMut for Optimizer<'_> { fn visit_mut_switch_stmt(&mut self, n: &mut SwitchStmt) { n.discriminant.visit_mut_with(self); - n.cases.visit_mut_with(self); + let ctx = Ctx { + bit_ctx: self.ctx.bit_ctx.with(BitCtx::InBlock, true), + scope: n.body_ctxt, + ..self.ctx + }; + n.cases.visit_mut_with(&mut *self.with_ctx(ctx)); } /// We don't optimize [Tpl] contained in [TaggedTpl]. diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs index dbca08ea5..5bb9c153d 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs @@ -20,10 +20,7 @@ use crate::{ }, option::CompressOptions, program_data::{ScopeData, VarUsageInfoFlags}, - usage_analyzer::{ - alias::{try_collect_infects_from, AccessKind, AliasConfig}, - util::is_global_var_with_pure_property_access, - }, + usage_analyzer::util::is_global_var_with_pure_property_access, util::{ idents_used_by, idents_used_by_ignoring_nested, ExprOptExt, IdentUsageCollector, ModuleItemExt, @@ -1102,56 +1099,7 @@ impl Optimizer<'_> { Mergable::Drop => return false, } - let e_id = e.to_id(); - let ids_used_by_a_init = match a { - Mergable::Var(a) => a.init.as_ref().map(|init| { - try_collect_infects_from( - init, - AliasConfig::default() - .marks(Some(self.marks)) - .ignore_nested(true) - .need_all(true), - 8, - ) - }), - Mergable::Expr(a) => match a { - Expr::Assign(a) if a.is_simple_assign() => Some(try_collect_infects_from( - &a.right, - AliasConfig::default() - .marks(Some(self.marks)) - .ignore_nested(true) - .need_all(true), - 8, - )), - - _ => None, - }, - - Mergable::FnDecl(a) => Some(try_collect_infects_from( - &a.function, - AliasConfig::default() - .marks(Some(self.marks)) - .ignore_nested(true) - .need_all(true), - 8, - )), - - Mergable::Drop => return false, - }; - - if let Some(deps) = ids_used_by_a_init { - let Ok(deps) = deps else { - return false; - }; - - if deps.iter().any(|(id, kind)| { - id == &e_id && matches!(kind, AccessKind::Reference | AccessKind::Call) - }) { - return false; - } - } - - if !self.assignee_skippable_for_seq(a, &e_id) { + if !self.assignee_skippable_for_seq(a, &e.to_id()) { return false; } } @@ -2442,10 +2390,9 @@ impl Optimizer<'_> { Mergable::Var(a) => { if self.options.unused { if let Some(usage) = self.data.vars.get(&left_id.to_id()) { - // We are eliminating one usage, so we use 1 instead of - // 0 + // We are eliminating one usage, so we use 1 instead of 0 if !force_drop - && usage.usage_count == 1 + && usage.ref_count == 1 && !usage.flags.contains(VarUsageInfoFlags::REASSIGNED) { report_change!("sequences: Dropping inlined variable"); diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/strings.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/strings.rs index eb46fbe97..01d796f09 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/strings.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/strings.rs @@ -1,9 +1,10 @@ -use swc_atoms::{atom, Atom, Wtf8Atom}; -use swc_common::{util::take::Take, Spanned, SyntaxContext}; +use swc_atoms::{Atom, Wtf8Atom}; +use swc_common::{util::take::Take, Spanned}; use swc_ecma_ast::*; use swc_ecma_utils::{ExprExt, Value::Known}; use super::Optimizer; +use crate::util::make_number; impl Optimizer<'_> { pub(super) fn optimize_expr_in_str_ctx_unsafely(&mut self, e: &mut Expr) { @@ -123,12 +124,7 @@ impl Optimizer<'_> { }) => { if let (Expr::Lit(Lit::Num(l)), Expr::Lit(Lit::Num(r))) = (&**left, &**right) { if l.value == 0.0 && r.value == 0.0 { - *n = Ident::new( - atom!("NaN"), - *span, - SyntaxContext::empty().apply_mark(self.marks.unresolved_mark), - ) - .into(); + *n = make_number(*span, f64::NAN); self.changed = true; report_change!("strings: Evaluated 0 / 0 => NaN in string context"); } diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/unused.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/unused.rs index d610fbdc8..70f21602f 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/unused.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/unused.rs @@ -707,7 +707,8 @@ impl Optimizer<'_> { if self .data - .top + .get_scope(self.ctx.var_scope) + .unwrap() .intersects(ScopeData::HAS_EVAL_CALL.union(ScopeData::HAS_WITH_STMT)) { return; @@ -753,7 +754,8 @@ impl Optimizer<'_> { if self .data - .top + .get_scope(self.ctx.var_scope) + .unwrap() .intersects(ScopeData::HAS_EVAL_CALL.union(ScopeData::HAS_WITH_STMT)) { return; @@ -1028,18 +1030,10 @@ impl Optimizer<'_> { }; match &**prop { - Prop::Method(prop) => { - if contains_this_expr(&prop.function.body) { - return None; - } - } - Prop::Getter(prop) => { - if contains_this_expr(&prop.body) { - return None; - } - } - Prop::Setter(prop) => { - if contains_this_expr(&prop.body) { + Prop::Method(MethodProp { function, .. }) + | Prop::Getter(GetterProp { function, .. }) + | Prop::Setter(SetterProp { function, .. }) => { + if contains_this_expr(&function.body) { return None; } } @@ -1160,6 +1154,10 @@ impl Optimizer<'_> { return; } + if self.ctx.bit_ctx.intersects(BitCtx::InWithStmt) { + return; + } + if e.args.iter().any(|a| a.spread.is_some()) { return; } @@ -1243,6 +1241,120 @@ impl Optimizer<'_> { } } } + + pub(crate) fn ignore_unused_args_of_new(&mut self, e: &mut NewExpr) { + if !self.options.unused && !self.options.reduce_vars { + return; + } + + if self.ctx.bit_ctx.intersects(BitCtx::InWithStmt) { + return; + } + + let args = if let Some(args) = &mut e.args { + args + } else { + return; + }; + + if args.iter().any(|a| a.spread.is_some()) { + return; + } + + let callee = &mut *e.callee; + + match callee { + Expr::Fn(FnExpr { function, .. }) => { + if let Some(scope) = self.data.get_scope(function.ctxt) { + if scope.intersects(ScopeData::USED_ARGUMENTS.union(ScopeData::HAS_EVAL_CALL)) { + return; + } + } + } + Expr::Class(c) => { + for m in &c.class.body { + if let Some(scope) = + m.as_constructor().and_then(|c| self.data.get_scope(c.ctxt)) + { + if scope + .intersects(ScopeData::USED_ARGUMENTS.union(ScopeData::HAS_EVAL_CALL)) + { + return; + } + } + } + } + _ => (), + } + + let params_len = match callee { + Expr::Fn(FnExpr { function, .. }) => { + let params = &function.params; + + if !params.iter().any(|p| p.pat.is_rest()) { + params.len() + } else { + return; + } + } + Expr::Class(ClassExpr { class, .. }) => { + let c = class + .body + .iter() + .filter_map(|c| c.as_constructor()) + .find(|c| c.body.is_some()); + + if let Some(c) = c { + if !c + .params + .iter() + .any(|p| p.as_param().and_then(|p| p.pat.as_rest()).is_some()) + { + c.params.len() + } else { + return; + } + } else { + return; + } + } + Expr::Ident(i) => { + if let Some(scope) = self.data.get_scope(i.ctxt) { + if scope.intersects(ScopeData::HAS_EVAL_CALL.union(ScopeData::HAS_WITH_STMT)) { + return; + } + } + + if let Some(data) = self.data.get_var_data(i.to_id()) { + if let (true, Some(Value::Known(count))) = ( + data.flags.intersects(VarUsageInfoFlags::DECLARED), + data.param_count, + ) { + count as usize + } else { + return; + } + } else { + return; + } + } + _ => return, + }; + + if args.len() > params_len { + for i in (params_len..args.len()).rev() { + if let Some(arg) = args.get_mut(i) { + let new = self.ignore_return_value(&mut arg.expr); + + if let Some(new) = new { + *arg.expr = new; + } else { + args.remove(i); + } + } + } + } + } } fn can_remove_property(sym: &swc_atoms::Wtf8Atom) -> bool { diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/util.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/util.rs index 7d0e77305..a99566068 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/util.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/optimize/util.rs @@ -304,23 +304,6 @@ impl Visit for ClassEffectVisitor { /// Don't recurse into fn fn visit_function(&mut self, _: &Function) {} - /// Don't recurse into fn - fn visit_getter_prop(&mut self, n: &GetterProp) { - n.key.visit_with(self); - } - - /// Don't recurse into fn - fn visit_method_prop(&mut self, n: &MethodProp) { - n.key.visit_with(self); - n.function.visit_with(self); - } - - /// Don't recurse into fn - fn visit_setter_prop(&mut self, n: &SetterProp) { - n.key.visit_with(self); - n.param.visit_with(self); - } - fn visit_this_expr(&mut self, _: &ThisExpr) { self.found = true; } diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/arrows.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/arrows.rs index de43003d1..9922f3be5 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/arrows.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/arrows.rs @@ -34,7 +34,9 @@ impl Pure<'_> { *e = ArrowExpr { span: function.span, params: function.params.take().into_iter().map(|p| p.pat).collect(), - body: Box::new(BlockStmtOrExpr::BlockStmt(function.body.take().unwrap())), + body: Box::new(ArrowFunctionBody::FunctionBody( + function.body.take().unwrap(), + )), is_async: function.is_async, is_generator: function.is_generator, ..Default::default() @@ -43,19 +45,19 @@ impl Pure<'_> { } } - pub(super) fn optimize_arrow_body(&mut self, b: &mut BlockStmtOrExpr) { + pub(super) fn optimize_arrow_body(&mut self, b: &mut ArrowFunctionBody) { match b { - BlockStmtOrExpr::BlockStmt(s) => { + ArrowFunctionBody::FunctionBody(s) => { if s.stmts.len() == 1 { if let Stmt::Return(s) = &mut s.stmts[0] { if let Some(arg) = &mut s.arg { report_change!("arrows: Optimizing the body of an arrow"); - *b = BlockStmtOrExpr::Expr(arg.take()); + *b = ArrowFunctionBody::Expr(arg.take()); } } } } - BlockStmtOrExpr::Expr(_) => {} + ArrowFunctionBody::Expr(_) => {} #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), } @@ -110,7 +112,7 @@ impl Pure<'_> { .into_iter() .map(|v| v.pat) .collect(), - body: Box::new(BlockStmtOrExpr::Expr(arg)), + body: Box::new(ArrowFunctionBody::Expr(arg)), is_async: m.function.is_async, is_generator: m.function.is_generator, ..Default::default() @@ -138,7 +140,7 @@ impl Pure<'_> { } match &mut *kv.value { - Expr::Arrow(m) if m.body.is_block_stmt() => { + Expr::Arrow(m) if m.body.is_function_body() => { *p = Prop::Method(MethodProp { key: kv.key.take(), function: Box::new(Function { @@ -153,7 +155,7 @@ impl Pure<'_> { }) .collect(), span: m.span, - body: m.body.take().block_stmt(), + body: m.body.take().function_body(), is_generator: m.is_generator, is_async: m.is_async, ..Default::default() diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/bools.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/bools.rs index edafd4f98..b56597288 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/bools.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/bools.rs @@ -7,7 +7,7 @@ use swc_ecma_utils::{ExprCtx, ExprExt, Type, Value}; use super::Pure; use crate::{ compress::util::{can_absorb_negate, is_eq, is_pure_undefined, negate, negate_cost}, - util::make_bool, + util::{is_falsy_number, make_bool}, }; #[inline(always)] @@ -529,7 +529,7 @@ impl Pure<'_> { self.changed = true; *n = Lit::Num(Number { span: *span, - value: if *value == 0.0 { 1.0 } else { 0.0 }, + value: if is_falsy_number(*value) { 1.0 } else { 0.0 }, raw: None, }) .into() @@ -601,7 +601,7 @@ impl Pure<'_> { self.changed = true; *n = Lit::Num(Number { span: num.span, - value: if num.value == 0.0 { 0.0 } else { 1.0 }, + value: if is_falsy_number(num.value) { 0.0 } else { 1.0 }, raw: None, }) .into(); diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/conds.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/conds.rs index 0fc6203de..587922cc7 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/conds.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/conds.rs @@ -223,16 +223,21 @@ impl Pure<'_> { return; } + fn can_rewrite_as_arithmetic(non_zero: &Number, zero: &Number) -> bool { + non_zero.value.is_finite() + && non_zero.value > 0.0 + && zero.value == 0.0 + && zero.value.is_sign_positive() + } + let Expr::Cond(cond) = e else { return }; let span = cond.span; match (&mut *cond.cons, &mut *cond.alt) { - ( - Expr::Lit(Lit::Num(Number { value, .. })), - Expr::Lit(Lit::Num(Number { value: 0.0, .. })), - ) if *value > 0.0 - && (!cond.test.is_bin() - || cond.test.get_type(self.expr_ctx) == Value::Known(Type::Bool)) => + (Expr::Lit(Lit::Num(non_zero)), Expr::Lit(Lit::Num(zero))) + if can_rewrite_as_arithmetic(non_zero, zero) + && (!cond.test.is_bin() + || cond.test.get_type(self.expr_ctx) == Value::Known(Type::Bool)) => { report_change!("conditionals: `foo ? num : 0` => `num * !!foo`"); self.changed = true; @@ -248,11 +253,9 @@ impl Pure<'_> { right, }) } - ( - Expr::Lit(Lit::Num(Number { value: 0.0, .. })), - Expr::Lit(Lit::Num(Number { value, .. })), - ) if *value > 0.0 - && (!cond.test.is_bin() || can_absorb_negate(&cond.test, self.expr_ctx)) => + (Expr::Lit(Lit::Num(zero)), Expr::Lit(Lit::Num(non_zero))) + if can_rewrite_as_arithmetic(non_zero, zero) + && (!cond.test.is_bin() || can_absorb_negate(&cond.test, self.expr_ctx)) => { report_change!("conditionals: `foo ? 0 : num` => `num * !foo`"); self.changed = true; diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs index e5d9dd086..602fa4a3a 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs @@ -1,9 +1,11 @@ +use std::{num::FpCategory, ops::RangeInclusive}; + use radix_fmt::Radix; use swc_atoms::atom; -use swc_common::{util::take::Take, Spanned, SyntaxContext}; +use swc_common::{util::take::Take, Spanned}; use swc_ecma_ast::*; use swc_ecma_utils::{ - number::ToJsString, + number::{parse_canonical_index, ToJsString}, unicode::{is_high_surrogate, is_low_surrogate}, ExprExt, IsEmpty, Type, Value, }; @@ -16,9 +18,62 @@ use crate::{ pure::Ctx, util::{eval_as_number, is_pure_undefined_or_null}, }, - util::ValueExt, + util::{make_number, ValueExt}, }; +/// Formats an integer with `radix_fmt` only where its exact integer output is +/// also a valid ECMAScript `Number::toString` result. +fn format_integer_in_radix(value: f64, radix: u8) -> Option { + const MAX_SAFE_INTEGER: f64 = 9_007_199_254_740_991_f64; + + let magnitude = value.abs(); + let is_safe_integer = magnitude <= MAX_SAFE_INTEGER; + let is_supported_binary_radix = radix.is_power_of_two() && magnitude < u128::MAX as f64; + + if !is_safe_integer && !is_supported_binary_radix { + return None; + } + + let digits = Radix::new(magnitude as u128, radix).to_string(); + if value >= 0_f64 { + return Some(digits); + } + + let mut output = String::with_capacity(digits.len() + 1); + output.push('-'); + output.push_str(&digits); + Some(output) +} + +/// Applies ECMAScript's `ToIntegerOrInfinity` operation to a known number. +/// +/// https://tc39.es/ecma262/multipage/abstract-operations.html#sec-tointegerorinfinity +fn to_integer_or_infinity(value: f64) -> f64 { + // Step 1 (`ToNumber`) is already satisfied by the `f64` input. + // 2. If number is one of NaN, +0𝔽, or -0𝔽, return 0. + // 3. If number is +∞𝔽, return +∞. + // 4. If number is -∞𝔽, return -∞. + // 5. Return truncate(ℝ(number)). + match value.classify() { + FpCategory::Nan | FpCategory::Zero => 0.0, + FpCategory::Infinite => value, + _ => value.trunc(), + } +} + +/// Converts a `ToIntegerOrInfinity` result to `u8` if it is within `range`. +fn to_u8_if_in_range(value: f64, range: RangeInclusive) -> Option { + let start = f64::from(*range.start()); + let end = f64::from(*range.end()); + let valid_range = start..=end; + + if !valid_range.contains(&value) { + return None; + } + + Some(value as u8) +} + impl Pure<'_> { /// /// - `1 == 1` => `true` @@ -412,7 +467,9 @@ impl Pure<'_> { MemberProp::Computed(p) => { if let Expr::Lit(Lit::Str(s)) = &*p.expr { if let Some(value) = s.value.as_str() { - if let Ok(value) = value.parse::() { + if let Some(value) = + parse_canonical_index(value).and_then(|value| u32::try_from(value).ok()) + { p.expr = Lit::Num(Number { span: s.span, value: value as f64, @@ -530,16 +587,16 @@ impl Pure<'_> { // 2. Let f be ? ToIntegerOrInfinity(fractionDigits). // 3. Assert: If fractionDigits is undefined, then f is 0. let precision = first_arg.unwrap_or(0f64); - let f = precision.trunc() as u8; // 4. If f is not finite, throw a RangeError exception. // 5. If f < 0 or f > 100, throw a RangeError exception. - + let f = to_integer_or_infinity(precision); // Note: ES2018 increased the maximum number of fraction digits from 20 to 100. - // It relies on runtime behavior. - if !(0..=20).contains(&f) { + // Preserve the optimizer's existing conservative folding range. Wider valid + // values are left to runtime. + let Some(f) = to_u8_if_in_range(f, 0..=20) else { return; - } + }; let mut buffer = ryu_js::Buffer::new(); let value = buffer.format_to_fixed(num.value, f); @@ -583,13 +640,23 @@ impl Pure<'_> { .into(); return; } else if let Some(precision) = first_arg { - let p = precision.trunc() as usize; - // 5. If p < 1 or p > 100, throw a RangeError exception. - if !(1..=21).contains(&p) { - return; - } + // 3. Let p be ? ToIntegerOrInfinity(precision). + let p = to_integer_or_infinity(precision); + + let value = if num.value.is_finite() { + // 5. If p < 1 or p > 100, throw a RangeError exception. + // Preserve the optimizer's existing conservative folding range. Wider valid + // values are left to runtime. + let Some(p) = to_u8_if_in_range(p, 1..=21) else { + return; + }; + + f64_to_precision(num.value, usize::from(p)) + } else { + // 4. If x is not finite, return Number::toString(x, 10). + num.value.to_js_string() + }; - let value = f64_to_precision(num.value, p); self.changed = true; report_change!( "evaluate: Evaluating `{}.toPrecision()` as `{}`", @@ -625,13 +692,22 @@ impl Pure<'_> { .into(); return; } else if let Some(precision) = first_arg { - let p = precision.trunc() as usize; - // 5. If p < 1 or p > 100, throw a RangeError exception. - if !(0..=20).contains(&p) { - return; - } + // 3. Let f be ? ToIntegerOrInfinity(fractionDigits). + let p = to_integer_or_infinity(precision); + + let value = if num.value.is_finite() { + // 5. If f < 0 or f > 100, throw a RangeError exception. + // Preserve the optimizer's existing conservative folding range. Wider valid + // values are left to runtime. + let Some(p) = to_u8_if_in_range(p, 0..=20) else { + return; + }; - let value = f64_to_exponential_with_precision(num.value, p).into(); + f64_to_exponential_with_precision(num.value, usize::from(p)).into() + } else { + // 4. If x is not finite, return Number::toString(x, 10). + num.value.to_js_string().into() + }; self.changed = true; report_change!( @@ -666,26 +742,17 @@ impl Pure<'_> { if num.value.fract() == 0.0 && (2.0..=36.0).contains(&base) && base.fract() == 0.0 { let base = base.floor() as u8; - - self.changed = true; - - let value = { - let x = num.value; - if x < 0. { - // I don't know if u128 is really needed, but it works. - format!("-{}", Radix::new(-x as u128, base)) - } else { - Radix::new(x as u128, base).to_string() - } - } - .into(); + let Some(value) = format_integer_in_radix(num.value, base) else { + return; + }; *e = Lit::Str(Str { span: e.span(), raw: None, - value, + value: value.into(), }) - .into() + .into(); + self.changed = true; } } } @@ -867,7 +934,7 @@ impl Pure<'_> { report_change!( "evaluate: Evaluated `charCodeAt` of a string literal as `NaN`", ); - *e = Ident::new(atom!("NaN"), e.span(), SyntaxContext::empty()).into() + *e = make_number(e.span(), f64::NAN) } } } @@ -932,12 +999,7 @@ impl Pure<'_> { report_change!( "evaluate: Evaluated `codePointAt` of a string literal as `NaN`", ); - *e = Ident::new( - atom!("NaN"), - e.span(), - SyntaxContext::empty().apply_mark(self.marks.unresolved_mark), - ) - .into() + *e = make_number(e.span(), f64::NAN) } } } @@ -960,6 +1022,10 @@ impl Pure<'_> { // Code from boa // https://github.com/boa-dev/boa/blob/f8b682085d7fe0bbfcd0333038e93cf2f5aee710/boa_engine/src/builtins/number/mod.rs#L408 fn f64_to_precision(value: f64, precision: usize) -> String { + if !value.is_finite() { + return value.to_js_string(); + } + let mut x = value; let p_i32 = precision as i32; @@ -1114,6 +1180,10 @@ fn round_to_precision(digits: &mut String, precision: usize) -> bool { /// Helper function that formats a float as a ES6-style exponential number /// string. fn f64_to_exponential(n: f64) -> String { + if !n.is_finite() { + return n.to_js_string(); + } + match n.abs() { x if x >= 1.0 || x == 0.0 => format!("{n:e}").replace('e', "e+"), _ => format!("{n:e}"), @@ -1127,6 +1197,10 @@ fn f64_to_exponential(n: f64) -> String { // Instead we get the index of 'e', and if the next character is not '-' // we insert the plus sign fn f64_to_exponential_with_precision(n: f64, prec: usize) -> String { + if !n.is_finite() { + return n.to_js_string(); + } + let mut res = format!("{n:.prec$e}"); let idx = res.find('e').expect("'e' not found in exponential string"); if res.as_bytes()[idx + 1] != b'-' { diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/member_expr.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/member_expr.rs index 85fe377e6..caea93c0d 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/member_expr.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/member_expr.rs @@ -5,7 +5,10 @@ use swc_ecma_ast::{ ArrayLit, Expr, ExprOrSpread, IdentName, Lit, MemberExpr, MemberProp, ObjectLit, Prop, PropOrSpread, SeqExpr, Str, }; -use swc_ecma_utils::{prop_name_eq, ExprExt, Known}; +use swc_ecma_utils::{ + number::{parse_canonical_index, ToJsString}, + prop_name_eq, ExprExt, Known, +}; use super::Pure; use crate::compress::pure::Ctx; @@ -150,6 +153,31 @@ fn is_string_symbol(sym: &str) -> bool { STRING_SYMBOLS.contains(sym) || is_object_symbol(sym) } +/// A statically known property key with optional metadata for literal indexing. +/// +/// `property_key` is always the exact ECMAScript property key. `index` is only +/// populated for canonical non-negative decimal keys that can index a literal +/// array or string without reinterpreting the property key. +struct KnownMemberKey { + property_key: Atom, + index: Option, +} + +impl KnownMemberKey { + fn from_number(value: f64) -> Self { + Self::from_property_key(Atom::from(value.to_js_string())) + } + + fn from_property_key(property_key: Atom) -> Self { + let index = parse_canonical_index(property_key.as_str()); + + Self { + property_key, + index, + } + } +} + /// Checks if the given key exists in the given properties, taking the /// `__proto__` property and order of keys into account (the order of keys /// matters for nested `__proto__` properties). @@ -258,29 +286,13 @@ impl Pure<'_> { return None; } - /// Taken from `simplify::expr`. - /// - /// `x.length` is handled as `IndexStr`, since `x.length` calls for - /// String and Array are handled in `simplify::expr` (the `length` - /// prototype for both of these types cannot be changed). - #[derive(Clone, PartialEq)] - enum KnownOp { - // [a, b][2] - // - // ({})[1] - Index(f64), - - /// ({}).foo - /// - /// ({}).length - IndexStr(Atom), - } - let op = match prop { - MemberProp::Ident(IdentName { sym, .. }) => KnownOp::IndexStr(sym.clone()), + MemberProp::Ident(IdentName { sym, .. }) => { + KnownMemberKey::from_property_key(sym.clone()) + } MemberProp::Computed(c) => match &*c.expr { - Expr::Lit(Lit::Num(n)) => KnownOp::Index(n.value), + Expr::Lit(Lit::Num(n)) => KnownMemberKey::from_number(n.value), Expr::Ident(..) => { return None; @@ -291,11 +303,7 @@ impl Pure<'_> { return None; }; - if let Ok(n) = s.parse::() { - KnownOp::Index(n) - } else { - KnownOp::IndexStr(Atom::from(s)) - } + KnownMemberKey::from_property_key(Atom::from(s)) } }, @@ -328,9 +336,14 @@ impl Pure<'_> { } Expr::Lit(Lit::Str(Str { value, span, .. })) => { - match op { - KnownOp::Index(idx) => { - if idx.fract() != 0.0 || idx < 0.0 || idx as usize >= value.len() { + match op.index { + Some(index) => { + // JavaScript indexes strings by UTF-16 code unit, not by WTF-8 byte. + // WTF-8 byte length remains a safe upper bound for a fast rejection. + let is_out_of_bounds = index >= value.len() + || value.to_ill_formed_utf16().nth(index).is_none(); + + if is_out_of_bounds { Some(*Expr::undefined(*span)) } else { // idx is in bounds, this is handled in simplify @@ -338,7 +351,9 @@ impl Pure<'_> { } } - KnownOp::IndexStr(key) => { + None => { + let key = op.property_key; + if key == "length" { // handled in simplify::expr return None; @@ -365,9 +380,9 @@ impl Pure<'_> { return None; } - match op { - KnownOp::Index(idx) => { - if idx >= 0.0 && (idx as usize) < elems.len() && idx.fract() == 0.0 { + match op.index { + Some(index) => { + if index < elems.len() { // idx is in bounds, handled in simplify return None; } @@ -400,7 +415,9 @@ impl Pure<'_> { }) } - KnownOp::IndexStr(key) if key != "length" /* handled in simplify */ => { + None if op.property_key != "length" /* handled in simplify */ => { + let key = op.property_key; + // If the property is a known symbol, e.g. [].push let is_known_symbol = is_array_symbol(&key); @@ -490,13 +507,10 @@ impl Pure<'_> { } // Get key as Atom - let key = match op { - KnownOp::Index(i) => Atom::from(i.to_string()), - KnownOp::IndexStr(key) if key != *"yield" => key, - _ => { - return None; - } - }; + let key = op.property_key; + if key == "yield" { + return None; + } // Check if key exists let exists = does_key_exist(&key, props); diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/misc.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/misc.rs index 665782bdb..d8af37512 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/misc.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/misc.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, fmt::Write, num::FpCategory}; +use std::{borrow::Cow, num::FpCategory}; use rustc_hash::FxHashSet; use swc_atoms::{ @@ -9,7 +9,9 @@ use swc_atoms::{ use swc_common::{iter::IdentifyLast, util::take::Take, Span, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_transforms_optimization::debug_assert_valid; -use swc_ecma_utils::{ExprCtx, ExprExt, ExprFactory, IdentUsageFinder, Type, Value}; +use swc_ecma_utils::{ + number::ToJsString, ExprCtx, ExprExt, ExprFactory, IdentUsageFinder, Type, Value, +}; use super::Pure; use crate::{ @@ -292,13 +294,32 @@ impl Pure<'_> { } } + // Spreading a primitive of these types copies zero own enumerable + // properties (`ToObject` on them yields a wrapper whose properties are + // all non-enumerable), so `{ ...x }` where `x` is one of them + // contributes nothing. + // + // Strings are intentionally EXCLUDED: they expose indexed own + // enumerable properties (`{ ..."ab" }` === `{ 0: "a", 1: "b" }`). + // Objects, arrays, functions, etc. are also excluded as they carry + // real properties. + fn spreads_no_props(expr: &Expr, expr_ctx: ExprCtx) -> bool { + matches!( + expr.get_type(expr_ctx), + Value::Known(Type::Undefined | Type::Null | Type::Bool | Type::Num | Type::Symbol) + ) + } + fn can_flatten_spread_expr(expr: &Expr, expr_ctx: ExprCtx) -> bool { match expr { Expr::Object(ObjectLit { props, .. }) => { props.iter().all(|p| can_flatten_spread_prop(p, expr_ctx)) } - Expr::Lit(Lit::Null(_)) => true, - _ => false, + // Spreading a side-effect-free expression that has no own + // enumerable properties contributes nothing. We require purity + // so that we never discard observable side effects + // (e.g. `{ ...void foo() }`). + _ => spreads_no_props(expr, expr_ctx) && !expr.may_have_side_effects(expr_ctx), } } @@ -374,16 +395,12 @@ impl Pure<'_> { PropOrSpread::Spread(SpreadElement { expr, .. }) if can_flatten_spread_expr(&expr, self.expr_ctx) => { - match *expr { - Expr::Object(ObjectLit { props, .. }) => { - for p in props { - new_props.push(p); - } - } - - Expr::Lit(Lit::Null(_)) => {} - - _ => {} + // A plain object literal is flattened into the target; any + // other flattenable spread is a no-property primitive + // (including `null`) that contributes nothing, so it is + // simply dropped. + if let Expr::Object(ObjectLit { props, .. }) = *expr { + new_props.extend(props); } } @@ -709,7 +726,7 @@ impl Pure<'_> { res.push_wtf8(&s.value); } Expr::Lit(Lit::Num(n)) => { - write!(res, "{}", n.value).unwrap(); + res.push_str(&n.value.to_js_string()); } e if is_pure_undefined(self.expr_ctx, e) => {} Expr::Lit(Lit::Null(..)) => {} @@ -901,7 +918,7 @@ impl Pure<'_> { for literal in literals.iter() { match &*literal.expr { Expr::Lit(Lit::Str(s)) => joined.push_wtf8(&s.value), - Expr::Lit(Lit::Num(n)) => write!(joined, "{}", n.value).unwrap(), + Expr::Lit(Lit::Num(n)) => joined.push_str(&n.value.to_js_string()), Expr::Lit(Lit::Null(..)) => { // For string concatenation, null becomes // empty string @@ -957,7 +974,7 @@ impl Pure<'_> { match &*literal.expr { Expr::Lit(Lit::Str(s)) => joined.push_wtf8(&s.value), - Expr::Lit(Lit::Num(n)) => write!(joined, "{}", n.value).unwrap(), + Expr::Lit(Lit::Num(n)) => joined.push_str(&n.value.to_js_string()), Expr::Lit(Lit::Null(..)) => { // null becomes empty string } @@ -1137,17 +1154,19 @@ impl Pure<'_> { if let ExprOrSpread { spread: None, expr } = &args[0] { match &**expr { Expr::Lit(Lit::Num(num)) => { - if num.value <= 5_f64 && num.value >= 0_f64 { - Some( - ArrayLit { - span: *span, - elems: vec![None; num.value as usize], - } - .into(), - ) - } else { - None + let length = num.value; + + if !(0_f64..=5_f64).contains(&length) || length.fract() != 0_f64 { + return None; } + + Some( + ArrayLit { + span: *span, + elems: vec![None; length as usize], + } + .into(), + ) } Expr::Lit(_) => Some( ArrayLit { @@ -2230,12 +2249,12 @@ impl Pure<'_> { } } Expr::Arrow(callee) => match &mut *callee.body { - BlockStmtOrExpr::BlockStmt(body) => { + ArrowFunctionBody::FunctionBody(body) => { for stmt in &mut body.stmts { self.ignore_return_value_of_return_stmt(stmt, opts); } } - BlockStmtOrExpr::Expr(body) => { + ArrowFunctionBody::Expr(body) => { self.ignore_return_value(body, opts); if body.is_invalid() { diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/mod.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/mod.rs index e5c1faf74..b0614a125 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/mod.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/mod.rs @@ -400,19 +400,19 @@ impl VisitMut for Pure<'_> { } } - fn visit_mut_block_stmt_or_expr(&mut self, body: &mut BlockStmtOrExpr) { + fn visit_mut_arrow_function_body(&mut self, body: &mut ArrowFunctionBody) { body.visit_mut_children_with(self); match body { - BlockStmtOrExpr::BlockStmt(b) => self.optimize_fn_stmts(&mut b.stmts), - BlockStmtOrExpr::Expr(_) => {} + ArrowFunctionBody::FunctionBody(b) => self.optimize_fn_stmts(&mut b.stmts), + ArrowFunctionBody::Expr(_) => {} #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), } self.optimize_arrow_body(body); - if let BlockStmtOrExpr::Expr(e) = body { + if let ArrowFunctionBody::Expr(e) = body { if self::bools::may_make_bool_short(e) { self.make_bool_short(e, false, false); } diff --git a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/vars.rs b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/vars.rs index 71e3c3f12..7a7f76c8a 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/compress/pure/vars.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/compress/pure/vars.rs @@ -314,10 +314,6 @@ impl Visit for VarWithOutInitCounter { fn visit_function(&mut self, _: &Function) {} - fn visit_getter_prop(&mut self, _: &GetterProp) {} - - fn visit_setter_prop(&mut self, _: &SetterProp) {} - fn visit_expr(&mut self, _: &Expr) {} fn visit_pat(&mut self, n: &Pat) { @@ -445,8 +441,6 @@ impl VisitMut for VarMover { /// Noop fn visit_mut_function(&mut self, _: &mut Function) {} - fn visit_mut_getter_prop(&mut self, _: &mut GetterProp) {} - fn visit_mut_module_decl(&mut self, _: &mut ModuleDecl) {} fn visit_mut_module_item(&mut self, s: &mut ModuleItem) { @@ -465,8 +459,6 @@ impl VisitMut for VarMover { } } - fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) {} - fn visit_mut_stmt(&mut self, s: &mut Stmt) { s.visit_mut_children_with(self); @@ -560,10 +552,6 @@ impl VisitMut for VarPrepender { /// Noop fn visit_mut_function(&mut self, _: &mut Function) {} - fn visit_mut_getter_prop(&mut self, _: &mut GetterProp) {} - - fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) {} - fn visit_mut_block_stmt(&mut self, n: &mut BlockStmt) { if self.target != VarDeclKind::Var { // noop diff --git a/deps/swc/crates/swc_ecma_minifier/src/eval.rs b/deps/swc/crates/swc_ecma_minifier/src/eval.rs index ecae2b90e..facceeb41 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/eval.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/eval.rs @@ -12,6 +12,7 @@ use crate::{ mode::Mode, option::{CompressOptions, TopLevelOptions}, usage_analyzer::marks::Marks, + util::is_falsy_number, }; pub struct Evaluator { @@ -313,7 +314,7 @@ fn is_truthy(lit: &EvalResult) -> Option { Lit::Str(v) => Some(!v.value.is_empty()), Lit::Bool(v) => Some(v.value), Lit::Null(_) => Some(false), - Lit::Num(v) => Some(v.value != 0.0 && v.value != -0.0), + Lit::Num(v) => Some(!is_falsy_number(v.value)), _ => None, }, EvalResult::Undefined => Some(false), diff --git a/deps/swc/crates/swc_ecma_minifier/src/pass/mangle_names/preserver.rs b/deps/swc/crates/swc_ecma_minifier/src/pass/mangle_names/preserver.rs index ff61d0e74..1be42028d 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/pass/mangle_names/preserver.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/pass/mangle_names/preserver.rs @@ -83,6 +83,15 @@ impl Preserver<'_> { self.idents.push(ident.to_id()); } + + fn visit_non_top_level_stmts(&mut self, stmts: &[Stmt]) { + let old_top_level = self.in_top_level; + for stmt in stmts { + self.in_top_level = false; + stmt.visit_with(self); + } + self.in_top_level = old_top_level; + } } impl Visit for Preserver<'_> { @@ -91,12 +100,11 @@ impl Visit for Preserver<'_> { visit_obj_and_computed!(); fn visit_block_stmt(&mut self, n: &BlockStmt) { - let old_top_level = self.in_top_level; - for n in n.stmts.iter() { - self.in_top_level = false; - n.visit_with(self); - } - self.in_top_level = old_top_level; + self.visit_non_top_level_stmts(&n.stmts); + } + + fn visit_function_body(&mut self, n: &FunctionBody) { + self.visit_non_top_level_stmts(&n.stmts); } fn visit_catch_clause(&mut self, n: &CatchClause) { diff --git a/deps/swc/crates/swc_ecma_minifier/src/program_data.rs b/deps/swc/crates/swc_ecma_minifier/src/program_data.rs index 9cf6051c2..eef6b3d61 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/program_data.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/program_data.rs @@ -42,8 +42,6 @@ pub(crate) struct ProgramData { initialized_vars: IndexSet, - pub(crate) top: ScopeData, - scopes: Vec, pub(crate) property_atoms: Option>, @@ -214,10 +212,6 @@ impl Storage for ProgramData { &self.scopes } - fn top_scope(&mut self) -> &mut Self::ScopeData { - &mut self.top - } - fn var_or_default(&mut self, id: Id) -> &mut Self::VarData { self.vars.entry(id).or_default() } diff --git a/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/alias/mod.rs b/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/alias/mod.rs index a2f2224b8..1ef2eadb1 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/alias/mod.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/alias/mod.rs @@ -295,7 +295,7 @@ impl Visit for InfectionCollector { match e { Expr::Ident(i) => { - if self.ctx.contains(Ctx::TrackExprIdent) { + if self.ctx.contains(Ctx::TrackExprIdent) || self.config.need_all { self.add_usage(i.to_id()); } } @@ -340,14 +340,12 @@ impl Visit for InfectionCollector { fn visit_member_expr(&mut self, n: &MemberExpr) { { - let mut ctx = self.ctx; - ctx.set(Ctx::TrackExprIdent, self.config.need_all); + let ctx = self.ctx - Ctx::TrackExprIdent; n.obj.visit_with(&mut *self.with_ctx(ctx)); } { - let mut ctx = self.ctx; - ctx.set(Ctx::TrackExprIdent, self.config.need_all); + let ctx = self.ctx - Ctx::TrackExprIdent; n.prop.visit_with(&mut *self.with_ctx(ctx)); } } diff --git a/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/analyzer/mod.rs b/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/analyzer/mod.rs index 00fc30bd3..678a4f5d3 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/analyzer/mod.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/analyzer/mod.rs @@ -44,8 +44,13 @@ where top_scope.merge(scope.clone(), true); } - v.data.top_scope().merge(top_scope.clone(), false); - v.data.scope(SyntaxContext::empty()).merge(top_scope, false); + v.data + .scope( + marks + .map(|m| m.top_level_ctxt) + .unwrap_or(SyntaxContext::empty()), + ) + .merge(top_scope, false); v.data } @@ -225,6 +230,68 @@ where }); } } + + fn store_function_arity(&mut self, id: Id, function: &Function) { + let scope = self.data.scope(function.ctxt); + + let known = !scope.used_arguments() + && !scope.used_eval() + && !function.params.iter().any(|p| p.pat.is_rest()); + + let arity = if known { + Self::param_count_to_value(function.params.len()) + } else { + Value::Unknown + }; + + self.data.var_or_default(id).store_param_count(arity); + } + + fn store_arrow_arity(&mut self, id: Id, arrow: &ArrowExpr) { + let scope = self.data.scope(arrow.ctxt); + let known = !scope.used_eval() && !arrow.params.iter().any(|p| p.is_rest()); + + let arity = if known { + Self::param_count_to_value(arrow.params.len()) + } else { + Value::Unknown + }; + + self.data.var_or_default(id).store_param_count(arity); + } + + fn store_class_arity(&mut self, id: Id, class: &Class) { + let constructor = class + .body + .iter() + .filter_map(|s| s.as_constructor()) + .find(|c| c.body.is_some()); + + let arity = if let Some(c) = constructor { + let scope = self.data.scope(c.ctxt); + let known = !scope.used_arguments() + && !scope.used_eval() + && !c + .params + .iter() + .filter_map(|p| p.as_param()) + .any(|p| p.pat.is_rest()); + + if known { + Self::param_count_to_value(c.params.len()) + } else { + Value::Unknown + } + } else { + if class.super_class.is_some() { + Value::Unknown + } else { + Value::Known(0) + } + }; + + self.data.var_or_default(id).store_param_count(arity); + } } impl Visit for UsageAnalyzer @@ -252,16 +319,7 @@ where n.params.visit_with(&mut *child.with_ctx(ctx)); } - match &*n.body { - BlockStmtOrExpr::BlockStmt(body) => { - body.visit_with(child); - } - BlockStmtOrExpr::Expr(body) => { - body.visit_with(child); - } - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } + n.body.visit_with(child); }) } @@ -337,28 +395,13 @@ where if let (Some(id), op!("=")) = (&n.left.as_ident(), n.op) { match &*n.right { Expr::Fn(n) => { - let scope = self.data.scope(n.function.ctxt); - let known = !scope.used_arguments() - && !scope.used_eval() - && !n.function.params.iter().any(|p| p.pat.is_rest()); - let data = self.data.var_or_default(id.id.to_id()); - - if known { - data.store_param_count(Self::param_count_to_value(n.function.params.len())); - } else { - data.store_param_count(Value::Unknown); - } + self.store_function_arity(id.id.to_id(), &n.function); } Expr::Arrow(n) => { - let scope = self.data.scope(n.ctxt); - let known = !scope.used_eval() && !n.params.iter().any(|p| p.is_rest()); - let data = self.data.var_or_default(id.id.to_id()); - - if known { - data.store_param_count(Self::param_count_to_value(n.params.len())); - } else { - data.store_param_count(Value::Unknown) - } + self.store_arrow_arity(id.id.to_id(), n); + } + Expr::Class(c) => { + self.store_class_arity(id.id.to_id(), &c.class); } _ => self .data @@ -609,6 +652,8 @@ where .insert(id.clone(), RecursiveUsage::FnOrClass); n.visit_children_with(self); + self.store_class_arity(n.ident.to_id(), &n.class); + self.used_recursively.remove(&id); } @@ -700,10 +745,7 @@ where n.params.visit_with(&mut *child.with_ctx(ctx)); } - // Bypass visit_block_stmt - if let Some(body) = &n.body { - body.visit_with(child); - } + n.body.visit_with(child); }) } @@ -875,18 +917,7 @@ where } } - let scope = self.data.scope(n.function.ctxt); - let known = !scope.used_arguments() - && !scope.used_eval() - && !n.function.params.iter().any(|p| p.pat.is_rest()); - - let data = self.data.var_or_default(n.ident.to_id()); - - if known { - data.store_param_count(Self::param_count_to_value(n.function.params.len())); - } else { - data.store_param_count(Value::Unknown); - } + self.store_function_arity(id, &n.function); } #[cfg_attr( @@ -1016,30 +1047,10 @@ where .with_child(n.ctxt, ScopeKind::Fn { is_arrow: false }, |child| { n.params.visit_with(child); - if let Some(body) = &n.body { - // We use visit_children_with instead of visit_with to bypass block scope - // handler. - body.visit_children_with(child); - } + n.body.visit_with(child); }) } - #[cfg_attr( - all(debug_assertions, feature = "tracing-spans"), - tracing::instrument(level = "debug", skip_all) - )] - fn visit_getter_prop(&mut self, n: &GetterProp) { - self.with_child( - SyntaxContext::empty(), - ScopeKind::Fn { is_arrow: false }, - |a| { - n.key.visit_with(a); - - n.body.visit_with(a); - }, - ); - } - #[cfg_attr( all(debug_assertions, feature = "tracing-spans"), tracing::instrument(level = "debug", skip_all) @@ -1302,26 +1313,6 @@ where n.visit_children_with(&mut *self.with_ctx(ctx)) } - #[cfg_attr( - all(debug_assertions, feature = "tracing-spans"), - tracing::instrument(level = "debug", skip_all) - )] - fn visit_setter_prop(&mut self, n: &SetterProp) { - self.with_child( - SyntaxContext::empty(), - ScopeKind::Fn { is_arrow: false }, - |a| { - n.key.visit_with(a); - { - let ctx = a.ctx.with(BitContext::InPatOfParam, true); - n.param.visit_with(&mut *a.with_ctx(ctx)); - } - - n.body.visit_with(a); - }, - ); - } - #[cfg_attr( all(debug_assertions, feature = "tracing-spans"), tracing::instrument(level = "debug", skip_all) @@ -1389,18 +1380,20 @@ where fn visit_switch_stmt(&mut self, n: &SwitchStmt) { n.discriminant.visit_with(self); - let mut fallthrough = false; + self.with_child(n.body_ctxt, ScopeKind::Block, |child| { + let mut fallthrough = false; - for case in n.cases.iter() { - let ctx = self.ctx.with(BitContext::InCond, true); - if fallthrough { - self.with_ctx(ctx).visit_in_cond(&case.test); - self.with_ctx(ctx).visit_in_cond(&case.cons); - } else { - self.with_ctx(ctx).visit_in_cond(case); + for case in n.cases.iter() { + let ctx = child.ctx.with(BitContext::InCond, true); + if fallthrough { + child.with_ctx(ctx).visit_in_cond(&case.test); + child.with_ctx(ctx).visit_in_cond(&case.cons); + } else { + child.with_ctx(ctx).visit_in_cond(case); + } + fallthrough = !case.cons.iter().rev().any(|s| s.terminates()) } - fallthrough = !case.cons.iter().rev().any(|s| s.terminates()) - } + }) } #[cfg_attr( @@ -1498,30 +1491,13 @@ where match init { Expr::Fn(n) => { - let scope = self.data.scope(n.function.ctxt); - let known = !scope.used_arguments() - && !scope.used_eval() - && !n.function.params.iter().any(|p| p.pat.is_rest()); - let data = self.data.var_or_default(var.id.to_id()); - - if known { - data.store_param_count(Self::param_count_to_value( - n.function.params.len(), - )); - } else { - data.store_param_count(Value::Unknown); - } + self.store_function_arity(var.id.to_id(), &n.function); } Expr::Arrow(n) => { - let scope = self.data.scope(n.ctxt); - let known = !scope.used_eval() && !n.params.iter().any(|p| p.is_rest()); - let data = self.data.var_or_default(var.id.to_id()); - - if known { - data.store_param_count(Self::param_count_to_value(n.params.len())); - } else { - data.store_param_count(Value::Unknown) - } + self.store_arrow_arity(var.id.to_id(), n); + } + Expr::Class(c) => { + self.store_class_arity(var.id.to_id(), &c.class); } _ => self .data @@ -1696,15 +1672,13 @@ fn for_each_id_ref_in_expr(e: &Expr, op: &mut impl FnMut(&Ident)) { for_each_id_ref_in_expr(&p.value, op); } Prop::Getter(p) => { - for_each_id_ref_in_prop_name(&p.key, op); + for_each_id_ref_in_prop_function(&p.key, &p.function, op); } Prop::Setter(p) => { - for_each_id_ref_in_prop_name(&p.key, op); - - for_each_id_ref_in_pat(&p.param, op); + for_each_id_ref_in_prop_function(&p.key, &p.function, op); } Prop::Method(p) => { - for_each_id_ref_in_fn(&p.function, op); + for_each_id_ref_in_prop_function(&p.key, &p.function, op); } #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), @@ -1778,6 +1752,15 @@ fn for_each_id_ref_in_prop_name(p: &PropName, op: &mut impl FnMut(&Ident)) { } } +fn for_each_id_ref_in_prop_function( + key: &PropName, + function: &Function, + op: &mut impl FnMut(&Ident), +) { + for_each_id_ref_in_prop_name(key, op); + for_each_id_ref_in_fn(function, op); +} + fn for_each_id_ref_in_pat(p: &Pat, op: &mut impl FnMut(&Ident)) { match p { Pat::Ident(..) => { diff --git a/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/analyzer/storage.rs b/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/analyzer/storage.rs index 24d03d7fe..61210081e 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/analyzer/storage.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/usage_analyzer/analyzer/storage.rs @@ -18,8 +18,6 @@ pub trait Storage: Sized { fn scopes(&self) -> &[Self::ScopeData]; - fn top_scope(&mut self) -> &mut Self::ScopeData; - fn var_or_default(&mut self, id: Id) -> &mut Self::VarData; fn merge(&mut self, kind: ScopeKind, child: Self); diff --git a/deps/swc/crates/swc_ecma_minifier/src/util/mod.rs b/deps/swc/crates/swc_ecma_minifier/src/util/mod.rs index 5692d8682..4e4b277c8 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/util/mod.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/util/mod.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use std::time::Instant; +use std::{num::FpCategory, time::Instant}; use rustc_hash::FxHashSet; use swc_atoms::Atom; @@ -14,6 +14,12 @@ pub(crate) mod base54; pub(crate) mod size; pub(crate) mod sort; +/// Returns whether a number is falsy according to ECMAScript semantics. +#[inline] +pub(crate) fn is_falsy_number(value: f64) -> bool { + matches!(value.classify(), FpCategory::Zero | FpCategory::Nan) +} + pub(crate) fn make_number(span: Span, value: f64) -> Expr { trace_op!("Creating a numeric literal"); Lit::Num(Number { @@ -260,10 +266,6 @@ impl Visit for LeapFinder { fn visit_function(&mut self, _: &Function) {} - fn visit_getter_prop(&mut self, _: &GetterProp) {} - - fn visit_setter_prop(&mut self, _: &SetterProp) {} - fn visit_yield_expr(&mut self, n: &YieldExpr) { n.visit_children_with(self); @@ -361,7 +363,7 @@ impl Visit for IdentUsageCollector { n.visit_children_with(self); } - fn visit_block_stmt_or_expr(&mut self, n: &BlockStmtOrExpr) { + fn visit_arrow_function_body(&mut self, n: &ArrowFunctionBody) { if self.ignore_nested { return; } @@ -385,22 +387,6 @@ impl Visit for IdentUsageCollector { n.visit_children_with(self); } - fn visit_getter_prop(&mut self, n: &GetterProp) { - if self.ignore_nested { - return; - } - - n.visit_children_with(self); - } - - fn visit_setter_prop(&mut self, n: &SetterProp) { - if self.ignore_nested { - return; - } - - n.visit_children_with(self); - } - fn visit_ident(&mut self, n: &Ident) { self.ids.insert(n.to_id()); } @@ -434,7 +420,7 @@ impl Visit for CapturedIdCollector { n.visit_children_with(self); } - fn visit_block_stmt_or_expr(&mut self, n: &BlockStmtOrExpr) { + fn visit_arrow_function_body(&mut self, n: &ArrowFunctionBody) { let old = self.is_nested; self.is_nested = true; n.visit_children_with(self); diff --git a/deps/swc/crates/swc_ecma_minifier/src/util/size.rs b/deps/swc/crates/swc_ecma_minifier/src/util/size.rs index e34cb2165..8e8541996 100644 --- a/deps/swc/crates/swc_ecma_minifier/src/util/size.rs +++ b/deps/swc/crates/swc_ecma_minifier/src/util/size.rs @@ -160,8 +160,8 @@ impl SizeWithCtxt for Expr { is_async, .. }) => match &**body { - BlockStmtOrExpr::BlockStmt(_) => TODO, - BlockStmtOrExpr::Expr(e) => { + ArrowFunctionBody::FunctionBody(_) => TODO, + ArrowFunctionBody::Expr(e) => { let p = match ¶ms[..] { [] => 2, [Pat::Ident(_)] => 1, diff --git a/deps/swc/crates/swc_ecma_parser/Cargo.toml b/deps/swc/crates/swc_ecma_parser/Cargo.toml index f500368c3..090de6900 100644 --- a/deps/swc/crates/swc_ecma_parser/Cargo.toml +++ b/deps/swc/crates/swc_ecma_parser/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "examples/**/*.rs"] license = { workspace = true } name = "swc_ecma_parser" repository = { workspace = true } -version = "41.1.2" +version = "45.0.0" [package.metadata.docs.rs] all-features = true @@ -31,17 +31,17 @@ verify = ["swc_ecma_visit"] [dependencies] bitflags = { workspace = true } +compact_str = { workspace = true } either = { workspace = true } num-bigint = { workspace = true } phf = { workspace = true, features = ["macros"] } rustc-hash = { workspace = true } seq-macro = { workspace = true } serde = { workspace = true, features = ["derive"] } -smartstring = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit", optional = true } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit", optional = true } tracing = { workspace = true } [target.'cfg(not(any(target_arch = "wasm32", target_arch = "arm")))'.dependencies] @@ -55,13 +55,13 @@ walkdir = { workspace = true } cbor4ii = { workspace = true, features = ["use_std"] } codspeed-criterion-compat = { workspace = true } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast", features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast", features = [ "serde-impl", "encoding-impl", ] } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } [[example]] name = "typescript" diff --git a/deps/swc/crates/swc_ecma_parser/src/error.rs b/deps/swc/crates/swc_ecma_parser/src/error.rs index 327936244..d6ab363a0 100644 --- a/deps/swc/crates/swc_ecma_parser/src/error.rs +++ b/deps/swc/crates/swc_ecma_parser/src/error.rs @@ -276,6 +276,7 @@ pub enum SyntaxError { TS2483, TS2491, TS2499, + TS2680, TS2703, TS4112, TS8038, @@ -713,6 +714,7 @@ impl SyntaxError { SyntaxError::TS2499 => "An interface can only extend an identifier/qualified-name \ with optional type arguments." .into(), + SyntaxError::TS2680 => "A 'this' parameter must be the first parameter.".into(), SyntaxError::TS4112 => "This member cannot have an 'override' modifier because its \ containing class does not extend another class." .into(), diff --git a/deps/swc/crates/swc_ecma_parser/src/legacy.rs b/deps/swc/crates/swc_ecma_parser/src/legacy.rs index 3b8944ea0..7f973de7f 100644 --- a/deps/swc/crates/swc_ecma_parser/src/legacy.rs +++ b/deps/swc/crates/swc_ecma_parser/src/legacy.rs @@ -295,7 +295,7 @@ pub mod token { name: Atom, }, JSXText { - value: Atom, + value: Wtf8Atom, raw: Atom, }, JSXTagStart, diff --git a/deps/swc/crates/swc_ecma_parser/src/lexer/mod.rs b/deps/swc/crates/swc_ecma_parser/src/lexer/mod.rs index 4d89c450e..dde9403af 100644 --- a/deps/swc/crates/swc_ecma_parser/src/lexer/mod.rs +++ b/deps/swc/crates/swc_ecma_parser/src/lexer/mod.rs @@ -2,12 +2,12 @@ use std::{borrow::Cow, char, rc::Rc}; +use compact_str::CompactString; use either::Either::{self, Left, Right}; use rustc_hash::FxHashMap; -use smartstring::{LazyCompact, SmartString}; use swc_atoms::{ wtf8::{CodePoint, Wtf8, Wtf8Buf}, - Atom, AtomStoreCell, + Atom, AtomStoreCell, Wtf8Atom, }; use swc_common::{ comments::{Comment, CommentKind, Comments}, @@ -1364,17 +1364,19 @@ impl<'a> Lexer<'a> { } } - fn read_jsx_entity(&mut self) -> LexResult<(char, String)> { + fn read_jsx_entity(&mut self) -> LexResult<(Wtf8Atom, String)> { debug_assert!(self.syntax().jsx()); - fn from_code(s: &str, radix: u32) -> LexResult { - // TODO(kdy1): unwrap -> Err - let c = char::from_u32( - u32::from_str_radix(s, radix).expect("failed to parse string as number"), - ) - .expect("failed to parse number as char"); + fn parse_from_code(lexer: &mut Lexer, s: &str, radix: u32) -> Option { + let num = match u32::from_str_radix(s, radix) { + Ok(num) if num <= 0x10ffff => num, + _ => { + lexer.emit_error(lexer.input.cur_pos(), SyntaxError::InvalidJSXValue); + return None; + } + }; - Ok(c) + Some(num) } fn is_hex(s: &str) -> bool { @@ -1385,49 +1387,96 @@ impl<'a> Lexer<'a> { s.chars().all(|c| c.is_ascii_digit()) } - let mut s = SmartString::::default(); + let mut s = CompactString::default(); debug_assert!(self.input().cur().is_some_and(|c| c == b'&')); self.bump(1); // `&` let start_pos = self.input().cur_pos(); - - for _ in 0..10 { + let mut buf = Wtf8Buf::with_capacity(8); + let mut raw = String::new(); + const NO_PREV_RESULT: u32 = 0xdc00; + let mut prev_result: u32 = NO_PREV_RESULT; + for _ in 0..20 { let c = match self.input().cur() { Some(c) => c, None => break, }; self.bump(1); // `c` is u8 - if c == b';' { - if let Some(stripped) = s.strip_prefix('#') { - if stripped.starts_with('x') { - if is_hex(&s[2..]) { - let value = from_code(&s[2..], 16)?; + if c != b';' { + s.push(c as char); + continue; + } + if let Some(stripped) = s.strip_prefix('#') { + let mut result: u32; + if stripped.starts_with('x') { + if is_hex(&s[2..]) { + result = parse_from_code(self, &s[2..], 16).unwrap(); + } else { + return Ok((Wtf8Atom::from(format!("&{s};")), format!("&{s};"))); + } + } else if is_dec(stripped) { + result = parse_from_code(self, stripped, 10).unwrap(); + } else { + return Ok((Wtf8Atom::from(format!("&{s};")), format!("&{s};"))); + } - return Ok((value, format!("&{s};"))); + if (0xd800..=0xdfff).contains(&result) { + if result < 0xdc00 { + if prev_result != NO_PREV_RESULT { + // If the previous result is a high surrogate + // We can be sure `prev_result` is less than 0xdc00 + buf.push_str(format!("&#x{prev_result:04X};").as_str()); } - } else if is_dec(stripped) { - let value = from_code(stripped, 10)?; - - return Ok((value, format!("&{s};"))); + if self.input().cur() == Some(b'&') && self.input().peek() == Some(b'#') { + self.bump(1); // `&` + + // wait for the next surrogate + prev_result = result; + raw.push_str(format!("&{s};").as_str()); + s.clear(); + continue; + } else { + // Safety: result is a valid Unicode code point + buf.push(unsafe { CodePoint::from_u32_unchecked(result) }); + return Ok((Wtf8Atom::from(buf), format!("&{s};"))); + } + } else if prev_result != NO_PREV_RESULT { + // Low surrogate pair + // Decode to supplementary plane code point + // (0x10000-0x10FFFF) + result = 0x10000 + ((result & 0x3ff) | ((prev_result & 0x3ff) << 10)); + // Safety: result is a valid Unicode code point + buf.push(unsafe { CodePoint::from_u32_unchecked(result) }); + raw.push_str(format!("&{s};").as_str()); + return Ok((Wtf8Atom::from(buf), raw)); + } + } else { + if prev_result != NO_PREV_RESULT { + buf.push(unsafe { CodePoint::from_u32_unchecked(prev_result) }); + raw.push_str(format!("&{s};").as_str()); } - } else if let Some(entity) = xhtml(&s) { - return Ok((entity, format!("&{s};"))); + // Safety: result is a valid Unicode code point + buf.push(unsafe { CodePoint::from_u32_unchecked(result) }); + return Ok((Wtf8Atom::from(buf), format!("&{s};"))); } - - break; + // Maybe prev_result here but ignore it follow babel behavior + // Safety: result is a valid Unicode code point + buf.push(unsafe { CodePoint::from_u32_unchecked(result) }); + return Ok((Wtf8Atom::from(buf), format!("&{s};"))); + } else if let Some(entity) = xhtml(&s) { + return Ok((Wtf8Atom::from(entity.to_string()), format!("&{s};"))); } - - s.push(c as char) } unsafe { // Safety: start_pos is a valid position because we got it from self.input self.input_mut().reset_to(start_pos); } + buf.push_char('&'); - Ok(('&', "&".to_string())) + Ok((Wtf8Atom::from(buf), "&".to_string())) } fn read_jsx_new_line(&mut self, normalize_crlf: bool) -> LexResult> { @@ -1448,7 +1497,7 @@ impl<'a> Lexer<'a> { debug_assert!(self.syntax().jsx()); let start = self.input().cur_pos(); self.bump(1); // `quote` - let mut out = String::new(); + let mut buf: Wtf8Buf = Wtf8Buf::new(); let mut chunk_start = self.input().cur_pos(); loop { let ch = match self.input().cur_as_char() { @@ -1465,8 +1514,8 @@ impl<'a> Lexer<'a> { self.input_slice_str(chunk_start, cur_pos) }; - out.push_str(value); - out.push('\\'); + buf.push_str(value); + buf.push_char('\\'); self.bump(1); // ch == '\\' @@ -1485,11 +1534,11 @@ impl<'a> Lexer<'a> { self.input_slice_str(chunk_start, cur_pos) }; - out.push_str(value); + buf.push_str(value); let jsx_entity = self.read_jsx_entity()?; - out.push(jsx_entity.0); + buf.push_wtf8(&jsx_entity.0); chunk_start = self.input().cur_pos(); } else if ch.is_line_terminator() { @@ -1498,14 +1547,14 @@ impl<'a> Lexer<'a> { self.input_slice_str(chunk_start, cur_pos) }; - out.push_str(value); + buf.push_str(value); match self.read_jsx_new_line(false)? { Either::Left(s) => { - out.push_str(s); + buf.push_str(s); } Either::Right(c) => { - out.push(c); + buf.push_char(c); } } @@ -1518,12 +1567,11 @@ impl<'a> Lexer<'a> { // Safety: We already checked for the range self.input_slice_str(chunk_start, self.cur_pos()) }; - let value = if out.is_empty() { - // Fast path: We don't need to allocate - self.atom(s) + let value = if buf.is_empty() { + self.wtf8_atom(Wtf8::from_str(s)) } else { - out.push_str(s); - self.atom(out) + buf.push_str(s); + self.wtf8_atom(&*buf) }; // it might be at the end of the file when @@ -1532,7 +1580,7 @@ impl<'a> Lexer<'a> { self.bump(1); } - Ok(Token::str(value.into(), self)) + Ok(Token::str(value, self)) } // Modified based on diff --git a/deps/swc/crates/swc_ecma_parser/src/lexer/state.rs b/deps/swc/crates/swc_ecma_parser/src/lexer/state.rs index 5ec5eb097..82e45fc2f 100644 --- a/deps/swc/crates/swc_ecma_parser/src/lexer/state.rs +++ b/deps/swc/crates/swc_ecma_parser/src/lexer/state.rs @@ -1,6 +1,9 @@ use std::mem::take; -use swc_atoms::{wtf8::CodePoint, Atom}; +use swc_atoms::{ + wtf8::{CodePoint, Wtf8, Wtf8Buf}, + Wtf8Atom, +}; use swc_common::{BytePos, Span}; use swc_ecma_ast::EsVersion; @@ -499,7 +502,7 @@ impl Lexer<'_> { self.input_slice_str(start, self.cur_pos()) }; - let value = self.atom(s); + let value = self.wtf8_atom(Wtf8::from_str(s)); self.state.set_token_value(TokenValue::JsxText(value)); return Ok(Token::JSXText); }, @@ -511,7 +514,7 @@ impl Lexer<'_> { self.input_slice_str(start, self.cur_pos()) }; - let value = self.atom(s); + let value = self.wtf8_atom(Wtf8::from_str(s)); self.state.set_token_value(TokenValue::JsxText(value)); Ok(Token::JSXText) } @@ -523,7 +526,7 @@ impl Lexer<'_> { /// Slow path: we encountered `&` in the jsx child, so we need to scan and /// resolve the jsx entity, which requires a dedicated string allocation. fn scan_jsx_token_with_jsx_entity(&mut self) -> LexResult { - let mut value = String::new(); + let mut buf = Wtf8Buf::new(); let mut chunk_start = self.input.cur_pos(); while let Some(ch) = self.input.cur_as_char() { @@ -556,13 +559,12 @@ impl Lexer<'_> { // Safety: We already checked for the range self.input_slice_str(chunk_start, self.cur_pos()) }; - value.push_str(s); + buf.push_str(s); // Read the jsx entity and update the start of chunk - if let Ok(jsx_entity) = self.read_jsx_entity() { - value.push(jsx_entity.0); - chunk_start = self.input.cur_pos(); - } + let jsx_entity = self.read_jsx_entity()?; + buf.push_wtf8(&jsx_entity.0); + chunk_start = self.input.cur_pos(); } '<' | '{' => break, c => { @@ -577,8 +579,8 @@ impl Lexer<'_> { self.input_slice_str(chunk_start, self.cur_pos()) }; - value.push_str(s); - let value = Atom::new(value); + buf.push_str(s); + let value = Wtf8Atom::new(buf); self.state.set_token_value(TokenValue::JsxText(value)); Ok(Token::JSXText) } diff --git a/deps/swc/crates/swc_ecma_parser/src/lexer/token.rs b/deps/swc/crates/swc_ecma_parser/src/lexer/token.rs index d19cb13b2..1dd5ce091 100644 --- a/deps/swc/crates/swc_ecma_parser/src/lexer/token.rs +++ b/deps/swc/crates/swc_ecma_parser/src/lexer/token.rs @@ -19,7 +19,7 @@ pub enum TokenValue { // string Str(Wtf8Atom), // jsx text - JsxText(Atom), + JsxText(Wtf8Atom), // regexp Regex(BytePos), Num(f64), diff --git a/deps/swc/crates/swc_ecma_parser/src/parser/class_and_fn.rs b/deps/swc/crates/swc_ecma_parser/src/parser/class_and_fn.rs index bb4915dc7..497d9c9a7 100644 --- a/deps/swc/crates/swc_ecma_parser/src/parser/class_and_fn.rs +++ b/deps/swc/crates/swc_ecma_parser/src/parser/class_and_fn.rs @@ -29,6 +29,70 @@ struct MakeMethodArgs { is_generator: bool, } +/// Parses a leading TypeScript or Flow `this` parameter directly into its +/// dedicated AST node. Invalid optional markers and initializers are recovered +/// here so the `this` parameter never enters the ordinary parameter list. +fn parse_ts_this_param(p: &mut Parser) -> PResult>> { + if !p.syntax().typescript() || !p.input().is(Token::This) { + return Ok(None); + } + + let start = p.cur_pos(); + let this_span = p.input().cur_span(); + let is_flow = p.syntax().flow(); + p.bump(); + + let is_optional = p.input_mut().eat(Token::QuestionMark); + if is_optional { + let error = if is_flow { + SyntaxError::TS1003 + } else { + SyntaxError::Expected(",".into(), "?".into()) + }; + p.emit_err(p.input().prev_span(), error); + } + + let type_ann = p.try_parse_ts_type_ann()?; + if is_flow + && type_ann.is_none() + && !p.ctx().contains(Context::InType) + && !p.ctx().contains(Context::InDeclare) + { + p.emit_err(this_span, SyntaxError::TS1003); + } + + let span = p.span(start); + if p.input_mut().eat(Token::Eq) { + if !is_optional { + let error = if is_flow { + SyntaxError::TS1003 + } else { + SyntaxError::Expected(",".into(), "=".into()) + }; + p.emit_err(p.input().prev_span(), error); + } + p.allow_in_expr(|p| p.parse_assignment_expr())?; + } + + if !p.input().is(Token::RParen) { + expect!(p, Token::Comma); + if p.input().is(Token::This) { + let error = if is_flow { + SyntaxError::TS1003 + } else { + SyntaxError::TS2680 + }; + p.emit_err(p.input().cur_span(), error); + } + } + + Ok(Some(Box::new(TsThisParam { + span, + this_span, + type_ann, + }))) +} + impl Parser { /// If `required` is `true`, this never returns `None`. fn parse_maybe_opt_binding_ident( @@ -299,14 +363,19 @@ impl Parser { expect!(p, Token::LParen); let parse_args_with_generator_ctx = |p: &mut Self| { + let parse_this_and_args = |p: &mut Self| { + let this_param = parse_ts_this_param(p)?; + parse_args(p).map(|params| (this_param, params)) + }; + if is_generator { - p.do_inside_of_context(Context::InGenerator, parse_args) + p.do_inside_of_context(Context::InGenerator, parse_this_and_args) } else { - p.do_outside_of_context(Context::InGenerator, parse_args) + p.do_outside_of_context(Context::InGenerator, parse_this_and_args) } }; - let params = p.do_inside_of_context(Context::InParameters, |p| { + let (this_param, params) = p.do_inside_of_context(Context::InParameters, |p| { p.do_outside_of_context(Context::InFunction, |p| { if is_async { p.do_inside_of_context(Context::InAsync, parse_args_with_generator_ctx) @@ -370,6 +439,7 @@ impl Parser { Ok(Box::new(Function { span: p.span(start), + this_param, decorators, type_params, params, @@ -581,6 +651,13 @@ impl Parser { }) })?; + if self.syntax().flow() + && matches!(kind, MethodKind::Getter | MethodKind::Setter) + && function.this_param.is_some() + { + self.emit_err(key.span(), SyntaxError::TS1003); + } + match kind { MethodKind::Getter | MethodKind::Setter if self.input().syntax().typescript() @@ -644,7 +721,7 @@ impl Parser { is_generator: bool, is_arrow_function: bool, is_simple_parameter_list: bool, - ) -> PResult> { + ) -> PResult> { self.parse_fn_body( is_async, is_generator, @@ -659,12 +736,14 @@ impl Parser { p.emit_err(span, SyntaxError::IllegalLanguageModeDirective); } } - BlockStmtOrExpr::BlockStmt(block_stmt) + ArrowFunctionBody::FunctionBody(function_body_from_block_stmt( + block_stmt, + )) }) .map(Box::new) } else { p.parse_assignment_expr() - .map(BlockStmtOrExpr::Expr) + .map(ArrowFunctionBody::Expr) .map(Box::new) } }, @@ -735,7 +814,7 @@ impl Parser { is_generator: bool, is_arrow_function: bool, is_simple_parameter_list: bool, - ) -> PResult> { + ) -> PResult> { self.parse_fn_body( is_async, is_generator, @@ -766,7 +845,7 @@ impl Parser { p.emit_err(span, SyntaxError::IllegalLanguageModeDirective); } } - Some(block_stmt) + Some(function_body_from_block_stmt(block_stmt)) }) }, ) @@ -1197,7 +1276,7 @@ impl Parser { let prev_allow_super_call = self.allow_super_call(); self.set_allow_super_call(true); let ctor_sig_and_body = - (|| -> PResult<(Vec, Option)> { + (|| -> PResult<(Vec, Option)> { expect!(self, Token::LParen); let params = self.parse_constructor_params()?; expect!(self, Token::RParen); @@ -1426,7 +1505,7 @@ impl Parser { p.emit_err(key_span, SyntaxError::TS1003); } - if params.iter().any(is_not_this) { + if !params.is_empty() { p.emit_err(key_span, SyntaxError::GetterParam); } @@ -1454,13 +1533,13 @@ impl Parser { p.emit_err(key_span, SyntaxError::TS1003); } - if params.iter().filter(|p| is_not_this(p)).count() != 1 { + if params.len() != 1 { p.emit_err(key_span, SyntaxError::SetterParam); } - if !params.is_empty() { - if let Pat::Rest(..) = params[0].pat { - p.emit_err(params[0].pat.span(), SyntaxError::RestPatInSetter); + if let Some(param) = params.first() { + if let Pat::Rest(..) = param.pat { + p.emit_err(param.pat.span(), SyntaxError::RestPatInSetter); } } @@ -2069,6 +2148,12 @@ impl OutputType for Decl { } } +fn function_body_from_block_stmt(block_stmt: BlockStmt) -> FunctionBody { + let BlockStmt { span, stmts, .. } = block_stmt; + + FunctionBody { span, stmts } +} + fn has_use_strict(block: &BlockStmt) -> Option { block .stmts diff --git a/deps/swc/crates/swc_ecma_parser/src/parser/expr.rs b/deps/swc/crates/swc_ecma_parser/src/parser/expr.rs index a7bdb5cb0..4209d4bd4 100644 --- a/deps/swc/crates/swc_ecma_parser/src/parser/expr.rs +++ b/deps/swc/crates/swc_ecma_parser/src/parser/expr.rs @@ -2578,7 +2578,7 @@ impl Parser { } { let params: Vec = self.parse_paren_items_as_params(items.clone(), None)?; - let body: Box = self.parse_fn_block_or_expr_body( + let body: Box = self.parse_fn_block_or_expr_body( false, false, true, @@ -2663,7 +2663,7 @@ impl Parser { let params: Vec = p.parse_paren_items_as_params(items_ref.clone(), trailing_comma)?; - let body: Box = p.parse_fn_block_or_expr_body( + let body: Box = p.parse_fn_block_or_expr_body( async_span.is_some(), false, true, @@ -2761,7 +2761,7 @@ impl Parser { let params: Vec = self.parse_paren_items_as_params(paren_items, trailing_comma)?; validate_arrow_params(self, ¶ms, async_span.is_some()); - let body: Box = self.parse_fn_block_or_expr_body( + let body: Box = self.parse_fn_block_or_expr_body( async_span.is_some(), false, true, @@ -2776,7 +2776,7 @@ impl Parser { return_type, ..Default::default() }; - if let BlockStmtOrExpr::BlockStmt(..) = &*arrow_expr.body { + if let ArrowFunctionBody::FunctionBody(..) = &*arrow_expr.body { let cur = self.input().cur(); let should_parse_bin_op_after_arrow = cur.is_bin_op() && !(self.syntax().flow() diff --git a/deps/swc/crates/swc_ecma_parser/src/parser/input.rs b/deps/swc/crates/swc_ecma_parser/src/parser/input.rs index ffeb0078b..a0f375d87 100644 --- a/deps/swc/crates/swc_ecma_parser/src/parser/input.rs +++ b/deps/swc/crates/swc_ecma_parser/src/parser/input.rs @@ -123,7 +123,7 @@ impl Buffer { value } - pub fn expect_jsx_text_token_value(&mut self) -> Atom { + pub fn expect_jsx_text_token_value(&mut self) -> Wtf8Atom { let Some(crate::lexer::TokenValue::JsxText(value)) = self.iter.take_token_value() else { unreachable!() }; diff --git a/deps/swc/crates/swc_ecma_parser/src/parser/jsx.rs b/deps/swc/crates/swc_ecma_parser/src/parser/jsx.rs index 9ddccba67..ca94a03e1 100644 --- a/deps/swc/crates/swc_ecma_parser/src/parser/jsx.rs +++ b/deps/swc/crates/swc_ecma_parser/src/parser/jsx.rs @@ -544,7 +544,7 @@ mod tests { children: vec![JSXElementChild::JSXText(JSXText { span, raw: atom!("foo"), - value: atom!("foo"), + value: atom!("foo").into(), })], closing: Some(JSXClosingElement { span, diff --git a/deps/swc/crates/swc_ecma_parser/src/parser/object.rs b/deps/swc/crates/swc_ecma_parser/src/parser/object.rs index d58aa4528..d856d7937 100644 --- a/deps/swc/crates/swc_ecma_parser/src/parser/object.rs +++ b/deps/swc/crates/swc_ecma_parser/src/parser/object.rs @@ -1,10 +1,7 @@ -use swc_common::{Span, Spanned, DUMMY_SP}; +use swc_common::{Span, Spanned}; use swc_ecma_ast::*; -use crate::{ - error::SyntaxError, input::Tokens, lexer::Token, parser::class_and_fn::is_not_this, Context, - PResult, Parser, -}; +use crate::{error::SyntaxError, input::Tokens, lexer::Token, Context, PResult, Parser}; fn prop_name_is(key: &PropName, expected: &str) -> bool { match key { @@ -388,7 +385,7 @@ impl Parser { |p| { let params = p.parse_formal_params()?; - if params.iter().any(is_not_this) { + if !params.is_empty() { p.emit_err(key_span, SyntaxError::GetterParam); } @@ -397,25 +394,19 @@ impl Parser { false, false, ) - .map(|v| *v) - .map( - |Function { - body, return_type, .. - }| { - if p.input().syntax().typescript() - && p.input().target() == EsVersion::Es3 - { - p.emit_err(key_span, SyntaxError::TS1056); - } - - PropOrSpread::Prop(Box::new(Prop::Getter(GetterProp { - span: p.span(start), - key, - type_ann: return_type, - body, - }))) - }, - ), + .map(|function| { + if p.input().syntax().typescript() + && p.input().target() == EsVersion::Es3 + { + p.emit_err(key_span, SyntaxError::TS1056); + } + + PropOrSpread::Prop(Box::new(Prop::Getter(GetterProp { + span: p.span(start), + key, + function, + }))) + }), Token::Set => { p.parse_fn_args_body( // no decorator in an object literal @@ -424,14 +415,14 @@ impl Parser { |p| { let params = p.parse_formal_params()?; - if params.iter().filter(|p| is_not_this(p)).count() != 1 { + if params.len() != 1 { p.emit_err(key_span, SyntaxError::SetterParam); } - if !params.is_empty() { - if let Pat::Rest(..) = params[0].pat { + if let Some(param) = params.first() { + if let Pat::Rest(..) = param.pat { p.emit_err( - params[0].span(), + param.span(), SyntaxError::RestPatInSetter, ); } @@ -448,38 +439,13 @@ impl Parser { false, false, ) - .map(|v| *v) - .map( - |Function { - mut params, body, .. - }| { - let mut this = None; - if params.len() >= 2 { - this = Some(params.remove(0).pat); - } - - let param = Box::new( - params - .into_iter() - .next() - .map(|v| v.pat) - .unwrap_or_else(|| { - p.emit_err(key_span, SyntaxError::SetterParam); - - Invalid { span: DUMMY_SP }.into() - }), - ); - - // debug_assert_eq!(params.len(), 1); - PropOrSpread::Prop(Box::new(Prop::Setter(SetterProp { - span: p.span(start), - key, - body, - param, - this_param: this, - }))) - }, - ) + .map(|function| { + PropOrSpread::Prop(Box::new(Prop::Setter(SetterProp { + span: p.span(start), + key, + function, + }))) + }) } Token::Async => p .parse_fn_args_body( diff --git a/deps/swc/crates/swc_ecma_parser/src/parser/pat.rs b/deps/swc/crates/swc_ecma_parser/src/parser/pat.rs index 503faa787..c4c8ad7e3 100644 --- a/deps/swc/crates/swc_ecma_parser/src/parser/pat.rs +++ b/deps/swc/crates/swc_ecma_parser/src/parser/pat.rs @@ -28,6 +28,27 @@ fn is_await_ident_or_expr(expr: &Expr) -> bool { || matches!(expr, Expr::Ident(Ident { sym, .. }) if &**sym == "await") } +/// Returns the identifier for a direct `this` pattern or a single assignment +/// layer whose left-hand side is a direct `this` pattern. +fn direct_ts_this_ident(pat: &Pat) -> Option<&Ident> { + let ident = match pat { + Pat::Ident(BindingIdent { id, .. }) => id, + Pat::Assign(AssignPat { left, .. }) => { + let Pat::Ident(BindingIdent { id, .. }) = &**left else { + return None; + }; + id + } + _ => return None, + }; + + if &*ident.sym != "this" { + return None; + } + + Some(ident) +} + impl Parser { pub fn parse_pat(&mut self) -> PResult { self.parse_binding_pat_or_ident(false) @@ -448,12 +469,21 @@ impl Parser { } pub(super) fn parse_binding_element(&mut self) -> PResult { + self.parse_binding_element_with_initializer() + .map(|(pat, _)| pat) + } + + /// Returns the span of an initializer owned by this binding element. + /// Initializers nested in destructuring patterns are not propagated. + fn parse_binding_element_with_initializer(&mut self) -> PResult<(Pat, Option)> { trace_cur!(self, parse_binding_element); let start = self.cur_pos(); let left = self.parse_binding_pat_or_ident(false)?; if self.input_mut().eat(Token::Eq) { + let initializer_span = self.input().prev_span(); + let right = self.allow_in_expr(Self::parse_assignment_expr)?; if self.ctx().contains(Context::InParameters) @@ -467,15 +497,18 @@ impl Parser { self.emit_err(self.span(start), SyntaxError::TS2371); } - return Ok(AssignPat { - span: self.span(start), - left: Box::new(left), - right, - } - .into()); + return Ok(( + AssignPat { + span: self.span(start), + left: Box::new(left), + right, + } + .into(), + Some(initializer_span), + )); } - Ok(left) + Ok((left, None)) } pub(crate) fn parse_binding_pat_or_ident(&mut self, disallow_let: bool) -> PResult { @@ -566,11 +599,27 @@ impl Parser { let has_modifier = self.eat_any_ts_modifier()?; let pat_start = self.cur_pos(); - let mut pat = self.parse_binding_element()?; + let (mut pat, initializer_span) = self.parse_binding_element_with_initializer()?; + let is_direct_ts_this_param = self.syntax().typescript() + && !self.syntax().flow() + && direct_ts_this_ident(&pat).is_some(); + if let (true, Some(initializer_span)) = (is_direct_ts_this_param, initializer_span) { + self.emit_err( + initializer_span, + SyntaxError::Expected(",".into(), "=".into()), + ); + } let mut opt = false; if self.input().syntax().typescript() { if self.input_mut().eat(Token::QuestionMark) { + if is_direct_ts_this_param { + self.emit_err( + self.input().prev_span(), + SyntaxError::Expected(",".into(), "?".into()), + ); + } + match pat { Pat::Ident(BindingIdent { id: @@ -642,8 +691,15 @@ impl Parser { } let pat = if self.input_mut().eat(Token::Eq) { + if is_direct_ts_this_param && !opt { + self.emit_err( + self.input().prev_span(), + SyntaxError::Expected(",".into(), "=".into()), + ); + } + // `=` cannot follow optional parameter. - if opt && !self.input().syntax().flow() { + if opt && !is_direct_ts_this_param && !self.input().syntax().flow() { self.emit_err(pat.span(), SyntaxError::TS1015); } @@ -847,6 +903,15 @@ impl Parser { } } + if self.syntax().typescript() && !self.syntax().flow() { + for param in params.iter().skip(1) { + let Some(ident) = direct_ts_this_ident(¶m.pat) else { + continue; + }; + self.emit_err(ident.span, SyntaxError::TS2680); + } + } + if self.syntax().flow() && !self.ctx().contains(Context::InType) { let in_declare = self.ctx().contains(Context::InDeclare); diff --git a/deps/swc/crates/swc_ecma_parser/src/parser/stmt.rs b/deps/swc/crates/swc_ecma_parser/src/parser/stmt.rs index 37dd04e37..b203c0162 100644 --- a/deps/swc/crates/swc_ecma_parser/src/parser/stmt.rs +++ b/deps/swc/crates/swc_ecma_parser/src/parser/stmt.rs @@ -1037,6 +1037,7 @@ impl Parser { Ok(SwitchStmt { span: self.span(switch_start), + body_ctxt: Default::default(), discriminant, cases, } @@ -1687,13 +1688,10 @@ impl Parser { ident: None, function: Box::new(Function { span, + this_param: None, params: Vec::new(), decorators: Vec::new(), - body: Some(BlockStmt { - span, - stmts, - ctxt: Default::default(), - }), + body: Some(FunctionBody { span, stmts }), is_async: false, is_generator: false, type_params: None, diff --git a/deps/swc/crates/swc_ecma_parser/src/parser/typescript.rs b/deps/swc/crates/swc_ecma_parser/src/parser/typescript.rs index 4b1d4de96..86aee0e90 100644 --- a/deps/swc/crates/swc_ecma_parser/src/parser/typescript.rs +++ b/deps/swc/crates/swc_ecma_parser/src/parser/typescript.rs @@ -458,6 +458,7 @@ impl Parser { ident, function: Box::new(Function { span: self.span(start), + this_param: None, decorators, type_params, params, diff --git a/deps/swc/crates/swc_ecma_preset_env/Cargo.toml b/deps/swc/crates/swc_ecma_preset_env/Cargo.toml index 4afaf7677..a4e5a6a97 100644 --- a/deps/swc/crates/swc_ecma_preset_env/Cargo.toml +++ b/deps/swc/crates/swc_ecma_preset_env/Cargo.toml @@ -13,7 +13,7 @@ include = [ license = { workspace = true } name = "swc_ecma_preset_env" repository = { workspace = true } -version = "57.0.0" +version = "63.0.0" [lib] bench = false @@ -29,23 +29,23 @@ once_cell = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } serde_json = { workspace = true } -preset_env_base = { version = "8.0.1", path = "../preset_env_base" } +preset_env_base = { version = "9.0.0", path = "../preset_env_base" } foldhash = { workspace = true } precomputed-map = { workspace = true } rustc-hash = { workspace = true } string_enum = { version = "1.0.2", path = "../string_enum" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transformer = { version = "16.0.3", path = "../swc_ecma_transformer" } -swc_ecma_transforms = { version = "56.0.0", path = "../swc_ecma_transforms", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transformer = { version = "21.0.0", path = "../swc_ecma_transformer" } +swc_ecma_transforms = { version = "62.0.0", path = "../swc_ecma_transforms", features = [ "compat", "proposal", ] } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [build-dependencies] anyhow = { workspace = true } @@ -59,9 +59,9 @@ serde_json = { workspace = true } codspeed-criterion-compat = { workspace = true } pretty_assertions = { workspace = true } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +testing = { version = "27.0.0", path = "../testing" } [[bench]] harness = false diff --git a/deps/swc/crates/swc_ecma_preset_env/src/lib.rs b/deps/swc/crates/swc_ecma_preset_env/src/lib.rs index 3539da18e..e5d4af472 100644 --- a/deps/swc/crates/swc_ecma_preset_env/src/lib.rs +++ b/deps/swc/crates/swc_ecma_preset_env/src/lib.rs @@ -163,6 +163,10 @@ where options.env.es2017.async_to_generator = true; } + if !caniuse(Feature::AsyncGeneratorFunctions) { + options.env.es2017.async_generator_functions = true; + } + // ES2016 if !caniuse(Feature::ExponentiationOperator) { options.env.es2016.exponentiation_operator = true; @@ -285,7 +289,6 @@ where // ObjectSuper, // DotAllRegex, // UnicodeRegex, - // AsyncGeneratorFunctions, // UnicodePropertyRegex, // JsonStrings, // NamedCapturingGroupsRegex, @@ -818,7 +821,8 @@ impl Caniuse for EsVersion { Feature::ObjectRestSpread | Feature::DotAllRegex | Feature::NamedCapturingGroupsRegex - | Feature::UnicodePropertyRegex => *self >= EsVersion::Es2018, + | Feature::UnicodePropertyRegex + | Feature::AsyncGeneratorFunctions => *self >= EsVersion::Es2018, // ES2017 Feature::AsyncToGenerator => *self >= EsVersion::Es2017, diff --git a/deps/swc/crates/swc_ecma_quote/Cargo.toml b/deps/swc/crates/swc_ecma_quote/Cargo.toml index 84787da48..e0f867e45 100644 --- a/deps/swc/crates/swc_ecma_quote/Cargo.toml +++ b/deps/swc/crates/swc_ecma_quote/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_quote" repository = { workspace = true } -version = "41.0.0" +version = "45.0.0" [lib] bench = false @@ -15,8 +15,8 @@ bench = false unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_quote_macros = { version = "41.0.0", path = "../swc_ecma_quote_macros" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_quote_macros = { version = "45.0.0", path = "../swc_ecma_quote_macros" } [dev-dependencies] diff --git a/deps/swc/crates/swc_ecma_quote_macros/Cargo.toml b/deps/swc/crates/swc_ecma_quote_macros/Cargo.toml index ee4f1ca1d..3989e8b90 100644 --- a/deps/swc/crates/swc_ecma_quote_macros/Cargo.toml +++ b/deps/swc/crates/swc_ecma_quote_macros/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_quote_macros" repository = { workspace = true } -version = "41.0.0" +version = "45.0.0" [lib] bench = false @@ -22,10 +22,10 @@ quote = { workspace = true } rustc-hash = { workspace = true } syn = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } swc_macros_common = { version = "1.0.1", path = "../swc_macros_common" } diff --git a/deps/swc/crates/swc_ecma_quote_macros/src/ast/expr.rs b/deps/swc/crates/swc_ecma_quote_macros/src/ast/expr.rs index c3364e766..222372878 100644 --- a/deps/swc/crates/swc_ecma_quote_macros/src/ast/expr.rs +++ b/deps/swc/crates/swc_ecma_quote_macros/src/ast/expr.rs @@ -113,6 +113,7 @@ impl_struct!( Function, [ ctxt, + this_param, params, decorators, span, diff --git a/deps/swc/crates/swc_ecma_quote_macros/src/ast/mod.rs b/deps/swc/crates/swc_ecma_quote_macros/src/ast/mod.rs index 28d5b1623..c46aa9cae 100644 --- a/deps/swc/crates/swc_ecma_quote_macros/src/ast/mod.rs +++ b/deps/swc/crates/swc_ecma_quote_macros/src/ast/mod.rs @@ -165,7 +165,7 @@ impl_enum!(ObjectPatProp, [KeyValue, Assign, Rest]); impl_enum!(PropName, [Ident, Str, Num, Computed, BigInt]); impl_enum!(ParamOrTsParamProp, [TsParamProp, Param]); impl_enum!(PropOrSpread, [Spread, Prop]); -impl_enum!(BlockStmtOrExpr, [BlockStmt, Expr]); +impl_enum!(ArrowFunctionBody, [FunctionBody, Expr]); impl_enum!(MemberProp, [Ident, PrivateName, Computed]); impl_enum!(SuperProp, [Ident, Computed]); impl_enum!(JSXObject, [Ident, JSXMemberExpr]); diff --git a/deps/swc/crates/swc_ecma_quote_macros/src/ast/prop.rs b/deps/swc/crates/swc_ecma_quote_macros/src/ast/prop.rs index 173f010ad..ca911aa6f 100644 --- a/deps/swc/crates/swc_ecma_quote_macros/src/ast/prop.rs +++ b/deps/swc/crates/swc_ecma_quote_macros/src/ast/prop.rs @@ -24,8 +24,8 @@ impl_struct!(KeyValueProp, [key, value]); impl_struct!(AssignProp, [span, key, value]); -impl_struct!(GetterProp, [span, key, type_ann, body]); -impl_struct!(SetterProp, [span, key, param, this_param, body]); +impl_struct!(GetterProp, [span, key, function]); +impl_struct!(SetterProp, [span, key, function]); impl_struct!(MethodProp, [key, function]); diff --git a/deps/swc/crates/swc_ecma_quote_macros/src/ast/stmt.rs b/deps/swc/crates/swc_ecma_quote_macros/src/ast/stmt.rs index 07d30a484..1da6310f4 100644 --- a/deps/swc/crates/swc_ecma_quote_macros/src/ast/stmt.rs +++ b/deps/swc/crates/swc_ecma_quote_macros/src/ast/stmt.rs @@ -10,13 +10,14 @@ impl_enum!( impl_struct!(EmptyStmt, [span]); impl_struct!(BlockStmt, [span, ctxt, stmts]); +impl_struct!(FunctionBody, [span, stmts]); impl_struct!(DebuggerStmt, [span]); impl_struct!(WithStmt, [span, obj, body]); impl_struct!(LabeledStmt, [span, label, body]); impl_struct!(BreakStmt, [span, label]); impl_struct!(ContinueStmt, [span, label]); impl_struct!(IfStmt, [span, test, cons, alt]); -impl_struct!(SwitchStmt, [span, discriminant, cases]); +impl_struct!(SwitchStmt, [span, body_ctxt, discriminant, cases]); impl_struct!(ThrowStmt, [span, arg]); impl_struct!(TryStmt, [span, block, handler, finalizer]); impl_struct!(WhileStmt, [span, test, body]); diff --git a/deps/swc/crates/swc_ecma_quote_macros/src/ast/typescript.rs b/deps/swc/crates/swc_ecma_quote_macros/src/ast/typescript.rs index 589df6080..f9d2712ee 100644 --- a/deps/swc/crates/swc_ecma_quote_macros/src/ast/typescript.rs +++ b/deps/swc/crates/swc_ecma_quote_macros/src/ast/typescript.rs @@ -14,6 +14,7 @@ fail_todo!(TsAsExpr); fail_todo!(TsInstantiation); fail_todo!(TsType); fail_todo!(TsTypeAnn); +fail_todo!(TsThisParam); fail_todo!(TsTypeParamInstantiation); fail_todo!(TsTypeParamDecl); fail_todo!(TsExprWithTypeArgs); diff --git a/deps/swc/crates/swc_ecma_react_compiler/Cargo.toml b/deps/swc/crates/swc_ecma_react_compiler/Cargo.toml index 88ac30640..86a3244f6 100644 --- a/deps/swc/crates/swc_ecma_react_compiler/Cargo.toml +++ b/deps/swc/crates/swc_ecma_react_compiler/Cargo.toml @@ -5,7 +5,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_react_compiler" repository = { workspace = true } -version = "20.0.2" +version = "24.0.0" [package.metadata.docs.rs] @@ -20,18 +20,18 @@ react_compiler_hir = { version = "=0.2.0", package = "forked_react_compiler_hir" rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_ecma_react_compiler/src/convert_ast.rs b/deps/swc/crates/swc_ecma_react_compiler/src/convert_ast.rs index 470484dbd..615385f9e 100644 --- a/deps/swc/crates/swc_ecma_react_compiler/src/convert_ast.rs +++ b/deps/swc/crates/swc_ecma_react_compiler/src/convert_ast.rs @@ -386,6 +386,16 @@ impl<'a> ConvertCtx<'a> { } } + fn convert_function_body(&self, body: &swc::FunctionBody) -> BlockStatement { + let (statements, directives) = self.convert_stmt_list_with_directives(&body.stmts); + + BlockStatement { + base: self.make_base_node(body.span), + body: statements, + directives, + } + } + fn convert_return_stmt(&self, ret: &swc::ReturnStmt) -> ReturnStatement { ReturnStatement { base: self.make_base_node(ret.span), @@ -631,7 +641,7 @@ impl<'a> ConvertCtx<'a> { }), swc::Lit::JSXText(t) => Expression::StringLiteral(StringLiteral { base: self.make_base_node(t.span), - value: decode_jsx_entities(t.value.as_ref()).into(), + value: decode_jsx_entities(&t.value.to_string_lossy()).into(), }), }, swc::Expr::Ident(id) => Expression::Identifier(self.convert_ident(id)), @@ -1118,12 +1128,12 @@ impl<'a> ConvertCtx<'a> { fn convert_arrow_expr(&self, arrow: &swc::ArrowExpr) -> ArrowFunctionExpression { self.preserved_ast.borrow_mut().save_arrow(arrow); - let is_expression = matches!(&*arrow.body, swc::BlockStmtOrExpr::Expr(_)); + let is_expression = matches!(&*arrow.body, swc::ArrowFunctionBody::Expr(_)); let body = match &*arrow.body { - swc::BlockStmtOrExpr::BlockStmt(block) => { - ArrowFunctionBody::BlockStatement(self.convert_block_stmt(block)) + swc::ArrowFunctionBody::FunctionBody(body) => { + ArrowFunctionBody::BlockStatement(self.convert_function_body(body)) } - swc::BlockStmtOrExpr::Expr(expr) => { + swc::ArrowFunctionBody::Expr(expr) => { ArrowFunctionBody::Expression(Box::new(self.convert_expr(expr))) } }; @@ -1154,7 +1164,7 @@ impl<'a> ConvertCtx<'a> { fn convert_block_stmt_as_optional_function_body( &self, - body: Option<&swc::BlockStmt>, + body: Option<&swc::FunctionBody>, span: Span, ) -> BlockStatement { body.map_or_else( @@ -1163,7 +1173,7 @@ impl<'a> ConvertCtx<'a> { body: vec![], directives: vec![], }, - |b| self.convert_block_stmt(b), + |body| self.convert_function_body(body), ) } @@ -1469,6 +1479,39 @@ impl<'a> ConvertCtx<'a> { } } + fn convert_object_method( + &self, + key: &swc::PropName, + function: &swc::Function, + kind: ObjectMethodKind, + method: bool, + ) -> ObjectExpressionProperty { + self.preserved_ast.borrow_mut().save_function(function); + + ObjectExpressionProperty::ObjectMethod(ObjectMethod { + base: self.make_base_node(function.span), + method, + kind, + key: Box::new(self.convert_prop_name(key)), + params: self.convert_param_list(&function.params), + body: self.convert_block_stmt_as_optional_function_body( + function.body.as_ref(), + function.span, + ), + computed: self.convert_prop_name_computed(key), + id: None, + generator: function.is_generator, + is_async: function.is_async, + decorators: None, + return_type: function + .return_type + .as_ref() + .map(|t| self.convert_ts_type_ann_json(t)), + type_parameters: function.type_params.as_ref().map(|_| RawNode::null()), + predicate: None, + }) + } + fn convert_prop_or_spread(&self, prop: &swc::PropOrSpread) -> ObjectExpressionProperty { match prop { swc::PropOrSpread::Spread(s) => { @@ -1493,69 +1536,14 @@ impl<'a> ConvertCtx<'a> { swc::Prop::KeyValue(kv) => { ObjectExpressionProperty::ObjectProperty(self.convert_key_value_prop(kv)) } - swc::Prop::Getter(g) => ObjectExpressionProperty::ObjectMethod(ObjectMethod { - base: self.make_base_node(g.span), - method: false, - kind: ObjectMethodKind::Get, - key: Box::new(self.convert_prop_name(&g.key)), - params: vec![], - body: self - .convert_block_stmt_as_optional_function_body(g.body.as_ref(), g.span), - computed: self.convert_prop_name_computed(&g.key), - id: None, - generator: false, - is_async: false, - decorators: None, - return_type: g - .type_ann - .as_ref() - .map(|t| self.convert_ts_type_ann_json(t)), - type_parameters: None, - predicate: None, - }), - swc::Prop::Setter(s) => ObjectExpressionProperty::ObjectMethod(ObjectMethod { - base: self.make_base_node(s.span), - method: false, - kind: ObjectMethodKind::Set, - key: Box::new(self.convert_prop_name(&s.key)), - params: vec![self.convert_pat(&s.param)], - body: self - .convert_block_stmt_as_optional_function_body(s.body.as_ref(), s.span), - computed: self.convert_prop_name_computed(&s.key), - id: None, - generator: false, - is_async: false, - decorators: None, - return_type: None, - type_parameters: None, - predicate: None, - }), + swc::Prop::Getter(g) => { + self.convert_object_method(&g.key, &g.function, ObjectMethodKind::Get, false) + } + swc::Prop::Setter(s) => { + self.convert_object_method(&s.key, &s.function, ObjectMethodKind::Set, false) + } swc::Prop::Method(m) => { - self.preserved_ast.borrow_mut().save_function(&m.function); - - ObjectExpressionProperty::ObjectMethod(ObjectMethod { - base: self.make_base_node(m.span()), - method: true, - kind: ObjectMethodKind::Method, - key: Box::new(self.convert_prop_name(&m.key)), - params: self.convert_param_list(&m.function.params), - body: self.convert_block_stmt_as_optional_function_body( - m.function.body.as_ref(), - m.function.span, - ), - computed: self.convert_prop_name_computed(&m.key), - id: None, - generator: m.function.is_generator, - is_async: m.function.is_async, - decorators: None, - return_type: m - .function - .return_type - .as_ref() - .map(|t| self.convert_ts_type_ann_json(t)), - type_parameters: m.function.type_params.as_ref().map(|_| RawNode::null()), - predicate: None, - }) + self.convert_object_method(&m.key, &m.function, ObjectMethodKind::Method, true) } swc::Prop::Assign(a) => { let ident = self.convert_ident(&a.key); @@ -1939,7 +1927,7 @@ impl<'a> ConvertCtx<'a> { base: self.make_base_node(t.span), // SWC stores the Babel-compatible decoded JSX text value here. // Future parser refactors must preserve that decoded value contract. - value: decode_jsx_entities(t.value.as_ref()), + value: decode_jsx_entities(&t.value.to_string_lossy()), }), swc::JSXElementChild::JSXExprContainer(ec) => { JSXChild::JSXExpressionContainer(self.convert_jsx_expr_container(ec)) diff --git a/deps/swc/crates/swc_ecma_react_compiler/src/convert_ast_reverse.rs b/deps/swc/crates/swc_ecma_react_compiler/src/convert_ast_reverse.rs index 0f88d7d41..7a7240ed4 100644 --- a/deps/swc/crates/swc_ecma_react_compiler/src/convert_ast_reverse.rs +++ b/deps/swc/crates/swc_ecma_react_compiler/src/convert_ast_reverse.rs @@ -323,6 +323,7 @@ impl ReverseCtx { .into(), Statement::SwitchStatement(switch_stmt) => swc::Stmt::Switch(swc::SwitchStmt { span: self.span_from_base(&switch_stmt.base), + body_ctxt: SyntaxContext::empty(), discriminant: Box::new(self.convert_expression(&switch_stmt.discriminant)), cases: switch_stmt .cases @@ -481,6 +482,12 @@ impl ReverseCtx { } } + fn convert_function_body(&self, block: &BlockStatement) -> swc::FunctionBody { + let swc::BlockStmt { span, stmts, .. } = self.convert_block_statement(block); + + swc::FunctionBody { span, stmts } + } + fn convert_catch_clause(&self, clause: &CatchClause) -> swc::CatchClause { let mut catch_clause = swc::CatchClause { span: self.span_from_base(&clause.base), @@ -1061,21 +1068,14 @@ impl ReverseCtx { swc::PropOrSpread::Prop(Box::new(swc::Prop::Getter(swc::GetterProp { span: self.span_from_base(&method.base), key, - type_ann: function.return_type, - body: function.body, + function: Box::new(function), }))) } ObjectMethodKind::Set => { - let param = function.params.into_iter().next().map_or_else( - || Box::new(swc::Pat::Invalid(swc::Invalid { span: DUMMY_SP })), - |param| Box::new(param.pat), - ); swc::PropOrSpread::Prop(Box::new(swc::Prop::Setter(swc::SetterProp { span: self.span_from_base(&method.base), key, - this_param: None, - param, - body: function.body, + function: Box::new(function), }))) } ObjectMethodKind::Method => { @@ -1154,6 +1154,7 @@ impl ReverseCtx { fn convert_function_declaration(&self, f: &FunctionDeclaration) -> swc::FnDecl { let mut function = swc::Function { + this_param: None, params: f .params .iter() @@ -1162,7 +1163,7 @@ impl ReverseCtx { decorators: vec![], span: self.span_from_base(&f.base), ctxt: SyntaxContext::empty(), - body: Some(self.convert_block_statement(&f.body)), + body: Some(self.convert_function_body(&f.body)), is_generator: f.generator, is_async: f.is_async, type_params: None, @@ -1220,6 +1221,7 @@ impl ReverseCtx { fn convert_function_expression(&self, f: &FunctionExpression) -> swc::Function { let mut function = swc::Function { + this_param: None, params: f .params .iter() @@ -1228,7 +1230,7 @@ impl ReverseCtx { decorators: vec![], span: self.span_from_base(&f.base), ctxt: SyntaxContext::empty(), - body: Some(self.convert_block_statement(&f.body)), + body: Some(self.convert_function_body(&f.body)), is_generator: f.generator, is_async: f.is_async, type_params: None, @@ -1246,6 +1248,7 @@ impl ReverseCtx { fn convert_object_method_to_function(&self, m: &ObjectMethod) -> swc::Function { swc::Function { + this_param: None, params: m .params .iter() @@ -1254,7 +1257,7 @@ impl ReverseCtx { decorators: vec![], span: self.span_from_base(&m.base), ctxt: SyntaxContext::empty(), - body: Some(self.convert_block_statement(&m.body)), + body: Some(self.convert_function_body(&m.body)), is_generator: m.generator, is_async: m.is_async, type_params: None, @@ -1273,10 +1276,10 @@ impl ReverseCtx { .collect(), body: Box::new(match arrow.body.as_ref() { ArrowFunctionBody::BlockStatement(block) => { - swc::BlockStmtOrExpr::BlockStmt(self.convert_block_statement(block)) + swc::ArrowFunctionBody::FunctionBody(self.convert_function_body(block)) } ArrowFunctionBody::Expression(expr) => { - swc::BlockStmtOrExpr::Expr(Box::new(self.convert_expression(expr))) + swc::ArrowFunctionBody::Expr(Box::new(self.convert_expression(expr))) } }), is_async: arrow.is_async, @@ -1638,7 +1641,7 @@ impl ReverseCtx { } JSXChild::JSXText(text) => swc::JSXElementChild::JSXText(swc::JSXText { span: self.span_from_base(&text.base), - value: Atom::from(text.value.as_str()), + value: Atom::from(text.value.as_str()).into(), raw: Atom::from(encode_jsx_text(&text.value)), }), } diff --git a/deps/swc/crates/swc_ecma_react_compiler/src/convert_scope.rs b/deps/swc/crates/swc_ecma_react_compiler/src/convert_scope.rs index 45752ffca..d720430ba 100644 --- a/deps/swc/crates/swc_ecma_react_compiler/src/convert_scope.rs +++ b/deps/swc/crates/swc_ecma_react_compiler/src/convert_scope.rs @@ -48,6 +48,7 @@ impl ScopeFlags { pub const ClassStaticBlock: Self = Self { bits: 1 << 2 }; pub const For: Self = Self { bits: 1 << 3 }; pub const Function: Self = Self { bits: 1 << 4 }; + pub const Parameter: Self = Self { bits: 1 << 9 }; pub const StrictMode: Self = Self { bits: 1 << 5 }; pub const Switch: Self = Self { bits: 1 << 6 }; pub const Top: Self = Self { bits: 1 << 7 }; @@ -100,6 +101,11 @@ impl ScopeFlags { pub fn is_catch_clause(self) -> bool { self.contains(Self::CatchClause) } + + #[inline] + pub fn is_parameter(self) -> bool { + self.contains(Self::Parameter) + } } impl std::ops::BitOr for ScopeFlags { @@ -140,6 +146,12 @@ impl SymbolFlags { pub const FunctionScopedVariable: Self = Self { bits: 1 << 7 }; pub const Import: Self = Self { bits: 1 << 8 }; pub const Param: Self = Self { bits: 1 << 9 }; + pub const Value: Self = Self { + bits: Self::Variable.bits | Self::Class.bits | Self::Function.bits | Self::Enum.bits, + }; + pub const Variable: Self = Self { + bits: Self::FunctionScopedVariable.bits | Self::BlockScopedVariable.bits, + }; #[inline] pub const fn contains(self, other: Self) -> bool { @@ -153,16 +165,7 @@ impl SymbolFlags { #[inline] pub fn is_value(self) -> bool { - self.intersects( - Self::FunctionScopedVariable - | Self::BlockScopedVariable - | Self::Function - | Self::FunctionExpression - | Self::Class - | Self::Enum - | Self::Import - | Self::Param, - ) + self.intersects(Self::Value | Self::Import) } #[inline] @@ -188,6 +191,7 @@ pub struct Symbol { pub name: String, pub span: swc_common::Span, pub flags: SymbolFlags, + pub scope_id: ScopeId, } /// A reference to a symbol. @@ -249,6 +253,10 @@ impl Scoping { self.symbols[symbol_id.0 as usize].span } + pub fn symbol_scope_id(&self, symbol_id: SymbolId) -> ScopeId { + self.symbols[symbol_id.0 as usize].scope_id + } + pub fn scope_flags(&self, scope_id: ScopeId) -> ScopeFlags { self.scopes[scope_id.0 as usize].flags } @@ -265,10 +273,26 @@ impl Scoping { self.scopes[scope_id.0 as usize].bindings.values().copied() } + pub fn iter_binding_entries_in( + &self, + scope_id: ScopeId, + ) -> impl Iterator + '_ { + self.scopes[scope_id.0 as usize] + .bindings + .iter() + .map(|(name, &symbol_id)| (name.as_str(), symbol_id)) + } + pub fn get_binding(&self, scope_id: ScopeId, name: &str) -> Option { self.scopes[scope_id.0 as usize].bindings.get(name).copied() } + pub fn bind_symbol_on_scope(&mut self, scope_id: ScopeId, name: String, symbol_id: SymbolId) { + if let Some(scope) = self.scopes.get_mut(scope_id.0 as usize) { + scope.bindings.insert(name, symbol_id); + } + } + pub fn root_scope_id(&self) -> ScopeId { ScopeId(0) } @@ -298,6 +322,7 @@ impl Scoping { name: name.clone(), span, flags, + scope_id, }); if let Some(scope) = self.scopes.get_mut(scope_id.0 as usize) { scope.bindings.insert(name, id); @@ -348,10 +373,8 @@ pub struct SemanticBuilder { declaration_starts: std::collections::HashSet, /// Re-declaration sites that should resolve to an existing binding. redeclaration_bindings: HashMap, - /// Flat list of unresolved references: (name, reference_id). + /// Flat list of unresolved references: (name, `reference_id`). unresolved_references: Vec<(String, ReferenceId)>, - /// Track function body spans so they don't create extra block scopes. - function_body_spans: std::collections::HashSet, } impl SemanticBuilder { @@ -371,7 +394,6 @@ impl SemanticBuilder { declaration_starts: std::collections::HashSet::new(), redeclaration_bindings: HashMap::new(), unresolved_references: Vec::new(), - function_body_spans: std::collections::HashSet::new(), } } @@ -427,7 +449,7 @@ impl SemanticBuilder { false } - fn body_scope_flags(&self, flags: ScopeFlags, body: Option<&BlockStmt>) -> ScopeFlags { + fn body_scope_flags(&self, flags: ScopeFlags, body: Option<&FunctionBody>) -> ScopeFlags { if body.is_some_and(|body| Self::strict_directives_present(&body.stmts)) { flags | ScopeFlags::StrictMode } else { @@ -464,8 +486,14 @@ impl SemanticBuilder { ) -> SymbolId { if flags.contains(SymbolFlags::FunctionScopedVariable) { if let Some(symbol_id) = self.scoping.get_binding(scope_id, &name) { - self.record_redeclaration_binding(span, symbol_id); - return symbol_id; + if !self + .scoping + .symbol_flags(symbol_id) + .contains(SymbolFlags::FunctionExpression) + { + self.record_redeclaration_binding(span, symbol_id); + return symbol_id; + } } } @@ -474,6 +502,35 @@ impl SemanticBuilder { symbol_id } + fn declare_symbol_on_scope_with_alias( + &mut self, + span: swc_common::Span, + name: String, + flags: SymbolFlags, + scope_id: ScopeId, + alias_scope_id: Option, + ) -> SymbolId { + let symbol_id = self.declare_symbol_on_scope(span, name.clone(), flags, scope_id); + if let Some(alias_scope_id) = alias_scope_id { + self.scoping + .bind_symbol_on_scope(alias_scope_id, name, symbol_id); + } + symbol_id + } + + fn alias_bindings_to_scope(&mut self, from_scope_id: ScopeId, to_scope_id: ScopeId) { + let bindings: Vec<(String, SymbolId)> = self + .scoping + .iter_binding_entries_in(from_scope_id) + .map(|(name, symbol_id)| (name.to_string(), symbol_id)) + .collect(); + + for (name, symbol_id) in bindings { + self.scoping + .bind_symbol_on_scope(to_scope_id, name, symbol_id); + } + } + fn record_redeclaration_binding(&mut self, span: swc_common::Span, symbol_id: SymbolId) { let start = self.start(span); self.declaration_starts.insert(start); @@ -509,11 +566,39 @@ impl SemanticBuilder { return true; } } - scope_id = self.scoping.scope_parent_id(sid); + scope_id = self.resolution_parent_id(sid); } false } + fn resolution_parent_id(&self, scope_id: ScopeId) -> Option { + let parent_id = self.scoping.scope_parent_id(scope_id)?; + if self.scoping.scope_flags(scope_id).is_parameter() { + // Parameter initializers run before the function body environment is + // visible. Check parameter aliases first, then continue at the + // outer scope instead of the function scope that will hold body + // bindings in the React Compiler-compatible output model. + return self.scoping.scope_parent_id(parent_id); + } + + Some(parent_id) + } + + /// Resolve references emitted while visiting function or catch parameters + /// before body bindings are added to the same scope. + fn resolve_references_from_checkpoint(&mut self, checkpoint: usize) { + if checkpoint >= self.unresolved_references.len() { + return; + } + + let references = self.unresolved_references.split_off(checkpoint); + for (name, reference_id) in references { + if !self.walk_up_resolve_reference(&name, reference_id) { + self.unresolved_references.push((name, reference_id)); + } + } + } + fn try_resolve_reference(&mut self, reference_id: ReferenceId, symbol_id: SymbolId) -> bool { let symbol_flags = self.scoping.symbol_flags(symbol_id); @@ -539,23 +624,54 @@ impl SemanticBuilder { .unwrap_or(ScopeId(0)) } + #[inline] + fn param_flags() -> SymbolFlags { + SymbolFlags::FunctionScopedVariable | SymbolFlags::Param + } + fn collect_pat_bindings(&mut self, pat: &Pat, flags: SymbolFlags) { + self.collect_pat_bindings_in_scope(pat, flags, self.current_scope(), None); + } + + fn collect_parameter_pat_bindings( + &mut self, + pat: &Pat, + function_scope_id: ScopeId, + parameter_scope_id: ScopeId, + ) { + self.collect_pat_bindings_in_scope( + pat, + Self::param_flags(), + function_scope_id, + Some(parameter_scope_id), + ); + } + + fn collect_pat_bindings_in_scope( + &mut self, + pat: &Pat, + flags: SymbolFlags, + scope_id: ScopeId, + alias_scope_id: Option, + ) { match pat { Pat::Ident(binding_ident) => { - // TypeScript `this` pseudo-parameters are type annotations only. - // They are erased before emit and must not be registered as bindings. + // Flow and object-setter `this` pseudo-parameters are represented + // as patterns. Other TypeScript functions use `Function::this_param`. if binding_ident.id.sym.as_str() == "this" { return; } - self.declare_symbol( + self.declare_symbol_on_scope_with_alias( binding_ident.id.span, binding_ident.id.sym.to_string(), flags, + scope_id, + alias_scope_id, ); } Pat::Array(arr) => { for p in arr.elems.iter().flatten() { - self.collect_pat_bindings(p, flags); + self.collect_pat_bindings_in_scope(p, flags, scope_id, alias_scope_id); } } Pat::Object(obj) => { @@ -565,56 +681,218 @@ impl SemanticBuilder { if let PropName::Computed(computed) = &kv.key { computed.visit_with(self); } - self.collect_pat_bindings(&kv.value, flags); + self.collect_pat_bindings_in_scope( + &kv.value, + flags, + scope_id, + alias_scope_id, + ); } ObjectPatProp::Assign(assign) => { - self.declare_symbol( + self.declare_symbol_on_scope_with_alias( assign.key.id.span, assign.key.id.sym.to_string(), flags, + scope_id, + alias_scope_id, ); if let Some(value) = &assign.value { value.visit_with(self); } } ObjectPatProp::Rest(rest) => { - self.collect_pat_bindings(&rest.arg, flags); + self.collect_pat_bindings_in_scope( + &rest.arg, + flags, + scope_id, + alias_scope_id, + ); } } } } Pat::Rest(rest) => { - self.collect_pat_bindings(&rest.arg, flags); + self.collect_pat_bindings_in_scope(&rest.arg, flags, scope_id, alias_scope_id); } Pat::Assign(assign) => { - self.collect_pat_bindings(&assign.left, flags); + self.collect_pat_bindings_in_scope(&assign.left, flags, scope_id, alias_scope_id); assign.right.visit_with(self); } Pat::Expr(_) | Pat::Invalid(_) => {} } } + fn visit_function_params( + &mut self, + function_scope_id: ScopeId, + scope_span: swc_common::Span, + params: &[Param], + ) { + if params + .iter() + .any(|param| Self::pat_needs_parameter_scope(¶m.pat)) + { + self.with_parameter_scope(function_scope_id, scope_span, |this, parameter_scope_id| { + for param in params { + this.collect_parameter_pat_bindings( + ¶m.pat, + function_scope_id, + parameter_scope_id, + ); + } + }); + } else { + for param in params { + self.collect_pat_bindings_in_scope( + ¶m.pat, + Self::param_flags(), + function_scope_id, + None, + ); + } + } + } + + fn visit_arrow_params( + &mut self, + function_scope_id: ScopeId, + scope_span: swc_common::Span, + params: &[Pat], + ) { + if params.iter().any(Self::pat_needs_parameter_scope) { + self.with_parameter_scope(function_scope_id, scope_span, |this, parameter_scope_id| { + for param in params { + this.collect_parameter_pat_bindings( + param, + function_scope_id, + parameter_scope_id, + ); + } + }); + } else { + for param in params { + self.collect_pat_bindings_in_scope( + param, + Self::param_flags(), + function_scope_id, + None, + ); + } + } + } + + fn visit_constructor_params( + &mut self, + function_scope_id: ScopeId, + scope_span: swc_common::Span, + params: &[ParamOrTsParamProp], + ) { + if params + .iter() + .any(Self::constructor_param_needs_parameter_scope) + { + self.with_parameter_scope(function_scope_id, scope_span, |this, parameter_scope_id| { + for param in params { + this.collect_constructor_param_bindings( + param, + function_scope_id, + Some(parameter_scope_id), + ); + } + }); + } else { + for param in params { + self.collect_constructor_param_bindings(param, function_scope_id, None); + } + } + } + + fn with_parameter_scope( + &mut self, + function_scope_id: ScopeId, + scope_span: swc_common::Span, + visit_params: F, + ) where + F: FnOnce(&mut Self, ScopeId), + { + let checkpoint = self.unresolved_references.len(); + let parameter_scope_id = self.push_scope(ScopeFlags::Parameter, scope_span); + // Named function expression bindings are visible in parameter defaults, + // but body bindings are not. Parameters are declared in the function + // scope for output compatibility and aliased here for resolution. + self.alias_bindings_to_scope(function_scope_id, parameter_scope_id); + visit_params(self, parameter_scope_id); + self.pop_scope(); + self.resolve_references_from_checkpoint(checkpoint); + } + + fn pat_needs_parameter_scope(pat: &Pat) -> bool { + match pat { + Pat::Ident(_) | Pat::Invalid(_) => false, + Pat::Array(arr) => arr + .elems + .iter() + .flatten() + .any(Self::pat_needs_parameter_scope), + Pat::Object(obj) => obj.props.iter().any(|prop| match prop { + ObjectPatProp::KeyValue(kv) => { + matches!(kv.key, PropName::Computed(_)) + || Self::pat_needs_parameter_scope(&kv.value) + } + ObjectPatProp::Assign(assign) => assign.value.is_some(), + ObjectPatProp::Rest(rest) => Self::pat_needs_parameter_scope(&rest.arg), + }), + Pat::Rest(rest) => Self::pat_needs_parameter_scope(&rest.arg), + Pat::Assign(_) | Pat::Expr(_) => true, + } + } + + fn constructor_param_needs_parameter_scope(param: &ParamOrTsParamProp) -> bool { + match param { + ParamOrTsParamProp::Param(param) => Self::pat_needs_parameter_scope(¶m.pat), + ParamOrTsParamProp::TsParamProp(param_prop) => { + matches!(param_prop.param, TsParamPropParam::Assign(_)) + } + } + } + + /// A simple catch parameter is function-scoped for `var` redeclaration + /// compatibility, while destructuring is block-scoped. + fn collect_catch_pat_bindings(&mut self, pat: &Pat) { + let flags = if matches!(pat, Pat::Ident(_)) { + SymbolFlags::FunctionScopedVariable | SymbolFlags::CatchVariable + } else { + SymbolFlags::BlockScopedVariable | SymbolFlags::CatchVariable + }; + self.collect_pat_bindings(pat, flags); + } + fn visit_function_inner(&mut self, function: &Function, flags: ScopeFlags) { self.visit_function_inner_with_span(function.span, function, flags); } + fn visit_object_method(&mut self, key: &PropName, function: &Function) { + if let PropName::Computed(computed) = key { + computed.visit_with(self); + } + + self.visit_function_inner(function, ScopeFlags::Function); + } + fn visit_function_inner_with_span( &mut self, scope_span: swc_common::Span, function: &Function, flags: ScopeFlags, ) { - let _scope_id = self.push_scope( + let scope_id = self.push_scope( self.body_scope_flags(flags, function.body.as_ref()), scope_span, ); - for param in &function.params { - self.collect_pat_bindings(¶m.pat, SymbolFlags::Param); - } + self.visit_function_params(scope_id, scope_span, &function.params); if let Some(body) = &function.body { - self.function_body_spans.insert(self.start(body.span)); body.visit_with(self); } @@ -622,63 +900,57 @@ impl SemanticBuilder { } fn visit_constructor_inner(&mut self, constructor: &Constructor) { - let _scope_id = self.push_scope( + let scope_id = self.push_scope( self.body_scope_flags(ScopeFlags::Function, constructor.body.as_ref()), constructor.span, ); - for param in &constructor.params { - self.collect_constructor_param_bindings(param); - } + self.visit_constructor_params(scope_id, constructor.span, &constructor.params); if let Some(body) = &constructor.body { - self.function_body_spans.insert(self.start(body.span)); body.visit_with(self); } self.pop_scope(); } - fn collect_constructor_param_bindings(&mut self, param: &ParamOrTsParamProp) { + fn collect_constructor_param_bindings( + &mut self, + param: &ParamOrTsParamProp, + function_scope_id: ScopeId, + alias_scope_id: Option, + ) { match param { ParamOrTsParamProp::Param(param) => { - self.collect_pat_bindings(¶m.pat, SymbolFlags::Param); + self.collect_pat_bindings_in_scope( + ¶m.pat, + Self::param_flags(), + function_scope_id, + alias_scope_id, + ); } ParamOrTsParamProp::TsParamProp(param_prop) => match ¶m_prop.param { TsParamPropParam::Ident(binding_ident) => { - self.declare_symbol( + self.declare_symbol_on_scope_with_alias( binding_ident.id.span, binding_ident.id.sym.to_string(), - SymbolFlags::Param, + Self::param_flags(), + function_scope_id, + alias_scope_id, ); } TsParamPropParam::Assign(assign) => { - self.collect_pat_bindings(&assign.left, SymbolFlags::Param); + self.collect_pat_bindings_in_scope( + &assign.left, + Self::param_flags(), + function_scope_id, + alias_scope_id, + ); assign.right.visit_with(self); } }, } } - - fn visit_accessor_inner( - &mut self, - span: swc_common::Span, - param: Option<&Pat>, - body: Option<&BlockStmt>, - ) { - let _scope_id = self.push_scope(self.body_scope_flags(ScopeFlags::Function, body), span); - - if let Some(param) = param { - self.collect_pat_bindings(param, SymbolFlags::Param); - } - - if let Some(body) = body { - self.function_body_spans.insert(self.start(body.span)); - body.visit_with(self); - } - - self.pop_scope(); - } } impl Visit for SemanticBuilder { @@ -780,22 +1052,19 @@ impl Visit for SemanticBuilder { fn visit_fn_expr(&mut self, fn_expr: &FnExpr) { let flags = self.body_scope_flags(ScopeFlags::Function, fn_expr.function.body.as_ref()); - self.push_scope(flags, fn_expr.function.span); + let scope_id = self.push_scope(flags, fn_expr.function.span); if let Some(ident) = &fn_expr.ident { self.declare_symbol( ident.span, ident.sym.to_string(), - SymbolFlags::FunctionExpression, + SymbolFlags::Function | SymbolFlags::FunctionExpression, ); } - for param in &fn_expr.function.params { - self.collect_pat_bindings(¶m.pat, SymbolFlags::Param); - } + self.visit_function_params(scope_id, fn_expr.function.span, &fn_expr.function.params); if let Some(body) = &fn_expr.function.body { - self.function_body_spans.insert(self.start(body.span)); body.visit_with(self); } @@ -804,23 +1073,20 @@ impl Visit for SemanticBuilder { fn visit_arrow_expr(&mut self, arrow: &ArrowExpr) { let flags = match &*arrow.body { - BlockStmtOrExpr::BlockStmt(block) => { - self.body_scope_flags(ScopeFlags::Function, Some(block)) + ArrowFunctionBody::FunctionBody(body) => { + self.body_scope_flags(ScopeFlags::Function, Some(body)) } - BlockStmtOrExpr::Expr(_) => ScopeFlags::Function, + ArrowFunctionBody::Expr(_) => ScopeFlags::Function, }; - self.push_scope(flags, arrow.span); + let scope_id = self.push_scope(flags, arrow.span); - for param in &arrow.params { - self.collect_pat_bindings(param, SymbolFlags::Param); - } + self.visit_arrow_params(scope_id, arrow.span, &arrow.params); match &*arrow.body { - BlockStmtOrExpr::BlockStmt(block) => { - self.function_body_spans.insert(self.start(block.span)); - block.visit_with(self); + ArrowFunctionBody::FunctionBody(body) => { + body.visit_with(self); } - BlockStmtOrExpr::Expr(expr) => { + ArrowFunctionBody::Expr(expr) => { expr.visit_with(self); } } @@ -829,13 +1095,9 @@ impl Visit for SemanticBuilder { } fn visit_block_stmt(&mut self, block: &BlockStmt) { - if self.function_body_spans.remove(&self.start(block.span)) { - block.visit_children_with(self); - } else { - self.push_scope(ScopeFlags::empty(), block.span); - block.visit_children_with(self); - self.pop_scope(); - } + self.push_scope(ScopeFlags::empty(), block.span); + block.visit_children_with(self); + self.pop_scope(); } fn visit_for_stmt(&mut self, for_stmt: &ForStmt) { @@ -873,10 +1135,11 @@ impl Visit for SemanticBuilder { self.push_scope(ScopeFlags::CatchClause, catch.span); if let Some(param) = &catch.param { - self.collect_pat_bindings(param, SymbolFlags::CatchVariable); + let checkpoint = self.unresolved_references.len(); + self.collect_catch_pat_bindings(param); + self.resolve_references_from_checkpoint(checkpoint); } - self.function_body_spans.insert(self.start(catch.body.span)); catch.body.visit_with(self); self.pop_scope(); @@ -1050,26 +1313,13 @@ impl Visit for SemanticBuilder { assign.value.visit_with(self); } Prop::Getter(getter) => { - if let PropName::Computed(computed) = &getter.key { - computed.visit_with(self); - } - self.visit_accessor_inner(getter.span, None, getter.body.as_ref()); + self.visit_object_method(&getter.key, &getter.function); } Prop::Setter(setter) => { - if let PropName::Computed(computed) = &setter.key { - computed.visit_with(self); - } - self.visit_accessor_inner( - setter.span, - Some(setter.param.as_ref()), - setter.body.as_ref(), - ); + self.visit_object_method(&setter.key, &setter.function); } Prop::Method(method) => { - if let PropName::Computed(computed) = &method.key { - computed.visit_with(self); - } - self.visit_function_inner(&method.function, ScopeFlags::Function); + self.visit_object_method(&method.key, &method.function); } } } @@ -1105,55 +1355,7 @@ impl Visit for SemanticBuilder { impl SemanticBuilder { fn collect_pat_bindings_with_scope(&mut self, pat: &Pat, flags: SymbolFlags, scope: ScopeId) { - match pat { - Pat::Ident(binding_ident) => { - let _symbol_id = self.declare_symbol_on_scope( - binding_ident.id.span, - binding_ident.id.sym.to_string(), - flags, - scope, - ); - } - Pat::Array(arr) => { - for p in arr.elems.iter().flatten() { - self.collect_pat_bindings_with_scope(p, flags, scope); - } - } - Pat::Object(obj) => { - for prop in &obj.props { - match prop { - ObjectPatProp::KeyValue(kv) => { - if let PropName::Computed(computed) = &kv.key { - computed.visit_with(self); - } - self.collect_pat_bindings_with_scope(&kv.value, flags, scope); - } - ObjectPatProp::Assign(assign) => { - let _symbol_id = self.declare_symbol_on_scope( - assign.key.id.span, - assign.key.id.sym.to_string(), - flags, - scope, - ); - if let Some(value) = &assign.value { - value.visit_with(self); - } - } - ObjectPatProp::Rest(rest) => { - self.collect_pat_bindings_with_scope(&rest.arg, flags, scope); - } - } - } - } - Pat::Rest(rest) => { - self.collect_pat_bindings_with_scope(&rest.arg, flags, scope); - } - Pat::Assign(assign) => { - self.collect_pat_bindings_with_scope(&assign.left, flags, scope); - assign.right.visit_with(self); - } - Pat::Expr(_) | Pat::Invalid(_) => {} - } + self.collect_pat_bindings_in_scope(pat, flags, scope, None); } /// Consume the builder and produce a React Compiler [`ScopeInfo`]. @@ -1205,12 +1407,39 @@ impl SemanticBuilder { }); } + // Parameter scopes are internal resolution environments. They must not + // overwrite BindingData.scope or appear as scope-creating AST nodes in + // the React Compiler ScopeInfo. + let mut scope_to_out_scope: HashMap = HashMap::new(); + for scope_id in self.scoping.scope_descendants_from_root() { + if self.scoping.scope_flags(scope_id).is_parameter() { + continue; + } + let out_scope_id = OutScopeId(scope_to_out_scope.len() as u32); + scope_to_out_scope.insert(scope_id, out_scope_id); + } + + for symbol_id in self.scoping.symbol_ids() { + if let Some(&binding_id) = symbol_to_binding.get(&symbol_id) { + let symbol_scope_id = self.scoping.symbol_scope_id(symbol_id); + let out_scope_id = output_scope_for_internal_scope( + &self.scoping, + &scope_to_out_scope, + symbol_scope_id, + ); + bindings[binding_id.0 as usize].scope = out_scope_id; + } + } + // Second pass: Create all scopes and update binding scope references for scope_id in self.scoping.scope_descendants_from_root() { let scope_flags = self.scoping.scope_flags(scope_id); - let parent = self.scoping.scope_parent_id(scope_id); + if scope_flags.is_parameter() { + continue; + } - let out_scope_id = OutScopeId(scope_id.0); + let out_scope_id = scope_to_out_scope[&scope_id]; + let parent = output_parent_scope(&self.scoping, &scope_to_out_scope, scope_id); let kind = get_scope_kind(scope_flags); @@ -1219,7 +1448,6 @@ impl SemanticBuilder { if let Some(&binding_id) = symbol_to_binding.get(&symbol_id) { let name = bindings[binding_id.0 as usize].name.clone(); scope_bindings.insert(name, binding_id); - bindings[binding_id.0 as usize].scope = out_scope_id; } } @@ -1237,7 +1465,7 @@ impl SemanticBuilder { scopes.push(ScopeData { id: out_scope_id, - parent: parent.map(|p| OutScopeId(p.0)), + parent, kind, bindings: scope_bindings, }); @@ -1292,7 +1520,7 @@ impl SemanticBuilder { } } - let program_scope = OutScopeId(self.scoping.root_scope_id().0); + let program_scope = scope_to_out_scope[&self.scoping.root_scope_id()]; ScopeInfo { scopes, @@ -1307,6 +1535,37 @@ impl SemanticBuilder { } } +fn output_parent_scope( + scoping: &Scoping, + scope_to_out_scope: &HashMap, + scope_id: ScopeId, +) -> Option { + let mut parent_id = scoping.scope_parent_id(scope_id); + while let Some(parent) = parent_id { + if let Some(&out_parent) = scope_to_out_scope.get(&parent) { + return Some(out_parent); + } + parent_id = scoping.scope_parent_id(parent); + } + None +} + +fn output_scope_for_internal_scope( + scoping: &Scoping, + scope_to_out_scope: &HashMap, + mut scope_id: ScopeId, +) -> react_compiler_ast::scope::ScopeId { + loop { + if let Some(&out_scope_id) = scope_to_out_scope.get(&scope_id) { + return out_scope_id; + } + + scope_id = scoping + .scope_parent_id(scope_id) + .expect("internal scope should have an output ancestor"); + } +} + /// Build a map from import specifier span start to its import data. fn build_import_map( program: &Program, @@ -1365,7 +1624,7 @@ fn build_import_map( map } -/// Map our ScopeFlags to react_compiler_ast ScopeKind. +/// Map our `ScopeFlags` to `react_compiler_ast` `ScopeKind`. fn get_scope_kind(flags: ScopeFlags) -> react_compiler_ast::scope::ScopeKind { use react_compiler_ast::scope::ScopeKind; @@ -1396,7 +1655,7 @@ fn get_scope_kind(flags: ScopeFlags) -> react_compiler_ast::scope::ScopeKind { ScopeKind::Block } -/// Map our SymbolFlags to react_compiler_ast BindingKind. +/// Map our `SymbolFlags` to `react_compiler_ast` `BindingKind`. fn get_binding_kind(flags: SymbolFlags) -> react_compiler_ast::scope::BindingKind { use react_compiler_ast::scope::BindingKind; @@ -1419,9 +1678,8 @@ fn get_binding_kind(flags: SymbolFlags) -> react_compiler_ast::scope::BindingKin if flags.contains(SymbolFlags::BlockScopedVariable) { if flags.contains(SymbolFlags::ConstVariable) { return BindingKind::Const; - } else { - return BindingKind::Let; } + return BindingKind::Let; } if flags.contains(SymbolFlags::FunctionExpression) { diff --git a/deps/swc/crates/swc_ecma_react_compiler/src/diagnostics.rs b/deps/swc/crates/swc_ecma_react_compiler/src/diagnostics.rs index cb45f8ff0..c768b45a7 100644 --- a/deps/swc/crates/swc_ecma_react_compiler/src/diagnostics.rs +++ b/deps/swc/crates/swc_ecma_react_compiler/src/diagnostics.rs @@ -4,20 +4,73 @@ // LICENSE file in the root directory of this source tree. use react_compiler::entrypoint::compile_result::{ - CompileResult, CompilerErrorDetailInfo, CompilerErrorInfo, LoggerEvent, + CompileResult, CompilerErrorDetailInfo, CompilerErrorInfo, CompilerErrorItemInfo, LoggerEvent, + LoggerPosition, LoggerSourceLocation, }; +use serde::Serialize; #[derive(Debug, Clone)] pub enum Severity { Error, Warning, } +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum DiagnosticSeverity { + Error, + Warning, +} + +impl From<&Severity> for DiagnosticSeverity { + fn from(value: &Severity) -> Self { + match value { + Severity::Error => Self::Error, + Severity::Warning => Self::Warning, + } + } +} + +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct DiagnosticPosition { + pub line: u32, + pub column: u32, + #[serde(skip_serializing_if = "Option::is_none")] + pub index: Option, +} + +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct DiagnosticLocation { + pub start: DiagnosticPosition, + pub end: DiagnosticPosition, + #[serde(skip_serializing_if = "Option::is_none")] + pub filename: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub identifier_name: Option, +} + +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct DiagnosticDetail { + pub kind: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub loc: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub message: Option, +} #[derive(Debug, Clone)] pub struct DiagnosticMessage { pub severity: Severity, pub message: String, pub span: Option<(u32, u32)>, + pub rule_id: Option, + pub category: Option, + pub reason: Option, + pub description: Option, + pub loc: Option, + pub details: Vec, } /// Convert a [`CompileResult`] into SWC-facing diagnostics. @@ -63,11 +116,18 @@ fn error_info_to_diagnostic(error: &CompilerErrorInfo) -> DiagnosticMessage { severity: Severity::Error, message, span: None, + rule_id: None, + category: None, + reason: Some(error.reason.clone()), + description: error.description.clone(), + loc: None, + details: Vec::new(), } } fn error_detail_to_diagnostic( detail: &CompilerErrorDetailInfo, + fn_loc: Option<&LoggerSourceLocation>, suppress_error_diagnostics: bool, ) -> Option { let message = if let Some(description) = &detail.description { @@ -92,7 +152,20 @@ fn error_detail_to_diagnostic( Some(DiagnosticMessage { severity, message, - span: None, + span: primary_location(detail, fn_loc) + .and_then(|loc| Some((loc.start.index?, loc.end.index?))), + rule_id: rule_id_for_category(&detail.category).map(str::to_string), + category: Some(detail.category.clone()), + reason: Some(detail.reason.clone()), + description: detail.description.clone(), + loc: primary_location(detail, fn_loc).map(Into::into), + details: detail + .details + .as_deref() + .unwrap_or_default() + .iter() + .map(Into::into) + .collect(), }) } @@ -102,9 +175,11 @@ fn event_to_diagnostic( ) -> Option { match event { LoggerEvent::CompileSuccess { .. } | LoggerEvent::CompileSkip { .. } => None, - LoggerEvent::CompileError { detail, .. } - | LoggerEvent::CompileErrorWithLoc { detail, .. } => { - error_detail_to_diagnostic(detail, suppress_error_diagnostics) + LoggerEvent::CompileError { detail, fn_loc } => { + error_detail_to_diagnostic(detail, fn_loc.as_ref(), suppress_error_diagnostics) + } + LoggerEvent::CompileErrorWithLoc { detail, fn_loc } => { + error_detail_to_diagnostic(detail, Some(fn_loc), suppress_error_diagnostics) } LoggerEvent::CompileUnexpectedThrow { .. } | LoggerEvent::PipelineError { .. } if suppress_error_diagnostics => @@ -115,11 +190,404 @@ fn event_to_diagnostic( severity: Severity::Error, message: format!("[ReactCompiler] Unexpected error: {data}"), span: None, + rule_id: None, + category: None, + reason: Some("Unexpected error".into()), + description: Some(data.clone()), + loc: None, + details: Vec::new(), }), LoggerEvent::PipelineError { data, .. } => Some(DiagnosticMessage { severity: Severity::Error, message: format!("[ReactCompiler] Pipeline error: {data}"), span: None, + rule_id: None, + category: None, + reason: Some("Pipeline error".into()), + description: Some(data.clone()), + loc: None, + details: Vec::new(), }), } } + +fn primary_location<'a>( + detail: &'a CompilerErrorDetailInfo, + fn_loc: Option<&'a LoggerSourceLocation>, +) -> Option<&'a LoggerSourceLocation> { + detail + .details + .as_deref() + .and_then(|details| { + details + .iter() + .find(|detail| detail.kind == "error") + .and_then(|detail| detail.loc.as_ref()) + }) + .or(detail.loc.as_ref()) + .or(fn_loc) +} + +fn rule_id_for_category(category: &str) -> Option<&'static str> { + Some(match category { + "CapitalizedCalls" => "capitalized-calls", + "Config" => "config", + "EffectDependencies" => "memoized-effect-dependencies", + "EffectExhaustiveDependencies" => "exhaustive-effect-dependencies", + "EffectDerivationsOfState" => "no-deriving-state-in-effects", + "EffectSetState" => "set-state-in-effect", + "ErrorBoundaries" => "error-boundaries", + "FBT" => "fbt", + "Gating" => "gating", + "Globals" => "globals", + "Hooks" => "hooks", + "Immutability" => "immutability", + "Invariant" => "invariant", + "PreserveManualMemo" => "preserve-manual-memoization", + "Purity" => "purity", + "Refs" => "refs", + "RenderSetState" => "set-state-in-render", + "StaticComponents" => "static-components", + "Suppression" => "rule-suppression", + "Syntax" => "syntax", + "Todo" => "todo", + "UnsupportedSyntax" => "unsupported-syntax", + "UseMemo" => "use-memo", + "VoidUseMemo" => "void-use-memo", + "MemoDependencies" => "memo-dependencies", + "IncompatibleLibrary" => "incompatible-library", + _ => return None, + }) +} + +impl From<&LoggerPosition> for DiagnosticPosition { + fn from(value: &LoggerPosition) -> Self { + Self { + line: value.line, + column: value.column, + index: value.index, + } + } +} + +impl From<&LoggerSourceLocation> for DiagnosticLocation { + fn from(value: &LoggerSourceLocation) -> Self { + Self { + start: (&value.start).into(), + end: (&value.end).into(), + filename: value.filename.clone(), + identifier_name: value.identifier_name.clone(), + } + } +} + +impl From<&CompilerErrorItemInfo> for DiagnosticDetail { + fn from(value: &CompilerErrorItemInfo) -> Self { + Self { + kind: value.kind.clone(), + loc: value.loc.as_ref().map(Into::into), + message: value.message.clone(), + } + } +} + +#[cfg(test)] +mod tests { + use react_compiler::entrypoint::compile_result::{ + CompileResult, CompilerErrorDetailInfo, LoggerEvent, LoggerPosition, LoggerSourceLocation, + }; + + use super::{compile_result_to_diagnostics, Severity}; + + fn loc() -> LoggerSourceLocation { + LoggerSourceLocation { + start: LoggerPosition { + line: 3, + column: 10, + index: Some(42), + }, + end: LoggerPosition { + line: 3, + column: 21, + index: Some(53), + }, + filename: Some("input.tsx".into()), + identifier_name: Some("value".into()), + } + } + + fn detail(category: &str, severity: &str) -> CompilerErrorDetailInfo { + CompilerErrorDetailInfo { + category: category.into(), + reason: format!("{category} reason"), + description: Some(format!("{category} description")), + severity: severity.into(), + suggestions: None, + details: None, + loc: Some(loc()), + } + } + + fn diagnostic_for(category: &str, severity: &str) -> super::DiagnosticMessage { + let result = CompileResult::Success { + ast: None, + events: vec![LoggerEvent::CompileErrorWithLoc { + fn_loc: loc(), + detail: detail(category, severity), + }], + ordered_log: Vec::new(), + renames: Vec::new(), + timing: Vec::new(), + }; + + compile_result_to_diagnostics(&result, true) + .into_iter() + .next() + .unwrap() + } + + #[test] + fn maps_documented_react_compiler_rule_ids() { + let cases = [ + ("Config", "config"), + ("ErrorBoundaries", "error-boundaries"), + ("Gating", "gating"), + ("Globals", "globals"), + ("Immutability", "immutability"), + ("IncompatibleLibrary", "incompatible-library"), + ("PreserveManualMemo", "preserve-manual-memoization"), + ("Purity", "purity"), + ("Refs", "refs"), + ("EffectSetState", "set-state-in-effect"), + ("RenderSetState", "set-state-in-render"), + ("StaticComponents", "static-components"), + ("UnsupportedSyntax", "unsupported-syntax"), + ("UseMemo", "use-memo"), + ]; + + for (category, rule_id) in cases { + let diagnostic = diagnostic_for(category, "Error"); + assert_eq!(diagnostic.category.as_deref(), Some(category)); + assert_eq!(diagnostic.rule_id.as_deref(), Some(rule_id)); + } + } + + fn assert_category_maps_to_rule_id(category: &str, rule_id: &str) { + let diagnostic = diagnostic_for(category, "Error"); + assert_eq!(diagnostic.category.as_deref(), Some(category)); + assert_eq!(diagnostic.rule_id.as_deref(), Some(rule_id)); + } + + #[test] + fn react_docs_rule_id_config() { + assert_category_maps_to_rule_id("Config", "config"); + } + + #[test] + fn react_docs_rule_id_error_boundaries() { + assert_category_maps_to_rule_id("ErrorBoundaries", "error-boundaries"); + } + + #[test] + fn react_docs_rule_id_gating() { + assert_category_maps_to_rule_id("Gating", "gating"); + } + + #[test] + fn react_docs_rule_id_globals() { + assert_category_maps_to_rule_id("Globals", "globals"); + } + + #[test] + fn react_docs_rule_id_immutability() { + assert_category_maps_to_rule_id("Immutability", "immutability"); + } + + #[test] + fn react_docs_rule_id_incompatible_library() { + assert_category_maps_to_rule_id("IncompatibleLibrary", "incompatible-library"); + } + + #[test] + fn react_docs_rule_id_preserve_manual_memoization() { + assert_category_maps_to_rule_id("PreserveManualMemo", "preserve-manual-memoization"); + } + + #[test] + fn react_docs_rule_id_purity() { + assert_category_maps_to_rule_id("Purity", "purity"); + } + + #[test] + fn react_docs_rule_id_refs() { + assert_category_maps_to_rule_id("Refs", "refs"); + } + + #[test] + fn react_docs_rule_id_set_state_in_effect() { + assert_category_maps_to_rule_id("EffectSetState", "set-state-in-effect"); + } + + #[test] + fn react_docs_rule_id_set_state_in_render() { + assert_category_maps_to_rule_id("RenderSetState", "set-state-in-render"); + } + + #[test] + fn react_docs_rule_id_static_components() { + assert_category_maps_to_rule_id("StaticComponents", "static-components"); + } + + #[test] + fn react_docs_rule_id_unsupported_syntax() { + assert_category_maps_to_rule_id("UnsupportedSyntax", "unsupported-syntax"); + } + + #[test] + fn react_docs_rule_id_use_memo() { + assert_category_maps_to_rule_id("UseMemo", "use-memo"); + } + + #[test] + fn react_docs_rule_id_exhaustive_deps_is_not_react_compiler_backed() { + assert!(![ + "Config", + "ErrorBoundaries", + "Gating", + "Globals", + "Immutability", + "IncompatibleLibrary", + "PreserveManualMemo", + "Purity", + "Refs", + "EffectSetState", + "RenderSetState", + "StaticComponents", + "UnsupportedSyntax", + "UseMemo", + ] + .into_iter() + .any(|category| { + diagnostic_for(category, "Error").rule_id.as_deref() == Some("exhaustive-deps") + })); + } + + #[test] + fn react_docs_rule_id_rules_of_hooks_is_not_the_compiler_hooks_id() { + let diagnostic = diagnostic_for("Hooks", "Error"); + assert_eq!(diagnostic.rule_id.as_deref(), Some("hooks")); + assert_ne!(diagnostic.rule_id.as_deref(), Some("rules-of-hooks")); + } + + #[test] + fn react_docs_rule_id_component_hook_factories_is_deprecated_not_compiler_backed() { + assert!(![ + "Config", + "ErrorBoundaries", + "Gating", + "Globals", + "Immutability", + "IncompatibleLibrary", + "PreserveManualMemo", + "Purity", + "Refs", + "EffectSetState", + "RenderSetState", + "StaticComponents", + "UnsupportedSyntax", + "UseMemo", + ] + .into_iter() + .any(|category| { + diagnostic_for(category, "Error").rule_id.as_deref() == Some("component-hook-factories") + })); + } + + #[test] + fn preserves_structured_diagnostic_location() { + let diagnostic = diagnostic_for("Refs", "Error"); + let loc = diagnostic.loc.expect("expected loc"); + + assert_eq!(loc.start.line, 3); + assert_eq!(loc.start.column, 10); + assert_eq!(loc.start.index, Some(42)); + assert_eq!(loc.end.line, 3); + assert_eq!(loc.end.column, 21); + assert_eq!(loc.end.index, Some(53)); + assert_eq!(loc.filename.as_deref(), Some("input.tsx")); + assert_eq!(loc.identifier_name.as_deref(), Some("value")); + } + + #[test] + fn maps_warning_severity_without_suppressing_lint_output() { + let diagnostic = diagnostic_for("UnsupportedSyntax", "Warning"); + + assert!(matches!(diagnostic.severity, Severity::Warning)); + assert_eq!(diagnostic.rule_id.as_deref(), Some("unsupported-syntax")); + } + + #[test] + fn maps_compiler_hooks_category_to_hooks_not_rules_of_hooks() { + let diagnostic = diagnostic_for("Hooks", "Error"); + + assert_eq!(diagnostic.category.as_deref(), Some("Hooks")); + assert_eq!(diagnostic.rule_id.as_deref(), Some("hooks")); + } + + #[test] + fn documents_all_react_docs_recommended_rule_ids() { + let compiler_backed = [ + "config", + "error-boundaries", + "gating", + "globals", + "immutability", + "incompatible-library", + "preserve-manual-memoization", + "purity", + "refs", + "set-state-in-effect", + "set-state-in-render", + "static-components", + "unsupported-syntax", + "use-memo", + ]; + let non_compiler_backed_in_this_path = [ + // Standalone eslint-plugin-react-hooks rules. + "exhaustive-deps", + "rules-of-hooks", + // Deprecated wrapper rule in the local React plugin index, not a + // React Compiler diagnostic category. + "component-hook-factories", + ]; + + let mut documented_recommended = compiler_backed + .into_iter() + .chain(non_compiler_backed_in_this_path) + .collect::>(); + documented_recommended.sort_unstable(); + + assert_eq!( + documented_recommended, + vec![ + "component-hook-factories", + "config", + "error-boundaries", + "exhaustive-deps", + "gating", + "globals", + "immutability", + "incompatible-library", + "preserve-manual-memoization", + "purity", + "refs", + "rules-of-hooks", + "set-state-in-effect", + "set-state-in-render", + "static-components", + "unsupported-syntax", + "use-memo", + ] + ); + } +} diff --git a/deps/swc/crates/swc_ecma_react_compiler/src/fast_check.rs b/deps/swc/crates/swc_ecma_react_compiler/src/fast_check.rs index 31b59d25a..a07cd0eac 100644 --- a/deps/swc/crates/swc_ecma_react_compiler/src/fast_check.rs +++ b/deps/swc/crates/swc_ecma_react_compiler/src/fast_check.rs @@ -1,8 +1,17 @@ +use react_compiler_hir::environment::is_hook_name; use swc_ecma_ast::{ - Callee, ExportDefaultDecl, ExportDefaultExpr, Expr, FnDecl, FnExpr, Pat, Program, Stmt, - VarDeclarator, + ArrowExpr, ArrowFunctionBody, CallExpr, Callee, Expr, Function, JSXElement, JSXFragment, Lit, + MemberProp, Module, ModuleItem, Program, Script, Stmt, Str, }; use swc_ecma_visit::{Visit, VisitWith}; + +/// Conservatively determines whether infer or annotation mode could compile +/// anything. +/// +/// There may be false positives, but no false negatives: a `false` result means +/// compilation cannot change the program. This scans every function context for +/// JSX, plausible hook calls, and opt-in directives, including dynamic gating +/// directives. pub fn is_required(program: &Program) -> bool { let mut finder = Finder::default(); finder.visit_program(program); @@ -12,114 +21,154 @@ pub fn is_required(program: &Program) -> bool { #[derive(Default)] struct Finder { found: bool, +} + +fn is_hook_callee(expr: &Expr) -> bool { + match expr { + Expr::Ident(ident) => is_hook_name(&ident.sym), + Expr::Member(member) => { + let Expr::Ident(object) = &*member.obj else { + return false; + }; + let MemberProp::Ident(property) = &member.prop else { + return false; + }; - /// We are in a function that starts with a capital letter or it's a - /// function that starts with `use` - is_interested: bool, + object + .sym + .starts_with(|character: char| character.is_ascii_uppercase()) + && is_hook_name(&property.sym) + } + _ => false, + } } -impl Visit for Finder { - fn visit_callee(&mut self, node: &Callee) { - if self.is_interested { - if let Callee::Expr(e) = node { - if let Expr::Ident(c) = &**e { - if c.sym.starts_with("use") { - self.found = true; - return; - } - } - } +fn is_opt_in_directive(value: &Str) -> bool { + value.value.as_str().is_some_and(|value| { + matches!(value, "use memo" | "use forget") || value.starts_with("use memo if(") + }) +} + +fn has_opt_in_directive<'a>(statements: impl IntoIterator) -> bool { + for statement in statements { + if !statement.can_precede_directive() { + break; } - node.visit_children_with(self); + let Stmt::Expr(expression) = statement else { + continue; + }; + let Expr::Lit(Lit::Str(value)) = &*expression.expr else { + continue; + }; + if is_opt_in_directive(value) { + return true; + } } - fn visit_export_default_decl(&mut self, node: &ExportDefaultDecl) { - let old = self.is_interested; - - self.is_interested = true; + false +} - node.visit_children_with(self); +fn module_has_opt_in_directive(module: &Module) -> bool { + for item in &module.body { + let ModuleItem::Stmt(statement) = item else { + break; + }; + if !statement.can_precede_directive() { + break; + } - self.is_interested = old; + let Stmt::Expr(expression) = statement else { + continue; + }; + let Expr::Lit(Lit::Str(value)) = &*expression.expr else { + continue; + }; + if is_opt_in_directive(value) { + return true; + } } - fn visit_export_default_expr(&mut self, node: &ExportDefaultExpr) { - let old = self.is_interested; + false +} - self.is_interested = true; +impl Visit for Finder { + fn visit_arrow_expr(&mut self, node: &ArrowExpr) { + if let ArrowFunctionBody::FunctionBody(body) = &*node.body { + if has_opt_in_directive(&body.stmts) { + self.found = true; + return; + } + } node.visit_children_with(self); - - self.is_interested = old; } - fn visit_expr(&mut self, node: &Expr) { + fn visit_call_expr(&mut self, node: &CallExpr) { if self.found { return; } - if self.is_interested - && matches!( - node, - Expr::JSXMember(..) - | Expr::JSXNamespacedName(..) - | Expr::JSXEmpty(..) - | Expr::JSXElement(..) - | Expr::JSXFragment(..) - ) - { - self.found = true; - return; + if let Callee::Expr(expr) = &node.callee { + if is_hook_callee(expr) { + self.found = true; + return; + } } node.visit_children_with(self); } - fn visit_fn_decl(&mut self, node: &FnDecl) { - let old = self.is_interested; - - self.is_interested = node.ident.sym.starts_with("use") - || node.ident.sym.starts_with(|c: char| c.is_ascii_uppercase()); + fn visit_function(&mut self, node: &Function) { + if node + .body + .as_ref() + .is_some_and(|body| has_opt_in_directive(&body.stmts)) + { + self.found = true; + return; + } node.visit_children_with(self); + } - self.is_interested = old; + fn visit_jsx_element(&mut self, _: &JSXElement) { + self.found = true; } - fn visit_fn_expr(&mut self, node: &FnExpr) { - let old = self.is_interested; + fn visit_jsx_fragment(&mut self, _: &JSXFragment) { + self.found = true; + } - self.is_interested |= node.ident.as_ref().is_some_and(|ident| { - ident.sym.starts_with("use") || ident.sym.starts_with(|c: char| c.is_ascii_uppercase()) - }); + fn visit_module(&mut self, node: &Module) { + if module_has_opt_in_directive(node) { + self.found = true; + return; + } node.visit_children_with(self); - - self.is_interested = old; } - fn visit_stmt(&mut self, node: &Stmt) { + fn visit_module_item(&mut self, node: &ModuleItem) { if self.found { return; } node.visit_children_with(self); } - fn visit_var_declarator(&mut self, node: &VarDeclarator) { - let old = self.is_interested; - - if matches!(node.init.as_deref(), Some(Expr::Fn(..) | Expr::Arrow(..))) { - if let Pat::Ident(ident) = &node.name { - self.is_interested = ident.sym.starts_with("use") - || ident.sym.starts_with(|c: char| c.is_ascii_uppercase()); - } else { - self.is_interested = false; - } + fn visit_script(&mut self, node: &Script) { + if has_opt_in_directive(&node.body) { + self.found = true; + return; } node.visit_children_with(self); + } - self.is_interested = old; + fn visit_stmt(&mut self, node: &Stmt) { + if self.found { + return; + } + node.visit_children_with(self); } } @@ -155,6 +204,19 @@ mod tests { .unwrap(); } + fn assert_not_compiled(code: &str) { + let result = crate::transform_source( + code, + Syntax::Es(EsSyntax { + jsx: true, + ..Default::default() + }), + crate::default_plugin_options(), + ); + assert!(result.program.is_none()); + assert!(result.diagnostics.is_empty()); + } + #[test] fn lazy_return() { assert_required( @@ -275,4 +337,84 @@ mod tests { false, ); } + + #[test] + fn conservative_check_detects_wrapped_callbacks() { + let source = " + const Foo = React.forwardRef((props, ref) =>
); + const Bar = memo(() => ); + "; + assert_required(source, true); + } + + #[test] + fn conservative_check_detects_member_hooks() { + let source = " + function useCounter() { + return React.useState(0); + } + "; + assert_required(source, true); + } + + #[test] + fn conservative_check_skips_names_without_react_patterns() { + for source in [ + "export function App() { return React.createElement('div'); }", + "export function useComputed() { return 1; }", + ] { + assert_required(source, false); + assert_not_compiled(source); + } + } + + #[test] + fn conservative_check_skips_jsx_free_wrapped_components() { + let source = " + const Button = React.forwardRef((props, ref) => + React.createElement('button', { ref }, props.label) + ); + "; + assert_required(source, false); + assert_not_compiled(source); + } + + #[test] + fn conservative_check_matches_hook_naming() { + assert_required("const state = useState();", true); + assert_required("const value = use3rdParty();", true); + assert_required("const user = getUser();", false); + assert_required("const value = useless();", false); + } + + #[test] + fn conservative_check_detects_opt_in_directives() { + assert_required("function lower() { 'use memo'; return 1; }", true); + assert_required("function lower() { 'use forget'; return 1; }", true); + assert_required( + "function lower() { 'use memo if(featureFlag)'; return 1; }", + true, + ); + assert_required("'use memo'; export const answer = 42;", true); + assert_required( + "function lower() { 'use strict'; 'use memo'; return 1; }", + true, + ); + assert_required("const lower = () => { 'use memo'; return 1; };", true); + assert_required("function lower() { work(); 'use memo'; return 1; }", false); + assert_required("const lower = () => 'use memo';", false); + assert_required("const marker = 'use memo';", false); + assert_required("import value from 'use memo'; export default value;", false); + } + + #[test] + fn conservative_check_skips_plain_modules() { + assert_required( + " + export const answer = 42; + export function add(a, b) { return a + b; } + ", + false, + ); + } } diff --git a/deps/swc/crates/swc_ecma_react_compiler/src/lib.rs b/deps/swc/crates/swc_ecma_react_compiler/src/lib.rs index b804bb4db..d1cfaf6e4 100644 --- a/deps/swc/crates/swc_ecma_react_compiler/src/lib.rs +++ b/deps/swc/crates/swc_ecma_react_compiler/src/lib.rs @@ -20,7 +20,7 @@ use apply_renames::{apply_renames, build_rename_plan}; use convert_ast::convert_program; use convert_ast_reverse::convert_program_to_swc; use diagnostics::{compile_result_to_diagnostics, DiagnosticMessage}; -use prefilter::{has_react_like_functions, has_resource_management_declarations}; +use prefilter::has_resource_management_declarations; use react_compiler::entrypoint::compile_result::LoggerEvent; // Re-exported so integrations needn't depend on the upstream `react_compiler` crate. pub use react_compiler::entrypoint::plugin_options::{ @@ -28,7 +28,7 @@ pub use react_compiler::entrypoint::plugin_options::{ }; use react_compiler_hir::environment_config::EnvironmentConfig; pub use source_type::SourceType; -use swc_common::comments::SingleThreadedComments; +use swc_common::{comments::SingleThreadedComments, sync::Lrc, FileName}; use swc_ecma_ast::Program; use crate::{convert_ast::ConvertResult, convert_scope::SemanticBuilder}; @@ -84,16 +84,6 @@ pub fn transform( comments: Option<&SingleThreadedComments>, options: PluginOptions, ) -> TransformResult { - if !matches!(options.compilation_mode.as_str(), "all" | "annotation") - && !has_react_like_functions(program) - { - return TransformResult { - program: None, - diagnostics: vec![], - events: vec![], - }; - } - if has_resource_management_declarations(program) { return TransformResult { program: None, @@ -146,13 +136,13 @@ pub(crate) fn transform_source( syntax: swc_ecma_parser::Syntax, options: PluginOptions, ) -> TransformResult { - match parse_source_for_tests(source_text, syntax) { + match parse_source(source_text, syntax) { Ok((program, comments, source_type)) => { transform(&program, source_type, source_text, Some(&comments), options) } Err(diagnostic) => TransformResult { program: None, - diagnostics: vec![diagnostic], + diagnostics: vec![*diagnostic], events: vec![], }, } @@ -179,33 +169,30 @@ pub fn lint( } } -/// Convenience wrapper: parses source text, then lints. -#[cfg(test)] -pub(crate) fn lint_source( +/// Parses source text, then lints it. This is the entry point for callers +/// (e.g. the `@swc/react-compiler` napi binding) that have not already +/// parsed their source into a [`Program`]. +pub fn lint_source( source_text: &str, syntax: swc_ecma_parser::Syntax, options: PluginOptions, ) -> LintResult { - match parse_source_for_tests(source_text, syntax) { + match parse_source(source_text, syntax) { Ok((program, comments, source_type)) => { lint(&program, source_type, source_text, Some(&comments), options) } Err(diagnostic) => LintResult { - diagnostics: vec![diagnostic], + diagnostics: vec![*diagnostic], }, } } -#[cfg(test)] -fn parse_source_for_tests( +fn parse_source( source_text: &str, syntax: swc_ecma_parser::Syntax, -) -> Result<(Program, SingleThreadedComments, SourceType), DiagnosticMessage> { - let cm = std::sync::Arc::new(swc_common::SourceMap::default()); - let fm = cm.new_source_file( - std::sync::Arc::new(swc_common::FileName::Anon), - source_text.to_string(), - ); +) -> Result<(Program, SingleThreadedComments, SourceType), Box> { + let cm = Lrc::new(swc_common::SourceMap::default()); + let fm = cm.new_source_file(Lrc::new(FileName::Anon), source_text.to_string()); let comments = SingleThreadedComments::default(); let mut errors = Vec::new(); let is_typescript = syntax.typescript(); @@ -220,10 +207,16 @@ fn parse_source_for_tests( let source_type = SourceType::from_program(&program).with_typescript(is_typescript); Ok((program, comments, source_type)) } - Err(error) => Err(DiagnosticMessage { + Err(error) => Err(Box::new(DiagnosticMessage { severity: diagnostics::Severity::Error, message: format!("[ReactCompiler] Parse error: {error:?}"), span: None, - }), + rule_id: None, + category: None, + reason: Some("Parse error".into()), + description: None, + loc: None, + details: Vec::new(), + })), } } diff --git a/deps/swc/crates/swc_ecma_react_compiler/src/prefilter.rs b/deps/swc/crates/swc_ecma_react_compiler/src/prefilter.rs index 01a2df4a9..895a18a7c 100644 --- a/deps/swc/crates/swc_ecma_react_compiler/src/prefilter.rs +++ b/deps/swc/crates/swc_ecma_react_compiler/src/prefilter.rs @@ -3,20 +3,9 @@ // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. -use react_compiler_hir::environment::is_react_like_name; use swc_ecma_ast as swc; use swc_ecma_visit::{Visit, VisitWith}; -/// Whether the program contains a component or hook candidate. -pub fn has_react_like_functions(program: &swc::Program) -> bool { - let mut visitor = ReactLikeVisitor { - found: false, - current_name: None, - }; - program.visit_with(&mut visitor); - visitor.found -} - /// Whether the program contains `using` or `await using` declarations. pub fn has_resource_management_declarations(program: &swc::Program) -> bool { let mut visitor = ResourceManagementVisitor { found: false }; @@ -24,28 +13,6 @@ pub fn has_resource_management_declarations(program: &swc::Program) -> bool { visitor.found } -/// `memo`/`forwardRef` wrappers mark callback functions as component-like even -/// when the callback itself is anonymous. -fn is_component_wrapper(callee: &swc::Callee) -> bool { - let is_wrapper = |name: &str| matches!(name, "memo" | "forwardRef"); - match callee { - swc::Callee::Expr(expr) => match &**expr { - swc::Expr::Ident(id) => is_wrapper(&id.sym), - swc::Expr::Member(member) => match &member.prop { - swc::MemberProp::Ident(prop) => is_wrapper(&prop.sym), - _ => false, - }, - _ => false, - }, - _ => false, - } -} - -struct ReactLikeVisitor { - found: bool, - current_name: Option, -} - struct ResourceManagementVisitor { found: bool, } @@ -66,119 +33,3 @@ impl Visit for ResourceManagementVisitor { let _ = decl; } } - -impl Visit for ReactLikeVisitor { - fn visit_var_declarator(&mut self, decl: &swc::VarDeclarator) { - if self.found { - return; - } - - let name = match &decl.name { - swc::Pat::Ident(ident) => Some(ident.id.sym.to_string()), - _ => None, - }; - - let prev_name = self.current_name.take(); - self.current_name = name; - - if let Some(init) = &decl.init { - init.visit_with(self); - } - - self.current_name = prev_name; - } - - fn visit_assign_expr(&mut self, expr: &swc::AssignExpr) { - if self.found { - return; - } - - let name = match &expr.left { - swc::AssignTarget::Simple(swc::SimpleAssignTarget::Ident(ident)) => { - Some(ident.id.sym.to_string()) - } - _ => None, - }; - - let prev_name = self.current_name.take(); - self.current_name = name; - - expr.right.visit_with(self); - - self.current_name = prev_name; - } - - fn visit_fn_decl(&mut self, decl: &swc::FnDecl) { - if self.found { - return; - } - - if is_react_like_name(&decl.ident.sym) { - self.found = true; - } - - // Do not traverse into function bodies. - } - - fn visit_fn_expr(&mut self, expr: &swc::FnExpr) { - if self.found { - return; - } - - if let Some(id) = &expr.ident { - if is_react_like_name(&id.sym) { - self.found = true; - return; - } - } - - if expr.ident.is_none() { - if let Some(name) = &self.current_name { - if is_react_like_name(name) { - self.found = true; - } - } - } - - // Do not traverse into function bodies. - } - - fn visit_arrow_expr(&mut self, expr: &swc::ArrowExpr) { - if self.found { - return; - } - - if let Some(name) = &self.current_name { - if is_react_like_name(name) { - self.found = true; - return; - } - } - - // Do not traverse into function bodies. - let _ = expr; - } - - fn visit_call_expr(&mut self, call: &swc::CallExpr) { - if self.found { - return; - } - - if is_component_wrapper(&call.callee) - && call - .args - .iter() - .any(|arg| matches!(&*arg.expr, swc::Expr::Fn(_) | swc::Expr::Arrow(_))) - { - self.found = true; - return; - } - - call.visit_children_with(self); - } - - fn visit_class(&mut self, class: &swc::Class) { - // Skip class bodies entirely. - let _ = class; - } -} diff --git a/deps/swc/crates/swc_ecma_react_compiler/src/preserved_ast.rs b/deps/swc/crates/swc_ecma_react_compiler/src/preserved_ast.rs index b40b6d24f..04cc3989c 100644 --- a/deps/swc/crates/swc_ecma_react_compiler/src/preserved_ast.rs +++ b/deps/swc/crates/swc_ecma_react_compiler/src/preserved_ast.rs @@ -42,10 +42,16 @@ pub struct ArrowShell { /// AST. #[derive(Clone)] pub struct FunctionShell { + this_param: Option>, params: Vec, decorators: Vec, type_params: Option>, return_type: Option>, + /// Whether the source function had an implementation body. + /// + /// React Compiler's `FunctionDeclaration` always has a block body, so this + /// is required to restore TypeScript overload signatures after compilation. + had_body: bool, } /// Lightweight variable declaration metadata not represented losslessly in @@ -262,10 +268,12 @@ impl PreservedAst { self.nodes.insert( function.span.lo.to_u32(), PreservedNode::Function(Box::new(FunctionShell { + this_param: function.this_param.clone(), params: function.params.clone(), decorators: function.decorators.clone(), type_params: function.type_params.clone(), return_type: function.return_type.clone(), + had_body: function.body.is_some(), })), ); } @@ -280,6 +288,10 @@ impl PreservedAst { unreachable!() }; + if !snapshot.had_body { + function.body = None; + } + function.this_param = snapshot.this_param; function.decorators = snapshot.decorators; function.type_params = snapshot.type_params; function.return_type = snapshot.return_type; @@ -303,6 +315,7 @@ impl PreservedAst { unreachable!() }; + function.this_param = snapshot.this_param; function.decorators = snapshot.decorators; function.type_params = snapshot.type_params; function.return_type = snapshot.return_type; diff --git a/deps/swc/crates/swc_ecma_regexp/Cargo.toml b/deps/swc/crates/swc_ecma_regexp/Cargo.toml index 347264859..c3c37434c 100644 --- a/deps/swc/crates/swc_ecma_regexp/Cargo.toml +++ b/deps/swc/crates/swc_ecma_regexp/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/**/*.json"] license = { workspace = true } name = "swc_ecma_regexp" repository = "https://github.com/swc-project/swc.git" -version = "0.12.0" +version = "0.15.0" [lib] bench = false @@ -20,11 +20,11 @@ phf = { workspace = true, features = ["macros"] } rustc-hash = { workspace = true } unicode-id-start = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_regexp_ast = { version = "0.12.0", path = "../swc_ecma_regexp_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_regexp_ast = { version = "3.0.0", path = "../swc_ecma_regexp_ast" } swc_ecma_regexp_common = { version = "0.0.1", path = "../swc_ecma_regexp_common" } -swc_ecma_regexp_visit = { version = "0.12.0", path = "../swc_ecma_regexp_visit" } +swc_ecma_regexp_visit = { version = "0.15.0", path = "../swc_ecma_regexp_visit" } [dev-dependencies] diff --git a/deps/swc/crates/swc_ecma_regexp_ast/Cargo.toml b/deps/swc/crates/swc_ecma_regexp_ast/Cargo.toml index 919fd7f13..920c54687 100644 --- a/deps/swc/crates/swc_ecma_regexp_ast/Cargo.toml +++ b/deps/swc/crates/swc_ecma_regexp_ast/Cargo.toml @@ -6,20 +6,18 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_regexp_ast" repository = { workspace = true } -version = "0.12.0" +version = "3.0.0" [lib] bench = false [features] -__rkyv = [] default = [] encoding-impl = [ "cbor4ii", "swc_atoms/encoding-impl", "swc_common/encoding-impl", ] -rkyv-impl = [] serde-impl = ["serde"] [dependencies] @@ -28,6 +26,6 @@ cbor4ii = { workspace = true, features = ["use_std"], optional = true } is-macro = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } swc_ecma_regexp_common = { version = "0.0.1", path = "../swc_ecma_regexp_common" } diff --git a/deps/swc/crates/swc_ecma_regexp_visit/Cargo.toml b/deps/swc/crates/swc_ecma_regexp_visit/Cargo.toml index a0b4738cc..8b1c329c2 100644 --- a/deps/swc/crates/swc_ecma_regexp_visit/Cargo.toml +++ b/deps/swc/crates/swc_ecma_regexp_visit/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_regexp_visit" repository = { workspace = true } -version = "0.12.0" +version = "0.15.0" [lib] bench = false @@ -19,7 +19,7 @@ serde-impl = ["serde"] [dependencies] serde = { workspace = true, optional = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_regexp_ast = { version = "0.12.0", path = "../swc_ecma_regexp_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_regexp_ast = { version = "3.0.0", path = "../swc_ecma_regexp_ast" } swc_visit = { version = "2.0.1", path = "../swc_visit" } diff --git a/deps/swc/crates/swc_ecma_testing/Cargo.toml b/deps/swc/crates/swc_ecma_testing/Cargo.toml index cde59fc36..393001c5e 100644 --- a/deps/swc/crates/swc_ecma_testing/Cargo.toml +++ b/deps/swc/crates/swc_ecma_testing/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_testing" repository = { workspace = true } -version = "24.0.1" +version = "27.0.0" [lib] bench = false @@ -17,4 +17,4 @@ hex = { workspace = true } sha2 = { workspace = true } tracing = { workspace = true } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_ecma_transformer/Cargo.toml b/deps/swc/crates/swc_ecma_transformer/Cargo.toml index 5ac346deb..967467594 100644 --- a/deps/swc/crates/swc_ecma_transformer/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transformer/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_transformer" repository = { workspace = true } -version = "16.0.3" +version = "21.0.0" [features] default = [] @@ -18,15 +18,15 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] rustc-hash = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_compat_regexp = { version = "6.0.0", path = "../swc_ecma_compat_regexp" } -swc_ecma_hooks = { version = "0.9.0", path = "../swc_ecma_hooks" } -swc_ecma_regexp = { version = "0.12.0", path = "../swc_ecma_regexp" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_compat_regexp = { version = "9.0.0", path = "../swc_ecma_compat_regexp" } +swc_ecma_hooks = { version = "1.0.0", path = "../swc_ecma_hooks" } +swc_ecma_regexp = { version = "0.15.0", path = "../swc_ecma_regexp" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit", features = [ "path", ] } tracing = { workspace = true } diff --git a/deps/swc/crates/swc_ecma_transformer/src/common/statement_injector.rs b/deps/swc/crates/swc_ecma_transformer/src/common/statement_injector.rs index e12d93f47..7ff65b3ca 100644 --- a/deps/swc/crates/swc_ecma_transformer/src/common/statement_injector.rs +++ b/deps/swc/crates/swc_ecma_transformer/src/common/statement_injector.rs @@ -85,26 +85,25 @@ impl VisitMutHook for StmtInjector { fn enter_arrow_expr(&mut self, node: &mut ArrowExpr, _: &mut TraverseCtx) { // We convert the arrow body to a block statement with a return statement // because we cannot inject statements after the arrow body. - if let BlockStmtOrExpr::Expr(expr) = &mut *node.body { - *node.body = BlockStmtOrExpr::BlockStmt(BlockStmt { + if let ArrowFunctionBody::Expr(expr) = &mut *node.body { + *node.body = ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, arg: Some(expr.take()), })], - ..Default::default() }); } } fn exit_arrow_expr(&mut self, node: &mut ArrowExpr, _: &mut TraverseCtx) { - if let BlockStmtOrExpr::BlockStmt(block_stmt) = &mut *node.body { + if let ArrowFunctionBody::FunctionBody(block_stmt) = &mut *node.body { // If the block statement is something we inserted, we need to // convert it back to an expression. if block_stmt.span == DUMMY_SP && block_stmt.stmts.len() == 1 { if let Stmt::Return(return_stmt) = &mut block_stmt.stmts[0] { if return_stmt.span == DUMMY_SP { - *node.body = BlockStmtOrExpr::Expr(return_stmt.arg.take().unwrap()); + *node.body = ArrowFunctionBody::Expr(return_stmt.arg.take().unwrap()); } } } diff --git a/deps/swc/crates/swc_ecma_transformer/src/common/var_declarations.rs b/deps/swc/crates/swc_ecma_transformer/src/common/var_declarations.rs index 5a062719b..ee2b1e7ba 100644 --- a/deps/swc/crates/swc_ecma_transformer/src/common/var_declarations.rs +++ b/deps/swc/crates/swc_ecma_transformer/src/common/var_declarations.rs @@ -37,10 +37,10 @@ pub struct VarDeclarations { #[derive(Debug)] struct ArrowExprScope { - /// The `BlockStmtOrExpr` for an expression-bodied arrow. Starting the scope - /// here keeps generated temps out of params while still catching body - /// transforms that queue declarations in `enter_expr`. - body: *const BlockStmtOrExpr, + /// The `ArrowFunctionBody` for an expression-bodied arrow. Starting the + /// scope here keeps generated temps out of params while still catching + /// body transforms that queue declarations in `enter_expr`. + body: *const ArrowFunctionBody, started: bool, declarations: Option<(Option, Option)>, } @@ -48,12 +48,12 @@ struct ArrowExprScope { impl VisitMutHook for VarDeclarations { fn enter_arrow_expr(&mut self, node: &mut ArrowExpr, _ctx: &mut TraverseCtx) { self.arrow_exprs.push(match &mut *node.body { - BlockStmtOrExpr::Expr(_) => Some(ArrowExprScope { + ArrowFunctionBody::Expr(_) => Some(ArrowExprScope { body: &*node.body, started: false, declarations: None, }), - BlockStmtOrExpr::BlockStmt(_) => None, + ArrowFunctionBody::FunctionBody(_) => None, #[cfg(swc_ast_unknown)] _ => None, }); @@ -73,25 +73,24 @@ impl VisitMutHook for VarDeclarations { }; match &mut *node.body { - BlockStmtOrExpr::Expr(expr) => { + ArrowFunctionBody::Expr(expr) => { stmts.push(Stmt::Return(ReturnStmt { span: DUMMY_SP, arg: Some(expr.take()), })); - *node.body = BlockStmtOrExpr::BlockStmt(BlockStmt { + *node.body = ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts, - ..Default::default() }); } - BlockStmtOrExpr::BlockStmt(block) => Self::insert_arrow_declarations(block, stmts), + ArrowFunctionBody::FunctionBody(body) => Self::insert_arrow_declarations(body, stmts), #[cfg(swc_ast_unknown)] _ => {} } } - fn enter_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut TraverseCtx) { + fn enter_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut TraverseCtx) { let Some(Some(scope)) = self.arrow_exprs.last_mut() else { return; }; @@ -102,7 +101,7 @@ impl VisitMutHook for VarDeclarations { } } - fn exit_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr, ctx: &mut TraverseCtx) { + fn exit_arrow_function_body(&mut self, node: &mut ArrowFunctionBody, ctx: &mut TraverseCtx) { let Some(Some(scope)) = self.arrow_exprs.last_mut() else { return; }; @@ -149,7 +148,7 @@ impl VarDeclarations { Some(stmts) } - fn insert_arrow_declarations(block: &mut BlockStmt, declarations: Vec) { + fn insert_arrow_declarations(block: &mut FunctionBody, declarations: Vec) { if declarations.is_empty() { return; } diff --git a/deps/swc/crates/swc_ecma_transformer/src/es2017/async_to_generator.rs b/deps/swc/crates/swc_ecma_transformer/src/es2017/async_to_generator.rs index 08fa30411..eb5beaee8 100644 --- a/deps/swc/crates/swc_ecma_transformer/src/es2017/async_to_generator.rs +++ b/deps/swc/crates/swc_ecma_transformer/src/es2017/async_to_generator.rs @@ -13,6 +13,8 @@ use swc_ecma_visit::VisitMutWith; use crate::TraverseCtx; pub fn hook( + transform_async_to_generator: bool, + transform_async_generator_functions: bool, unresolved_ctxt: SyntaxContext, ignore_function_length: bool, ) -> impl VisitMutHook { @@ -23,13 +25,15 @@ pub fn hook( in_subclass_stack: vec![], ignore_function_length, unresolved_ctxt, + transform_async_to_generator, + transform_async_generator_functions, this_var: None, } } #[derive(Default, Clone, Debug)] struct FnState { - is_async: bool, + should_transform: bool, is_generator: bool, use_this: bool, use_arguments: bool, @@ -46,6 +50,10 @@ struct AsyncToGeneratorPass { in_subclass_stack: Vec, ignore_function_length: bool, unresolved_ctxt: SyntaxContext, + /// Whether ordinary async functions should be lowered. + transform_async_to_generator: bool, + /// Whether async generators should be lowered. + transform_async_generator_functions: bool, /// The `_this` identifier to use in constructor context this_var: Option, } @@ -62,7 +70,7 @@ impl VisitMutHook for AsyncToGeneratorPass { return; }; - if !fn_state.is_async { + if !fn_state.should_transform { // Restore the previous fn_state from stack self.fn_state = self.fn_state_stack.pop(); return; @@ -122,9 +130,9 @@ impl VisitMutHook for AsyncToGeneratorPass { .into(), ); - function.body = Some(BlockStmt { + function.body = Some(FunctionBody { + span: DUMMY_SP, stmts, - ..Default::default() }); // Restore the previous fn_state from stack after processing async function @@ -142,14 +150,19 @@ impl VisitMutHook for AsyncToGeneratorPass { } self.fn_state = Some(FnState { - is_async: function.is_async, + should_transform: function.is_async + && if function.is_generator { + self.transform_async_generator_functions + } else { + self.transform_async_to_generator + }, is_generator: function.is_generator, ..Default::default() }); } fn exit_arrow_expr(&mut self, arrow_expr: &mut ArrowExpr, _ctx: &mut TraverseCtx) { - if !arrow_expr.is_async { + if !arrow_expr.is_async || !self.transform_async_to_generator { return; } @@ -191,20 +204,20 @@ impl VisitMutHook for AsyncToGeneratorPass { self.this_var = Some(private_ident!("_this")); } let this_var = self.this_var.clone().unwrap(); - replace_this_in_block_stmt_or_expr(&mut arrow_expr.body, &this_var); + replace_this_in_arrow_function_body(&mut arrow_expr.body, &this_var); } arrow_expr.is_async = false; let body = match *arrow_expr.body.take() { - BlockStmtOrExpr::BlockStmt(block_stmt) => block_stmt, - BlockStmtOrExpr::Expr(expr) => BlockStmt { + ArrowFunctionBody::FunctionBody(body) => body, + ArrowFunctionBody::Expr(expr) => FunctionBody { + span: DUMMY_SP, stmts: vec![ReturnStmt { arg: Some(expr), ..Default::default() } .into()], - ..Default::default() }, #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), @@ -214,18 +227,18 @@ impl VisitMutHook for AsyncToGeneratorPass { arrow_expr.body = if fn_state.use_super { stmts.push(expr.into_stmt()); - BlockStmtOrExpr::BlockStmt(BlockStmt { + ArrowFunctionBody::FunctionBody(FunctionBody { + span: DUMMY_SP, stmts, - ..Default::default() }) } else { - BlockStmtOrExpr::Expr(Box::new(expr)) + ArrowFunctionBody::Expr(Box::new(expr)) } .into() } fn enter_arrow_expr(&mut self, arrow_expr: &mut ArrowExpr, _ctx: &mut TraverseCtx) { - if !arrow_expr.is_async { + if !arrow_expr.is_async || !self.transform_async_to_generator { return; } @@ -241,7 +254,7 @@ impl VisitMutHook for AsyncToGeneratorPass { } self.fn_state = Some(FnState { - is_async: true, + should_transform: true, is_generator: false, in_constructor, ..Default::default() @@ -277,7 +290,7 @@ impl VisitMutHook for AsyncToGeneratorPass { let fn_state = self.fn_state.take(); // If any async arrows used `this`, we need to add var _this and _this = this - if let Some(BlockStmt { stmts, .. }) = &mut constructor.body { + if let Some(FunctionBody { stmts, .. }) = &mut constructor.body { if let Some(fn_state) = &fn_state { if fn_state.use_this { let this_var = self.this_var.take().unwrap(); @@ -308,28 +321,14 @@ impl VisitMutHook for AsyncToGeneratorPass { } } - fn enter_getter_prop(&mut self, _f: &mut GetterProp, _ctx: &mut TraverseCtx) { - if let Some(prev) = self.fn_state.take() { - self.fn_state_stack.push(prev); - } - } - - fn exit_getter_prop(&mut self, _f: &mut GetterProp, _ctx: &mut TraverseCtx) { - self.fn_state = self.fn_state_stack.pop(); - } - - fn enter_setter_prop(&mut self, _f: &mut SetterProp, _ctx: &mut TraverseCtx) { - if let Some(prev) = self.fn_state.take() { - self.fn_state_stack.push(prev); - } - } - - fn exit_setter_prop(&mut self, _f: &mut SetterProp, _ctx: &mut TraverseCtx) { - self.fn_state = self.fn_state_stack.pop(); - } - fn exit_expr(&mut self, expr: &mut Expr, _ctx: &mut TraverseCtx) { - let Some(fn_state @ FnState { is_async: true, .. }) = &mut self.fn_state else { + let Some( + fn_state @ FnState { + should_transform: true, + .. + }, + ) = &mut self.fn_state + else { return; }; @@ -390,7 +389,7 @@ impl VisitMutHook for AsyncToGeneratorPass { fn exit_stmt(&mut self, stmt: &mut Stmt, _ctx: &mut TraverseCtx) { if let Some(FnState { - is_async: true, + should_transform: true, is_generator, .. }) = self.fn_state @@ -410,7 +409,7 @@ impl VisitMutHook for AsyncToGeneratorPass { /// /// `_async_to_generator(function*() {})()` from `async function() {}`; #[cfg_attr(debug_assertions, tracing::instrument(level = "debug", skip_all))] -fn make_fn_ref(fn_state: &FnState, params: Vec, body: BlockStmt) -> Expr { +fn make_fn_ref(fn_state: &FnState, params: Vec, body: FunctionBody) -> Expr { let helper = if fn_state.is_generator { helper_expr!(DUMMY_SP, wrap_async_generator) } else { @@ -874,13 +873,13 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) { } /// Replace all `this` expressions with the given identifier in a -/// BlockStmtOrExpr -fn replace_this_in_block_stmt_or_expr(body: &mut BlockStmtOrExpr, this_var: &Ident) { +/// Arrow function body. +fn replace_this_in_arrow_function_body(body: &mut ArrowFunctionBody, this_var: &Ident) { match body { - BlockStmtOrExpr::BlockStmt(block) => { + ArrowFunctionBody::FunctionBody(block) => { replace_this_in_stmts(&mut block.stmts, this_var); } - BlockStmtOrExpr::Expr(expr) => { + ArrowFunctionBody::Expr(expr) => { replace_this_in_expr(expr, this_var); } #[cfg(swc_ast_unknown)] @@ -1205,7 +1204,7 @@ fn replace_this_in_expr(expr: &mut Expr, this_var: &Ident) { // Arrow functions don't have their own `this` context - they inherit from the // enclosing scope, so we need to traverse into them Expr::Arrow(arrow) => { - replace_this_in_block_stmt_or_expr(&mut arrow.body, this_var); + replace_this_in_arrow_function_body(&mut arrow.body, this_var); } // Don't traverse into nested functions/classes as they have their own `this` context Expr::Fn(_) | Expr::Class(_) => {} diff --git a/deps/swc/crates/swc_ecma_transformer/src/es2017/mod.rs b/deps/swc/crates/swc_ecma_transformer/src/es2017/mod.rs index e949a6e24..b883b6c0b 100644 --- a/deps/swc/crates/swc_ecma_transformer/src/es2017/mod.rs +++ b/deps/swc/crates/swc_ecma_transformer/src/es2017/mod.rs @@ -8,13 +8,18 @@ use crate::TraverseCtx; #[derive(Debug, Default)] #[non_exhaustive] pub struct Es2017Options { + /// Lower async functions to generators. This also lowers async generators + /// to preserve the existing behavior of this option. pub async_to_generator: bool, + + /// Lower async generators without lowering ordinary async functions. + pub async_generator_functions: bool, } impl Es2017Options { /// Returns true if any transform is enabled. pub fn is_enabled(&self) -> bool { - self.async_to_generator + self.async_to_generator || self.async_generator_functions } } @@ -23,8 +28,10 @@ pub fn hook( unresolved_ctxt: SyntaxContext, ignore_function_length: bool, ) -> impl VisitMutHook { - if options.async_to_generator { + if options.is_enabled() { Some(async_to_generator::hook( + options.async_to_generator, + options.async_to_generator || options.async_generator_functions, unresolved_ctxt, ignore_function_length, )) diff --git a/deps/swc/crates/swc_ecma_transformer/src/es2018/object_rest_spread.rs b/deps/swc/crates/swc_ecma_transformer/src/es2018/object_rest_spread.rs index efd93637f..7cb097395 100644 --- a/deps/swc/crates/swc_ecma_transformer/src/es2018/object_rest_spread.rs +++ b/deps/swc/crates/swc_ecma_transformer/src/es2018/object_rest_spread.rs @@ -5,7 +5,9 @@ use swc_common::{util::take::Take, Spanned, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_hooks::VisitMutHook; use swc_ecma_transforms_base::{assumptions::Assumptions, helper, helper_expr}; -use swc_ecma_utils::{alias_if_required, private_ident, quote_ident, ExprFactory}; +use swc_ecma_utils::{ + alias_if_required, number::ToJsString, private_ident, quote_ident, ExprFactory, +}; use crate::TraverseCtx; @@ -302,10 +304,10 @@ impl VisitMutHook for ObjectRestSpreadPass { if !stmts.is_empty() { // Insert into body match &mut *arrow.body { - BlockStmtOrExpr::BlockStmt(block) => { + ArrowFunctionBody::FunctionBody(block) => { prepend_stmts_to_front(&mut block.stmts, stmts); } - BlockStmtOrExpr::Expr(expr) => { + ArrowFunctionBody::Expr(expr) => { let mut body_stmts = stmts; body_stmts.push( ReturnStmt { @@ -314,9 +316,9 @@ impl VisitMutHook for ObjectRestSpreadPass { } .into(), ); - *arrow.body = BlockStmtOrExpr::BlockStmt(BlockStmt { + *arrow.body = ArrowFunctionBody::FunctionBody(FunctionBody { + span: DUMMY_SP, stmts: body_stmts, - ..Default::default() }); } #[cfg(swc_ast_unknown)] @@ -1053,7 +1055,7 @@ fn make_rest_call(config: Config, source: Ident, excluded: Vec) -> Exp PropName::Str(s) => Expr::Lit(Lit::Str(s)), PropName::Num(n) => Expr::Lit(Lit::Str(Str { span: n.span, - value: n.value.to_string().into(), + value: n.value.to_js_string().into(), raw: None, })), PropName::Computed(c) if impure_count == 1 && !is_lit_str(&c.expr) => CallExpr { diff --git a/deps/swc/crates/swc_ecma_transformer/src/es2022/class_static_block.rs b/deps/swc/crates/swc_ecma_transformer/src/es2022/class_static_block.rs index 2c1504ccc..ef3112e90 100644 --- a/deps/swc/crates/swc_ecma_transformer/src/es2022/class_static_block.rs +++ b/deps/swc/crates/swc_ecma_transformer/src/es2022/class_static_block.rs @@ -149,10 +149,9 @@ impl ClassStaticBlock { let arrow = ArrowExpr { span: DUMMY_SP, params: vec![], - body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt { + body: Box::new(ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts, - ctxt: Default::default(), })), is_async: false, is_generator: false, diff --git a/deps/swc/crates/swc_ecma_transformer/src/es2022/private_property_in_object.rs b/deps/swc/crates/swc_ecma_transformer/src/es2022/private_property_in_object.rs index f7ac565a3..623311b66 100644 --- a/deps/swc/crates/swc_ecma_transformer/src/es2022/private_property_in_object.rs +++ b/deps/swc/crates/swc_ecma_transformer/src/es2022/private_property_in_object.rs @@ -329,7 +329,10 @@ impl VisitMutHook for PrivatePropertyInObjectPass { callee: ArrowExpr { span: DUMMY_SP, params: Default::default(), - body: Box::new(BlockStmtOrExpr::BlockStmt(bs)), + body: Box::new(ArrowFunctionBody::FunctionBody(FunctionBody { + span: bs.span, + stmts: bs.stmts, + })), is_async: false, is_generator: false, type_params: Default::default(), diff --git a/deps/swc/crates/swc_ecma_transformer/src/hook_utils.rs b/deps/swc/crates/swc_ecma_transformer/src/hook_utils.rs index 06debc5ce..ebb739212 100644 --- a/deps/swc/crates/swc_ecma_transformer/src/hook_utils.rs +++ b/deps/swc/crates/swc_ecma_transformer/src/hook_utils.rs @@ -43,9 +43,9 @@ where chained_method!(enter_block_stmt, exit_block_stmt, BlockStmt); chained_method!( - enter_block_stmt_or_expr, - exit_block_stmt_or_expr, - BlockStmtOrExpr + enter_arrow_function_body, + exit_arrow_function_body, + ArrowFunctionBody ); chained_method!(enter_module_item, exit_module_item, ModuleItem); diff --git a/deps/swc/crates/swc_ecma_transformer/src/lib.rs b/deps/swc/crates/swc_ecma_transformer/src/lib.rs index 7929cdf1e..77d9523cd 100644 --- a/deps/swc/crates/swc_ecma_transformer/src/lib.rs +++ b/deps/swc/crates/swc_ecma_transformer/src/lib.rs @@ -177,6 +177,8 @@ pub fn es2017_async_to_generator( ignore_function_length: bool, ) -> impl Pass { hook_pass(crate::es2017::async_to_generator::hook( + true, + true, unresolved_ctxt, ignore_function_length, )) diff --git a/deps/swc/crates/swc_ecma_transforms/Cargo.toml b/deps/swc/crates/swc_ecma_transforms/Cargo.toml index 6bb412450..de14d82f9 100644 --- a/deps/swc/crates/swc_ecma_transforms/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_transforms" repository = { workspace = true } -version = "56.0.0" +version = "62.0.0" [package.metadata.docs.rs] all-features = true @@ -38,23 +38,23 @@ typescript = ["swc_ecma_transforms_typescript"] [dependencies] par-core = { workspace = true } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_compat = { version = "52.0.1", path = "../swc_ecma_transforms_compat", optional = true, default-features = false } -swc_ecma_transforms_module = { version = "49.0.1", path = "../swc_ecma_transforms_module", optional = true } -swc_ecma_transforms_optimization = { version = "47.0.1", path = "../swc_ecma_transforms_optimization", optional = true } -swc_ecma_transforms_proposal = { version = "44.0.1", path = "../swc_ecma_transforms_proposal", optional = true } -swc_ecma_transforms_react = { version = "50.0.0", path = "../swc_ecma_transforms_react", optional = true } -swc_ecma_transforms_typescript = { version = "50.0.0", path = "../swc_ecma_transforms_typescript", optional = true } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_compat = { version = "57.0.0", path = "../swc_ecma_transforms_compat", optional = true, default-features = false } +swc_ecma_transforms_module = { version = "55.0.0", path = "../swc_ecma_transforms_module", optional = true } +swc_ecma_transforms_optimization = { version = "52.0.0", path = "../swc_ecma_transforms_optimization", optional = true } +swc_ecma_transforms_proposal = { version = "49.0.0", path = "../swc_ecma_transforms_proposal", optional = true } +swc_ecma_transforms_react = { version = "55.0.0", path = "../swc_ecma_transforms_react", optional = true } +swc_ecma_transforms_typescript = { version = "55.0.0", path = "../swc_ecma_transforms_typescript", optional = true } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } [dev-dependencies] par-core = { workspace = true, features = ["chili"] } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base", features = [ +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base", features = [ "inline-helpers", ] } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_ecma_transforms_base/Cargo.toml b/deps/swc/crates/swc_ecma_transforms_base/Cargo.toml index 90b84c9af..dd44c935f 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms_base/Cargo.toml @@ -3,11 +3,11 @@ authors = ["강동윤 "] description = "rust port of babel and closure compiler." documentation = "https://rustdoc.swc.rs/swc_ecma_transforms_base/" edition = { workspace = true } -include = ["Cargo.toml", "src/**/*.rs", "src/**/*.js"] +include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_transforms_base" repository = { workspace = true } -version = "44.0.3" +version = "49.0.0" [lib] bench = false @@ -32,23 +32,23 @@ rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] codspeed-criterion-compat = { workspace = true } par-core = { workspace = true, features = ["chili"] } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } swc_ecma_transforms_macros = { version = "1.0.1", path = "../swc_ecma_transforms_macros" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } [[bench]] harness = false diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/fixer.rs b/deps/swc/crates/swc_ecma_transforms_base/src/fixer.rs index 94682e66d..cea654061 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/fixer.rs +++ b/deps/swc/crates/swc_ecma_transforms_base/src/fixer.rs @@ -71,6 +71,28 @@ enum Context { } impl Fixer<'_> { + /// `Pat::Expr` is needed for parenthesized for-head expressions, but a + /// bare identifier should use the same pattern shape as `for (x of y)`. + fn normalize_for_head_pat(n: &mut ForHead) { + let ForHead::Pat(pat) = n else { + return; + }; + + if pat.as_expr().and_then(|expr| expr.as_ident()).is_none() { + return; + } + + let Pat::Expr(expr) = *pat.take() else { + unreachable!() + }; + + let Expr::Ident(ident) = *expr else { + unreachable!() + }; + + **pat = ident.into(); + } + fn should_wrap_tagged_tpl_new_callee(tag: &Expr) -> bool { match tag { Expr::Call(..) | Expr::New(..) => true, @@ -120,11 +142,11 @@ impl VisitMut for Fixer<'_> { self.ctx = Context::Default; node.visit_mut_children_with(self); match &mut *node.body { - BlockStmtOrExpr::Expr(e) if e.is_seq() => { + ArrowFunctionBody::Expr(e) if e.is_seq() => { self.wrap(e); } - BlockStmtOrExpr::Expr(e) if e.is_assign() => { + ArrowFunctionBody::Expr(e) if e.is_assign() => { if let Expr::Assign(assign) = &**e { if let AssignTarget::Pat(..) = &assign.left { self.wrap(e); @@ -371,11 +393,17 @@ impl VisitMut for Fixer<'_> { self.in_for_stmt_head = in_for_stmt_head; } - fn visit_mut_block_stmt_or_expr(&mut self, body: &mut BlockStmtOrExpr) { + fn visit_mut_function_body(&mut self, n: &mut FunctionBody) { + let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false); + n.visit_mut_children_with(self); + self.in_for_stmt_head = in_for_stmt_head; + } + + fn visit_mut_arrow_function_body(&mut self, body: &mut ArrowFunctionBody) { body.visit_mut_children_with(self); match body { - BlockStmtOrExpr::Expr(expr) if expr.is_object() => { + ArrowFunctionBody::Expr(expr) if expr.is_object() => { self.wrap(expr); } @@ -390,6 +418,25 @@ impl VisitMut for Fixer<'_> { if let Callee::Expr(e) = &mut node.callee { match &**e { Expr::OptChain(_) if !self.in_opt_chain => self.wrap(e), + // Preserve parentheses around callees that carry a leading + // annotation like `/* @__PURE__ */` so downstream tools do not + // interpret the annotation as applying to the outer chained + // call expression. See issue #12019. + Expr::New(..) | Expr::Call(..) | Expr::TaggedTpl(..) if !self.remove_only => { + let span = e.span(); + let has_annotation = !span.is_dummy() + && self.comments.is_some_and(|c| { + c.has_flag(span.lo, "PURE") || c.has_flag(span.lo, "NO_SIDE_EFFECTS") + }); + if has_annotation { + let expr = e.take(); + *e = ParenExpr { + expr, + span: DUMMY_SP, + } + .into(); + } + } _ => self.wrap_callee(e), } } @@ -507,30 +554,30 @@ impl VisitMut for Fixer<'_> { let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, true); n.visit_mut_children_with(self); self.in_for_stmt_head = in_for_stmt_head; + + Self::normalize_for_head_pat(n); } fn visit_mut_for_of_stmt(&mut self, s: &mut ForOfStmt) { s.visit_mut_children_with(self); - if !s.is_await { - match &s.left { - ForHead::Pat(p) - if match &**p { - Pat::Ident(BindingIdent { - id: Ident { sym, .. }, - .. - }) => &**sym == "async", - _ => false, - } => - { - let expr: Pat = p.clone().expect_ident().into(); - s.left = ForHead::Pat(expr.into()); + if !self.remove_only && !s.is_await { + if let ForHead::Pat(p) = &mut s.left { + if matches!( + &**p, + Pat::Ident(BindingIdent { + id: Ident { sym, .. }, + .. + }) if &**sym == "async" + ) { + let Pat::Ident(ident) = *p.take() else { + unreachable!() + }; + + **p = Pat::Expr(ident.into()); } - _ => (), - } - if let ForHead::Pat(e) = &mut s.left { - if let Pat::Expr(expr) = &mut **e { + if let Pat::Expr(expr) = &mut **p { if expr.is_ident_ref_to("async") { self.wrap(&mut *expr); } @@ -609,6 +656,25 @@ impl VisitMut for Fixer<'_> { Expr::OptChain(..) if !self.in_opt_chain => { self.wrap(&mut n.obj); } + // Preserve parentheses around expressions that carry a leading + // annotation like `/* @__PURE__ */` so downstream tools do not + // interpret the annotation as applying to the full chained + // expression. See issue #12019. + Expr::New(..) | Expr::Call(..) | Expr::TaggedTpl(..) if !self.remove_only => { + let span = n.obj.span(); + let has_annotation = !span.is_dummy() + && self.comments.is_some_and(|c| { + c.has_flag(span.lo, "PURE") || c.has_flag(span.lo, "NO_SIDE_EFFECTS") + }); + if has_annotation { + let expr = n.obj.take(); + n.obj = ParenExpr { + expr, + span: DUMMY_SP, + } + .into(); + } + } _ => {} } } @@ -1224,7 +1290,10 @@ fn will_eat_else_token(s: &Stmt) -> bool { #[cfg(test)] mod tests { - use swc_ecma_ast::noop_pass; + use swc_ecma_ast::{noop_pass, ForHead, ModuleItem, Pat, Program, Stmt}; + use swc_ecma_parser::Syntax; + + use super::paren_remover; fn run_test(from: &str, to: &str) { crate::tests::test_transform( @@ -1253,6 +1322,46 @@ mod tests { }; } + fn assert_for_head_ident(left: &ForHead, expected: &str) { + let ForHead::Pat(pat) = left else { + panic!("expected for head pattern"); + }; + + let Pat::Ident(ident) = &**pat else { + panic!("expected identifier pattern"); + }; + + assert_eq!(&*ident.sym, expected); + } + + #[test] + fn paren_remover_normalizes_ident_for_head_pat_exprs() { + crate::tests::Tester::run(|tester| { + let program = tester.apply_transform( + paren_remover(None), + "input.js", + Syntax::default(), + "for ((((x))) of y) {}\nfor ((((x))) in y) {}\nfor ((((async))) of y) {}", + )?; + + let Program::Module(module) = program else { + panic!("expected module"); + }; + + let [ModuleItem::Stmt(Stmt::ForOf(for_of)), ModuleItem::Stmt(Stmt::ForIn(for_in)), ModuleItem::Stmt(Stmt::ForOf(for_of_async))] = + &module.body[..] + else { + panic!("expected for-of, for-in, and async for-of"); + }; + + assert_for_head_ident(&for_of.left, "x"); + assert_for_head_ident(&for_in.left, "x"); + assert_for_head_ident(&for_of_async.left, "async"); + + Ok(()) + }); + } + identical!(fn_expr_position, r#"foo(function(){}())"#); identical!(fn_decl, r#"function foo(){}"#); @@ -1346,6 +1455,12 @@ const _ref = {}, { c =( _tmp = {}, d = _extends({}, _tmp), _tmp) } = _ref;" test_fixer!(fixer_04, "for ((a, b), c;;) ;", "for(a, b, c;;);"); + test_fixer!( + for_of_async_head, + "var async; for (async of [1, 2]);", + "var async; for ((async) of [1, 2]);" + ); + test_fixer!( fixer_05, "var a, b, c = (1), d, e, f = (2); diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_like_to_array.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_like_to_array.js deleted file mode 100644 index 89ef96932..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_like_to_array.js +++ /dev/null @@ -1,5 +0,0 @@ -function _array_like_to_array(arr, len) { - if (len == null || len > arr.length) len = arr.length; - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; - return arr2; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_with_holes.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_with_holes.js deleted file mode 100644 index 2078741c0..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_with_holes.js +++ /dev/null @@ -1,3 +0,0 @@ -function _array_with_holes(arr) { - if (Array.isArray(arr)) return arr; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_without_holes.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_without_holes.js deleted file mode 100644 index 146ae6fa7..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_array_without_holes.js +++ /dev/null @@ -1,3 +0,0 @@ -function _array_without_holes(arr) { - if (Array.isArray(arr)) return _array_like_to_array(arr); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_assert_this_initialized.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_assert_this_initialized.js deleted file mode 100644 index ae7cb5f9e..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_assert_this_initialized.js +++ /dev/null @@ -1,6 +0,0 @@ -function _assert_this_initialized(self) { - if (self === void 0) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - return self; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_to_generator.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_to_generator.js deleted file mode 100644 index 0d39cafa9..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_to_generator.js +++ /dev/null @@ -1,29 +0,0 @@ -function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error) { - reject(error); - return; - } - if (info.done) { - resolve(value); - } else { - Promise.resolve(value).then(_next, _throw); - } -} -function _async_to_generator(fn) { - return function() { - var self = this, args = arguments; - return new Promise(function(resolve, reject) { - var gen = fn.apply(self, args); - function _next(value) { - asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); - } - function _throw(err) { - asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); - } - _next(undefined); - }); - }; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_await_async_generator.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_await_async_generator.js deleted file mode 100644 index e85565425..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_await_async_generator.js +++ /dev/null @@ -1,3 +0,0 @@ -function _await_async_generator(value) { - return new _overload_yield(value, /* kind: await */ 0); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_await_value.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_await_value.js deleted file mode 100644 index 1673e3a7f..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_await_value.js +++ /dev/null @@ -1,3 +0,0 @@ -function _await_value(value) { - this.wrapped = value; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_call_super.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_call_super.js deleted file mode 100644 index 9ff48ed01..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_call_super.js +++ /dev/null @@ -1,11 +0,0 @@ -function _call_super(_this, derived, args) { - // Super - derived = _get_prototype_of(derived); - return _possible_constructor_return( - _this, - _is_native_reflect_construct() - // NOTE: This doesn't work if this.__proto__.constructor has been modified. - ? Reflect.construct(derived, args || [], _get_prototype_of(_this).constructor) - : derived.apply(_this, args) - ); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_check_private_redeclaration.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_check_private_redeclaration.js deleted file mode 100644 index f4bb5162d..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_check_private_redeclaration.js +++ /dev/null @@ -1,5 +0,0 @@ -function _check_private_redeclaration(obj, privateCollection) { - if (privateCollection.has(obj)) { - throw new TypeError("Cannot initialize the same private elements twice on an object"); - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_destructure.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_destructure.js deleted file mode 100644 index 2e3fd3d63..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_destructure.js +++ /dev/null @@ -1,20 +0,0 @@ -function _class_apply_descriptor_destructure(receiver, descriptor) { - if (descriptor.set) { - if (!("__destrObj" in descriptor)) { - descriptor.__destrObj = { - set value(v) { - descriptor.set.call(receiver, v); - } - }; - } - return descriptor.__destrObj; - } else { - if (!descriptor.writable) { - // This should only throw in strict mode, but class bodies are - // always strict and private fields can only be used inside - // class bodies. - throw new TypeError("attempted to set read only private field"); - } - return descriptor; - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_get.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_get.js deleted file mode 100644 index 8d9e823e2..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_get.js +++ /dev/null @@ -1,6 +0,0 @@ -function _class_apply_descriptor_get(receiver, descriptor) { - if (descriptor.get) { - return descriptor.get.call(receiver); - } - return descriptor.value; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_set.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_set.js deleted file mode 100644 index dc1730d12..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_set.js +++ /dev/null @@ -1,13 +0,0 @@ -function _class_apply_descriptor_set(receiver, descriptor, value) { - if (descriptor.set) { - descriptor.set.call(receiver, value); - } else { - if (!descriptor.writable) { - // This should only throw in strict mode, but class bodies are - // always strict and private fields can only be used inside - // class bodies. - throw new TypeError("attempted to set read only private field"); - } - descriptor.value = value; - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_update.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_update.js deleted file mode 100644 index 79dd0f80d..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_apply_descriptor_update.js +++ /dev/null @@ -1,26 +0,0 @@ -function _class_apply_descriptor_update(receiver, descriptor) { - if (descriptor.set) { - if (!descriptor.get) { - throw new TypeError("attempted to read set only private field"); - } - if (!("__destrWrapper" in descriptor)) { - descriptor.__destrWrapper = { - set value(v) { - descriptor.set.call(receiver, v); - }, - get value() { - return descriptor.get.call(receiver); - } - }; - } - return descriptor.__destrWrapper; - } else { - if (!descriptor.writable) { - // This should only throw in strict mode, but class bodies are - // always strict and private fields can only be used inside - // class bodies. - throw new TypeError("attempted to set read only private field"); - } - return descriptor; - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_call_check.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_call_check.js deleted file mode 100644 index fc3d8cd30..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_call_check.js +++ /dev/null @@ -1,5 +0,0 @@ -function _class_call_check(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_check_private_static_access.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_check_private_static_access.js deleted file mode 100644 index 9f111acac..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_check_private_static_access.js +++ /dev/null @@ -1,5 +0,0 @@ -function _class_check_private_static_access(receiver, classConstructor) { - if (receiver !== classConstructor) { - throw new TypeError("Private static access of wrong provenance"); - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_check_private_static_field_descriptor.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_check_private_static_field_descriptor.js deleted file mode 100644 index 0c713ac4d..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_check_private_static_field_descriptor.js +++ /dev/null @@ -1,5 +0,0 @@ -function _class_check_private_static_field_descriptor(descriptor, action) { - if (descriptor === undefined) { - throw new TypeError("attempted to " + action + " private static field before its declaration"); - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_extract_field_descriptor.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_extract_field_descriptor.js deleted file mode 100644 index 3bb24f479..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_extract_field_descriptor.js +++ /dev/null @@ -1,6 +0,0 @@ -function _class_extract_field_descriptor(receiver, privateMap, action) { - if (!privateMap.has(receiver)) { - throw new TypeError("attempted to " + action + " private field on non-instance"); - } - return privateMap.get(receiver); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_name_tdz_error.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_name_tdz_error.js deleted file mode 100644 index 441bcb97f..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_name_tdz_error.js +++ /dev/null @@ -1,3 +0,0 @@ -function _class_name_tdz_error(name) { - throw new ReferenceError("Class \"" + name + "\" cannot be referenced in computed property keys."); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_destructure.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_destructure.js deleted file mode 100644 index 9ce317bdd..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_destructure.js +++ /dev/null @@ -1,4 +0,0 @@ -function _class_private_field_destructure(receiver, privateMap) { - var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set"); - return _class_apply_descriptor_destructure(receiver, descriptor); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_get.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_get.js deleted file mode 100644 index 583c164d2..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_get.js +++ /dev/null @@ -1,4 +0,0 @@ -function _class_private_field_get(receiver, privateMap) { - var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get"); - return _class_apply_descriptor_get(receiver, descriptor); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_init.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_init.js deleted file mode 100644 index b2c9c03bc..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_init.js +++ /dev/null @@ -1,4 +0,0 @@ -function _class_private_field_init(obj, privateMap, value) { - _check_private_redeclaration(obj, privateMap); - privateMap.set(obj, value); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_loose_base.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_loose_base.js deleted file mode 100644 index 4a6752e70..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_loose_base.js +++ /dev/null @@ -1,6 +0,0 @@ -function _class_private_field_loose_base(receiver, privateKey) { - if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { - throw new TypeError("attempted to use private field on non-instance"); - } - return receiver; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_loose_key.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_loose_key.js deleted file mode 100644 index a04419c1f..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_loose_key.js +++ /dev/null @@ -1,4 +0,0 @@ -var id = 0; -function _class_private_field_loose_key(name) { - return "__private_" + id++ + "_" + name; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_set.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_set.js deleted file mode 100644 index 71c9defdf..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_set.js +++ /dev/null @@ -1,5 +0,0 @@ -function _class_private_field_set(receiver, privateMap, value) { - var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set"); - _class_apply_descriptor_set(receiver, descriptor, value); - return value; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_update.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_update.js deleted file mode 100644 index 2bae86cff..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_field_update.js +++ /dev/null @@ -1,4 +0,0 @@ -function _class_private_field_update(receiver, privateMap) { - var descriptor = _class_extract_field_descriptor(receiver, privateMap, "update"); - return _class_apply_descriptor_update(receiver, descriptor); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_get.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_get.js deleted file mode 100644 index 4fb72d8ea..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_get.js +++ /dev/null @@ -1,6 +0,0 @@ -function _class_private_method_get(receiver, privateSet, fn) { - if (!privateSet.has(receiver)) { - throw new TypeError("attempted to get private field on non-instance"); - } - return fn; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_init.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_init.js deleted file mode 100644 index a2085b74d..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_init.js +++ /dev/null @@ -1,4 +0,0 @@ -function _class_private_method_init(obj, privateSet) { - _check_private_redeclaration(obj, privateSet); - privateSet.add(obj); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_set.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_set.js deleted file mode 100644 index 79fd1f375..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_private_method_set.js +++ /dev/null @@ -1,3 +0,0 @@ -function _class_private_method_set() { - throw new TypeError("attempted to reassign private method"); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_destructure.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_destructure.js deleted file mode 100644 index 9c41b7088..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_destructure.js +++ /dev/null @@ -1,5 +0,0 @@ -function _class_static_private_field_destructure(receiver, classConstructor, descriptor) { - _class_check_private_static_access(receiver, classConstructor); - _class_check_private_static_field_descriptor(descriptor, "set"); - return _class_apply_descriptor_destructure(receiver, descriptor); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_spec_get.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_spec_get.js deleted file mode 100644 index 65fddaf01..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_spec_get.js +++ /dev/null @@ -1,5 +0,0 @@ -function _class_static_private_field_spec_get(receiver, classConstructor, descriptor) { - _class_check_private_static_access(receiver, classConstructor); - _class_check_private_static_field_descriptor(descriptor, "get"); - return _class_apply_descriptor_get(receiver, descriptor); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_spec_set.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_spec_set.js deleted file mode 100644 index df6f3c8ca..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_spec_set.js +++ /dev/null @@ -1,6 +0,0 @@ -function _class_static_private_field_spec_set(receiver, classConstructor, descriptor, value) { - _class_check_private_static_access(receiver, classConstructor); - _class_check_private_static_field_descriptor(descriptor, "set"); - _class_apply_descriptor_set(receiver, descriptor, value); - return value; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_update.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_update.js deleted file mode 100644 index 2c1778e5b..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_field_update.js +++ /dev/null @@ -1,5 +0,0 @@ -function _class_static_private_field_update(receiver, classConstructor, descriptor) { - _class_check_private_static_access(receiver, classConstructor); - _class_check_private_static_field_descriptor(descriptor, "update"); - return _class_apply_descriptor_update(receiver, descriptor); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_method_get.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_method_get.js deleted file mode 100644 index e1b0ba546..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_class_static_private_method_get.js +++ /dev/null @@ -1,4 +0,0 @@ -function _class_static_private_method_get(receiver, classConstructor, method) { - _class_check_private_static_access(receiver, classConstructor); - return method; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_construct.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_construct.js deleted file mode 100644 index 31f863015..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_construct.js +++ /dev/null @@ -1,15 +0,0 @@ -function _construct(Parent, args, Class) { - if (_is_native_reflect_construct()) { - _construct = Reflect.construct; - } else { - _construct = function construct(Parent, args, Class) { - var a = [null]; - a.push.apply(a, args); - var Constructor = Function.bind.apply(Parent, a); - var instance = new Constructor(); - if (Class) _set_prototype_of(instance, Class.prototype); - return instance; - }; - } - return _construct.apply(null, arguments); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_class.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_class.js deleted file mode 100644 index 7b7e1a1fc..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_class.js +++ /dev/null @@ -1,14 +0,0 @@ -function _defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } -} -function _create_class(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_for_of_iterator_helper_loose.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_for_of_iterator_helper_loose.js deleted file mode 100644 index 02f06b754..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_for_of_iterator_helper_loose.js +++ /dev/null @@ -1,18 +0,0 @@ -function _create_for_of_iterator_helper_loose(o, allowArrayLike) { - var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; - if (it) return (it = it.call(o)).next.bind(it); - // Fallback for engines without symbol support - if (Array.isArray(o) || (it = _unsupported_iterable_to_array(o)) || allowArrayLike && o && typeof o.length === "number") { - if (it) o = it; - var i = 0; - return function() { - if (i >= o.length) { - return { done: true }; - } - return { done: false, value: o[i++] }; - }; - } - throw new TypeError( - "Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." - ); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_super.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_super.js deleted file mode 100644 index db281bc57..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_create_super.js +++ /dev/null @@ -1,13 +0,0 @@ -function _create_super(Derived) { - var hasNativeReflectConstruct = _is_native_reflect_construct(); - return function _createSuperInternal() { - var Super = _get_prototype_of(Derived), result; - if (hasNativeReflectConstruct) { - var NewTarget = _get_prototype_of(this).constructor; - result = Reflect.construct(Super, arguments, NewTarget); - } else { - result = Super.apply(this, arguments); - } - return _possible_constructor_return(this, result); - }; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_defaults.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_defaults.js deleted file mode 100644 index 2ba392ed6..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_defaults.js +++ /dev/null @@ -1,11 +0,0 @@ -function _defaults(obj, defaults) { - var keys = Object.getOwnPropertyNames(defaults); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var value = Object.getOwnPropertyDescriptor(defaults, key); - if (value && value.configurable && obj[key] === undefined) { - Object.defineProperty(obj, key, value); - } - } - return obj; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_define_enumerable_properties.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_define_enumerable_properties.js deleted file mode 100644 index f935fce01..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_define_enumerable_properties.js +++ /dev/null @@ -1,19 +0,0 @@ -function _define_enumerable_properties(obj, descs) { - for (var key in descs) { - var desc = descs[key]; - desc.configurable = desc.enumerable = true; - if ("value" in desc) desc.writable = true; - Object.defineProperty(obj, key, desc); - } - if (Object.getOwnPropertySymbols) { - var objectSymbols = Object.getOwnPropertySymbols(descs); - for (var i = 0; i < objectSymbols.length; i++) { - var sym = objectSymbols[i]; - var desc = descs[sym]; - desc.configurable = desc.enumerable = true; - if ("value" in desc) desc.writable = true; - Object.defineProperty(obj, sym, desc); - } - } - return obj; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_define_property.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_define_property.js deleted file mode 100644 index e766329cb..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_define_property.js +++ /dev/null @@ -1,8 +0,0 @@ -function _define_property(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); - } else { - obj[key] = value; - } - return obj; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_export_star.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_export_star.js deleted file mode 100644 index 65e1cc949..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_export_star.js +++ /dev/null @@ -1,13 +0,0 @@ -function _export_star(from, to) { - Object.keys(from).forEach(function(k) { - if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) { - Object.defineProperty(to, k, { - enumerable: true, - get: function() { - return from[k]; - } - }); - } - }); - return from; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_extends.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_extends.js deleted file mode 100644 index acef0a282..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_extends.js +++ /dev/null @@ -1,14 +0,0 @@ -function _extends() { - _extends = Object.assign || function(target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - return target; - }; - return _extends.apply(this, arguments); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_get.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_get.js deleted file mode 100644 index f222cf82b..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_get.js +++ /dev/null @@ -1,16 +0,0 @@ -function _get(target, property, receiver) { - if (typeof Reflect !== "undefined" && Reflect.get) { - _get = Reflect.get; - } else { - _get = function get(target, property, receiver) { - var base = _super_prop_base(target, property); - if (!base) return; - var desc = Object.getOwnPropertyDescriptor(base, property); - if (desc.get) { - return desc.get.call(receiver || target); - } - return desc.value; - }; - } - return _get(target, property, receiver || target); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_get_prototype_of.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_get_prototype_of.js deleted file mode 100644 index 458439f51..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_get_prototype_of.js +++ /dev/null @@ -1,6 +0,0 @@ -function _get_prototype_of(o) { - _get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) { - return o.__proto__ || Object.getPrototypeOf(o); - }; - return _get_prototype_of(o); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_identity.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_identity.js deleted file mode 100644 index 2eed63eb2..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_identity.js +++ /dev/null @@ -1 +0,0 @@ -function _identity(x) { return x; } diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_inherits.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_inherits.js deleted file mode 100644 index d16557677..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_inherits.js +++ /dev/null @@ -1,9 +0,0 @@ -function _inherits(subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function"); - } - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { value: subClass, writable: true, configurable: true } - }); - if (superClass) _set_prototype_of(subClass, superClass); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_inherits_loose.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_inherits_loose.js deleted file mode 100644 index c045a102d..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_inherits_loose.js +++ /dev/null @@ -1,5 +0,0 @@ -function _inherits_loose(subClass, superClass) { - subClass.prototype = Object.create(superClass.prototype); - subClass.prototype.constructor = subClass; - subClass.__proto__ = superClass; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_initializer_define_property.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_initializer_define_property.js deleted file mode 100644 index 042dcb0bf..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_initializer_define_property.js +++ /dev/null @@ -1,9 +0,0 @@ -function _initializer_define_property(target, property, descriptor, context) { - if (!descriptor) return; - Object.defineProperty(target, property, { - enumerable: descriptor.enumerable, - configurable: descriptor.configurable, - writable: descriptor.writable, - value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 - }); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_initializer_warning_helper.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_initializer_warning_helper.js deleted file mode 100644 index f05909123..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_initializer_warning_helper.js +++ /dev/null @@ -1,7 +0,0 @@ -function _initializer_warning_helper(descriptor, context) { - throw new Error( - "Decorating class property failed. Please ensure that " + "proposal-class-properties is enabled and set to use loose mode. " - + "To use proposal-class-properties in spec mode with decorators, wait for " - + "the next major version of decorators in stage 2." - ); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_instanceof.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_instanceof.js deleted file mode 100644 index 5e83a5dcc..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_instanceof.js +++ /dev/null @@ -1,9 +0,0 @@ -function _instanceof(left, right) { - "@swc/helpers - instanceof"; - - if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { - return !!right[Symbol.hasInstance](left); - } else { - return left instanceof right; - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_interop_require_default.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_interop_require_default.js deleted file mode 100644 index 42b216fbe..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_interop_require_default.js +++ /dev/null @@ -1,3 +0,0 @@ -function _interop_require_default(obj) { - return obj && obj.__esModule ? obj : { default: obj }; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_interop_require_wildcard.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_interop_require_wildcard.js deleted file mode 100644 index 22aab86e4..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_interop_require_wildcard.js +++ /dev/null @@ -1,37 +0,0 @@ -function _getRequireWildcardCache(nodeInterop) { - if (typeof WeakMap !== "function") return null; - var cacheBabelInterop = new WeakMap(); - var cacheNodeInterop = new WeakMap(); - return (_getRequireWildcardCache = function(nodeInterop) { - return nodeInterop ? cacheNodeInterop : cacheBabelInterop; - })(nodeInterop); -} -function _interop_require_wildcard(obj, nodeInterop) { - if (!nodeInterop && obj && obj.__esModule) { - return obj; - } - if (obj === null || typeof obj !== "object" && typeof obj !== "function") { - return { default: obj }; - } - var cache = _getRequireWildcardCache(nodeInterop); - if (cache && cache.has(obj)) { - return cache.get(obj); - } - var newObj = { __proto__: null }; - var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; - for (var key in obj) { - if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { - var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; - if (desc && (desc.get || desc.set)) { - Object.defineProperty(newObj, key, desc); - } else { - newObj[key] = obj[key]; - } - } - } - newObj.default = obj; - if (cache) { - cache.set(obj, newObj); - } - return newObj; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_is_native_function.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_is_native_function.js deleted file mode 100644 index 2148fba01..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_is_native_function.js +++ /dev/null @@ -1,3 +0,0 @@ -function _is_native_function(fn) { - return Function.toString.call(fn).indexOf("[native code]") !== -1; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_is_native_reflect_construct.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_is_native_reflect_construct.js deleted file mode 100644 index 74d2cdc0d..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_is_native_reflect_construct.js +++ /dev/null @@ -1,14 +0,0 @@ -function _is_native_reflect_construct() { - // Since Reflect.construct can't be properly polyfilled, some - // implementations (e.g. core-js@2) don't set the correct internal slots. - // Those polyfills don't allow us to subclass built-ins, so we need to - // use our fallback implementation. - try { - // If the internal slots aren't set, this throws an error similar to - // TypeError: this is not a Boolean object. - var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {})); - } catch (_) {} - return (_is_native_reflect_construct = function() { - return !!result; - })(); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array.js deleted file mode 100644 index e21d1637d..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array.js +++ /dev/null @@ -1,3 +0,0 @@ -function _iterable_to_array(iter) { - if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array_limit.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array_limit.js deleted file mode 100644 index 9ab87e786..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array_limit.js +++ /dev/null @@ -1,24 +0,0 @@ -function _iterable_to_array_limit(arr, i) { - var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; - if (_i == null) return; - var _arr = []; - var _n = true; - var _d = false; - var _s, _e; - try { - for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; - } - } - return _arr; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array_limit_loose.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array_limit_loose.js deleted file mode 100644 index 24b507417..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_iterable_to_array_limit_loose.js +++ /dev/null @@ -1,10 +0,0 @@ -function _iterable_to_array_limit_loose(arr, i) { - var _i = arr && (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]); - if (_i == null) return; - var _arr = []; - for (_i = _i.call(arr), _step; !(_step = _i.next()).done;) { - _arr.push(_step.value); - if (i && _arr.length === i) break; - } - return _arr; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_jsx.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_jsx.js deleted file mode 100644 index 0e155e403..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_jsx.js +++ /dev/null @@ -1,30 +0,0 @@ -var REACT_ELEMENT_TYPE; -function _jsx(type, props, key, children) { - if (!REACT_ELEMENT_TYPE) { - REACT_ELEMENT_TYPE = typeof Symbol === "function" && Symbol.for && Symbol.for("react.element") || 0xeac7; - } - var defaultProps = type && type.defaultProps; - var childrenLength = arguments.length - 3; - if (!props && childrenLength !== 0) { - props = { children: void 0 }; - } - if (props && defaultProps) { - for (var propName in defaultProps) { - if (props[propName] === void 0) { - props[propName] = defaultProps[propName]; - } - } - } else if (!props) { - props = defaultProps || {}; - } - if (childrenLength === 1) { - props.children = children; - } else if (childrenLength > 1) { - var childArray = new Array(childrenLength); - for (var i = 0; i < childrenLength; i++) { - childArray[i] = arguments[i + 3]; - } - props.children = childArray; - } - return { $$typeof: REACT_ELEMENT_TYPE, type: type, key: key === undefined ? null : "" + key, ref: null, props: props, _owner: null }; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_new_arrow_check.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_new_arrow_check.js deleted file mode 100644 index 11ce97952..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_new_arrow_check.js +++ /dev/null @@ -1,5 +0,0 @@ -function _new_arrow_check(innerThis, boundThis) { - if (innerThis !== boundThis) { - throw new TypeError("Cannot instantiate an arrow function"); - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_non_iterable_rest.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_non_iterable_rest.js deleted file mode 100644 index 649c15433..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_non_iterable_rest.js +++ /dev/null @@ -1,5 +0,0 @@ -function _non_iterable_rest() { - throw new TypeError( - "Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." - ); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_non_iterable_spread.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_non_iterable_spread.js deleted file mode 100644 index d450671a1..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_non_iterable_spread.js +++ /dev/null @@ -1,5 +0,0 @@ -function _non_iterable_spread() { - throw new TypeError( - "Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." - ); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_destructuring_empty.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_destructuring_empty.js deleted file mode 100644 index 6be6fae5b..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_destructuring_empty.js +++ /dev/null @@ -1,4 +0,0 @@ -function _object_destructuring_empty(o) { - if (o === null || o === void 0) throw new TypeError("Cannot destructure " + o); - return o; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_spread.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_spread.js deleted file mode 100644 index 6528e5b40..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_spread.js +++ /dev/null @@ -1,17 +0,0 @@ -function _object_spread(target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i] != null ? arguments[i] : {}; - var ownKeys = Object.keys(source); - if (typeof Object.getOwnPropertySymbols === "function") { - ownKeys = ownKeys.concat( - Object.getOwnPropertySymbols(source).filter(function(sym) { - return Object.getOwnPropertyDescriptor(source, sym).enumerable; - }) - ); - } - ownKeys.forEach(function(key) { - _define_property(target, key, source[key]); - }); - } - return target; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_spread_props.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_spread_props.js deleted file mode 100644 index f569e4082..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_spread_props.js +++ /dev/null @@ -1,24 +0,0 @@ -function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object); - if (enumerableOnly) { - symbols = symbols.filter(function(sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - }); - } - keys.push.apply(keys, symbols); - } - return keys; -} -function _object_spread_props(target, source) { - source = source != null ? source : {}; - if (Object.getOwnPropertyDescriptors) { - Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); - } else { - ownKeys(Object(source)).forEach(function(key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); - } - return target; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_without_properties_loose.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_without_properties_loose.js deleted file mode 100644 index b38cbe5af..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_without_properties_loose.js +++ /dev/null @@ -1,13 +0,0 @@ -function _object_without_properties_loose(source, excluded) { - if (source == null) return {}; - - var target = {}, sourceKeys = Object.getOwnPropertyNames(source), key, i; - for (i = 0; i < sourceKeys.length; i++) { - key = sourceKeys[i]; - if (excluded.indexOf(key) >= 0) continue; - if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; - target[key] = source[key]; - } - - return target; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_overload_yield.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_overload_yield.js deleted file mode 100644 index bb2897917..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_overload_yield.js +++ /dev/null @@ -1,4 +0,0 @@ -function _overload_yield(value, /** 0: await 1: delegate */ kind) { - this.v = value; - this.k = kind; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_possible_constructor_return.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_possible_constructor_return.js deleted file mode 100644 index ab98d13a4..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_possible_constructor_return.js +++ /dev/null @@ -1,6 +0,0 @@ -function _possible_constructor_return(self, call) { - if (call && (_type_of(call) === "object" || typeof call === "function")) { - return call; - } - return _assert_this_initialized(self); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_read_only_error.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_read_only_error.js deleted file mode 100644 index e953a3a92..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_read_only_error.js +++ /dev/null @@ -1,3 +0,0 @@ -function _read_only_error(name) { - throw new TypeError("\"" + name + "\" is read-only"); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_set_prototype_of.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_set_prototype_of.js deleted file mode 100644 index 4edc6a97e..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_set_prototype_of.js +++ /dev/null @@ -1,7 +0,0 @@ -function _set_prototype_of(o, p) { - _set_prototype_of = Object.setPrototypeOf || function setPrototypeOf(o, p) { - o.__proto__ = p; - return o; - }; - return _set_prototype_of(o, p); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_skip_first_generator_next.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_skip_first_generator_next.js deleted file mode 100644 index 900e68661..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_skip_first_generator_next.js +++ /dev/null @@ -1,7 +0,0 @@ -function _skip_first_generator_next(fn) { - return function() { - var it = fn.apply(this, arguments); - it.next(); - return it; - }; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_sliced_to_array.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_sliced_to_array.js deleted file mode 100644 index ee2a8ee4f..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_sliced_to_array.js +++ /dev/null @@ -1,3 +0,0 @@ -function _sliced_to_array(arr, i) { - return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest(); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_sliced_to_array_loose.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_sliced_to_array_loose.js deleted file mode 100644 index dcbe68f93..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_sliced_to_array_loose.js +++ /dev/null @@ -1,4 +0,0 @@ -function _sliced_to_array_loose(arr, i) { - return _array_with_holes(arr) || _iterable_to_array_limit_loose(arr, i) || _unsupported_iterable_to_array(arr, i) - || _non_iterable_rest(); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_super_prop_base.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_super_prop_base.js deleted file mode 100644 index 87bc9bc8f..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_super_prop_base.js +++ /dev/null @@ -1,7 +0,0 @@ -function _super_prop_base(object, property) { - while (!Object.prototype.hasOwnProperty.call(object, property)) { - object = _get_prototype_of(object); - if (object === null) break; - } - return object; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_tagged_template_literal.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_tagged_template_literal.js deleted file mode 100644 index 0b558f527..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_tagged_template_literal.js +++ /dev/null @@ -1,6 +0,0 @@ -function _tagged_template_literal(strings, raw) { - if (!raw) { - raw = strings.slice(0); - } - return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_tagged_template_literal_loose.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_tagged_template_literal_loose.js deleted file mode 100644 index f9c525878..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_tagged_template_literal_loose.js +++ /dev/null @@ -1,7 +0,0 @@ -function _tagged_template_literal_loose(strings, raw) { - if (!raw) { - raw = strings.slice(0); - } - strings.raw = raw; - return strings; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_throw.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_throw.js deleted file mode 100644 index 1ce873108..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_throw.js +++ /dev/null @@ -1,3 +0,0 @@ -function _throw(e) { - throw e; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_array.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_array.js deleted file mode 100644 index 8126c7edd..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_array.js +++ /dev/null @@ -1,3 +0,0 @@ -function _to_array(arr) { - return _array_with_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_rest(); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_consumable_array.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_consumable_array.js deleted file mode 100644 index d9bbf962b..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_consumable_array.js +++ /dev/null @@ -1,3 +0,0 @@ -function _to_consumable_array(arr) { - return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread(); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_primitive.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_primitive.js deleted file mode 100644 index 239f50f33..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_primitive.js +++ /dev/null @@ -1,10 +0,0 @@ -function _to_primitive(input, hint) { - if (_type_of(input) !== "object" || input === null) return input; - var prim = input[Symbol.toPrimitive]; - if (prim !== undefined) { - var res = prim.call(input, hint || "default"); - if (_type_of(res) !== "object") return res; - throw new TypeError("@@toPrimitive must return a primitive value."); - } - return (hint === "string" ? String : Number)(input); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_property_key.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_property_key.js deleted file mode 100644 index 383beec99..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_to_property_key.js +++ /dev/null @@ -1,4 +0,0 @@ -function _to_property_key(arg) { - var key = _to_primitive(arg, "string"); - return _type_of(key) === "symbol" ? key : String(key); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_add_disposable_resource.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_add_disposable_resource.js deleted file mode 100644 index 2ecbaaa88..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_add_disposable_resource.js +++ /dev/null @@ -1,22 +0,0 @@ -function _ts_add_disposable_resource(env, value, async) { - if (value !== null && value !== void 0) { - if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); - var dispose, inner; - if (async) { - if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); - dispose = value[Symbol.asyncDispose]; - } - if (dispose === void 0) { - if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); - dispose = value[Symbol.dispose]; - if (async) inner = dispose; - } - if (typeof dispose !== "function") throw new TypeError("Object not disposable."); - if (inner) dispose = function () { try { inner.call(this); } catch (e) { return Promise.reject(e); } }; - env.stack.push({ value: value, dispose: dispose, async: async }); - } - else if (async) { - env.stack.push({ async: true }); - } - return value; -} \ No newline at end of file diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_decorate.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_decorate.js deleted file mode 100644 index 986e404fd..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_decorate.js +++ /dev/null @@ -1,6 +0,0 @@ -function _ts_decorate(decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -} \ No newline at end of file diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_dispose_resources.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_dispose_resources.js deleted file mode 100644 index 8865a070c..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_dispose_resources.js +++ /dev/null @@ -1,33 +0,0 @@ -function _ts_dispose_resources(env) { - var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { - var e = new Error(message); - return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; - }; - - - return (_ts_dispose_resources = function _ts_dispose_resources(env) { - function fail(e) { - env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; - env.hasError = true; - } - var r, s = 0; - function next() { - while (r = env.stack.pop()) { - try { - if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); - if (r.dispose) { - var result = r.dispose.call(r.value); - if (r.async) return s |= 2, Promise.resolve(result).then(next, function (e) { fail(e); return next(); }); - } - else s |= 1; - } - catch (e) { - fail(e); - } - } - if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); - if (env.hasError) throw env.error; - } - return next(); - })(env); -} \ No newline at end of file diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_metadata.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_metadata.js deleted file mode 100644 index 4d28dd307..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_metadata.js +++ /dev/null @@ -1,3 +0,0 @@ -function _ts_metadata(k, v) { - if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); -} \ No newline at end of file diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_param.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_param.js deleted file mode 100644 index a52ed9e6f..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_param.js +++ /dev/null @@ -1,3 +0,0 @@ -function _ts_param(paramIndex, decorator) { - return function (target, key) { decorator(target, key, paramIndex); } -} \ No newline at end of file diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_rewrite_relative_import_extension.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_rewrite_relative_import_extension.js deleted file mode 100644 index adb3e6f3f..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_rewrite_relative_import_extension.js +++ /dev/null @@ -1,8 +0,0 @@ -function _ts_rewrite_relative_import_extension(path, preserveJsx) { - if (typeof path === "string" && /^\.\.?\//.test(path)) { - return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) { - return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js"); - }); - } - return path; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_values.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_values.js deleted file mode 100644 index cdfde621a..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_values.js +++ /dev/null @@ -1,11 +0,0 @@ -function _ts_values(o) { - var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; - if (m) return m.call(o); - if (o && typeof o.length === "number") return { - next: function () { - if (o && i >= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; - throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); -} \ No newline at end of file diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_type_of.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_type_of.js deleted file mode 100644 index 6ac66d204..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_type_of.js +++ /dev/null @@ -1,4 +0,0 @@ -function _type_of(obj) { - "@swc/helpers - typeof"; - return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_unsupported_iterable_to_array.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_unsupported_iterable_to_array.js deleted file mode 100644 index 048124613..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_unsupported_iterable_to_array.js +++ /dev/null @@ -1,8 +0,0 @@ -function _unsupported_iterable_to_array(o, minLen) { - if (!o) return; - if (typeof o === "string") return _array_like_to_array(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(n); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_update.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_update.js deleted file mode 100644 index 0fd806042..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_update.js +++ /dev/null @@ -1,10 +0,0 @@ -function _update(target, property, receiver, isStrict) { - return { - get _() { - return _get(target, property, receiver); - }, - set _(value) { - _set(target, property, value, receiver, isStrict); - } - }; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_using.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_using.js deleted file mode 100644 index 9e837f488..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_using.js +++ /dev/null @@ -1,19 +0,0 @@ -function _using(stack, value, isAwait) { - if (value === null || value === void 0) return value; - if (Object(value) !== value) { - throw new TypeError("using declarations can only be used with objects, functions, null, or undefined."); - } - // core-js-pure uses Symbol.for for polyfilling well-known symbols - if (isAwait) { - var dispose = - value[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")]; - } - if (dispose === null || dispose === void 0) { - dispose = value[Symbol.dispose || Symbol.for("Symbol.dispose")]; - } - if (typeof dispose !== "function") { - throw new TypeError(`Property [Symbol.dispose] is not a function.`); - } - stack.push({ v: value, d: dispose, a: isAwait }); - return value; -} \ No newline at end of file diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_async_generator.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_async_generator.js deleted file mode 100644 index 1381a8583..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_async_generator.js +++ /dev/null @@ -1,5 +0,0 @@ -function _wrap_async_generator(fn) { - return function() { - return new _async_generator(fn.apply(this, arguments)); - }; -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_native_super.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_native_super.js deleted file mode 100644 index 31c53f4be..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_native_super.js +++ /dev/null @@ -1,21 +0,0 @@ -function _wrap_native_super(Class) { - var _cache = typeof Map === "function" ? new Map() : undefined; - _wrap_native_super = function wrapNativeSuper(Class) { - if (Class === null || !_is_native_function(Class)) return Class; - if (typeof Class !== "function") { - throw new TypeError("Super expression must either be null or a function"); - } - if (typeof _cache !== "undefined") { - if (_cache.has(Class)) return _cache.get(Class); - _cache.set(Class, Wrapper); - } - function Wrapper() { - return _construct(Class, arguments, _get_prototype_of(this).constructor); - } - Wrapper.prototype = Object.create(Class.prototype, { - constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } - }); - return _set_prototype_of(Wrapper, Class); - }; - return _wrap_native_super(Class); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_write_only_error.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_write_only_error.js deleted file mode 100644 index 48589660a..000000000 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_write_only_error.js +++ /dev/null @@ -1,3 +0,0 @@ -function _write_only_error(name) { - throw new TypeError("\"" + name + "\" is write-only"); -} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_apply_decorated_descriptor.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_apply_decorated_descriptor.rs similarity index 51% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_apply_decorated_descriptor.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_apply_decorated_descriptor.rs index de19a79c8..b63fcc302 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_apply_decorated_descriptor.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_apply_decorated_descriptor.rs @@ -1,17 +1,28 @@ -function _apply_decorated_descriptor(target, property, decorators, descriptor, context) { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::apply_decorated_descriptor, + local: "_apply_decorated_descriptor", + import_path: "@swc/helpers/_/_apply_decorated_descriptor", + #[cfg(feature = "inline-helpers")] + source: r#"function _apply_decorated_descriptor(target, property, decorators, descriptor, context) { var desc = {}; + Object["ke" + "ys"](descriptor).forEach(function(key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; - if ("value" in desc || desc.initializer) { - desc.writable = true; - } + + if ("value" in desc || desc.initializer) desc.writable = true; desc = decorators.slice().reverse().reduce(function(desc, decorator) { return decorator ? decorator(target, property, desc) || desc : desc; }, desc); + var hasAccessor = Object.prototype.hasOwnProperty.call(desc, "get") || Object.prototype.hasOwnProperty.call(desc, "set"); + if (context && desc.initializer !== void 0 && !hasAccessor) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; @@ -25,5 +36,17 @@ function _apply_decorated_descriptor(target, property, decorators, descriptor, c Object["define" + "Property"](target, property, desc); desc = null; } + return desc; } +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000000001), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_apply_decs_2203_r.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_apply_decs_2203_r.rs similarity index 71% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_apply_decs_2203_r.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_apply_decs_2203_r.rs index 6e898d16a..b5453f0e4 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_apply_decs_2203_r.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_apply_decs_2203_r.rs @@ -1,4 +1,13 @@ -/* @minVersion 7.20.0 */ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::apply_decs_2203_r, + local: "_apply_decs_2203_r", + import_path: "@swc/helpers/_/_apply_decs_2203_r", + #[cfg(feature = "inline-helpers")] + source: r##"/* @minVersion 7.20.0 */ /** Enums are used in this file, but not assigned to vars to avoid non-hoistable values @@ -18,7 +27,7 @@ CLASS = 10; // only used in assertValidReturnValue */ -function applyDecs2203RFactory() { +function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) { function createAddInitializerMethod(initializers, decoratorFinishedRef) { return function addInitializer(initializer) { assertNotFinished(decoratorFinishedRef, "addInitializer"); @@ -27,17 +36,7 @@ function applyDecs2203RFactory() { }; } - function memberDec( - dec, - name, - desc, - initializers, - kind, - isStatic, - isPrivate, - metadata, - value - ) { + function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) { var kindStr; switch (kind) { @@ -57,20 +56,11 @@ function applyDecs2203RFactory() { kindStr = "field"; } - var ctx = { - kind: kindStr, - name: isPrivate ? "#" + name : name, - static: isStatic, - private: isPrivate, - metadata: metadata, - }; + var ctx = { kind: kindStr, name: isPrivate ? "#" + name : name, static: isStatic, private: isPrivate, metadata: metadata }; var decoratorFinishedRef = { v: false }; - ctx.addInitializer = createAddInitializerMethod( - initializers, - decoratorFinishedRef - ); + ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef); var get, set; if (kind === 0 /* FIELD */) { @@ -78,27 +68,27 @@ function applyDecs2203RFactory() { get = desc.get; set = desc.set; } else { - get = function () { + get = function() { return this[name]; }; - set = function (v) { + set = function(v) { this[name] = v; }; } } else if (kind === 2 /* METHOD */) { - get = function () { + get = function() { return desc.value; }; } else { // replace with values that will go through the final getter and setter if (kind === 1 /* ACCESSOR */ || kind === 3 /* GETTER */) { - get = function () { + get = function() { return desc.get.call(this); }; } if (kind === 1 /* ACCESSOR */ || kind === 4 /* SETTER */) { - set = function (v) { + set = function(v) { desc.set.call(this, v); }; } @@ -106,7 +96,7 @@ function applyDecs2203RFactory() { if (get) { var originalGet = get; - get = function (target) { + get = function(target) { if (arguments.length === 0) { target = this; } @@ -116,7 +106,7 @@ function applyDecs2203RFactory() { if (set) { var originalSet = set; - set = function (target, value) { + set = function(target, value) { if (arguments.length === 1) { value = target; target = this; @@ -126,18 +116,12 @@ function applyDecs2203RFactory() { } if (isPrivate) { - ctx.access = - get && set ? { get: get, set: set } : get ? { get: get } : { set: set }; + ctx.access = get && set ? { get: get, set: set } : get ? { get: get } : { set: set }; } else { - var has = function (target) { + var has = function(target) { return name in target; }; - ctx.access = - get && set - ? { has: has, get: get, set: set } - : get - ? { has: has, get: get } - : { has: has, set: set }; + ctx.access = get && set ? { has: has, get: get, set: set } : get ? { has: has, get: get } : { has: has, set: set }; } var newValue = dec(value, ctx); @@ -147,9 +131,7 @@ function applyDecs2203RFactory() { function assertNotFinished(decoratorFinishedRef, fnName) { if (decoratorFinishedRef.v) { - throw new Error( - "attempted to call " + fnName + " after decoration was finished" - ); + throw new Error("attempted to call " + fnName + " after decoration was finished"); } } @@ -164,9 +146,7 @@ function applyDecs2203RFactory() { if (kind === 1 /* ACCESSOR */) { if (type !== "object" || value === null) { - throw new TypeError( - "accessor decorators must return an object with get, set, or init properties or void 0" - ); + throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0"); } if (value.get !== undefined) { assertCallable(value.get, "accessor.get"); @@ -186,55 +166,31 @@ function applyDecs2203RFactory() { } else { hint = "method"; } - throw new TypeError( - hint + " decorators must return a function or void 0" - ); + throw new TypeError(hint + " decorators must return a function or void 0"); } } - function applyMemberDec( - ret, - base, - decInfo, - name, - kind, - isStatic, - isPrivate, - initializers, - metadata - ) { + function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) { var decs = decInfo[0]; var desc, init, value; if (isPrivate) { if (kind === 0 /* FIELD */ || kind === 1 /* ACCESSOR */) { - desc = { - get: decInfo[3], - set: decInfo[4], - }; + desc = { get: decInfo[3], set: decInfo[4] }; } else if (kind === 3 /* GETTER */) { - desc = { - get: decInfo[3], - }; + desc = { get: decInfo[3] }; } else if (kind === 4 /* SETTER */) { - desc = { - set: decInfo[3], - }; + desc = { set: decInfo[3] }; } else { - desc = { - value: decInfo[3], - }; + desc = { value: decInfo[3] }; } } else if (kind !== 0 /* FIELD */) { desc = Object.getOwnPropertyDescriptor(base, name); } if (kind === 1 /* ACCESSOR */) { - value = { - get: desc.get, - set: desc.set, - }; + value = { get: desc.get, set: desc.set }; } else if (kind === 2 /* METHOD */) { value = desc.value; } else if (kind === 3 /* GETTER */) { @@ -246,17 +202,7 @@ function applyDecs2203RFactory() { var newValue, get, set; if (typeof decs === "function") { - newValue = memberDec( - decs, - name, - desc, - initializers, - kind, - isStatic, - isPrivate, - metadata, - value - ); + newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value); if (newValue !== void 0) { assertValidReturnValue(kind, newValue); @@ -277,17 +223,7 @@ function applyDecs2203RFactory() { for (var i = decs.length - 1; i >= 0; i--) { var dec = decs[i]; - newValue = memberDec( - dec, - name, - desc, - initializers, - kind, - isStatic, - isPrivate, - metadata, - value - ); + newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value); if (newValue !== void 0) { assertValidReturnValue(kind, newValue); @@ -321,25 +257,23 @@ function applyDecs2203RFactory() { if (kind === 0 /* FIELD */ || kind === 1 /* ACCESSOR */) { if (init === void 0) { // If the initializer was void 0, sub in a dummy initializer - init = function (instance, init) { + init = function(instance, init) { return init; }; } else if (typeof init !== "function") { var ownInitializers = init; - init = function (instance, init) { + init = function(instance, init) { var value = init; - for (var i = 0; i < ownInitializers.length; i++) { - value = ownInitializers[i].call(instance, value); - } + for (var i = 0; i < ownInitializers.length; i++) value = ownInitializers[i].call(instance, value); return value; }; } else { var originalInitializer = init; - init = function (instance, init) { + init = function(instance, init) { return originalInitializer.call(instance, init); }; } @@ -361,16 +295,16 @@ function applyDecs2203RFactory() { if (isPrivate) { if (kind === 1 /* ACCESSOR */) { - ret.push(function (instance, args) { + ret.push(function(instance, args) { return value.get.call(instance, args); }); - ret.push(function (instance, args) { + ret.push(function(instance, args) { return value.set.call(instance, args); }); } else if (kind === 2 /* METHOD */) { ret.push(value); } else { - ret.push(function (instance, args) { + ret.push(function(instance, args) { return value.call(instance, args); }); } @@ -416,20 +350,14 @@ function applyDecs2203RFactory() { } if (kind !== 0 /* FIELD */ && !isPrivate) { - var existingNonFields = isStatic - ? existingStaticNonFields - : existingProtoNonFields; + var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields; var existingKind = existingNonFields.get(name) || 0; - if ( - existingKind === true || - (existingKind === 3 /* GETTER */ && kind !== 4) /* SETTER */ || - (existingKind === 4 /* SETTER */ && kind !== 3) /* GETTER */ - ) { + if (existingKind === true || (existingKind === 3 /* GETTER */ && kind !== 4) /* SETTER */ || (existingKind === 4 /* SETTER */ && kind !== 3) /* GETTER */) { throw new Error( - "Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + - name + "Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + + name ); } else if (!existingKind && kind > 2 /* METHOD */) { existingNonFields.set(name, kind); @@ -438,17 +366,7 @@ function applyDecs2203RFactory() { } } - applyMemberDec( - ret, - base, - decInfo, - name, - kind, - isStatic, - isPrivate, - initializers, - metadata - ); + applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata); } pushInitializers(ret, protoInitializers); @@ -458,10 +376,8 @@ function applyDecs2203RFactory() { function pushInitializers(ret, initializers) { if (initializers) { - ret.push(function (instance) { - for (var i = 0; i < initializers.length; i++) { - initializers[i].call(instance); - } + ret.push(function(instance) { + for (var i = 0; i < initializers.length; i++) initializers[i].call(instance); return instance; }); } @@ -476,47 +392,30 @@ function applyDecs2203RFactory() { for (var i = classDecs.length - 1; i >= 0; i--) { var decoratorFinishedRef = { v: false }; - var nextNewClass = classDecs[i](newClass, { - kind: "class", - name: name, - addInitializer: createAddInitializerMethod( - initializers, - decoratorFinishedRef - ), - metadata, - }); + var nextNewClass = classDecs[i](newClass, { kind: "class", name: name, addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef), metadata }); decoratorFinishedRef.v = true; if (nextNewClass !== undefined) { - assertValidReturnValue(10 /* CLASS */, nextNewClass); + assertValidReturnValue(10, /* CLASS */ nextNewClass); newClass = nextNewClass; } } - return [ - defineMetadata(newClass, metadata), - function () { - for (var i = 0; i < initializers.length; i++) { - initializers[i].call(newClass); - } - }, - ]; + return [defineMetadata(newClass, metadata), function() { + for (var i = 0; i < initializers.length; i++) initializers[i].call(newClass); + }]; } // The transformer will not emit assignment when there are no class decorators, // so we don't have to return an empty array here. } function defineMetadata(Class, metadata) { - return Object.defineProperty( - Class, - Symbol.metadata || Symbol.for("Symbol.metadata"), - { configurable: true, enumerable: true, value: metadata } - ); + return Object.defineProperty(Class, Symbol.metadata || Symbol.for("Symbol.metadata"), { configurable: true, enumerable: true, value: metadata }); } /** Basic usage: - + applyDecs( Class, [ @@ -534,59 +433,59 @@ function applyDecs2203RFactory() { ] ) ``` - + Fully transpiled example: - + ```js @dec class Class { @dec a = 123; - + @dec #a = 123; - + @dec @dec2 accessor b = 123; - + @dec accessor #b = 123; - + @dec c() { console.log('c'); } - + @dec #c() { console.log('privC'); } - + @dec get d() { console.log('d'); } - + @dec get #d() { console.log('privD'); } - + @dec set e(v) { console.log('e'); } - + @dec set #e(v) { console.log('privE'); } } - - + + // becomes let initializeInstance; let initializeClass; - + let initA; let initPrivA; - + let initB; let initPrivB, getPrivB, setPrivB; - + let privC; let privD; let privE; - + let Class; class _Class { static { @@ -608,66 +507,63 @@ function applyDecs2203RFactory() { dec ] ) - + initA = ret[0]; - + initPrivA = ret[1]; - + initB = ret[2]; - + initPrivB = ret[3]; getPrivB = ret[4]; setPrivB = ret[5]; - + privC = ret[6]; - + privD = ret[7]; - + privE = ret[8]; - + initializeInstance = ret[9]; - + Class = ret[10] - + initializeClass = ret[11]; } - + a = (initializeInstance(this), initA(this, 123)); - + #a = initPrivA(this, 123); - + #bData = initB(this, 123); get b() { return this.#bData } set b(v) { this.#bData = v } - + #privBData = initPrivB(this, 123); get #b() { return getPrivB(this); } set #b(v) { setPrivB(this, v); } - + c() { console.log('c'); } - + #c(...args) { return privC(this, ...args) } - + get d() { console.log('d'); } - + get #d() { return privD(this); } - + set e(v) { console.log('e'); } - + set #e(v) { privE(this, v); } } - + initializeClass(Class); */ - return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) { + _apply_decs_2203_r = function(targetClass, memberDecs, classDecs, parentClass) { if (parentClass !== void 0) { - var parentMetadata = - parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")]; + var parentMetadata = parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")]; } - var metadata = Object.create( - parentMetadata === void 0 ? null : parentMetadata - ); + var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata); var e = applyMemberDecs(targetClass, memberDecs, metadata); if (!classDecs.length) defineMetadata(targetClass, metadata); return { @@ -675,16 +571,20 @@ function applyDecs2203RFactory() { // Lazily apply class decorations so that member init locals can be properly bound. get c() { return applyClassDecs(targetClass, classDecs, metadata); - }, + } }; }; -} -function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) { - return (_apply_decs_2203_r = applyDecs2203RFactory())( - targetClass, - memberDecs, - classDecs, - parentClass - ); + return _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass); +} +"##, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000000002), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS } diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_apply_decs_2311.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_apply_decs_2311.rs similarity index 61% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_apply_decs_2311.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_apply_decs_2311.rs index fe647d209..e1b9995d8 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_apply_decs_2311.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_apply_decs_2311.rs @@ -1,4 +1,13 @@ -/* @minVersion 7.24.0 */ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::apply_decs_2311, + local: "_apply_decs_2311", + import_path: "@swc/helpers/_/_apply_decs_2311", + #[cfg(feature = "inline-helpers")] + source: r##"/* @minVersion 7.24.0 */ function toPrimitive(input, hint) { if (typeof input !== "object" || input === null) { @@ -24,10 +33,7 @@ function toPropertyKey(arg) { function checkInRHS(value) { if (Object(value) !== value) { - throw TypeError( - "right-hand side of 'in' should be an object, got " + - (value !== null ? typeof value : "null") - ); + throw TypeError("right-hand side of 'in' should be an object, got " + (value !== null ? typeof value : "null")); } return value; @@ -40,10 +46,7 @@ function setFunctionName(fn, name, prefix) { } try { - Object.defineProperty(fn, "name", { - configurable: true, - value: prefix ? prefix + " " + name : name, - }); + Object.defineProperty(fn, "name", { configurable: true, value: prefix ? prefix + " " + name : name }); } catch (_) {} return fn; @@ -62,14 +65,7 @@ function setFunctionName(fn, name, prefix) { STATIC = 8 DECORATORS_HAVE_THIS = 16 */ -function _apply_decs_2311( - targetClass, - classDecs, - memberDecs, - classDecsHaveThis, - instanceBrand, - parentClass -) { +function _apply_decs_2311(targetClass, classDecs, memberDecs, classDecsHaveThis, instanceBrand, parentClass) { var symbolMetadata = Symbol.metadata || Symbol.for("Symbol.metadata"); var defineProperty = Object.defineProperty; var create = Object.create; @@ -79,15 +75,13 @@ function _apply_decs_2311( var _; function createRunInitializers(initializers, useStaticThis, hasValue) { - return function (thisArg, value) { + return function(thisArg, value) { if (useStaticThis) { value = thisArg; thisArg = targetClass; } - for (var i = 0; i < initializers.length; i++) { - value = initializers[i].apply(thisArg, hasValue ? [value] : []); - } + for (var i = 0; i < initializers.length; i++) value = initializers[i].apply(thisArg, hasValue ? [value] : []); return hasValue ? value : thisArg; }; @@ -96,37 +90,17 @@ function _apply_decs_2311( function assertCallable(fn, hint1, hint2, throwUndefined) { if (typeof fn !== "function") { if (throwUndefined || fn !== void 0) { - throw new TypeError( - hint1 + - " must " + - (hint2 || "be") + - " a function" + - (throwUndefined ? "" : " or undefined") - ); + throw new TypeError(hint1 + " must " + (hint2 || "be") + " a function" + (throwUndefined ? "" : " or undefined")); } } return fn; } - function applyDec( - Class, - decInfo, - decoratorsHaveThis, - name, - kind, - initializers, - ret, - isStatic, - isPrivate, - isField, - hasPrivateBrand - ) { + function applyDec(Class, decInfo, decoratorsHaveThis, name, kind, initializers, ret, isStatic, isPrivate, isField, hasPrivateBrand) { function assertInstanceIfPrivate(target) { if (!hasPrivateBrand(target)) { - throw new TypeError( - "Attempted to access private element on non-instance" - ); + throw new TypeError("Attempted to access private element on non-instance"); } } @@ -140,7 +114,7 @@ function _apply_decs_2311( var isMethod = kind === 2; function bindPropCall(name, useStaticThis, before) { - return function (_this, value) { + return function(_this, value) { if (useStaticThis) { value = _this; _this = Class; @@ -163,15 +137,15 @@ function _apply_decs_2311( if (isField || isAccessor) { desc = { get: setFunctionName( - function () { + function() { return decVal(this); }, name, "get" ), - set: function (value) { + set: function(value) { decInfo[4](this, value); - }, + } }; } else { desc[key] = decVal; @@ -187,11 +161,7 @@ function _apply_decs_2311( if (!isField && !isPrivate) { _ = existingNonFields[+isStatic][name]; if (_ && (_ ^ kind) !== 7) { - throw new Error( - "Decorating two elements with the same name (" + - desc[key].name + - ") is not supported yet" - ); + throw new Error("Decorating two elements with the same name (" + desc[key].name + ") is not supported yet"); } existingNonFields[+isStatic][name] = kind < 3 ? 1 : kind; @@ -209,15 +179,14 @@ function _apply_decs_2311( kind: ["field", "accessor", "method", "getter", "setter", "class"][kind], name: name, metadata: metadata, - addInitializer: function (decoratorFinishedRef, initializer) { + addInitializer: function(decoratorFinishedRef, initializer) { if (decoratorFinishedRef.v) { - throw new TypeError( - "attempted to call addInitializer after decoration was finished" - ); + throw new TypeError("attempted to call addInitializer after decoration was finished"); } assertCallable(initializer, "An initializer", "be", true); initializers.push(initializer); - }.bind(null, decoratorFinishedRef), + } + .bind(null, decoratorFinishedRef) }; if (isClass) { @@ -233,44 +202,31 @@ function _apply_decs_2311( ctx.static = isStatic; ctx.private = isPrivate; _ = ctx.access = { - has: isPrivate - ? hasPrivateBrand.bind() - : function (target) { - return name in target; - }, + has: isPrivate ? hasPrivateBrand.bind() : function(target) { + return name in target; + } }; if (!isSetter) { _.get = isPrivate ? isMethod - ? function (_this) { - assertInstanceIfPrivate(_this); - return desc.value; - } + ? function(_this) { + assertInstanceIfPrivate(_this); + return desc.value; + } : bindPropCall("get", 0, assertInstanceIfPrivate) - : function (target) { - return target[name]; - }; + : function(target) { + return target[name]; + }; } if (!isMethod && !isGetter) { - _.set = isPrivate - ? bindPropCall("set", 0, assertInstanceIfPrivate) - : function (target, value) { - target[name] = value; - }; + _.set = isPrivate ? bindPropCall("set", 0, assertInstanceIfPrivate) : function(target, value) { + target[name] = value; + }; } - newValue = dec.call( - decThis, - isAccessor - ? { - get: desc.get, - set: desc.set, - } - : desc[key], - ctx - ); + newValue = dec.call(decThis, isAccessor ? { get: desc.get, set: desc.set } : desc[key], ctx); decoratorFinishedRef.v = 1; @@ -286,17 +242,9 @@ function _apply_decs_2311( init.unshift(_); } } else if (newValue !== void 0) { - throw new TypeError( - "accessor decorators must return an object with get, set, or init properties or undefined" - ); + throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } - } else if ( - assertCallable( - newValue, - (isField ? "field" : "method") + " decorators", - "return" - ) - ) { + } else if (assertCallable(newValue, (isField ? "field" : "method") + " decorators", "return")) { if (isField) { init.unshift(newValue); } else { @@ -306,21 +254,13 @@ function _apply_decs_2311( } if (kind < 2) { - ret.push( - createRunInitializers(init, isStatic, 1), - createRunInitializers(initializers, isStatic, 0) - ); + ret.push(createRunInitializers(init, isStatic, 1), createRunInitializers(initializers, isStatic, 0)); } if (!isField && !isClass) { if (isPrivate) { if (isAccessor) { - ret.splice( - -1, - 0, - bindPropCall("get", isStatic), - bindPropCall("set", isStatic) - ); + ret.splice(-1, 0, bindPropCall("get", isStatic), bindPropCall("set", isStatic)); } else { ret.push(isMethod ? desc[key] : assertCallable.call.bind(desc[key])); } @@ -337,13 +277,13 @@ function _apply_decs_2311( var protoInitializers; var staticInitializers; - var pushInitializers = function (initializers) { + var pushInitializers = function(initializers) { if (initializers) { ret.push(createRunInitializers(initializers)); } }; - var applyMemberDecsOfKind = function (isStatic, isField) { + var applyMemberDecsOfKind = function(isStatic, isField) { for (var i = 0; i < memberDecs.length; i++) { var decInfo = memberDecs[i]; var kind = decInfo[1]; @@ -360,19 +300,15 @@ function _apply_decs_2311( decoratorsHaveThis, isPrivate ? "#" + name : toPropertyKey(name), kindOnly, - kindOnly < 2 - ? [] - : isStatic - ? (staticInitializers = staticInitializers || []) - : (protoInitializers = protoInitializers || []), + kindOnly < 2 ? [] : isStatic ? (staticInitializers = staticInitializers || []) : (protoInitializers = protoInitializers || []), ret, !!isStatic, isPrivate, isField, isStatic && isPrivate - ? function (_) { - return checkInRHS(_) === targetClass; - } + ? function(_) { + return checkInRHS(_) === targetClass; + } : instanceBrand ); } @@ -391,11 +327,7 @@ function _apply_decs_2311( } function defineMetadata(Class) { - return defineProperty(Class, symbolMetadata, { - configurable: true, - enumerable: true, - value: metadata, - }); + return defineProperty(Class, symbolMetadata, { configurable: true, enumerable: true, value: metadata }); } if (parentClass !== undefined) { @@ -413,21 +345,18 @@ function _apply_decs_2311( e: _, get c() { var initializers = []; - return ( - hasClassDecs && [ - defineMetadata( - (targetClass = applyDec( - targetClass, - [classDecs], - classDecsHaveThis, - targetClass.name, - 5, - initializers - )) - ), - createRunInitializers(initializers, 1), - ] - ); - }, + return (hasClassDecs && [defineMetadata(targetClass = applyDec(targetClass, [classDecs], classDecsHaveThis, targetClass.name, 5, initializers)), createRunInitializers(initializers, 1)]); + } }; } +"##, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000000004), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_like_to_array.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_like_to_array.rs new file mode 100644 index 000000000..2d9b49658 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_like_to_array.rs @@ -0,0 +1,27 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::array_like_to_array, + local: "_array_like_to_array", + import_path: "@swc/helpers/_/_array_like_to_array", + #[cfg(feature = "inline-helpers")] + source: r#"function _array_like_to_array(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000000008), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_with_holes.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_with_holes.rs new file mode 100644 index 000000000..41be758d0 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_with_holes.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::array_with_holes, + local: "_array_with_holes", + import_path: "@swc/helpers/_/_array_with_holes", + #[cfg(feature = "inline-helpers")] + source: r#"function _array_with_holes(arr) { + if (Array.isArray(arr)) return arr; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000000010), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_without_holes.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_without_holes.rs new file mode 100644 index 000000000..b16a9bf13 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_array_without_holes.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::array_without_holes, + local: "_array_without_holes", + import_path: "@swc/helpers/_/_array_without_holes", + #[cfg(feature = "inline-helpers")] + source: r#"function _array_without_holes(arr) { + if (Array.isArray(arr)) return _array_like_to_array(arr); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000000028), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_assert_this_initialized.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_assert_this_initialized.rs new file mode 100644 index 000000000..5fc9b0ece --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_assert_this_initialized.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::assert_this_initialized, + local: "_assert_this_initialized", + import_path: "@swc/helpers/_/_assert_this_initialized", + #[cfg(feature = "inline-helpers")] + source: r#"function _assert_this_initialized(self) { + if (self === void 0) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + + return self; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000000040), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_generator.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_generator.rs similarity index 74% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_generator.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_generator.rs index 69d23f2db..b2b775077 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_generator.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_generator.rs @@ -1,5 +1,15 @@ -function _async_generator(gen) { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::async_generator, + local: "_async_generator", + import_path: "@swc/helpers/_/_async_generator", + #[cfg(feature = "inline-helpers")] + source: r#"function _async_generator(gen) { var front, back; + function send(key, arg) { return new Promise(function(resolve, reject) { var request = { key: key, arg: arg, resolve: resolve, reject: reject, next: null }; @@ -10,6 +20,7 @@ function _async_generator(gen) { } }); } + function resume(key, arg) { try { var result = gen[key](arg); @@ -29,6 +40,7 @@ function _async_generator(gen) { settle("throw", err); } } + function settle(type, value) { switch (type) { case "return": @@ -47,17 +59,33 @@ function _async_generator(gen) { } this._invoke = send; + if (typeof gen.return !== "function") this.return = undefined; } + _async_generator.prototype[(typeof Symbol === "function" && Symbol.asyncIterator) || "@@asyncIterator"] = function() { return this; }; + _async_generator.prototype.next = function(arg) { return this._invoke("next", arg); }; + _async_generator.prototype.throw = function(arg) { return this._invoke("throw", arg); }; + _async_generator.prototype.return = function(arg) { return this._invoke("return", arg); }; +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000002000000000000000080), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_generator_delegate.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_generator_delegate.rs similarity index 58% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_generator_delegate.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_generator_delegate.rs index b05d51506..ac7d80cac 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_generator_delegate.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_generator_delegate.rs @@ -1,28 +1,45 @@ -function _async_generator_delegate(inner) { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::async_generator_delegate, + local: "_async_generator_delegate", + import_path: "@swc/helpers/_/_async_generator_delegate", + #[cfg(feature = "inline-helpers")] + source: r#"function _async_generator_delegate(inner) { var iter = {}, waiting = false; + function pump(key, value) { waiting = true; value = new Promise(function(resolve) { resolve(inner[key](value)); }); + return { done: false, value: new _overload_yield(value, /* kind: delegate */ 1) }; } + iter[(typeof Symbol !== "undefined" && Symbol.iterator) || "@@iterator"] = function() { return this; }; + iter.next = function(value) { if (waiting) { waiting = false; + return value; } + return pump("next", value); }; + if (typeof inner.throw === "function") { iter.throw = function(value) { if (waiting) { waiting = false; throw value; } + return pump("throw", value); }; } @@ -35,5 +52,17 @@ function _async_generator_delegate(inner) { return pump("return", value); }; } + return iter; } +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000002000000000000000100), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_iterator.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_iterator.rs similarity index 63% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_iterator.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_iterator.rs index afc18a37e..1be99010d 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_async_iterator.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_iterator.rs @@ -1,4 +1,13 @@ -function _async_iterator(iterable) { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::async_iterator, + local: "_async_iterator", + import_path: "@swc/helpers/_/_async_iterator", + #[cfg(feature = "inline-helpers")] + source: r#"function _async_iterator(iterable) { var method, async, sync, retry = 2; for ("undefined" != typeof Symbol && (async = Symbol.asyncIterator, sync = Symbol.iterator); retry--;) { if (async && null != (method = iterable[async])) return method.call(iterable); @@ -10,30 +19,45 @@ function _async_iterator(iterable) { function AsyncFromSyncIterator(s) { function AsyncFromSyncIteratorContinuation(r) { if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object.")); + var done = r.done; + return Promise.resolve(r.value).then(function(value) { return { value: value, done: done }; }); } + return AsyncFromSyncIterator = function(s) { this.s = s, this.n = s.next; }, AsyncFromSyncIterator.prototype = { s: null, n: null, + next: function() { return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); }, return: function(value) { var ret = this.s.return; - return void 0 === ret - ? Promise.resolve({ value: value, done: !0 }) - : AsyncFromSyncIteratorContinuation(ret.apply(this.s, arguments)); + + return void 0 === ret ? Promise.resolve({ value: value, done: !0 }) : AsyncFromSyncIteratorContinuation(ret.apply(this.s, arguments)); }, throw: function(value) { var thr = this.s.return; + return void 0 === thr ? Promise.reject(value) : AsyncFromSyncIteratorContinuation(thr.apply(this.s, arguments)); } }, new AsyncFromSyncIterator(s); } +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000000200), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_to_generator.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_to_generator.rs new file mode 100644 index 000000000..a44d29d4a --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_async_to_generator.rs @@ -0,0 +1,50 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::async_to_generator, + local: "_async_to_generator", + import_path: "@swc/helpers/_/_async_to_generator", + #[cfg(feature = "inline-helpers")] + source: r#"function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + if (info.done) resolve(value); + else Promise.resolve(value).then(_next, _throw); +} +function _async_to_generator(fn) { + return function() { + var self = this, args = arguments; + + return new Promise(function(resolve, reject) { + var gen = fn.apply(self, args); + + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); + } + + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); + } + + _next(undefined); + }); + }; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000000400), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_await_async_generator.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_await_async_generator.rs new file mode 100644 index 000000000..d8ca6e880 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_await_async_generator.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::await_async_generator, + local: "_await_async_generator", + import_path: "@swc/helpers/_/_await_async_generator", + #[cfg(feature = "inline-helpers")] + source: r#"function _await_async_generator(value) { + return new _overload_yield(value, /* kind: await */ 0); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000002000000000000000800), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_await_value.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_await_value.rs new file mode 100644 index 000000000..6db475d65 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_await_value.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::await_value, + local: "_await_value", + import_path: "@swc/helpers/_/_await_value", + #[cfg(feature = "inline-helpers")] + source: r#"function _await_value(value) { + this.wrapped = value; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000001000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_call_super.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_call_super.rs new file mode 100644 index 000000000..e65c97bc7 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_call_super.rs @@ -0,0 +1,31 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::call_super, + local: "_call_super", + import_path: "@swc/helpers/_/_call_super", + #[cfg(feature = "inline-helpers")] + source: r#"function _call_super(_this, derived, args) { + // Super + derived = _get_prototype_of(derived); + return _possible_constructor_return( + _this, + _is_native_reflect_construct() + // NOTE: This doesn't work if this.__proto__.constructor has been modified. + ? Reflect.construct(derived, args || [], _get_prototype_of(_this).constructor) + : derived.apply(_this, args) + ); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000002000004002008000000002040), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_check_private_redeclaration.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_check_private_redeclaration.rs new file mode 100644 index 000000000..533df06a4 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_check_private_redeclaration.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::check_private_redeclaration, + local: "_check_private_redeclaration", + import_path: "@swc/helpers/_/_check_private_redeclaration", + #[cfg(feature = "inline-helpers")] + source: r#"function _check_private_redeclaration(obj, privateCollection) { + if (privateCollection.has(obj)) { + throw new TypeError("Cannot initialize the same private elements twice on an object"); + } +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000004000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_destructure.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_destructure.rs new file mode 100644 index 000000000..40a56ef44 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_destructure.rs @@ -0,0 +1,42 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_apply_descriptor_destructure, + local: "_class_apply_descriptor_destructure", + import_path: "@swc/helpers/_/_class_apply_descriptor_destructure", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_apply_descriptor_destructure(receiver, descriptor) { + if (descriptor.set) { + if (!("__destrObj" in descriptor)) { + descriptor.__destrObj = { + set value(v) { + descriptor.set.call(receiver, v); + } + }; + } + + return descriptor.__destrObj; + } else { + if (!descriptor.writable) { + // This should only throw in strict mode, but class bodies are + // always strict and private fields can only be used inside + // class bodies. + throw new TypeError("attempted to set read only private field"); + } + + return descriptor; + } +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000008000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_get.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_get.rs new file mode 100644 index 000000000..8d27d904f --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_get.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_apply_descriptor_get, + local: "_class_apply_descriptor_get", + import_path: "@swc/helpers/_/_class_apply_descriptor_get", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_apply_descriptor_get(receiver, descriptor) { + if (descriptor.get) return descriptor.get.call(receiver); + + return descriptor.value; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000010000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_set.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_set.rs new file mode 100644 index 000000000..e05d1e9d0 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_set.rs @@ -0,0 +1,32 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_apply_descriptor_set, + local: "_class_apply_descriptor_set", + import_path: "@swc/helpers/_/_class_apply_descriptor_set", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_apply_descriptor_set(receiver, descriptor, value) { + if (descriptor.set) descriptor.set.call(receiver, value); + else { + if (!descriptor.writable) { + // This should only throw in strict mode, but class bodies are + // always strict and private fields can only be used inside + // class bodies. + throw new TypeError("attempted to set read only private field"); + } + descriptor.value = value; + } +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000020000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_update.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_update.rs new file mode 100644 index 000000000..f343c8b1c --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_apply_descriptor_update.rs @@ -0,0 +1,47 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_apply_descriptor_update, + local: "_class_apply_descriptor_update", + import_path: "@swc/helpers/_/_class_apply_descriptor_update", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_apply_descriptor_update(receiver, descriptor) { + if (descriptor.set) { + if (!descriptor.get) throw new TypeError("attempted to read set only private field"); + + if (!("__destrWrapper" in descriptor)) { + descriptor.__destrWrapper = { + set value(v) { + descriptor.set.call(receiver, v); + }, + get value() { + return descriptor.get.call(receiver); + } + }; + } + + return descriptor.__destrWrapper; + } else { + if (!descriptor.writable) { + // This should only throw in strict mode, but class bodies are + // always strict and private fields can only be used inside + // class bodies. + throw new TypeError("attempted to set read only private field"); + } + + return descriptor; + } +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000040000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_call_check.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_call_check.rs new file mode 100644 index 000000000..635c99335 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_call_check.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_call_check, + local: "_class_call_check", + import_path: "@swc/helpers/_/_class_call_check", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_call_check(instance, Constructor) { + if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000080000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_check_private_static_access.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_check_private_static_access.rs new file mode 100644 index 000000000..e9821f569 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_check_private_static_access.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_check_private_static_access, + local: "_class_check_private_static_access", + import_path: "@swc/helpers/_/_class_check_private_static_access", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_check_private_static_access(receiver, classConstructor) { + if (receiver !== classConstructor) throw new TypeError("Private static access of wrong provenance"); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000100000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_check_private_static_field_descriptor.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_check_private_static_field_descriptor.rs new file mode 100644 index 000000000..429c45682 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_check_private_static_field_descriptor.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_check_private_static_field_descriptor, + local: "_class_check_private_static_field_descriptor", + import_path: "@swc/helpers/_/_class_check_private_static_field_descriptor", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_check_private_static_field_descriptor(descriptor, action) { + if (descriptor === undefined) { + throw new TypeError("attempted to " + action + " private static field before its declaration"); + } +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000200000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_extract_field_descriptor.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_extract_field_descriptor.rs new file mode 100644 index 000000000..3f1d71657 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_extract_field_descriptor.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_extract_field_descriptor, + local: "_class_extract_field_descriptor", + import_path: "@swc/helpers/_/_class_extract_field_descriptor", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_extract_field_descriptor(receiver, privateMap, action) { + if (!privateMap.has(receiver)) throw new TypeError("attempted to " + action + " private field on non-instance"); + + return privateMap.get(receiver); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000400000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_name_tdz_error.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_name_tdz_error.rs new file mode 100644 index 000000000..b3aa4f304 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_name_tdz_error.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_name_tdz_error, + local: "_class_name_tdz_error", + import_path: "@swc/helpers/_/_class_name_tdz_error", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_name_tdz_error(name) { + throw new ReferenceError("Class \"" + name + "\" cannot be referenced in computed property keys."); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000000800000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_destructure.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_destructure.rs new file mode 100644 index 000000000..92c7cd2c6 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_destructure.rs @@ -0,0 +1,24 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_field_destructure, + local: "_class_private_field_destructure", + import_path: "@swc/helpers/_/_class_private_field_destructure", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_private_field_destructure(receiver, privateMap) { + var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set"); + return _class_apply_descriptor_destructure(receiver, descriptor); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000001408000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_get.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_get.rs new file mode 100644 index 000000000..71f2e7fed --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_get.rs @@ -0,0 +1,24 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_field_get, + local: "_class_private_field_get", + import_path: "@swc/helpers/_/_class_private_field_get", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_private_field_get(receiver, privateMap) { + var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get"); + return _class_apply_descriptor_get(receiver, descriptor); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000002410000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_init.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_init.rs new file mode 100644 index 000000000..efa57ec1a --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_init.rs @@ -0,0 +1,24 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_field_init, + local: "_class_private_field_init", + import_path: "@swc/helpers/_/_class_private_field_init", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_private_field_init(obj, privateMap, value) { + _check_private_redeclaration(obj, privateMap); + privateMap.set(obj, value); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000004004000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_loose_base.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_loose_base.rs new file mode 100644 index 000000000..bef81e7de --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_loose_base.rs @@ -0,0 +1,27 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_field_loose_base, + local: "_class_private_field_loose_base", + import_path: "@swc/helpers/_/_class_private_field_loose_base", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_private_field_loose_base(receiver, privateKey) { + if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { + throw new TypeError("attempted to use private field on non-instance"); + } + + return receiver; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000008000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_loose_key.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_loose_key.rs new file mode 100644 index 000000000..468b10d8c --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_loose_key.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_field_loose_key, + local: "_class_private_field_loose_key", + import_path: "@swc/helpers/_/_class_private_field_loose_key", + #[cfg(feature = "inline-helpers")] + source: r#"var id = 0; + +function _class_private_field_loose_key(name) { + return "__private_" + id++ + "_" + name; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000010000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_set.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_set.rs new file mode 100644 index 000000000..0c6ab27bf --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_set.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_field_set, + local: "_class_private_field_set", + import_path: "@swc/helpers/_/_class_private_field_set", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_private_field_set(receiver, privateMap, value) { + var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set"); + _class_apply_descriptor_set(receiver, descriptor, value); + return value; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000020420000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_update.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_update.rs new file mode 100644 index 000000000..f9b4f2103 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_field_update.rs @@ -0,0 +1,24 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_field_update, + local: "_class_private_field_update", + import_path: "@swc/helpers/_/_class_private_field_update", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_private_field_update(receiver, privateMap) { + var descriptor = _class_extract_field_descriptor(receiver, privateMap, "update"); + return _class_apply_descriptor_update(receiver, descriptor); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000040440000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_get.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_get.rs new file mode 100644 index 000000000..7d4552e5a --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_get.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_method_get, + local: "_class_private_method_get", + import_path: "@swc/helpers/_/_class_private_method_get", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_private_method_get(receiver, privateSet, fn) { + if (!privateSet.has(receiver)) throw new TypeError("attempted to get private field on non-instance"); + + return fn; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000080000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_init.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_init.rs new file mode 100644 index 000000000..52440ca9a --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_init.rs @@ -0,0 +1,24 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_method_init, + local: "_class_private_method_init", + import_path: "@swc/helpers/_/_class_private_method_init", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_private_method_init(obj, privateSet) { + _check_private_redeclaration(obj, privateSet); + privateSet.add(obj); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000100004000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_set.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_set.rs new file mode 100644 index 000000000..d260aa836 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_private_method_set.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_private_method_set, + local: "_class_private_method_set", + import_path: "@swc/helpers/_/_class_private_method_set", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_private_method_set() { + throw new TypeError("attempted to reassign private method"); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000200000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_field_destructure.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_field_destructure.rs new file mode 100644 index 000000000..8e0cdfd2d --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_field_destructure.rs @@ -0,0 +1,26 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_static_private_field_destructure, + local: "_class_static_private_field_destructure", + import_path: "@swc/helpers/_/_class_static_private_field_destructure", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_static_private_field_destructure(receiver, classConstructor, descriptor) { + _class_check_private_static_access(receiver, classConstructor); + _class_check_private_static_field_descriptor(descriptor, "set"); + + return _class_apply_descriptor_destructure(receiver, descriptor); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000000400308000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_field_update.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_field_update.rs new file mode 100644 index 000000000..be4522715 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_field_update.rs @@ -0,0 +1,26 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_static_private_field_update, + local: "_class_static_private_field_update", + import_path: "@swc/helpers/_/_class_static_private_field_update", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_static_private_field_update(receiver, classConstructor, descriptor) { + _class_check_private_static_access(receiver, classConstructor); + _class_check_private_static_field_descriptor(descriptor, "update"); + + return _class_apply_descriptor_update(receiver, descriptor); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000002000340000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_method_get.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_method_get.rs new file mode 100644 index 000000000..0e8b1852b --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_class_static_private_method_get.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::class_static_private_method_get, + local: "_class_static_private_method_get", + import_path: "@swc/helpers/_/_class_static_private_method_get", + #[cfg(feature = "inline-helpers")] + source: r#"function _class_static_private_method_get(receiver, classConstructor, method) { + _class_check_private_static_access(receiver, classConstructor); + + return method; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000004000100000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_construct.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_construct.rs new file mode 100644 index 000000000..e13784300 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_construct.rs @@ -0,0 +1,37 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::construct, + local: "_construct", + import_path: "@swc/helpers/_/_construct", + #[cfg(feature = "inline-helpers")] + source: r#"function _construct(Parent, args, Class) { + if (_is_native_reflect_construct()) _construct = Reflect.construct; + else { + _construct = function construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + + if (Class) _set_prototype_of(instance, Class.prototype); + + return instance; + }; + } + + return _construct.apply(null, arguments); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000020002000008000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_class.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_class.rs new file mode 100644 index 000000000..035323145 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_class.rs @@ -0,0 +1,37 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::create_class, + local: "_create_class", + import_path: "@swc/helpers/_/_create_class", + #[cfg(feature = "inline-helpers")] + source: r#"function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + + if ("value" in descriptor) descriptor.writable = true; + + Object.defineProperty(target, descriptor.key, descriptor); + } +} +function _create_class(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + + return Constructor; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000010000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_for_of_iterator_helper_loose.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_for_of_iterator_helper_loose.rs new file mode 100644 index 000000000..543fb223e --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_for_of_iterator_helper_loose.rs @@ -0,0 +1,39 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::create_for_of_iterator_helper_loose, + local: "_create_for_of_iterator_helper_loose", + import_path: "@swc/helpers/_/_create_for_of_iterator_helper_loose", + #[cfg(feature = "inline-helpers")] + source: r#"function _create_for_of_iterator_helper_loose(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + + if (it) return (it = it.call(o)).next.bind(it); + // Fallback for engines without symbol support + if (Array.isArray(o) || (it = _unsupported_iterable_to_array(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + + var i = 0; + + return function() { + if (i >= o.length) return { done: true }; + + return { done: false, value: o[i++] }; + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000004000000000000020000000008), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_super.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_super.rs new file mode 100644 index 000000000..ad0745c64 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_create_super.rs @@ -0,0 +1,36 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::create_super, + local: "_create_super", + import_path: "@swc/helpers/_/_create_super", + #[cfg(feature = "inline-helpers")] + source: r#"function _create_super(Derived) { + var hasNativeReflectConstruct = _is_native_reflect_construct(); + + return function _createSuperInternal() { + var Super = _get_prototype_of(Derived), result; + + if (hasNativeReflectConstruct) { + var NewTarget = _get_prototype_of(this).constructor; + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + + return _possible_constructor_return(this, result); + }; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000002000004002008040000000040), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_decorate.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_decorate.rs similarity index 75% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_decorate.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_decorate.rs index 16e0a58a9..a5811125d 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_decorate.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_decorate.rs @@ -1,50 +1,55 @@ -function _decorate(decorators, factory, superClass) { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::decorate, + local: "_decorate", + import_path: "@swc/helpers/_/_decorate", + #[cfg(feature = "inline-helpers")] + source: r#"function _decorate(decorators, factory, superClass) { var r = factory(function initialize(O) { _initializeInstanceElements(O, decorated.elements); }, superClass); var decorated = _decorateClass(_coalesceClassElements(r.d.map(_createElementDescriptor)), decorators); _initializeClassElements(r.F, decorated.elements); + return _runClassFinishers(r.F, decorated.finishers); } function _createElementDescriptor(def) { var key = _to_property_key(def.key); var descriptor; + if (def.kind === "method") { descriptor = { value: def.value, writable: true, configurable: true, enumerable: false }; Object.defineProperty(def.value, "name", { value: _type_of(key) === "symbol" ? "" : key, configurable: true }); - } else if (def.kind === "get") { - descriptor = { get: def.value, configurable: true, enumerable: false }; - } else if (def.kind === "set") { - descriptor = { set: def.value, configurable: true, enumerable: false }; - } else if (def.kind === "field") { - descriptor = { configurable: true, writable: true, enumerable: true }; - } - var element = { - kind: def.kind === "field" ? "field" : "method", - key: key, - placement: def.static ? "static" : def.kind === "field" ? "own" : "prototype", - descriptor: descriptor - }; + } else if (def.kind === "get") descriptor = { get: def.value, configurable: true, enumerable: false }; + else if (def.kind === "set") descriptor = { set: def.value, configurable: true, enumerable: false }; + else if (def.kind === "field") descriptor = { configurable: true, writable: true, enumerable: true }; + + var element = { kind: def.kind === "field" ? "field" : "method", key: key, placement: def.static ? "static" : def.kind === "field" ? "own" : "prototype", descriptor: descriptor }; + if (def.decorators) element.decorators = def.decorators; + if (def.kind === "field") element.initializer = def.value; + return element; } function _coalesceGetterSetter(element, other) { - if (element.descriptor.get !== undefined) { - other.descriptor.get = element.descriptor.get; - } else { - other.descriptor.set = element.descriptor.set; - } + if (element.descriptor.get !== undefined) other.descriptor.get = element.descriptor.get; + else other.descriptor.set = element.descriptor.set; } function _coalesceClassElements(elements) { var newElements = []; var isSameElement = function isSameElement(other) { return other.kind === "method" && other.key === element.key && other.placement === element.placement; }; + for (var i = 0; i < elements.length; i++) { var element = elements[i]; var other; + if (element.kind === "method" && (other = newElements.find(isSameElement))) { if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) { if (_hasDecorators(element) || _hasDecorators(other)) { @@ -54,9 +59,7 @@ function _coalesceClassElements(elements) { } else { if (_hasDecorators(element)) { if (_hasDecorators(other)) { - throw new ReferenceError( - "Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ")." - ); + throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ")."); } other.decorators = element.decorators; } @@ -66,6 +69,7 @@ function _coalesceClassElements(elements) { newElements.push(element); } } + return newElements; } function _hasDecorators(element) { @@ -89,9 +93,7 @@ function _initializeClassElements(F, elements) { function _initializeInstanceElements(O, elements) { ["method", "field"].forEach(function(kind) { elements.forEach(function(element) { - if (element.kind === kind && element.placement === "own") { - _defineClassElement(O, element); - } + if (element.kind === kind && element.placement === "own") _defineClassElement(O, element); }); }); } @@ -99,12 +101,7 @@ function _defineClassElement(receiver, element) { var descriptor = element.descriptor; if (element.kind === "field") { var initializer = element.initializer; - descriptor = { - enumerable: descriptor.enumerable, - writable: descriptor.writable, - configurable: descriptor.configurable, - value: initializer === void 0 ? void 0 : initializer.call(receiver) - }; + descriptor = { enumerable: descriptor.enumerable, writable: descriptor.writable, configurable: descriptor.configurable, value: initializer === void 0 ? void 0 : initializer.call(receiver) }; } Object.defineProperty(receiver, element.key, descriptor); } @@ -122,19 +119,16 @@ function _decorateClass(elements, decorators) { newElements.push.apply(newElements, elementFinishersExtras.extras); finishers.push.apply(finishers, elementFinishersExtras.finishers); }); - if (!decorators) { - return { elements: newElements, finishers: finishers }; - } + if (!decorators) return { elements: newElements, finishers: finishers }; var result = _decorateConstructor(newElements, decorators); finishers.push.apply(finishers, result.finishers); result.finishers = finishers; + return result; } function _addElementPlacement(element, placements, silent) { var keys = placements[element.placement]; - if (!silent && keys.indexOf(element.key) !== -1) { - throw new TypeError("Duplicated element (" + element.key + ")"); - } + if (!silent && keys.indexOf(element.key) !== -1) throw new TypeError("Duplicated element (" + element.key + ")"); keys.push(element.key); } function _decorateElement(element, placements) { @@ -147,17 +141,14 @@ function _decorateElement(element, placements) { var elementFinisherExtras = _toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject); element = elementFinisherExtras.element; _addElementPlacement(element, placements); - if (elementFinisherExtras.finisher) { - finishers.push(elementFinisherExtras.finisher); - } + if (elementFinisherExtras.finisher) finishers.push(elementFinisherExtras.finisher); var newExtras = elementFinisherExtras.extras; if (newExtras) { - for (var j = 0; j < newExtras.length; j++) { - _addElementPlacement(newExtras[j], placements); - } + for (var j = 0; j < newExtras.length; j++) _addElementPlacement(newExtras[j], placements); extras.push.apply(extras, newExtras); } } + return { element: element, finishers: finishers, extras: extras }; } function _decorateConstructor(elements, decorators) { @@ -165,9 +156,7 @@ function _decorateConstructor(elements, decorators) { for (var i = decorators.length - 1; i >= 0; i--) { var obj = _fromClassDescriptor(elements); var elementsAndFinisher = _toClassDescriptor((0, decorators[i])(obj) || obj); - if (elementsAndFinisher.finisher !== undefined) { - finishers.push(elementsAndFinisher.finisher); - } + if (elementsAndFinisher.finisher !== undefined) finishers.push(elementsAndFinisher.finisher); if (elementsAndFinisher.elements !== undefined) { elements = elementsAndFinisher.elements; for (var j = 0; j < elements.length - 1; j++) { @@ -179,6 +168,7 @@ function _decorateConstructor(elements, decorators) { } } } + return { elements: elements, finishers: finishers }; } function _fromElementDescriptor(element) { @@ -186,65 +176,67 @@ function _fromElementDescriptor(element) { var desc = { value: "Descriptor", configurable: true }; Object.defineProperty(obj, Symbol.toStringTag, desc); if (element.kind === "field") obj.initializer = element.initializer; + return obj; } function _toElementDescriptors(elementObjects) { if (elementObjects === undefined) return; + return _to_array(elementObjects).map(function(elementObject) { var element = _toElementDescriptor(elementObject); _disallowProperty(elementObject, "finisher", "An element descriptor"); _disallowProperty(elementObject, "extras", "An element descriptor"); + return element; }); } function _toElementDescriptor(elementObject) { var kind = String(elementObject.kind); if (kind !== "method" && kind !== "field") { - throw new TypeError( - "An element descriptor's .kind property must be either \"method\" or" - + " \"field\", but a decorator created an element descriptor with" + " .kind \"" + kind + "\"" - ); + throw new TypeError("An element descriptor's .kind property must be either \"method\" or" + " \"field\", but a decorator created an element descriptor with" + " .kind \"" + kind + "\""); } var key = _to_property_key(elementObject.key); var placement = String(elementObject.placement); if (placement !== "static" && placement !== "prototype" && placement !== "own") { throw new TypeError( "An element descriptor's .placement property must be one of \"static\"," - + " \"prototype\" or \"own\", but a decorator created an element descriptor" + " with .placement \"" + placement + "\"" + + " \"prototype\" or \"own\", but a decorator created an element descriptor" + + " with .placement \"" + + placement + + "\"" ); } var descriptor = elementObject.descriptor; _disallowProperty(elementObject, "elements", "An element descriptor"); var element = { kind: kind, key: key, placement: placement, descriptor: Object.assign({}, descriptor) }; - if (kind !== "field") { - _disallowProperty(elementObject, "initializer", "A method descriptor"); - } else { + if (kind !== "field") _disallowProperty(elementObject, "initializer", "A method descriptor"); + else { _disallowProperty(descriptor, "get", "The property descriptor of a field descriptor"); _disallowProperty(descriptor, "set", "The property descriptor of a field descriptor"); _disallowProperty(descriptor, "value", "The property descriptor of a field descriptor"); element.initializer = elementObject.initializer; } + return element; } function _toElementFinisherExtras(elementObject) { var element = _toElementDescriptor(elementObject); var finisher = _optionalCallableProperty(elementObject, "finisher"); var extras = _toElementDescriptors(elementObject.extras); + return { element: element, finisher: finisher, extras: extras }; } function _fromClassDescriptor(elements) { var obj = { kind: "class", elements: elements.map(_fromElementDescriptor) }; var desc = { value: "Descriptor", configurable: true }; Object.defineProperty(obj, Symbol.toStringTag, desc); + return obj; } function _toClassDescriptor(obj) { var kind = String(obj.kind); if (kind !== "class") { - throw new TypeError( - "A class descriptor's .kind property must be \"class\", but a decorator" + " created a class descriptor with .kind \"" + kind - + "\"" - ); + throw new TypeError("A class descriptor's .kind property must be \"class\", but a decorator" + " created a class descriptor with .kind \"" + kind + "\""); } _disallowProperty(obj, "key", "A class descriptor"); _disallowProperty(obj, "placement", "A class descriptor"); @@ -253,29 +245,39 @@ function _toClassDescriptor(obj) { _disallowProperty(obj, "extras", "A class descriptor"); var finisher = _optionalCallableProperty(obj, "finisher"); var elements = _toElementDescriptors(obj.elements); + return { elements: elements, finisher: finisher }; } function _disallowProperty(obj, name, objectType) { - if (obj[name] !== undefined) { - throw new TypeError(objectType + " can't have a ." + name + " property."); - } + if (obj[name] !== undefined) throw new TypeError(objectType + " can't have a ." + name + " property."); } function _optionalCallableProperty(obj, name) { var value = obj[name]; if (value !== undefined && typeof value !== "function") { throw new TypeError("Expected '" + name + "' to be a function"); } + return value; } function _runClassFinishers(constructor, finishers) { for (var i = 0; i < finishers.length; i++) { var newConstructor = (0, finishers[i])(constructor); if (newConstructor !== undefined) { - if (typeof newConstructor !== "function") { - throw new TypeError("Finishers must return a constructor."); - } + if (typeof newConstructor !== "function") throw new TypeError("Finishers must return a constructor."); constructor = newConstructor; } } + return constructor; } +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x0000000601a000044000080000000018), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_defaults.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_defaults.rs new file mode 100644 index 000000000..0501a57b2 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_defaults.rs @@ -0,0 +1,32 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::defaults, + local: "_defaults", + import_path: "@swc/helpers/_/_defaults", + #[cfg(feature = "inline-helpers")] + source: r#"function _defaults(obj, defaults) { + var keys = Object.getOwnPropertyNames(defaults); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var value = Object.getOwnPropertyDescriptor(defaults, key); + + if (value && value.configurable && obj[key] === undefined) Object.defineProperty(obj, key, value); + } + + return obj; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000100000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_define_enumerable_properties.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_define_enumerable_properties.rs new file mode 100644 index 000000000..df2c111eb --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_define_enumerable_properties.rs @@ -0,0 +1,43 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::define_enumerable_properties, + local: "_define_enumerable_properties", + import_path: "@swc/helpers/_/_define_enumerable_properties", + #[cfg(feature = "inline-helpers")] + source: r#"function _define_enumerable_properties(obj, descs) { + for (var key in descs) { + var desc = descs[key]; + desc.configurable = desc.enumerable = true; + + if ("value" in desc) desc.writable = true; + + Object.defineProperty(obj, key, desc); + } + + if (Object.getOwnPropertySymbols) { + var objectSymbols = Object.getOwnPropertySymbols(descs); + for (var i = 0; i < objectSymbols.length; i++) { + var sym = objectSymbols[i]; + var desc = descs[sym]; + desc.configurable = desc.enumerable = true; + if ("value" in desc) desc.writable = true; + Object.defineProperty(obj, sym, desc); + } + } + + return obj; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000200000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_define_property.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_define_property.rs new file mode 100644 index 000000000..b04235e8a --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_define_property.rs @@ -0,0 +1,27 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::define_property, + local: "_define_property", + import_path: "@swc/helpers/_/_define_property", + #[cfg(feature = "inline-helpers")] + source: r#"function _define_property(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); + } else obj[key] = value; + + return obj; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000400000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_dispose.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_dispose.rs similarity index 57% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_dispose.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_dispose.rs index 8d1b848fa..bfce08426 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_dispose.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_dispose.rs @@ -1,4 +1,13 @@ -/* @minVersion 7.22.0 */ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::dispose, + local: "_dispose", + import_path: "@swc/helpers/_/_dispose", + #[cfg(feature = "inline-helpers")] + source: r#"/* @minVersion 7.22.0 */ function dispose_SuppressedError(error, suppressed) { if (typeof SuppressedError !== "undefined") { // eslint-disable-next-line no-undef @@ -9,13 +18,7 @@ function dispose_SuppressedError(error, suppressed) { this.error = error; this.stack = new Error().stack; }; - dispose_SuppressedError.prototype = Object.create(Error.prototype, { - constructor: { - value: dispose_SuppressedError, - writable: true, - configurable: true, - }, - }); + dispose_SuppressedError.prototype = Object.create(Error.prototype, { constructor: { value: dispose_SuppressedError, writable: true, configurable: true } }); } return new dispose_SuppressedError(error, suppressed); } @@ -42,4 +45,15 @@ function _dispose(stack, error, hasError) { } return next(); -} \ No newline at end of file +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000000800000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_export_star.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_export_star.rs new file mode 100644 index 000000000..acf55f5f7 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_export_star.rs @@ -0,0 +1,34 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::export_star, + local: "_export_star", + import_path: "@swc/helpers/_/_export_star", + #[cfg(feature = "inline-helpers")] + source: r#"function _export_star(from, to) { + Object.keys(from).forEach(function(k) { + if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) { + Object.defineProperty(to, k, { + enumerable: true, + get: function() { + return from[k]; + } + }); + } + }); + + return from; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000001000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_extends.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_extends.rs new file mode 100644 index 000000000..585beb764 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_extends.rs @@ -0,0 +1,32 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::extends, + local: "_extends", + import_path: "@swc/helpers/_/_extends", + #[cfg(feature = "inline-helpers")] + source: r#"function _extends() { + _extends = Object.assign || function assign(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var key in source) if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key]; + } + + return target; + }; + + return _extends.apply(this, arguments); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000002000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_get.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_get.rs new file mode 100644 index 000000000..b38dc318a --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_get.rs @@ -0,0 +1,38 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::get, + local: "_get", + import_path: "@swc/helpers/_/_get", + #[cfg(feature = "inline-helpers")] + source: r#"function _get(target, property, receiver) { + if (typeof Reflect !== "undefined" && Reflect.get) _get = Reflect.get; + else { + _get = function get(target, property, receiver) { + var base = _super_prop_base(target, property); + + if (!base) return; + + var desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.get) return desc.get.call(receiver || target); + + return desc.value; + }; + } + + return _get(target, property, receiver || target); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x0000000000020000000c000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_get_prototype_of.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_get_prototype_of.rs new file mode 100644 index 000000000..2f3503595 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_get_prototype_of.rs @@ -0,0 +1,27 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::get_prototype_of, + local: "_get_prototype_of", + import_path: "@swc/helpers/_/_get_prototype_of", + #[cfg(feature = "inline-helpers")] + source: r#"function _get_prototype_of(o) { + _get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + + return _get_prototype_of(o); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000008000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_identity.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_identity.rs new file mode 100644 index 000000000..3843a12f2 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_identity.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::identity, + local: "_identity", + import_path: "@swc/helpers/_/_identity", + #[cfg(feature = "inline-helpers")] + source: r#"function _identity(x) { + return x; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000010000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_inherits.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_inherits.rs new file mode 100644 index 000000000..211708ddd --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_inherits.rs @@ -0,0 +1,29 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::inherits, + local: "_inherits", + import_path: "@swc/helpers/_/_inherits", + #[cfg(feature = "inline-helpers")] + source: r#"function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); + + if (superClass) _set_prototype_of(subClass, superClass); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000020000020000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_inherits_loose.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_inherits_loose.rs new file mode 100644 index 000000000..00d24a5b2 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_inherits_loose.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::inherits_loose, + local: "_inherits_loose", + import_path: "@swc/helpers/_/_inherits_loose", + #[cfg(feature = "inline-helpers")] + source: r#"function _inherits_loose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + subClass.__proto__ = superClass; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000040000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_initializer_define_property.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_initializer_define_property.rs new file mode 100644 index 000000000..ad7a5e0d8 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_initializer_define_property.rs @@ -0,0 +1,30 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::initializer_define_property, + local: "_initializer_define_property", + import_path: "@swc/helpers/_/_initializer_define_property", + #[cfg(feature = "inline-helpers")] + source: r#"function _initializer_define_property(target, property, descriptor, context) { + if (!descriptor) return; + + Object.defineProperty(target, property, { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: descriptor.writable, + value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 + }); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000080000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_initializer_warning_helper.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_initializer_warning_helper.rs new file mode 100644 index 000000000..ae59aa6a0 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_initializer_warning_helper.rs @@ -0,0 +1,28 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::initializer_warning_helper, + local: "_initializer_warning_helper", + import_path: "@swc/helpers/_/_initializer_warning_helper", + #[cfg(feature = "inline-helpers")] + source: r#"function _initializer_warning_helper(descriptor, context) { + throw new Error( + "Decorating class property failed. Please ensure that " + + "proposal-class-properties is enabled and set to use loose mode. " + + "To use proposal-class-properties in spec mode with decorators, wait for " + + "the next major version of decorators in stage 2." + ); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000100000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_instanceof.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_instanceof.rs new file mode 100644 index 000000000..da9bf00f2 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_instanceof.rs @@ -0,0 +1,27 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::instanceof, + local: "_instanceof", + import_path: "@swc/helpers/_/_instanceof", + #[cfg(feature = "inline-helpers")] + source: r#"function _instanceof(left, right) { + "@swc/helpers - instanceof"; + + if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { + return !!right[Symbol.hasInstance](left); + } else return left instanceof right; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000200000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_interop_require_default.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_interop_require_default.rs new file mode 100644 index 000000000..c615754d8 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_interop_require_default.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::interop_require_default, + local: "_interop_require_default", + import_path: "@swc/helpers/_/_interop_require_default", + #[cfg(feature = "inline-helpers")] + source: r#"function _interop_require_default(obj) { + return obj && obj.__esModule ? obj : { default: obj }; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000400000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_interop_require_wildcard.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_interop_require_wildcard.rs new file mode 100644 index 000000000..dfb73204c --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_interop_require_wildcard.rs @@ -0,0 +1,55 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::interop_require_wildcard, + local: "_interop_require_wildcard", + import_path: "@swc/helpers/_/_interop_require_wildcard", + #[cfg(feature = "inline-helpers")] + source: r#"function _getRequireWildcardCache(nodeInterop) { + if (typeof WeakMap !== "function") return null; + + var cacheBabelInterop = new WeakMap(); + var cacheNodeInterop = new WeakMap(); + + return (_getRequireWildcardCache = function(nodeInterop) { + return nodeInterop ? cacheNodeInterop : cacheBabelInterop; + })(nodeInterop); +} +function _interop_require_wildcard(obj, nodeInterop) { + if (!nodeInterop && obj && obj.__esModule) return obj; + if (obj === null || typeof obj !== "object" && typeof obj !== "function") return { default: obj }; + + var cache = _getRequireWildcardCache(nodeInterop); + + if (cache && cache.has(obj)) return cache.get(obj); + + var newObj = { __proto__: null }; + var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; + + for (var key in obj) { + if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; + if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc); + else newObj[key] = obj[key]; + } + } + + newObj.default = obj; + + if (cache) cache.set(obj, newObj); + + return newObj; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000000800000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_is_native_function.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_is_native_function.rs new file mode 100644 index 000000000..5138ac0ab --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_is_native_function.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::is_native_function, + local: "_is_native_function", + import_path: "@swc/helpers/_/_is_native_function", + #[cfg(feature = "inline-helpers")] + source: r#"function _is_native_function(fn) { + return Function.toString.call(fn).indexOf("[native code]") !== -1; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000001000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_is_native_reflect_construct.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_is_native_reflect_construct.rs new file mode 100644 index 000000000..c8b010af3 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_is_native_reflect_construct.rs @@ -0,0 +1,34 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::is_native_reflect_construct, + local: "_is_native_reflect_construct", + import_path: "@swc/helpers/_/_is_native_reflect_construct", + #[cfg(feature = "inline-helpers")] + source: r#"function _is_native_reflect_construct() { + // Since Reflect.construct can't be properly polyfilled, some + // implementations (e.g. core-js@2) don't set the correct internal slots. + // Those polyfills don't allow us to subclass built-ins, so we need to + // use our fallback implementation. + try { + // If the internal slots aren't set, this throws an error similar to + // TypeError: this is not a Boolean object. + var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {})); + } catch (_) {} + return (_is_native_reflect_construct = function() { + return !!result; + })(); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000002000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array.rs new file mode 100644 index 000000000..789083f54 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::iterable_to_array, + local: "_iterable_to_array", + import_path: "@swc/helpers/_/_iterable_to_array", + #[cfg(feature = "inline-helpers")] + source: r#"function _iterable_to_array(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) { + return Array.from(iter); + } +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000004000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array_limit.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array_limit.rs new file mode 100644 index 000000000..cde95ee04 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array_limit.rs @@ -0,0 +1,48 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::iterable_to_array_limit, + local: "_iterable_to_array_limit", + import_path: "@swc/helpers/_/_iterable_to_array_limit", + #[cfg(feature = "inline-helpers")] + source: r#"function _iterable_to_array_limit(arr, i) { + var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; + + if (_i == null) return; + + var _arr = []; + var _n = true; + var _d = false; + var _s, _e; + + try { + for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000008000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array_limit_loose.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array_limit_loose.rs new file mode 100644 index 000000000..c1580e975 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_iterable_to_array_limit_loose.rs @@ -0,0 +1,34 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::iterable_to_array_limit_loose, + local: "_iterable_to_array_limit_loose", + import_path: "@swc/helpers/_/_iterable_to_array_limit_loose", + #[cfg(feature = "inline-helpers")] + source: r#"function _iterable_to_array_limit_loose(arr, i) { + var _i = arr && (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]); + + if (_i == null) return; + + var _arr = []; + + for (_i = _i.call(arr), _step; !(_step = _i.next()).done;) { + _arr.push(_step.value); + if (i && _arr.length === i) break; + } + + return _arr; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000010000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_new_arrow_check.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_new_arrow_check.rs new file mode 100644 index 000000000..5ae814b12 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_new_arrow_check.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::new_arrow_check, + local: "_new_arrow_check", + import_path: "@swc/helpers/_/_new_arrow_check", + #[cfg(feature = "inline-helpers")] + source: r#"function _new_arrow_check(innerThis, boundThis) { + if (innerThis !== boundThis) throw new TypeError("Cannot instantiate an arrow function"); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000020000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_non_iterable_rest.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_non_iterable_rest.rs new file mode 100644 index 000000000..3d9bc0db9 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_non_iterable_rest.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::non_iterable_rest, + local: "_non_iterable_rest", + import_path: "@swc/helpers/_/_non_iterable_rest", + #[cfg(feature = "inline-helpers")] + source: r#"function _non_iterable_rest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000040000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_non_iterable_spread.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_non_iterable_spread.rs new file mode 100644 index 000000000..2ea177969 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_non_iterable_spread.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::non_iterable_spread, + local: "_non_iterable_spread", + import_path: "@swc/helpers/_/_non_iterable_spread", + #[cfg(feature = "inline-helpers")] + source: r#"function _non_iterable_spread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000080000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_destructuring_empty.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_destructuring_empty.rs new file mode 100644 index 000000000..4bf56e6bd --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_destructuring_empty.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::object_destructuring_empty, + local: "_object_destructuring_empty", + import_path: "@swc/helpers/_/_object_destructuring_empty", + #[cfg(feature = "inline-helpers")] + source: r#"function _object_destructuring_empty(o) { + if (o === null || o === void 0) throw new TypeError("Cannot destructure " + o); + + return o; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000100000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_spread.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_spread.rs new file mode 100644 index 000000000..00a401d0a --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_spread.rs @@ -0,0 +1,40 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::object_spread, + local: "_object_spread", + import_path: "@swc/helpers/_/_object_spread", + #[cfg(feature = "inline-helpers")] + source: r#"function _object_spread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === "function") { + ownKeys = ownKeys.concat( + Object.getOwnPropertySymbols(source).filter(function(sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + }) + ); + } + + ownKeys.forEach(function(key) { + _define_property(target, key, source[key]); + }); + } + + return target; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000200000400000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_spread_props.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_spread_props.rs new file mode 100644 index 000000000..0d1c52498 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_spread_props.rs @@ -0,0 +1,47 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::object_spread_props, + local: "_object_spread_props", + import_path: "@swc/helpers/_/_object_spread_props", + #[cfg(feature = "inline-helpers")] + source: r#"function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + if (enumerableOnly) { + symbols = symbols.filter(function(sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + } + keys.push.apply(keys, symbols); + } + + return keys; +} +function _object_spread_props(target, source) { + source = source != null ? source : {}; + + if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + else { + ownKeys(Object(source)).forEach(function(key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + + return target; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000000400000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_without_properties.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_without_properties.rs similarity index 54% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_without_properties.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_without_properties.rs index 518a15ade..57ea35a20 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_object_without_properties.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_without_properties.rs @@ -1,4 +1,13 @@ -function _object_without_properties(source, excluded) { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::object_without_properties, + local: "_object_without_properties", + import_path: "@swc/helpers/_/_object_without_properties", + #[cfg(feature = "inline-helpers")] + source: r#"function _object_without_properties(source, excluded) { if (source == null) return {}; var target = {}, sourceKeys, key, i; @@ -27,3 +36,14 @@ function _object_without_properties(source, excluded) { return target; } +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000001800000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_without_properties_loose.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_without_properties_loose.rs new file mode 100644 index 000000000..a5d172bdd --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_object_without_properties_loose.rs @@ -0,0 +1,33 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::object_without_properties_loose, + local: "_object_without_properties_loose", + import_path: "@swc/helpers/_/_object_without_properties_loose", + #[cfg(feature = "inline-helpers")] + source: r#"function _object_without_properties_loose(source, excluded) { + if (source == null) return {}; + + var target = {}, sourceKeys = Object.getOwnPropertyNames(source), key, i; + for (i = 0; i < sourceKeys.length; i++) { + key = sourceKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; + target[key] = source[key]; + } + + return target; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000001000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_overload_yield.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_overload_yield.rs new file mode 100644 index 000000000..e89fe0434 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_overload_yield.rs @@ -0,0 +1,24 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::overload_yield, + local: "_overload_yield", + import_path: "@swc/helpers/_/_overload_yield", + #[cfg(feature = "inline-helpers")] + source: r#"function _overload_yield(value, /** 0: await 1: delegate */ kind) { + this.v = value; + this.k = kind; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000002000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_possible_constructor_return.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_possible_constructor_return.rs new file mode 100644 index 000000000..3b254e480 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_possible_constructor_return.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::possible_constructor_return, + local: "_possible_constructor_return", + import_path: "@swc/helpers/_/_possible_constructor_return", + #[cfg(feature = "inline-helpers")] + source: r#"function _possible_constructor_return(self, call) { + if (call && (_type_of(call) === "object" || typeof call === "function")) return call; + + return _assert_this_initialized(self); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000002000004000000000000000040), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_read_only_error.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_read_only_error.rs new file mode 100644 index 000000000..d703cc78e --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_read_only_error.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::read_only_error, + local: "_read_only_error", + import_path: "@swc/helpers/_/_read_only_error", + #[cfg(feature = "inline-helpers")] + source: r#"function _read_only_error(name) { + throw new TypeError("\"" + name + "\" is read-only"); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000008000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_set.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_set.rs similarity index 52% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_set.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_set.rs index cd527d856..9a447bd01 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_set.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_set.rs @@ -1,7 +1,15 @@ -function set(target, property, value, receiver) { - if (typeof Reflect !== "undefined" && Reflect.set) { - set = Reflect.set; - } else { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::set, + local: "_set", + import_path: "@swc/helpers/_/_set", + #[cfg(feature = "inline-helpers")] + source: r#"function set(target, property, value, receiver) { + if (typeof Reflect !== "undefined" && Reflect.set) set = Reflect.set; + else { set = function set(target, property, value, receiver) { var base = _super_prop_base(target, property); var desc; @@ -9,6 +17,7 @@ function set(target, property, value, receiver) { desc = Object.getOwnPropertyDescriptor(base, property); if (desc.set) { desc.set.call(receiver, value); + return true; } else if (!desc.writable) { return false; @@ -16,23 +25,34 @@ function set(target, property, value, receiver) { } desc = Object.getOwnPropertyDescriptor(receiver, property); if (desc) { - if (!desc.writable) { - return false; - } + if (!desc.writable) return false; desc.value = value; Object.defineProperty(receiver, property, desc); } else { _define_property(receiver, property, value); } + return true; }; } + return set(target, property, value, receiver); } + function _set(target, property, value, receiver, isStrict) { var s = set(target, property, value, receiver || target); - if (!s && isStrict) { - throw new Error("failed to set property"); - } + if (!s && isStrict) throw new Error("failed to set property"); + return value; } +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000210000008400000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_set_prototype_of.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_set_prototype_of.rs new file mode 100644 index 000000000..fea0cec11 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_set_prototype_of.rs @@ -0,0 +1,29 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::set_prototype_of, + local: "_set_prototype_of", + import_path: "@swc/helpers/_/_set_prototype_of", + #[cfg(feature = "inline-helpers")] + source: r#"function _set_prototype_of(o, p) { + _set_prototype_of = Object.setPrototypeOf || function setPrototypeOf(o, p) { + o.__proto__ = p; + + return o; + }; + + return _set_prototype_of(o, p); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000020000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_skip_first_generator_next.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_skip_first_generator_next.rs new file mode 100644 index 000000000..85056a61a --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_skip_first_generator_next.rs @@ -0,0 +1,28 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::skip_first_generator_next, + local: "_skip_first_generator_next", + import_path: "@swc/helpers/_/_skip_first_generator_next", + #[cfg(feature = "inline-helpers")] + source: r#"function _skip_first_generator_next(fn) { + return function() { + var it = fn.apply(this, arguments); + it.next(); + + return it; + }; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000040000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_sliced_to_array.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_sliced_to_array.rs new file mode 100644 index 000000000..55f96bcb4 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_sliced_to_array.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::sliced_to_array, + local: "_sliced_to_array", + import_path: "@swc/helpers/_/_sliced_to_array", + #[cfg(feature = "inline-helpers")] + source: r#"function _sliced_to_array(arr, i) { + return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest(); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000004000080048000000000000018), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_sliced_to_array_loose.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_sliced_to_array_loose.rs new file mode 100644 index 000000000..8fda428fd --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_sliced_to_array_loose.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::sliced_to_array_loose, + local: "_sliced_to_array_loose", + import_path: "@swc/helpers/_/_sliced_to_array_loose", + #[cfg(feature = "inline-helpers")] + source: r#"function _sliced_to_array_loose(arr, i) { + return _array_with_holes(arr) || _iterable_to_array_limit_loose(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest(); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000004000100050000000000000018), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_super_prop_base.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_super_prop_base.rs new file mode 100644 index 000000000..e7371b277 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_super_prop_base.rs @@ -0,0 +1,28 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::super_prop_base, + local: "_super_prop_base", + import_path: "@swc/helpers/_/_super_prop_base", + #[cfg(feature = "inline-helpers")] + source: r#"function _super_prop_base(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _get_prototype_of(object); + if (object === null) break; + } + + return object; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000200000008000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_tagged_template_literal.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_tagged_template_literal.rs new file mode 100644 index 000000000..11c2c5e38 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_tagged_template_literal.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::tagged_template_literal, + local: "_tagged_template_literal", + import_path: "@swc/helpers/_/_tagged_template_literal", + #[cfg(feature = "inline-helpers")] + source: r#"function _tagged_template_literal(strings, raw) { + if (!raw) raw = strings.slice(0); + + return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000400000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_tagged_template_literal_loose.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_tagged_template_literal_loose.rs new file mode 100644 index 000000000..e68c2d995 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_tagged_template_literal_loose.rs @@ -0,0 +1,27 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::tagged_template_literal_loose, + local: "_tagged_template_literal_loose", + import_path: "@swc/helpers/_/_tagged_template_literal_loose", + #[cfg(feature = "inline-helpers")] + source: r#"function _tagged_template_literal_loose(strings, raw) { + if (!raw) raw = strings.slice(0); + + strings.raw = raw; + + return strings; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000000800000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_throw.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_throw.rs new file mode 100644 index 000000000..a17fbbec4 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_throw.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::throw, + local: "_throw", + import_path: "@swc/helpers/_/_throw", + #[cfg(feature = "inline-helpers")] + source: r#"function _throw(e) { + throw e; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000001000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_array.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_array.rs new file mode 100644 index 000000000..eb2a2b6b3 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_array.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::to_array, + local: "_to_array", + import_path: "@swc/helpers/_/_to_array", + #[cfg(feature = "inline-helpers")] + source: r#"function _to_array(arr) { + return _array_with_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_rest(); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000004002000044000000000000018), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_consumable_array.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_consumable_array.rs new file mode 100644 index 000000000..5fe422a6f --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_consumable_array.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::to_consumable_array, + local: "_to_consumable_array", + import_path: "@swc/helpers/_/_to_consumable_array", + #[cfg(feature = "inline-helpers")] + source: r#"function _to_consumable_array(arr) { + return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread(); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000004004000084000000000000028), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_primitive.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_primitive.rs new file mode 100644 index 000000000..42c7a2de7 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_primitive.rs @@ -0,0 +1,33 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::to_primitive, + local: "_to_primitive", + import_path: "@swc/helpers/_/_to_primitive", + #[cfg(feature = "inline-helpers")] + source: r#"function _to_primitive(input, hint) { + if (_type_of(input) !== "object" || input === null) return input; + + var prim = input[Symbol.toPrimitive]; + + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (_type_of(res) !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + + return (hint === "string" ? String : Number)(input); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000002008000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_property_key.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_property_key.rs new file mode 100644 index 000000000..3a1035bfb --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_to_property_key.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::to_property_key, + local: "_to_property_key", + import_path: "@swc/helpers/_/_to_property_key", + #[cfg(feature = "inline-helpers")] + source: r#"function _to_property_key(arg) { + var key = _to_primitive(arg, "string"); + + return _type_of(key) === "symbol" ? key : String(key); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000002018000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_add_disposable_resource.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_add_disposable_resource.rs new file mode 100644 index 000000000..67c10dab0 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_add_disposable_resource.rs @@ -0,0 +1,59 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::ts_add_disposable_resource, + local: "_ts_add_disposable_resource", + import_path: "@swc/helpers/_/_ts_add_disposable_resource", + #[cfg(feature = "inline-helpers")] + source: r#"function _ts_add_disposable_resource(env, value, async) { + if (value !== null && value !== void 0) { + if (typeof value !== "object" && typeof value !== "function") { + throw new TypeError("Object expected."); + } + var dispose, inner; + if (async) { + if (!Symbol.asyncDispose) { + throw new TypeError("Symbol.asyncDispose is not defined."); + } + dispose = value[Symbol.asyncDispose]; + } + if (dispose === void 0) { + if (!Symbol.dispose) { + throw new TypeError("Symbol.dispose is not defined."); + } + dispose = value[Symbol.dispose]; + if (async) { + inner = dispose; + } + } + if (typeof dispose !== "function") { + throw new TypeError("Object not disposable."); + } + if (inner) { + dispose = function() { + try { + inner.call(this); + } catch (e) { + return Promise.reject(e); + } + }; + } + env.stack.push({ value: value, dispose: dispose, async: async }); + } else if (async) { + env.stack.push({ async: true }); + } + return value; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000020000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_decorate.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_decorate.rs new file mode 100644 index 000000000..a49103e1b --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_decorate.rs @@ -0,0 +1,33 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::ts_decorate, + local: "_ts_decorate", + import_path: "@swc/helpers/_/_ts_decorate", + #[cfg(feature = "inline-helpers")] + source: r#"function _ts_decorate(decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") { + r = Reflect.decorate(decorators, target, key, desc); + } else { + for (var i = decorators.length - 1; i >= 0; i--) { + if (d = decorators[i]) { + r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + } + } + } + return c > 3 && r && Object.defineProperty(target, key, r), r; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000040000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_dispose_resources.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_dispose_resources.rs new file mode 100644 index 000000000..4644cdf1c --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_dispose_resources.rs @@ -0,0 +1,62 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::ts_dispose_resources, + local: "_ts_dispose_resources", + import_path: "@swc/helpers/_/_ts_dispose_resources", + #[cfg(feature = "inline-helpers")] + source: r#"var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +function _ts_dispose_resources(env) { + function fail(e) { + env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; + env.hasError = true; + } + var r, s = 0; + function next() { + while (r = env.stack.pop()) { + try { + if (!r.async && s === 1) { + return s = 0, env.stack.push(r), Promise.resolve().then(next); + } + if (r.dispose) { + var result = r.dispose.call(r.value); + if (r.async) { + return s |= 2, + Promise.resolve(result).then(next, function(e) { + fail(e); + return next(); + }); + } + } else { + s |= 1; + } + } catch (e) { + fail(e); + } + } + if (s === 1) { + return env.hasError ? Promise.reject(env.error) : Promise.resolve(); + } + if (env.hasError) { + throw env.error; + } + } + return next(); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000080000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_generator.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_generator.rs similarity index 72% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_generator.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_generator.rs index 4fde75b49..f0ae7ba07 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_ts_generator.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_generator.rs @@ -1,4 +1,13 @@ -function _ts_generator(thisArg, body) { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::ts_generator, + local: "_ts_generator", + import_path: "@swc/helpers/_/_ts_generator", + #[cfg(feature = "inline-helpers")] + source: r#"function _ts_generator(thisArg, body) { var f, y, t, _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty; return d(g, "next", { value: verb(0) }), d(g, "throw", { value: verb(1) }), d(g, "return", { value: verb(2) }), typeof Symbol === "function" && d(g, Symbol.iterator, { value: function () { return this; } }), g; function verb(n) { return function (v) { return step([n, v]); }; } @@ -24,4 +33,15 @@ function _ts_generator(thisArg, body) { } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } -} \ No newline at end of file +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000100000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_metadata.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_metadata.rs new file mode 100644 index 000000000..41d1afa34 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_metadata.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::ts_metadata, + local: "_ts_metadata", + import_path: "@swc/helpers/_/_ts_metadata", + #[cfg(feature = "inline-helpers")] + source: r#"function _ts_metadata(metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") { + return Reflect.metadata(metadataKey, metadataValue); + } +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000200000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_param.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_param.rs new file mode 100644 index 000000000..a698aee98 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_param.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::ts_param, + local: "_ts_param", + import_path: "@swc/helpers/_/_ts_param", + #[cfg(feature = "inline-helpers")] + source: r#"function _ts_param(paramIndex, decorator) { + return function(target, key) { + decorator(target, key, paramIndex); + }; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000400000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_rewrite_relative_import_extension.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_rewrite_relative_import_extension.rs new file mode 100644 index 000000000..3269d0643 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_rewrite_relative_import_extension.rs @@ -0,0 +1,28 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::ts_rewrite_relative_import_extension, + local: "_ts_rewrite_relative_import_extension", + import_path: "@swc/helpers/_/_ts_rewrite_relative_import_extension", + #[cfg(feature = "inline-helpers")] + source: r#"function _ts_rewrite_relative_import_extension(path, preserveJsx) { + if (typeof path === "string" && /^\.\.?\//.test(path)) { + return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) { + return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js"; + }); + } + return path; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000000800000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_values.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_values.rs new file mode 100644 index 000000000..975ac44f4 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_ts_values.rs @@ -0,0 +1,37 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::ts_values, + local: "_ts_values", + import_path: "@swc/helpers/_/_ts_values", + #[cfg(feature = "inline-helpers")] + source: r#"function _ts_values(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) { + return m.call(o); + } + if (o && typeof o.length === "number") { + return { + next: function() { + if (o && i >= o.length) { + o = void 0; + } + return { value: o && o[i++], done: !o }; + } + }; + } + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000001000000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_type_of.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_type_of.rs new file mode 100644 index 000000000..f760ae32a --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_type_of.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::type_of, + local: "_type_of", + import_path: "@swc/helpers/_/_type_of", + #[cfg(feature = "inline-helpers")] + source: r#"function _type_of(obj) { + "@swc/helpers - typeof"; + + return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000002000000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_unsupported_iterable_to_array.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_unsupported_iterable_to_array.rs new file mode 100644 index 000000000..c473ff218 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_unsupported_iterable_to_array.rs @@ -0,0 +1,30 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::unsupported_iterable_to_array, + local: "_unsupported_iterable_to_array", + import_path: "@swc/helpers/_/_unsupported_iterable_to_array", + #[cfg(feature = "inline-helpers")] + source: r#"function _unsupported_iterable_to_array(o, minLen) { + if (!o) return; + if (typeof o === "string") return _array_like_to_array(o, minLen); + + var n = Object.prototype.toString.call(o).slice(8, -1); + + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(n); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000004000000000000000000000008), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_update.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_update.rs new file mode 100644 index 000000000..9eb359ba9 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_update.rs @@ -0,0 +1,30 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::update, + local: "_update", + import_path: "@swc/helpers/_/_update", + #[cfg(feature = "inline-helpers")] + source: r#"function _update(target, property, receiver, isStrict) { + return { + get _() { + return _get(target, property, receiver); + }, + set _(value) { + _set(target, property, value, receiver, isStrict); + } + }; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x0000000800021000000c400000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_using.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_using.rs new file mode 100644 index 000000000..1a9b8f167 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_using.rs @@ -0,0 +1,40 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::using, + local: "_using", + import_path: "@swc/helpers/_/_using", + #[cfg(feature = "inline-helpers")] + source: r#"/* @minVersion 7.22.0 */ + +function _using(stack, value, isAwait) { + if (value === null || value === void 0) return value; + if (Object(value) !== value) { + throw new TypeError("using declarations can only be used with objects, functions, null, or undefined."); + } + // core-js-pure uses Symbol.for for polyfilling well-known symbols + if (isAwait) { + var dispose = value[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")]; + } + if (dispose === null || dispose === void 0) { + dispose = value[Symbol.dispose || Symbol.for("Symbol.dispose")]; + } + if (typeof dispose !== "function") { + throw new TypeError(`Property [Symbol.dispose] is not a function.`); + } + stack.push({ v: value, d: dispose, a: isAwait }); + return value; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000010000000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_using_ctx.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_using_ctx.rs similarity index 60% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_using_ctx.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_using_ctx.rs index 29c3422f4..3ad85b2c6 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_using_ctx.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_using_ctx.rs @@ -1,9 +1,17 @@ -function _using_ctx() { - var _disposeSuppressedError = - typeof SuppressedError === "function" - ? // eslint-disable-next-line no-undef - SuppressedError - : (function (error, suppressed) { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::using_ctx, + local: "_using_ctx", + import_path: "@swc/helpers/_/_using_ctx", + #[cfg(feature = "inline-helpers")] + source: r#"function _using_ctx() { + var _disposeSuppressedError = typeof SuppressedError === "function" + // eslint-disable-next-line no-undef + ? SuppressedError + : (function(error, suppressed) { var err = new Error(); err.name = "SuppressedError"; err.suppressed = suppressed; @@ -15,14 +23,11 @@ function _using_ctx() { function using(isAwait, value) { if (value != null) { if (Object(value) !== value) { - throw new TypeError( - "using declarations can only be used with objects, functions, null, or undefined.", - ); + throw new TypeError("using declarations can only be used with objects, functions, null, or undefined."); } // core-js-pure uses Symbol.for for polyfilling well-known symbols if (isAwait) { - var dispose = - value[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")]; + var dispose = value[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")]; } if (dispose == null) { dispose = value[Symbol.dispose || Symbol.for("Symbol.dispose")]; @@ -45,15 +50,14 @@ function _using_ctx() { // await using a: using.bind(null, true), // dispose - d: function () { + d: function() { var error = this.e; function next() { // eslint-disable-next-line @typescript-eslint/no-use-before-define while ((resource = stack.pop())) { try { - var resource, - disposalResult = resource.d && resource.d.call(resource.v); + var resource, disposalResult = resource.d && resource.d.call(resource.v); if (resource.a) { return Promise.resolve(disposalResult).then(next, err); } @@ -71,6 +75,17 @@ function _using_ctx() { } return next(); - }, + } }; -} \ No newline at end of file +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000020000000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_async_generator.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_async_generator.rs new file mode 100644 index 000000000..702776b93 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_async_generator.rs @@ -0,0 +1,25 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::wrap_async_generator, + local: "_wrap_async_generator", + import_path: "@swc/helpers/_/_wrap_async_generator", + #[cfg(feature = "inline-helpers")] + source: r#"function _wrap_async_generator(fn) { + return function() { + return new _async_generator(fn.apply(this, arguments)); + }; +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000040000002000000000000000080), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_native_super.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_native_super.rs new file mode 100644 index 000000000..1f16d5d62 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_native_super.rs @@ -0,0 +1,40 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::wrap_native_super, + local: "_wrap_native_super", + import_path: "@swc/helpers/_/_wrap_native_super", + #[cfg(feature = "inline-helpers")] + source: r#"function _wrap_native_super(Class) { + var _cache = typeof Map === "function" ? new Map() : undefined; + _wrap_native_super = function(Class) { + if (Class === null || !_is_native_function(Class)) return Class; + if (typeof Class !== "function") throw new TypeError("Super expression must either be null or a function"); + if (typeof _cache !== "undefined") { + if (_cache.has(Class)) return _cache.get(Class); + _cache.set(Class, Wrapper); + } + + function Wrapper() { + return _construct(Class, arguments, _get_prototype_of(this).constructor); + } + Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); + + return _set_prototype_of(Wrapper, Class); + }; + + return _wrap_native_super(Class); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000080000020003008008000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_reg_exp.js b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_reg_exp.rs similarity index 80% rename from deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_reg_exp.js rename to deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_reg_exp.rs index e26d6c77a..29326a5d2 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/_wrap_reg_exp.js +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_wrap_reg_exp.rs @@ -1,4 +1,13 @@ -function _wrap_reg_exp(re, groups, source) { +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::wrap_reg_exp, + local: "_wrap_reg_exp", + import_path: "@swc/helpers/_/_wrap_reg_exp", + #[cfg(feature = "inline-helpers")] + source: r#"function _wrap_reg_exp(re, groups, source) { _wrap_reg_exp = function(re, groups, source) { return new WrappedRegExp(re, undefined, groups, source); }; @@ -76,3 +85,14 @@ function _wrap_reg_exp(re, groups, source) { } return _wrap_reg_exp.apply(this, arguments); } +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000100000020000020000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_write_only_error.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_write_only_error.rs new file mode 100644 index 000000000..88c86a2ff --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/_write_only_error.rs @@ -0,0 +1,23 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. + +use super::{HelperDef, HelperName}; + +pub const DEF: HelperDef = HelperDef { + name: HelperName::write_only_error, + local: "_write_only_error", + import_path: "@swc/helpers/_/_write_only_error", + #[cfg(feature = "inline-helpers")] + source: r#"function _write_only_error(name) { + throw new TypeError("\"" + name + "\" is write-only"); +} +"#, + #[cfg(feature = "inline-helpers")] + deps: super::HelperBitmap::from_bits(0x00000200000000000000000000000000), +}; + +#[cfg(feature = "inline-helpers")] +pub fn stmts() -> &'static [swc_ecma_ast::Stmt] { + static STMTS: once_cell::sync::Lazy> = + once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path)); + &STMTS +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/mod.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/mod.rs new file mode 100644 index 000000000..67177c4a7 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/generated/mod.rs @@ -0,0 +1,1070 @@ +// This file is generated by `cargo codegen helpers`. DO NOT MODIFY. +#![allow(clippy::all)] + +mod _apply_decorated_descriptor; +mod _apply_decs_2203_r; +mod _apply_decs_2311; +mod _array_like_to_array; +mod _array_with_holes; +mod _array_without_holes; +mod _assert_this_initialized; +mod _async_generator; +mod _async_generator_delegate; +mod _async_iterator; +mod _async_to_generator; +mod _await_async_generator; +mod _await_value; +mod _call_super; +mod _check_private_redeclaration; +mod _class_apply_descriptor_destructure; +mod _class_apply_descriptor_get; +mod _class_apply_descriptor_set; +mod _class_apply_descriptor_update; +mod _class_call_check; +mod _class_check_private_static_access; +mod _class_check_private_static_field_descriptor; +mod _class_extract_field_descriptor; +mod _class_name_tdz_error; +mod _class_private_field_destructure; +mod _class_private_field_get; +mod _class_private_field_init; +mod _class_private_field_loose_base; +mod _class_private_field_loose_key; +mod _class_private_field_set; +mod _class_private_field_update; +mod _class_private_method_get; +mod _class_private_method_init; +mod _class_private_method_set; +mod _class_static_private_field_destructure; +mod _class_static_private_field_spec_get; +mod _class_static_private_field_spec_set; +mod _class_static_private_field_update; +mod _class_static_private_method_get; +mod _construct; +mod _create_class; +mod _create_for_of_iterator_helper_loose; +mod _create_super; +mod _decorate; +mod _defaults; +mod _define_enumerable_properties; +mod _define_property; +mod _dispose; +mod _export_star; +mod _extends; +mod _get; +mod _get_prototype_of; +mod _identity; +mod _inherits; +mod _inherits_loose; +mod _initializer_define_property; +mod _initializer_warning_helper; +mod _instanceof; +mod _interop_require_default; +mod _interop_require_wildcard; +mod _is_native_function; +mod _is_native_reflect_construct; +mod _iterable_to_array; +mod _iterable_to_array_limit; +mod _iterable_to_array_limit_loose; +mod _new_arrow_check; +mod _non_iterable_rest; +mod _non_iterable_spread; +mod _object_destructuring_empty; +mod _object_spread; +mod _object_spread_props; +mod _object_without_properties; +mod _object_without_properties_loose; +mod _overload_yield; +mod _possible_constructor_return; +mod _read_only_error; +mod _set; +mod _set_prototype_of; +mod _skip_first_generator_next; +mod _sliced_to_array; +mod _sliced_to_array_loose; +mod _super_prop_base; +mod _tagged_template_literal; +mod _tagged_template_literal_loose; +mod _throw; +mod _to_array; +mod _to_consumable_array; +mod _to_primitive; +mod _to_property_key; +mod _ts_add_disposable_resource; +mod _ts_decorate; +mod _ts_dispose_resources; +mod _ts_generator; +mod _ts_metadata; +mod _ts_param; +mod _ts_rewrite_relative_import_extension; +mod _ts_values; +mod _type_of; +mod _unsupported_iterable_to_array; +mod _update; +mod _using; +mod _using_ctx; +mod _wrap_async_generator; +mod _wrap_native_super; +mod _wrap_reg_exp; +mod _write_only_error; + +#[allow(non_camel_case_types)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[repr(usize)] +pub enum HelperName { + apply_decorated_descriptor, + apply_decs_2203_r, + apply_decs_2311, + array_like_to_array, + array_with_holes, + array_without_holes, + assert_this_initialized, + async_generator, + async_generator_delegate, + async_iterator, + async_to_generator, + await_async_generator, + await_value, + call_super, + check_private_redeclaration, + class_apply_descriptor_destructure, + class_apply_descriptor_get, + class_apply_descriptor_set, + class_apply_descriptor_update, + class_call_check, + class_check_private_static_access, + class_check_private_static_field_descriptor, + class_extract_field_descriptor, + class_name_tdz_error, + class_private_field_destructure, + class_private_field_get, + class_private_field_init, + class_private_field_loose_base, + class_private_field_loose_key, + class_private_field_set, + class_private_field_update, + class_private_method_get, + class_private_method_init, + class_private_method_set, + class_static_private_field_destructure, + class_static_private_field_spec_get, + class_static_private_field_spec_set, + class_static_private_field_update, + class_static_private_method_get, + construct, + create_class, + create_for_of_iterator_helper_loose, + create_super, + decorate, + defaults, + define_enumerable_properties, + define_property, + dispose, + export_star, + extends, + get, + get_prototype_of, + identity, + inherits, + inherits_loose, + initializer_define_property, + initializer_warning_helper, + instanceof, + interop_require_default, + interop_require_wildcard, + is_native_function, + is_native_reflect_construct, + iterable_to_array, + iterable_to_array_limit, + iterable_to_array_limit_loose, + new_arrow_check, + non_iterable_rest, + non_iterable_spread, + object_destructuring_empty, + object_spread, + object_spread_props, + object_without_properties, + object_without_properties_loose, + overload_yield, + possible_constructor_return, + read_only_error, + set, + set_prototype_of, + skip_first_generator_next, + sliced_to_array, + sliced_to_array_loose, + super_prop_base, + tagged_template_literal, + tagged_template_literal_loose, + throw, + to_array, + to_consumable_array, + to_primitive, + to_property_key, + ts_add_disposable_resource, + ts_decorate, + ts_dispose_resources, + ts_generator, + ts_metadata, + ts_param, + ts_rewrite_relative_import_extension, + ts_values, + type_of, + unsupported_iterable_to_array, + update, + using, + using_ctx, + wrap_async_generator, + wrap_native_super, + wrap_reg_exp, + write_only_error, +} + +pub const HELPER_COUNT: usize = 106; + +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct HelperBitmap(u128); + +impl HelperBitmap { + pub const EMPTY: Self = Self(0); + + pub const fn single(name: HelperName) -> Self { + Self(1u128 << (name as usize)) + } + + pub const fn from_bits(bits: u128) -> Self { + Self(bits) + } + + pub fn contains(self, name: HelperName) -> bool { + self.0 & Self::single(name).0 != 0 + } + + pub fn insert(&mut self, name: HelperName) { + self.0 |= Self::single(name).0; + } + + pub fn is_empty(self) -> bool { + self.0 == 0 + } +} + +impl core::ops::BitOr for HelperBitmap { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } +} + +impl core::ops::BitOrAssign for HelperBitmap { + fn bitor_assign(&mut self, rhs: Self) { + self.0 |= rhs.0; + } +} + +#[derive(Clone, Copy, Debug)] +pub struct HelperDef { + pub name: HelperName, + pub local: &'static str, + pub import_path: &'static str, + #[cfg(feature = "inline-helpers")] + pub source: &'static str, + #[cfg(feature = "inline-helpers")] + pub deps: HelperBitmap, +} + +pub const ALL: &[HelperDef; HELPER_COUNT] = &[ + _apply_decorated_descriptor::DEF, + _apply_decs_2203_r::DEF, + _apply_decs_2311::DEF, + _array_like_to_array::DEF, + _array_with_holes::DEF, + _array_without_holes::DEF, + _assert_this_initialized::DEF, + _async_generator::DEF, + _async_generator_delegate::DEF, + _async_iterator::DEF, + _async_to_generator::DEF, + _await_async_generator::DEF, + _await_value::DEF, + _call_super::DEF, + _check_private_redeclaration::DEF, + _class_apply_descriptor_destructure::DEF, + _class_apply_descriptor_get::DEF, + _class_apply_descriptor_set::DEF, + _class_apply_descriptor_update::DEF, + _class_call_check::DEF, + _class_check_private_static_access::DEF, + _class_check_private_static_field_descriptor::DEF, + _class_extract_field_descriptor::DEF, + _class_name_tdz_error::DEF, + _class_private_field_destructure::DEF, + _class_private_field_get::DEF, + _class_private_field_init::DEF, + _class_private_field_loose_base::DEF, + _class_private_field_loose_key::DEF, + _class_private_field_set::DEF, + _class_private_field_update::DEF, + _class_private_method_get::DEF, + _class_private_method_init::DEF, + _class_private_method_set::DEF, + _class_static_private_field_destructure::DEF, + _class_static_private_field_spec_get::DEF, + _class_static_private_field_spec_set::DEF, + _class_static_private_field_update::DEF, + _class_static_private_method_get::DEF, + _construct::DEF, + _create_class::DEF, + _create_for_of_iterator_helper_loose::DEF, + _create_super::DEF, + _decorate::DEF, + _defaults::DEF, + _define_enumerable_properties::DEF, + _define_property::DEF, + _dispose::DEF, + _export_star::DEF, + _extends::DEF, + _get::DEF, + _get_prototype_of::DEF, + _identity::DEF, + _inherits::DEF, + _inherits_loose::DEF, + _initializer_define_property::DEF, + _initializer_warning_helper::DEF, + _instanceof::DEF, + _interop_require_default::DEF, + _interop_require_wildcard::DEF, + _is_native_function::DEF, + _is_native_reflect_construct::DEF, + _iterable_to_array::DEF, + _iterable_to_array_limit::DEF, + _iterable_to_array_limit_loose::DEF, + _new_arrow_check::DEF, + _non_iterable_rest::DEF, + _non_iterable_spread::DEF, + _object_destructuring_empty::DEF, + _object_spread::DEF, + _object_spread_props::DEF, + _object_without_properties::DEF, + _object_without_properties_loose::DEF, + _overload_yield::DEF, + _possible_constructor_return::DEF, + _read_only_error::DEF, + _set::DEF, + _set_prototype_of::DEF, + _skip_first_generator_next::DEF, + _sliced_to_array::DEF, + _sliced_to_array_loose::DEF, + _super_prop_base::DEF, + _tagged_template_literal::DEF, + _tagged_template_literal_loose::DEF, + _throw::DEF, + _to_array::DEF, + _to_consumable_array::DEF, + _to_primitive::DEF, + _to_property_key::DEF, + _ts_add_disposable_resource::DEF, + _ts_decorate::DEF, + _ts_dispose_resources::DEF, + _ts_generator::DEF, + _ts_metadata::DEF, + _ts_param::DEF, + _ts_rewrite_relative_import_extension::DEF, + _ts_values::DEF, + _type_of::DEF, + _unsupported_iterable_to_array::DEF, + _update::DEF, + _using::DEF, + _using_ctx::DEF, + _wrap_async_generator::DEF, + _wrap_native_super::DEF, + _wrap_reg_exp::DEF, + _write_only_error::DEF, +]; + +pub fn helper(name: HelperName) -> &'static HelperDef { + &ALL[name as usize] +} + +pub fn helper_name(name: &str) -> Option { + match name { + "apply_decorated_descriptor" => Some(HelperName::apply_decorated_descriptor), + "apply_decs_2203_r" => Some(HelperName::apply_decs_2203_r), + "apply_decs_2311" => Some(HelperName::apply_decs_2311), + "array_like_to_array" => Some(HelperName::array_like_to_array), + "array_with_holes" => Some(HelperName::array_with_holes), + "array_without_holes" => Some(HelperName::array_without_holes), + "assert_this_initialized" => Some(HelperName::assert_this_initialized), + "async_generator" => Some(HelperName::async_generator), + "async_generator_delegate" => Some(HelperName::async_generator_delegate), + "async_iterator" => Some(HelperName::async_iterator), + "async_to_generator" => Some(HelperName::async_to_generator), + "await_async_generator" => Some(HelperName::await_async_generator), + "await_value" => Some(HelperName::await_value), + "call_super" => Some(HelperName::call_super), + "check_private_redeclaration" => Some(HelperName::check_private_redeclaration), + "class_apply_descriptor_destructure" => { + Some(HelperName::class_apply_descriptor_destructure) + } + "class_apply_descriptor_get" => Some(HelperName::class_apply_descriptor_get), + "class_apply_descriptor_set" => Some(HelperName::class_apply_descriptor_set), + "class_apply_descriptor_update" => Some(HelperName::class_apply_descriptor_update), + "class_call_check" => Some(HelperName::class_call_check), + "class_check_private_static_access" => Some(HelperName::class_check_private_static_access), + "class_check_private_static_field_descriptor" => { + Some(HelperName::class_check_private_static_field_descriptor) + } + "class_extract_field_descriptor" => Some(HelperName::class_extract_field_descriptor), + "class_name_tdz_error" => Some(HelperName::class_name_tdz_error), + "class_private_field_destructure" => Some(HelperName::class_private_field_destructure), + "class_private_field_get" => Some(HelperName::class_private_field_get), + "class_private_field_init" => Some(HelperName::class_private_field_init), + "class_private_field_loose_base" => Some(HelperName::class_private_field_loose_base), + "class_private_field_loose_key" => Some(HelperName::class_private_field_loose_key), + "class_private_field_set" => Some(HelperName::class_private_field_set), + "class_private_field_update" => Some(HelperName::class_private_field_update), + "class_private_method_get" => Some(HelperName::class_private_method_get), + "class_private_method_init" => Some(HelperName::class_private_method_init), + "class_private_method_set" => Some(HelperName::class_private_method_set), + "class_static_private_field_destructure" => { + Some(HelperName::class_static_private_field_destructure) + } + "class_static_private_field_spec_get" => { + Some(HelperName::class_static_private_field_spec_get) + } + "class_static_private_field_spec_set" => { + Some(HelperName::class_static_private_field_spec_set) + } + "class_static_private_field_update" => Some(HelperName::class_static_private_field_update), + "class_static_private_method_get" => Some(HelperName::class_static_private_method_get), + "construct" => Some(HelperName::construct), + "create_class" => Some(HelperName::create_class), + "create_for_of_iterator_helper_loose" => { + Some(HelperName::create_for_of_iterator_helper_loose) + } + "create_super" => Some(HelperName::create_super), + "decorate" => Some(HelperName::decorate), + "defaults" => Some(HelperName::defaults), + "define_enumerable_properties" => Some(HelperName::define_enumerable_properties), + "define_property" => Some(HelperName::define_property), + "dispose" => Some(HelperName::dispose), + "export_star" => Some(HelperName::export_star), + "extends" => Some(HelperName::extends), + "get" => Some(HelperName::get), + "get_prototype_of" => Some(HelperName::get_prototype_of), + "identity" => Some(HelperName::identity), + "inherits" => Some(HelperName::inherits), + "inherits_loose" => Some(HelperName::inherits_loose), + "initializer_define_property" => Some(HelperName::initializer_define_property), + "initializer_warning_helper" => Some(HelperName::initializer_warning_helper), + "instanceof" => Some(HelperName::instanceof), + "interop_require_default" => Some(HelperName::interop_require_default), + "interop_require_wildcard" => Some(HelperName::interop_require_wildcard), + "is_native_function" => Some(HelperName::is_native_function), + "is_native_reflect_construct" => Some(HelperName::is_native_reflect_construct), + "iterable_to_array" => Some(HelperName::iterable_to_array), + "iterable_to_array_limit" => Some(HelperName::iterable_to_array_limit), + "iterable_to_array_limit_loose" => Some(HelperName::iterable_to_array_limit_loose), + "new_arrow_check" => Some(HelperName::new_arrow_check), + "non_iterable_rest" => Some(HelperName::non_iterable_rest), + "non_iterable_spread" => Some(HelperName::non_iterable_spread), + "object_destructuring_empty" => Some(HelperName::object_destructuring_empty), + "object_spread" => Some(HelperName::object_spread), + "object_spread_props" => Some(HelperName::object_spread_props), + "object_without_properties" => Some(HelperName::object_without_properties), + "object_without_properties_loose" => Some(HelperName::object_without_properties_loose), + "overload_yield" => Some(HelperName::overload_yield), + "possible_constructor_return" => Some(HelperName::possible_constructor_return), + "read_only_error" => Some(HelperName::read_only_error), + "set" => Some(HelperName::set), + "set_prototype_of" => Some(HelperName::set_prototype_of), + "skip_first_generator_next" => Some(HelperName::skip_first_generator_next), + "sliced_to_array" => Some(HelperName::sliced_to_array), + "sliced_to_array_loose" => Some(HelperName::sliced_to_array_loose), + "super_prop_base" => Some(HelperName::super_prop_base), + "tagged_template_literal" => Some(HelperName::tagged_template_literal), + "tagged_template_literal_loose" => Some(HelperName::tagged_template_literal_loose), + "throw" => Some(HelperName::throw), + "to_array" => Some(HelperName::to_array), + "to_consumable_array" => Some(HelperName::to_consumable_array), + "to_primitive" => Some(HelperName::to_primitive), + "to_property_key" => Some(HelperName::to_property_key), + "ts_add_disposable_resource" => Some(HelperName::ts_add_disposable_resource), + "ts_decorate" => Some(HelperName::ts_decorate), + "ts_dispose_resources" => Some(HelperName::ts_dispose_resources), + "ts_generator" => Some(HelperName::ts_generator), + "ts_metadata" => Some(HelperName::ts_metadata), + "ts_param" => Some(HelperName::ts_param), + "ts_rewrite_relative_import_extension" => { + Some(HelperName::ts_rewrite_relative_import_extension) + } + "ts_values" => Some(HelperName::ts_values), + "type_of" => Some(HelperName::type_of), + "unsupported_iterable_to_array" => Some(HelperName::unsupported_iterable_to_array), + "update" => Some(HelperName::update), + "using" => Some(HelperName::using), + "using_ctx" => Some(HelperName::using_ctx), + "wrap_async_generator" => Some(HelperName::wrap_async_generator), + "wrap_native_super" => Some(HelperName::wrap_native_super), + "wrap_reg_exp" => Some(HelperName::wrap_reg_exp), + "write_only_error" => Some(HelperName::write_only_error), + _ => None, + } +} + +impl super::Helpers { + pub fn apply_decorated_descriptor(&self) { + self.enable(HelperName::apply_decorated_descriptor); + } + + pub fn apply_decs_2203_r(&self) { + self.enable(HelperName::apply_decs_2203_r); + } + + pub fn apply_decs_2311(&self) { + self.enable(HelperName::apply_decs_2311); + } + + pub fn array_like_to_array(&self) { + self.enable(HelperName::array_like_to_array); + } + + pub fn array_with_holes(&self) { + self.enable(HelperName::array_with_holes); + } + + pub fn array_without_holes(&self) { + self.enable(HelperName::array_without_holes); + } + + pub fn assert_this_initialized(&self) { + self.enable(HelperName::assert_this_initialized); + } + + pub fn async_generator(&self) { + self.enable(HelperName::async_generator); + } + + pub fn async_generator_delegate(&self) { + self.enable(HelperName::async_generator_delegate); + } + + pub fn async_iterator(&self) { + self.enable(HelperName::async_iterator); + } + + pub fn async_to_generator(&self) { + self.enable(HelperName::async_to_generator); + } + + pub fn await_async_generator(&self) { + self.enable(HelperName::await_async_generator); + } + + pub fn await_value(&self) { + self.enable(HelperName::await_value); + } + + pub fn call_super(&self) { + self.enable(HelperName::call_super); + } + + pub fn check_private_redeclaration(&self) { + self.enable(HelperName::check_private_redeclaration); + } + + pub fn class_apply_descriptor_destructure(&self) { + self.enable(HelperName::class_apply_descriptor_destructure); + } + + pub fn class_apply_descriptor_get(&self) { + self.enable(HelperName::class_apply_descriptor_get); + } + + pub fn class_apply_descriptor_set(&self) { + self.enable(HelperName::class_apply_descriptor_set); + } + + pub fn class_apply_descriptor_update(&self) { + self.enable(HelperName::class_apply_descriptor_update); + } + + pub fn class_call_check(&self) { + self.enable(HelperName::class_call_check); + } + + pub fn class_check_private_static_access(&self) { + self.enable(HelperName::class_check_private_static_access); + } + + pub fn class_check_private_static_field_descriptor(&self) { + self.enable(HelperName::class_check_private_static_field_descriptor); + } + + pub fn class_extract_field_descriptor(&self) { + self.enable(HelperName::class_extract_field_descriptor); + } + + pub fn class_name_tdz_error(&self) { + self.enable(HelperName::class_name_tdz_error); + } + + pub fn class_private_field_destructure(&self) { + self.enable(HelperName::class_private_field_destructure); + } + + pub fn class_private_field_get(&self) { + self.enable(HelperName::class_private_field_get); + } + + pub fn class_private_field_init(&self) { + self.enable(HelperName::class_private_field_init); + } + + pub fn class_private_field_loose_base(&self) { + self.enable(HelperName::class_private_field_loose_base); + } + + pub fn class_private_field_loose_key(&self) { + self.enable(HelperName::class_private_field_loose_key); + } + + pub fn class_private_field_set(&self) { + self.enable(HelperName::class_private_field_set); + } + + pub fn class_private_field_update(&self) { + self.enable(HelperName::class_private_field_update); + } + + pub fn class_private_method_get(&self) { + self.enable(HelperName::class_private_method_get); + } + + pub fn class_private_method_init(&self) { + self.enable(HelperName::class_private_method_init); + } + + pub fn class_private_method_set(&self) { + self.enable(HelperName::class_private_method_set); + } + + pub fn class_static_private_field_destructure(&self) { + self.enable(HelperName::class_static_private_field_destructure); + } + + pub fn class_static_private_field_spec_get(&self) { + self.enable(HelperName::class_static_private_field_spec_get); + } + + pub fn class_static_private_field_spec_set(&self) { + self.enable(HelperName::class_static_private_field_spec_set); + } + + pub fn class_static_private_field_update(&self) { + self.enable(HelperName::class_static_private_field_update); + } + + pub fn class_static_private_method_get(&self) { + self.enable(HelperName::class_static_private_method_get); + } + + pub fn construct(&self) { + self.enable(HelperName::construct); + } + + pub fn create_class(&self) { + self.enable(HelperName::create_class); + } + + pub fn create_for_of_iterator_helper_loose(&self) { + self.enable(HelperName::create_for_of_iterator_helper_loose); + } + + pub fn create_super(&self) { + self.enable(HelperName::create_super); + } + + pub fn decorate(&self) { + self.enable(HelperName::decorate); + } + + pub fn defaults(&self) { + self.enable(HelperName::defaults); + } + + pub fn define_enumerable_properties(&self) { + self.enable(HelperName::define_enumerable_properties); + } + + pub fn define_property(&self) { + self.enable(HelperName::define_property); + } + + pub fn dispose(&self) { + self.enable(HelperName::dispose); + } + + pub fn export_star(&self) { + self.enable(HelperName::export_star); + } + + pub fn extends(&self) { + self.enable(HelperName::extends); + } + + pub fn get(&self) { + self.enable(HelperName::get); + } + + pub fn get_prototype_of(&self) { + self.enable(HelperName::get_prototype_of); + } + + pub fn identity(&self) { + self.enable(HelperName::identity); + } + + pub fn inherits(&self) { + self.enable(HelperName::inherits); + } + + pub fn inherits_loose(&self) { + self.enable(HelperName::inherits_loose); + } + + pub fn initializer_define_property(&self) { + self.enable(HelperName::initializer_define_property); + } + + pub fn initializer_warning_helper(&self) { + self.enable(HelperName::initializer_warning_helper); + } + + pub fn instanceof(&self) { + self.enable(HelperName::instanceof); + } + + pub fn interop_require_default(&self) { + self.enable(HelperName::interop_require_default); + } + + pub fn interop_require_wildcard(&self) { + self.enable(HelperName::interop_require_wildcard); + } + + pub fn is_native_function(&self) { + self.enable(HelperName::is_native_function); + } + + pub fn is_native_reflect_construct(&self) { + self.enable(HelperName::is_native_reflect_construct); + } + + pub fn iterable_to_array(&self) { + self.enable(HelperName::iterable_to_array); + } + + pub fn iterable_to_array_limit(&self) { + self.enable(HelperName::iterable_to_array_limit); + } + + pub fn iterable_to_array_limit_loose(&self) { + self.enable(HelperName::iterable_to_array_limit_loose); + } + + pub fn new_arrow_check(&self) { + self.enable(HelperName::new_arrow_check); + } + + pub fn non_iterable_rest(&self) { + self.enable(HelperName::non_iterable_rest); + } + + pub fn non_iterable_spread(&self) { + self.enable(HelperName::non_iterable_spread); + } + + pub fn object_destructuring_empty(&self) { + self.enable(HelperName::object_destructuring_empty); + } + + pub fn object_spread(&self) { + self.enable(HelperName::object_spread); + } + + pub fn object_spread_props(&self) { + self.enable(HelperName::object_spread_props); + } + + pub fn object_without_properties(&self) { + self.enable(HelperName::object_without_properties); + } + + pub fn object_without_properties_loose(&self) { + self.enable(HelperName::object_without_properties_loose); + } + + pub fn overload_yield(&self) { + self.enable(HelperName::overload_yield); + } + + pub fn possible_constructor_return(&self) { + self.enable(HelperName::possible_constructor_return); + } + + pub fn read_only_error(&self) { + self.enable(HelperName::read_only_error); + } + + pub fn set(&self) { + self.enable(HelperName::set); + } + + pub fn set_prototype_of(&self) { + self.enable(HelperName::set_prototype_of); + } + + pub fn skip_first_generator_next(&self) { + self.enable(HelperName::skip_first_generator_next); + } + + pub fn sliced_to_array(&self) { + self.enable(HelperName::sliced_to_array); + } + + pub fn sliced_to_array_loose(&self) { + self.enable(HelperName::sliced_to_array_loose); + } + + pub fn super_prop_base(&self) { + self.enable(HelperName::super_prop_base); + } + + pub fn tagged_template_literal(&self) { + self.enable(HelperName::tagged_template_literal); + } + + pub fn tagged_template_literal_loose(&self) { + self.enable(HelperName::tagged_template_literal_loose); + } + + pub fn throw(&self) { + self.enable(HelperName::throw); + } + + pub fn to_array(&self) { + self.enable(HelperName::to_array); + } + + pub fn to_consumable_array(&self) { + self.enable(HelperName::to_consumable_array); + } + + pub fn to_primitive(&self) { + self.enable(HelperName::to_primitive); + } + + pub fn to_property_key(&self) { + self.enable(HelperName::to_property_key); + } + + pub fn ts_add_disposable_resource(&self) { + self.enable(HelperName::ts_add_disposable_resource); + } + + pub fn ts_decorate(&self) { + self.enable(HelperName::ts_decorate); + } + + pub fn ts_dispose_resources(&self) { + self.enable(HelperName::ts_dispose_resources); + } + + pub fn ts_generator(&self) { + self.enable(HelperName::ts_generator); + } + + pub fn ts_metadata(&self) { + self.enable(HelperName::ts_metadata); + } + + pub fn ts_param(&self) { + self.enable(HelperName::ts_param); + } + + pub fn ts_rewrite_relative_import_extension(&self) { + self.enable(HelperName::ts_rewrite_relative_import_extension); + } + + pub fn ts_values(&self) { + self.enable(HelperName::ts_values); + } + + pub fn type_of(&self) { + self.enable(HelperName::type_of); + } + + pub fn unsupported_iterable_to_array(&self) { + self.enable(HelperName::unsupported_iterable_to_array); + } + + pub fn update(&self) { + self.enable(HelperName::update); + } + + pub fn using(&self) { + self.enable(HelperName::using); + } + + pub fn using_ctx(&self) { + self.enable(HelperName::using_ctx); + } + + pub fn wrap_async_generator(&self) { + self.enable(HelperName::wrap_async_generator); + } + + pub fn wrap_native_super(&self) { + self.enable(HelperName::wrap_native_super); + } + + pub fn wrap_reg_exp(&self) { + self.enable(HelperName::wrap_reg_exp); + } + + pub fn write_only_error(&self) { + self.enable(HelperName::write_only_error); + } +} + +#[cfg(feature = "inline-helpers")] +pub fn stmts(name: HelperName) -> &'static [swc_ecma_ast::Stmt] { + match name { + HelperName::apply_decorated_descriptor => _apply_decorated_descriptor::stmts(), + HelperName::apply_decs_2203_r => _apply_decs_2203_r::stmts(), + HelperName::apply_decs_2311 => _apply_decs_2311::stmts(), + HelperName::array_like_to_array => _array_like_to_array::stmts(), + HelperName::array_with_holes => _array_with_holes::stmts(), + HelperName::array_without_holes => _array_without_holes::stmts(), + HelperName::assert_this_initialized => _assert_this_initialized::stmts(), + HelperName::async_generator => _async_generator::stmts(), + HelperName::async_generator_delegate => _async_generator_delegate::stmts(), + HelperName::async_iterator => _async_iterator::stmts(), + HelperName::async_to_generator => _async_to_generator::stmts(), + HelperName::await_async_generator => _await_async_generator::stmts(), + HelperName::await_value => _await_value::stmts(), + HelperName::call_super => _call_super::stmts(), + HelperName::check_private_redeclaration => _check_private_redeclaration::stmts(), + HelperName::class_apply_descriptor_destructure => { + _class_apply_descriptor_destructure::stmts() + } + HelperName::class_apply_descriptor_get => _class_apply_descriptor_get::stmts(), + HelperName::class_apply_descriptor_set => _class_apply_descriptor_set::stmts(), + HelperName::class_apply_descriptor_update => _class_apply_descriptor_update::stmts(), + HelperName::class_call_check => _class_call_check::stmts(), + HelperName::class_check_private_static_access => { + _class_check_private_static_access::stmts() + } + HelperName::class_check_private_static_field_descriptor => { + _class_check_private_static_field_descriptor::stmts() + } + HelperName::class_extract_field_descriptor => _class_extract_field_descriptor::stmts(), + HelperName::class_name_tdz_error => _class_name_tdz_error::stmts(), + HelperName::class_private_field_destructure => _class_private_field_destructure::stmts(), + HelperName::class_private_field_get => _class_private_field_get::stmts(), + HelperName::class_private_field_init => _class_private_field_init::stmts(), + HelperName::class_private_field_loose_base => _class_private_field_loose_base::stmts(), + HelperName::class_private_field_loose_key => _class_private_field_loose_key::stmts(), + HelperName::class_private_field_set => _class_private_field_set::stmts(), + HelperName::class_private_field_update => _class_private_field_update::stmts(), + HelperName::class_private_method_get => _class_private_method_get::stmts(), + HelperName::class_private_method_init => _class_private_method_init::stmts(), + HelperName::class_private_method_set => _class_private_method_set::stmts(), + HelperName::class_static_private_field_destructure => { + _class_static_private_field_destructure::stmts() + } + HelperName::class_static_private_field_spec_get => { + _class_static_private_field_spec_get::stmts() + } + HelperName::class_static_private_field_spec_set => { + _class_static_private_field_spec_set::stmts() + } + HelperName::class_static_private_field_update => { + _class_static_private_field_update::stmts() + } + HelperName::class_static_private_method_get => _class_static_private_method_get::stmts(), + HelperName::construct => _construct::stmts(), + HelperName::create_class => _create_class::stmts(), + HelperName::create_for_of_iterator_helper_loose => { + _create_for_of_iterator_helper_loose::stmts() + } + HelperName::create_super => _create_super::stmts(), + HelperName::decorate => _decorate::stmts(), + HelperName::defaults => _defaults::stmts(), + HelperName::define_enumerable_properties => _define_enumerable_properties::stmts(), + HelperName::define_property => _define_property::stmts(), + HelperName::dispose => _dispose::stmts(), + HelperName::export_star => _export_star::stmts(), + HelperName::extends => _extends::stmts(), + HelperName::get => _get::stmts(), + HelperName::get_prototype_of => _get_prototype_of::stmts(), + HelperName::identity => _identity::stmts(), + HelperName::inherits => _inherits::stmts(), + HelperName::inherits_loose => _inherits_loose::stmts(), + HelperName::initializer_define_property => _initializer_define_property::stmts(), + HelperName::initializer_warning_helper => _initializer_warning_helper::stmts(), + HelperName::instanceof => _instanceof::stmts(), + HelperName::interop_require_default => _interop_require_default::stmts(), + HelperName::interop_require_wildcard => _interop_require_wildcard::stmts(), + HelperName::is_native_function => _is_native_function::stmts(), + HelperName::is_native_reflect_construct => _is_native_reflect_construct::stmts(), + HelperName::iterable_to_array => _iterable_to_array::stmts(), + HelperName::iterable_to_array_limit => _iterable_to_array_limit::stmts(), + HelperName::iterable_to_array_limit_loose => _iterable_to_array_limit_loose::stmts(), + HelperName::new_arrow_check => _new_arrow_check::stmts(), + HelperName::non_iterable_rest => _non_iterable_rest::stmts(), + HelperName::non_iterable_spread => _non_iterable_spread::stmts(), + HelperName::object_destructuring_empty => _object_destructuring_empty::stmts(), + HelperName::object_spread => _object_spread::stmts(), + HelperName::object_spread_props => _object_spread_props::stmts(), + HelperName::object_without_properties => _object_without_properties::stmts(), + HelperName::object_without_properties_loose => _object_without_properties_loose::stmts(), + HelperName::overload_yield => _overload_yield::stmts(), + HelperName::possible_constructor_return => _possible_constructor_return::stmts(), + HelperName::read_only_error => _read_only_error::stmts(), + HelperName::set => _set::stmts(), + HelperName::set_prototype_of => _set_prototype_of::stmts(), + HelperName::skip_first_generator_next => _skip_first_generator_next::stmts(), + HelperName::sliced_to_array => _sliced_to_array::stmts(), + HelperName::sliced_to_array_loose => _sliced_to_array_loose::stmts(), + HelperName::super_prop_base => _super_prop_base::stmts(), + HelperName::tagged_template_literal => _tagged_template_literal::stmts(), + HelperName::tagged_template_literal_loose => _tagged_template_literal_loose::stmts(), + HelperName::throw => _throw::stmts(), + HelperName::to_array => _to_array::stmts(), + HelperName::to_consumable_array => _to_consumable_array::stmts(), + HelperName::to_primitive => _to_primitive::stmts(), + HelperName::to_property_key => _to_property_key::stmts(), + HelperName::ts_add_disposable_resource => _ts_add_disposable_resource::stmts(), + HelperName::ts_decorate => _ts_decorate::stmts(), + HelperName::ts_dispose_resources => _ts_dispose_resources::stmts(), + HelperName::ts_generator => _ts_generator::stmts(), + HelperName::ts_metadata => _ts_metadata::stmts(), + HelperName::ts_param => _ts_param::stmts(), + HelperName::ts_rewrite_relative_import_extension => { + _ts_rewrite_relative_import_extension::stmts() + } + HelperName::ts_values => _ts_values::stmts(), + HelperName::type_of => _type_of::stmts(), + HelperName::unsupported_iterable_to_array => _unsupported_iterable_to_array::stmts(), + HelperName::update => _update::stmts(), + HelperName::using => _using::stmts(), + HelperName::using_ctx => _using_ctx::stmts(), + HelperName::wrap_async_generator => _wrap_async_generator::stmts(), + HelperName::wrap_native_super => _wrap_native_super::stmts(), + HelperName::wrap_reg_exp => _wrap_reg_exp::stmts(), + HelperName::write_only_error => _write_only_error::stmts(), + } +} diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/mod.rs b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/mod.rs index e8d4120a6..855212885 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/helpers/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_base/src/helpers/mod.rs @@ -6,22 +6,28 @@ use swc_ecma_ast::*; use swc_ecma_utils::{prepend_stmts, quote_ident, DropSpan, ExprFactory}; use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith}; +#[doc(hidden)] +pub mod generated; + +use generated::{HelperBitmap, HelperName}; + #[macro_export] macro_rules! enable_helper { ($i:ident) => {{ $crate::helpers::HELPERS.with(|helpers| { - helpers.$i(); + let helper = $crate::helpers::generated::HelperName::$i; + helpers.enable(helper); helpers.mark() }) }}; } #[cfg(feature = "inline-helpers")] -fn parse(code: &str) -> Vec { +fn parse(code: &str, path: &str) -> Vec { let cm = swc_common::SourceMap::default(); let fm = cm.new_source_file( - swc_common::FileName::Custom(stringify!($name).into()).into(), + swc_common::FileName::Custom(path.into()).into(), code.to_string(), ); swc_ecma_parser::parse_file_as_script( @@ -41,55 +47,6 @@ fn parse(code: &str) -> Vec { .unwrap() } -#[cfg(feature = "inline-helpers")] -macro_rules! add_to { - ($buf:expr, $name:ident, $b:expr, $mark:expr) => {{ - static STMTS: once_cell::sync::Lazy> = once_cell::sync::Lazy::new(|| { - let code = include_str!(concat!("./_", stringify!($name), ".js")); - parse(&code) - }); - - let enable = $b; - if enable { - $buf.extend(STMTS.iter().cloned().map(|mut stmt| { - stmt.visit_mut_with(&mut Marker { - base: SyntaxContext::empty().apply_mark($mark), - decls: Default::default(), - - decl_ctxt: SyntaxContext::empty().apply_mark(Mark::new()), - }); - stmt - })) - } - }}; -} - -macro_rules! add_import_to { - ($buf:expr, $name:ident, $b:expr, $mark:expr) => {{ - let enable = $b; - if enable { - let ctxt = SyntaxContext::empty().apply_mark($mark); - let s = ImportSpecifier::Named(ImportNamedSpecifier { - span: DUMMY_SP, - local: Ident::new(concat!("_", stringify!($name)).into(), DUMMY_SP, ctxt), - imported: Some(quote_ident!("_").into()), - is_type_only: false, - }); - - let src: Str = concat!("@swc/helpers/_/_", stringify!($name)).into(); - - $buf.push(ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { - span: DUMMY_SP, - specifiers: vec![s], - src: Box::new(src), - with: Default::default(), - type_only: Default::default(), - phase: Default::default(), - }))) - } - }}; -} - better_scoped_tls::scoped_tls!( /// This variable is used to manage helper scripts like `_inherits` from babel. /// @@ -154,274 +111,43 @@ impl Default for HelperMark { } } -macro_rules! define_helpers { - ( - Helpers { - $( $name:ident : ( $( $dep:ident ),* ), )* - } - ) => { - #[derive(Debug,Default, Clone, Copy)] - struct Inner { - $( $name: bool, )* - } - - impl Helpers { - $( - pub fn $name(&self) { - self.inner.borrow_mut().$name = true; - - if !self.external { - $( - self.$dep(); - )* - } - } - )* - } - - - impl Helpers { - pub fn extend_from(&self, other: &Self) { - let other = other.inner.borrow(); - let mut me = self.inner.borrow_mut(); - $( - if other.$name { - me.$name = true; - } - )* - } - } - - impl InjectHelpers { - fn is_helper_used(&self) -> bool{ - - HELPERS.with(|helpers|{ - let inner = helpers.inner.borrow(); - false $( - || inner.$name - )* - }) - } +#[derive(Debug, Clone, Copy, Default)] +struct Inner { + used: HelperBitmap, +} - #[cfg(feature = "inline-helpers")] - fn build_helpers(&self) -> Vec { - let mut buf = Vec::new(); +impl Inner { + fn enable(&mut self, name: HelperName) { + self.used.insert(name); + } - HELPERS.with(|helpers|{ - let inner = helpers.inner.borrow(); - $( - add_to!(buf, $name, inner.$name, helpers.mark.0); - )* - }); + fn extend_from(&mut self, other: &Self) { + self.used |= other.used; + } - buf - } + fn is_enabled(&self, name: HelperName) -> bool { + self.used.contains(name) + } - fn build_imports(&self) -> Vec { - let mut buf = Vec::new(); + fn any(&self) -> bool { + !self.used.is_empty() + } +} - HELPERS.with(|helpers|{ - let inner = helpers.inner.borrow(); - $( - add_import_to!(buf, $name, inner.$name, helpers.mark.0); - )* - }); +impl Helpers { + #[doc(hidden)] + pub fn enable(&self, name: HelperName) { + self.inner.borrow_mut().enable(name); + } - buf - } + pub fn extend_from(&self, other: &Self) { + let other = other.inner.borrow(); + let mut me = self.inner.borrow_mut(); - fn build_requires(&self) -> Vec{ - let mut buf = Vec::new(); - HELPERS.with(|helpers|{ - let inner = helpers.inner.borrow(); - $( - let enable = inner.$name; - if enable { - buf.push(self.build_reqire(stringify!($name), helpers.mark.0)) - } - // add_require_to!(buf, $name, helpers.inner.$name, helpers.mark.0, self.global_mark); - )* - }); - buf - } - } - }; + me.extend_from(&other); + } } -define_helpers!(Helpers { - apply_decorated_descriptor: (), - array_like_to_array: (), - array_with_holes: (), - array_without_holes: (array_like_to_array), - assert_this_initialized: (), - async_generator: (overload_yield), - async_generator_delegate: (overload_yield), - async_iterator: (), - async_to_generator: (), - await_async_generator: (overload_yield), - await_value: (), - call_super: ( - get_prototype_of, - is_native_reflect_construct, - possible_constructor_return - ), - check_private_redeclaration: (), - class_apply_descriptor_destructure: (), - class_apply_descriptor_get: (), - class_apply_descriptor_set: (), - class_apply_descriptor_update: (), - class_call_check: (), - class_check_private_static_field_descriptor: (), - class_extract_field_descriptor: (), - class_name_tdz_error: (), - class_private_field_get: (class_extract_field_descriptor, class_apply_descriptor_get), - class_private_field_init: (check_private_redeclaration), - class_private_field_loose_base: (), - class_private_field_loose_key: (), - class_private_field_set: (class_extract_field_descriptor, class_apply_descriptor_set), - class_private_field_update: ( - class_extract_field_descriptor, - class_apply_descriptor_update - ), - class_private_method_get: (), - class_private_method_init: (check_private_redeclaration), - class_private_method_set: (), - class_static_private_field_spec_get: ( - class_check_private_static_access, - class_check_private_static_field_descriptor, - class_apply_descriptor_get - ), - class_static_private_field_spec_set: ( - class_check_private_static_access, - class_check_private_static_field_descriptor, - class_apply_descriptor_set - ), - class_static_private_field_update: ( - class_check_private_static_access, - class_check_private_static_field_descriptor, - class_apply_descriptor_update - ), - construct: (is_native_reflect_construct, set_prototype_of), - create_class: (), - decorate: (to_array, to_property_key), - defaults: (), - define_enumerable_properties: (), - define_property: (), - export_star: (), - extends: (), - get: (super_prop_base), - get_prototype_of: (), - inherits: (set_prototype_of), - inherits_loose: (), - initializer_define_property: (), - initializer_warning_helper: (), - instanceof: (), - interop_require_default: (), - interop_require_wildcard: (), - is_native_function: (), - iterable_to_array: (), - iterable_to_array_limit: (), - iterable_to_array_limit_loose: (), - jsx: (), - new_arrow_check: (), - non_iterable_rest: (), - non_iterable_spread: (), - object_destructuring_empty: (), - object_spread: (define_property), - object_spread_props: (), - object_without_properties: (object_without_properties_loose), - object_without_properties_loose: (), - overload_yield: (), - possible_constructor_return: (type_of, assert_this_initialized), - read_only_error: (), - set: (super_prop_base, define_property), - set_prototype_of: (), - skip_first_generator_next: (), - sliced_to_array: ( - array_with_holes, - iterable_to_array_limit, - unsupported_iterable_to_array, - non_iterable_rest - ), - sliced_to_array_loose: ( - array_with_holes, - iterable_to_array_limit_loose, - unsupported_iterable_to_array, - non_iterable_rest - ), - super_prop_base: (get_prototype_of), - tagged_template_literal: (), - tagged_template_literal_loose: (), - // temporal_ref: (temporal_undefined), - // temporal_undefined: (), - throw: (), - to_array: ( - array_with_holes, - iterable_to_array, - unsupported_iterable_to_array, - non_iterable_rest - ), - to_consumable_array: ( - array_without_holes, - iterable_to_array, - unsupported_iterable_to_array, - non_iterable_spread - ), - to_primitive: (type_of), - to_property_key: (type_of, to_primitive), - update: (get, set), - type_of: (), - unsupported_iterable_to_array: (array_like_to_array), - wrap_async_generator: (async_generator), - wrap_native_super: ( - construct, - get_prototype_of, - set_prototype_of, - is_native_function - ), - wrap_reg_exp: (inherits, set_prototype_of), - write_only_error: (), - - class_private_field_destructure: ( - class_extract_field_descriptor, - class_apply_descriptor_destructure - ), - class_static_private_field_destructure: ( - class_check_private_static_access, - class_extract_field_descriptor, - class_apply_descriptor_destructure - ), - - class_static_private_method_get: (class_check_private_static_access), - class_check_private_static_access: (), - - is_native_reflect_construct: (), - - create_super: ( - get_prototype_of, - is_native_reflect_construct, - possible_constructor_return - ), - - create_for_of_iterator_helper_loose: (unsupported_iterable_to_array), - - ts_decorate: (), - ts_generator: (), - ts_metadata: (), - ts_param: (), - ts_values: (), - ts_add_disposable_resource: (), - ts_dispose_resources: (), - ts_rewrite_relative_import_extension: (), - - apply_decs_2203_r: (), - apply_decs_2311: (), - identity: (), - dispose: (), - using: (), - using_ctx: (), -}); - pub fn inject_helpers(global_mark: Mark) -> impl Pass + VisitMut { visit_mut_pass(InjectHelpers { global_mark, @@ -435,6 +161,96 @@ struct InjectHelpers { } impl InjectHelpers { + fn is_helper_used(&self) -> bool { + HELPERS.with(|helpers| helpers.inner.borrow().any()) + } + + #[cfg(feature = "inline-helpers")] + fn build_helpers(&self) -> Vec { + let (required, mark) = HELPERS.with(|helpers| { + let inner = helpers.inner.borrow(); + let mut required = HelperBitmap::EMPTY; + + for helper in generated::ALL { + if inner.is_enabled(helper.name) { + required |= helper.deps; + } + } + + (required, helpers.mark.0) + }); + + let base = SyntaxContext::empty().apply_mark(mark); + let mut buf = Vec::new(); + + for helper in generated::ALL { + if required.contains(helper.name) { + buf.extend( + generated::stmts(helper.name) + .iter() + .cloned() + .map(|mut stmt| { + stmt.visit_mut_with(&mut Marker { + base, + decls: Default::default(), + decl_ctxt: SyntaxContext::empty().apply_mark(Mark::new()), + }); + stmt + }), + ); + } + } + + buf + } + + fn build_imports(&self) -> Vec { + let mut buf = Vec::new(); + + HELPERS.with(|helpers| { + let inner = helpers.inner.borrow(); + let ctxt = SyntaxContext::empty().apply_mark(helpers.mark.0); + + for helper in generated::ALL { + if inner.is_enabled(helper.name) { + let specifier = ImportSpecifier::Named(ImportNamedSpecifier { + span: DUMMY_SP, + local: Ident::new(helper.local.into(), DUMMY_SP, ctxt), + imported: Some(quote_ident!("_").into()), + is_type_only: false, + }); + + buf.push(ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { + span: DUMMY_SP, + specifiers: vec![specifier], + src: Box::new(Str::from(helper.import_path)), + with: Default::default(), + type_only: Default::default(), + phase: Default::default(), + }))); + } + } + }); + + buf + } + + fn build_requires(&self) -> Vec { + let mut buf = Vec::new(); + + HELPERS.with(|helpers| { + let inner = helpers.inner.borrow(); + + for helper in generated::ALL { + if inner.is_enabled(helper.name) { + buf.push(self.build_reqire(helper, helpers.mark.0)); + } + } + }); + + buf + } + #[allow(unused_variables)] fn make_helpers_for_module(&mut self) -> Vec { let (helper_mark, external) = HELPERS.with(|helper| (helper.mark(), helper.external())); @@ -473,7 +289,7 @@ impl InjectHelpers { } } - fn build_reqire(&self, name: &str, mark: Mark) -> Stmt { + fn build_reqire(&self, helper: &generated::HelperDef, mark: Mark) -> Stmt { let c = CallExpr { span: DUMMY_SP, callee: Expr::from(Ident { @@ -485,7 +301,7 @@ impl InjectHelpers { .as_callee(), args: vec![Str { span: DUMMY_SP, - value: format!("@swc/helpers/_/_{name}").into(), + value: helper.import_path.into(), raw: None, } .as_arg()], @@ -496,7 +312,7 @@ impl InjectHelpers { kind: VarDeclKind::Var, decls: vec![VarDeclarator { span: DUMMY_SP, - name: Pat::Ident(Ident::new(format!("_{name}").into(), DUMMY_SP, ctxt).into()), + name: Pat::Ident(Ident::new(helper.local.into(), DUMMY_SP, ctxt).into()), init: Some(c.into()), definite: false, }], @@ -728,6 +544,45 @@ let _throw1 = null; ) } + #[test] + #[cfg(feature = "inline-helpers")] + fn inline_helper_dependencies() { + let input = "_to_consumable_array(foo);"; + crate::tests::Tester::run(|tester| { + HELPERS.set(&Helpers::new(false), || { + enable_helper!(to_consumable_array); + + let tr = inject_helpers(Mark::new()); + let actual = tester + .apply_transform(tr, "input.js", Default::default(), input)? + .apply(crate::hygiene::hygiene()) + .apply(crate::fixer::fixer(None)); + let actual_src = tester.print(&actual); + + for helper in [ + "_array_like_to_array", + "_array_without_holes", + "_iterable_to_array", + "_non_iterable_spread", + "_to_consumable_array", + "_unsupported_iterable_to_array", + ] { + assert!( + actual_src.contains(&format!("function {helper}(")), + "expected inline helper `{helper}` in output:\n{actual_src}" + ); + } + + assert!( + !actual_src.contains("@swc/helpers"), + "inline helpers should not emit external imports:\n{actual_src}" + ); + + Ok(()) + }) + }); + } + #[test] fn use_strict_abort() { crate::tests::test_transform( @@ -810,7 +665,7 @@ let x = 4;", if (error !== empty) throw error; } function err(e) { - error = error !== empty ? new _disposeSuppressedError(error, e) : e; + error = error !== empty ? new _disposeSuppressedError(e, error) : e; return next(); } return next(); diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/hygiene/mod.rs b/deps/swc/crates/swc_ecma_transforms_base/src/hygiene/mod.rs index 3224ddc6e..b69ace488 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/hygiene/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_base/src/hygiene/mod.rs @@ -23,10 +23,20 @@ pub struct Config { pub ignore_eval: bool, } +// https://github.com/swc-project/swc/issues/9791 +impl Config { + pub fn hygiene_default() -> Self { + Self { + ignore_eval: true, + ..Default::default() + } + } +} + /// See [hygiene_with_config] for doc. Creates a `hygiene` pass with default /// value of [Config]. pub fn hygiene() -> impl Pass + VisitMut { - hygiene_with_config(Default::default()) + hygiene_with_config(Config::hygiene_default()) } /// The pass actually modifies the identifiers in the way that different diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyer_and_collector.rs b/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyer_and_collector.rs index 63756bdd4..2b3e2e803 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyer_and_collector.rs +++ b/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyer_and_collector.rs @@ -98,8 +98,8 @@ impl Visit for AnalyzerAndCollector { self.analyzer.is_pat_decl = false; match node.body.as_ref() { - BlockStmtOrExpr::BlockStmt(n) => n.visit_children_with(self), - BlockStmtOrExpr::Expr(n) => n.visit_with(self), + ArrowFunctionBody::FunctionBody(n) => n.visit_with(self), + ArrowFunctionBody::Expr(n) => n.visit_with(self), #[cfg(swc_ast_unknown)] _ => (), } @@ -197,9 +197,7 @@ impl Visit for AnalyzerAndCollector { node.function.decorators.visit_with(self); node.function.params.visit_with(self); - if let Some(body) = &node.function.body { - body.visit_children_with(self); - } + node.function.body.visit_with(self); self.analyzer.exit_scope(old_analyzer); } @@ -208,9 +206,7 @@ impl Visit for AnalyzerAndCollector { let old_analyzer = self.analyzer.enter_fn_scope(); node.key.visit_with(self); node.params.visit_with(self); - if let Some(body) = &node.body { - body.visit_children_with(self); - } + node.body.visit_with(self); self.analyzer.exit_scope(old_analyzer); } @@ -302,9 +298,7 @@ impl Visit for AnalyzerAndCollector { node.function.decorators.visit_with(self); node.function.params.visit_with(self); - if let Some(body) = &node.function.body { - body.visit_children_with(self); - } + node.function.body.visit_with(self); self.analyzer.exit_scope(old_analyzer); self.decl_collector.add(&node.ident); @@ -335,9 +329,7 @@ impl Visit for AnalyzerAndCollector { } node.function.decorators.visit_with(self); node.function.params.visit_with(self); - if let Some(body) = &node.function.body { - body.visit_children_with(self); - } + node.function.body.visit_with(self); self.analyzer.exit_scope(old_analyzer1); self.analyzer.exit_scope(old_analyzer0); } else { @@ -392,9 +384,7 @@ impl Visit for AnalyzerAndCollector { node.decorators.visit_with(self); node.params.visit_with(self); - if let Some(body) = &node.body { - body.visit_children_with(self); - } + node.body.visit_with(self); self.analyzer.exit_scope(old_analyzer); } diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyzer/mod.rs b/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyzer/mod.rs index 3271c2be6..adc9bd4d1 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyzer/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyzer/mod.rs @@ -1,3 +1,4 @@ +use swc_atoms::atom; use swc_common::Mark; use swc_ecma_ast::*; @@ -180,8 +181,16 @@ impl Analyzer { } pub(super) fn handle_expr(&mut self, e: &Expr) { - if let Expr::Ident(i) = e { - self.add_usage(i.to_id()); + match e { + Expr::Ident(i) => self.add_usage(i.to_id()), + Expr::Lit(Lit::Num(num)) if !num.value.is_finite() => match num.raw.as_deref() { + Some("NaN") => self.scope.reserve_output_symbol(atom!("NaN")), + Some("Infinity") => { + self.scope.reserve_output_symbol(atom!("Infinity")); + } + _ => {} + }, + _ => {} } } diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyzer/scope.rs b/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyzer/scope.rs index 4e1f92dee..da62953dd 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyzer/scope.rs +++ b/deps/swc/crates/swc_ecma_transforms_base/src/rename/analyzer/scope.rs @@ -42,6 +42,10 @@ pub(super) struct ScopeData { all: FxHashSet, queue: FxIndexSet, + + /// Names emitted by non-identifier expressions in this scope or its + /// descendants. Renamed bindings must not capture these names. + reserved_output_symbols: FxHashSet, } impl Scope { @@ -75,6 +79,10 @@ impl Scope { self.data.all.insert(id); } + pub(super) fn reserve_output_symbol(&mut self, symbol: Atom) { + self.data.reserved_output_symbols.insert(symbol); + } + pub(crate) fn reserve_usage(&mut self, len: usize) { self.data.all.reserve(len); } @@ -85,6 +93,9 @@ impl Scope { child.prepare_renaming(); self.data.all.extend(child.data.all.iter().cloned()); + self.data + .reserved_output_symbols + .extend(child.data.reserved_output_symbols.iter().cloned()); }); } @@ -159,7 +170,9 @@ impl Scope { loop { let sym = renamer.new_name_for(&id, &mut n); - if preserved_symbols.contains(&sym) { + if preserved_symbols.contains(&sym) + || self.data.reserved_output_symbols.contains(&sym) + { continue; } @@ -305,7 +318,9 @@ impl Scope { let sym = renamer.new_name_for(&id, &mut n); // TODO: Use base54::decode - if preserved_symbols.contains(&sym) { + if preserved_symbols.contains(&sym) + || self.data.reserved_output_symbols.contains(&sym) + { continue; } diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/rename/mod.rs b/deps/swc/crates/swc_ecma_transforms_base/src/rename/mod.rs index bca6a153e..c0efba0c1 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/rename/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_base/src/rename/mod.rs @@ -311,6 +311,24 @@ where } } + // Drop identity mappings before apply. Operator already no-ops when + // `sym == ident.sym`, so they only inflate the apply walk. + // + // Identities must still be inserted into `map` *during* analysis so + // later scopes can skip via `to.get(id)`. Without that (e.g. hygiene + // alone, no resolver), the same Id is reprocessed in every scope and + // the reverse map blows up. + // + // Keep identities when `keep_class_names` is set: Operator uses that + // flag to rewrite `class Foo` into `let Foo = class Foo`, and on the + // old path those identity entries were what kept the map non-empty so + // Operator ran. Minifier `keep_classnames` preserves class Ids instead + // (they never enter the map), so this does not reintroduce apply work + // for those fixtures. + if !self.config.keep_class_names { + map.retain(|id, v| v.atom() != &id.0); + } + map } diff --git a/deps/swc/crates/swc_ecma_transforms_base/src/resolver/mod.rs b/deps/swc/crates/swc_ecma_transforms_base/src/resolver/mod.rs index c07694088..df704bc84 100644 --- a/deps/swc/crates/swc_ecma_transforms_base/src/resolver/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_base/src/resolver/mod.rs @@ -528,6 +528,7 @@ impl VisitMut for Resolver<'_> { fn visit_mut_arrow_expr(&mut self, e: &mut ArrowExpr) { self.with_child(ScopeKind::Fn, |child| { + child.mark_block(&mut e.ctxt); e.type_params.visit_mut_with(child); let old = child.ident_type; @@ -547,9 +548,7 @@ impl VisitMut for Resolver<'_> { child.ident_type = old; match &mut *e.body { - BlockStmtOrExpr::BlockStmt(s) => { - child.mark_block(&mut s.ctxt); - + ArrowFunctionBody::FunctionBody(s) => { let old_strict_mode = child.strict_mode; if !child.strict_mode { @@ -559,11 +558,10 @@ impl VisitMut for Resolver<'_> { .map(|stmt| stmt.is_use_strict()) .unwrap_or(false); } - // Prevent creating new scope. - s.stmts.visit_mut_with(child); + s.visit_mut_with(child); child.strict_mode = old_strict_mode; } - BlockStmtOrExpr::Expr(e) => e.visit_mut_with(child), + ArrowFunctionBody::Expr(e) => e.visit_mut_with(child), #[cfg(swc_ast_unknown)] _ => (), } @@ -719,6 +717,7 @@ impl VisitMut for Resolver<'_> { } self.with_child(ScopeKind::Fn, |child| { + child.mark_block(&mut c.ctxt); let old = child.ident_type; child.ident_type = IdentType::Binding; { @@ -741,8 +740,7 @@ impl VisitMut for Resolver<'_> { child.ident_type = old; if let Some(body) = &mut c.body { - child.mark_block(&mut body.ctxt); - body.visit_mut_children_with(child); + body.visit_mut_with(child); } }); } @@ -898,6 +896,8 @@ impl VisitMut for Resolver<'_> { self.current.declared_symbols.insert(id.0, DeclKind::Param); } } + f.this_param.visit_mut_with(self); + self.ident_type = IdentType::Binding; f.params.visit_mut_with(self); @@ -905,7 +905,6 @@ impl VisitMut for Resolver<'_> { self.ident_type = IdentType::Ref; if let Some(body) = &mut f.body { - self.mark_block(&mut body.ctxt); let old_strict_mode = self.strict_mode; if !self.strict_mode { self.strict_mode = body @@ -914,23 +913,11 @@ impl VisitMut for Resolver<'_> { .map(|stmt| stmt.is_use_strict()) .unwrap_or(false); } - // Prevent creating new scope. - body.visit_mut_children_with(self); + body.visit_mut_with(self); self.strict_mode = old_strict_mode; } } - fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) { - let old = self.ident_type; - self.ident_type = IdentType::Ref; - f.key.visit_mut_with(self); - self.ident_type = old; - - f.type_ann.visit_mut_with(self); - - f.body.visit_mut_with(self); - } - fn visit_mut_jsx_element_name(&mut self, node: &mut JSXElementName) { if let JSXElementName::Ident(i) = node { if i.as_ref().starts_with(|c: char| c.is_ascii_lowercase()) { @@ -1060,13 +1047,6 @@ impl VisitMut for Resolver<'_> { s.body.visit_mut_with(self); } - fn visit_mut_method_prop(&mut self, m: &mut MethodProp) { - m.key.visit_mut_with(self); - - // Child folder - self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child)); - } - fn visit_mut_module(&mut self, module: &mut Module) { self.strict_mode = true; self.is_module = true; @@ -1136,6 +1116,18 @@ impl VisitMut for Resolver<'_> { } } + fn visit_mut_prop(&mut self, prop: &mut Prop) { + match prop { + Prop::Getter(GetterProp { key, function, .. }) + | Prop::Setter(SetterProp { key, function, .. }) + | Prop::Method(MethodProp { key, function }) => { + key.visit_mut_with(self); + self.with_child(ScopeKind::Fn, |child| function.visit_mut_with(child)); + } + _ => prop.visit_mut_children_with(self), + } + } + fn visit_mut_rest_pat(&mut self, node: &mut RestPat) { node.arg.visit_mut_with(self); node.type_ann.visit_mut_with(self); @@ -1150,19 +1142,6 @@ impl VisitMut for Resolver<'_> { script.visit_mut_children_with(self) } - fn visit_mut_setter_prop(&mut self, n: &mut SetterProp) { - n.key.visit_mut_with(self); - - { - self.with_child(ScopeKind::Fn, |child| { - child.ident_type = IdentType::Binding; - n.this_param.visit_mut_with(child); - n.param.visit_mut_with(child); - n.body.visit_mut_with(child); - }); - }; - } - fn visit_mut_stmts(&mut self, stmts: &mut Vec) { #[cfg(debug_assertions)] let _span = if LOG { @@ -1205,6 +1184,7 @@ impl VisitMut for Resolver<'_> { s.discriminant.visit_mut_with(self); self.with_child(ScopeKind::Block, |child| { + child.mark_block(&mut s.body_ctxt); s.cases.visit_mut_with(child); }); } @@ -1892,9 +1872,6 @@ impl VisitMut for Hoister<'_, '_> { #[inline] fn visit_mut_assign_target(&mut self, _: &mut AssignTarget) {} - #[inline] - fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) {} - fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) { s.discriminant.visit_mut_with(self); diff --git a/deps/swc/crates/swc_ecma_transforms_classes/Cargo.toml b/deps/swc/crates/swc_ecma_transforms_classes/Cargo.toml index 905357278..7a807e453 100644 --- a/deps/swc/crates/swc_ecma_transforms_classes/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms_classes/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_transforms_classes" repository = { workspace = true } -version = "44.0.0" +version = "49.0.0" [lib] bench = false @@ -15,8 +15,8 @@ bench = false unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } [dependencies] -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } diff --git a/deps/swc/crates/swc_ecma_transforms_classes/src/super_field.rs b/deps/swc/crates/swc_ecma_transforms_classes/src/super_field.rs index 4ca1d95d4..11dc57830 100644 --- a/deps/swc/crates/swc_ecma_transforms_classes/src/super_field.rs +++ b/deps/swc/crates/swc_ecma_transforms_classes/src/super_field.rs @@ -282,25 +282,12 @@ impl VisitMut for MovedStaticSuperFieldAccessFolder<'_> { // should not be rewritten against the moved static member. } - fn visit_mut_getter_prop(&mut self, n: &mut GetterProp) { - n.key.visit_mut_with(self); - } - - fn visit_mut_method_prop(&mut self, n: &mut MethodProp) { - n.key.visit_mut_with(self); - } - fn visit_mut_pat(&mut self, n: &mut Pat) { let in_pat = self.folder.in_pat; self.folder.in_pat = true; n.visit_mut_children_with(self); self.folder.in_pat = in_pat; } - - fn visit_mut_setter_prop(&mut self, n: &mut SetterProp) { - n.key.visit_mut_with(self); - n.param.visit_mut_with(self); - } } impl SuperFieldAccessFolder<'_> { diff --git a/deps/swc/crates/swc_ecma_transforms_compat/Cargo.toml b/deps/swc/crates/swc_ecma_transforms_compat/Cargo.toml index cfbfc5d3c..21de49131 100644 --- a/deps/swc/crates/swc_ecma_transforms_compat/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms_compat/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_transforms_compat" repository = { workspace = true } -version = "52.0.1" +version = "57.0.0" [lib] bench = false @@ -29,31 +29,31 @@ par-core = { workspace = true } serde = { workspace = true, features = ["derive"] } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_compat_bugfixes = { version = "51.0.0", path = "../swc_ecma_compat_bugfixes" } -swc_ecma_compat_common = { version = "40.0.1", path = "../swc_ecma_compat_common" } -swc_ecma_compat_es2015 = { version = "50.0.0", path = "../swc_ecma_compat_es2015" } -swc_ecma_compat_es2016 = { version = "45.0.0", path = "../swc_ecma_compat_es2016" } -swc_ecma_compat_es2017 = { version = "45.0.0", path = "../swc_ecma_compat_es2017" } -swc_ecma_compat_es2018 = { version = "46.0.0", path = "../swc_ecma_compat_es2018" } -swc_ecma_compat_es2019 = { version = "45.0.0", path = "../swc_ecma_compat_es2019" } -swc_ecma_compat_es2020 = { version = "48.0.0", path = "../swc_ecma_compat_es2020" } -swc_ecma_compat_es2021 = { version = "45.0.0", path = "../swc_ecma_compat_es2021" } -swc_ecma_compat_es2022 = { version = "48.0.0", path = "../swc_ecma_compat_es2022" } -swc_ecma_compat_es3 = { version = "36.0.0", path = "../swc_ecma_compat_es3", optional = true } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_compat_bugfixes = { version = "56.0.0", path = "../swc_ecma_compat_bugfixes" } +swc_ecma_compat_common = { version = "45.0.0", path = "../swc_ecma_compat_common" } +swc_ecma_compat_es2015 = { version = "55.0.0", path = "../swc_ecma_compat_es2015" } +swc_ecma_compat_es2016 = { version = "50.0.0", path = "../swc_ecma_compat_es2016" } +swc_ecma_compat_es2017 = { version = "50.0.0", path = "../swc_ecma_compat_es2017" } +swc_ecma_compat_es2018 = { version = "51.0.0", path = "../swc_ecma_compat_es2018" } +swc_ecma_compat_es2019 = { version = "50.0.0", path = "../swc_ecma_compat_es2019" } +swc_ecma_compat_es2020 = { version = "53.0.0", path = "../swc_ecma_compat_es2020" } +swc_ecma_compat_es2021 = { version = "50.0.0", path = "../swc_ecma_compat_es2021" } +swc_ecma_compat_es2022 = { version = "53.0.0", path = "../swc_ecma_compat_es2022" } +swc_ecma_compat_es3 = { version = "41.0.0", path = "../swc_ecma_compat_es3", optional = true } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] par-core = { workspace = true, features = ["chili"] } serde_json = { workspace = true } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base", features = [ +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base", features = [ "inline-helpers", ] } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_ecma_transforms_module/Cargo.toml b/deps/swc/crates/swc_ecma_transforms_module/Cargo.toml index 8b3208eb0..06b530999 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms_module/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_transforms_module" repository = { workspace = true } -version = "49.0.1" +version = "55.0.0" [lib] bench = false @@ -28,31 +28,31 @@ rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_config = { version = "5.0.0", path = "../swc_config", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_config = { version = "6.0.0", path = "../swc_config", features = [ "file_pattern", ] } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_loader = { version = "24.0.1", path = "../swc_ecma_loader", features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_loader = { version = "27.0.0", path = "../swc_ecma_loader", features = [ ] } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] indexmap = { workspace = true, features = ["serde"] } serde_json = { workspace = true } tempfile = { workspace = true } -swc_ecma_loader = { version = "24.0.1", path = "../swc_ecma_loader", features = [ +swc_ecma_loader = { version = "27.0.0", path = "../swc_ecma_loader", features = [ "node", "tsc", ] } -swc_ecma_transforms_compat = { version = "52.0.1", path = "../swc_ecma_transforms_compat" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } -swc_ecma_transforms_typescript = { version = "50.0.0", path = "../swc_ecma_transforms_typescript" } -testing = { version = "24.0.1", path = "../testing/" } +swc_ecma_transforms_compat = { version = "57.0.0", path = "../swc_ecma_transforms_compat" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } +swc_ecma_transforms_typescript = { version = "55.0.0", path = "../swc_ecma_transforms_typescript" } +testing = { version = "27.0.0", path = "../testing/" } diff --git a/deps/swc/crates/swc_ecma_transforms_module/README.md b/deps/swc/crates/swc_ecma_transforms_module/README.md new file mode 100644 index 000000000..a53d99795 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/README.md @@ -0,0 +1,390 @@ +# Module Transforms + +This crate lowers ECMAScript module syntax into several legacy module formats. +The CommonJS, AMD, and UMD passes share one source-module collection and +reduction model, then diverge at the format-specific import/export emit +boundary. The SystemJS pass also reuses source-module collection, but it lowers +the collected records into a SystemJS-specific IR instead of using the shared +CommonJS-like reducer. + +```mermaid +flowchart TD + Input["Input ECMAScript module AST"] + TopLevelThis["Top-level this rewrite"] + Source["SourceModule::collect"] + Strip["syntax_strip::lower"] + Reducer["ModuleRecordEntryReducer"] + Rewrite["ImportMap and export getter list"] + Cjs["CommonJS emitter"] + Amd["AMD emitter"] + Umd["UMD emitter"] + SysLower["SystemJS lower"] + SysRewrite["SystemJS rewrite"] + SysEmit["SystemJS emitter"] + CjsOut["require calls, export getters, and module.exports"] + AmdOut["define dependency array and factory body"] + UmdOut["adapter IIFE and shared factory body"] + SysOut["System.register call"] + + Input --> TopLevelThis --> Source + Source --> Strip --> Reducer --> Rewrite + Rewrite --> Cjs --> CjsOut + Rewrite --> Amd --> AmdOut + Rewrite --> Umd --> UmdOut + Source --> SysLower --> SysRewrite --> SysEmit --> SysOut +``` + +SystemJS is documented separately below because its live-binding and execution +model is organized around `System.register`, dependency setters, and an +`execute` function. + +## Shared Terminology + +The shared collector in `src/module_record.rs` intentionally uses names close +to the ECMAScript module record vocabulary: + +- `SourceModule::collect` walks source module declarations, records their + module linkage information, and keeps ordered executable source items. +- `SourceModuleItem` keeps declarations that target lowerers still need to + lower, including exported declarations, default exports, and external + TypeScript `import = require(...)`. +- `RequestedModules` is grouped by `ModuleRequestRecord` and preserves source + order with `IndexMap`. +- `ModuleRequestRecord` stores the module specifier and normalized import + attributes for that request. +- `RequestedModule` stores the first useful source span, the collected + `ModuleRecordEntry` set, and `ModuleRequestUsage`. +- `LocalExportEntries` stores local exports keyed by exported name. +- `ModuleRecordEntry` represents import entries, indirect export entries, and + star exports. +- `syntax_strip::lower` converts `SourceModule` into `SyntaxStrippedModule` for + the CommonJS, AMD, and UMD passes. +- `ModuleRecordEntryReducer` converts collected entries into emitter-facing + structures: an `ImportMap` for rewritten local references and an + `ExportObjectProperties` list for generated export getters. + +`SourceModule` is a target-neutral collection model, not a full ECMAScript +linker. `ModuleRecordEntryReducer` converts its syntactic linkage facts for +CommonJS-like emitters and keeps unresolved binding access lazy through generated +property reads. + +SystemJS preserves import attributes in its dependency metadata. CommonJS, AMD, +and UMD do not process import attributes because their output formats cannot +express them; those lowering paths assume attributed requests are not provided. + +## Shared Front-End Flow + +The CommonJS, AMD, and UMD transforms follow the same broad pipeline: + +1. Replace top-level `this` with `undefined` unless + `Config::allow_top_level_this` is enabled. +2. Run `SourceModule::collect`. +3. Run `syntax_strip::lower` to remove module syntax from the executable body. +4. Move initial directive statements into the output body. +5. Insert `"use strict"` when `Config::strict_mode` requires it and the module + does not already contain one. +6. Emit an `__esModule` marker when the input had module syntax, import interop + is enabled, and the module is not a TypeScript `export =` module. +7. Convert collected module entries into format-specific import statements, + dependency parameters, export getters, and import-reference rewrites. +8. Append the stripped executable body. +9. Apply format-specific handling for `export =`, dynamic `import()`, and + `import.meta` where supported by that transform. +10. Rewrite local import binding references using the generated `ImportMap`. + +The strip step removes module declarations while preserving executable +declarations: + +- `import ... from "mod"` is removed after its import entries are collected. +- `export const foo = 1` becomes `const foo = 1`, and `foo` is registered in + `LocalExportEntries`. +- `export { foo as bar }` is removed and recorded as a local export entry. +- `export { foo as bar } from "mod"` is removed and recorded as an indirect + export entry under the requested module. +- `export * from "mod"` is removed and recorded as `StarExport`. +- `export default function foo() {}` keeps the declaration and records + `"default" -> foo`. +- `export default expr` becomes a generated `_default` binding and records + `"default" -> _default`. +- A non-exported external TypeScript `import x = require("mod")` is kept as an + ordered source item for the target lowerer. It models the CTS form of ES + `import.sync`, so it does not participate in ES module linking or mark the + source as an ES module. +- The exported form also registers `x` in `LocalExportEntries` and therefore + participates in module linking. +- Type-only imports and exports do not create runtime module entries. + +## Module Request Usage + +`ModuleRequestUsage` summarizes which runtime shape a requested module needs: + +- `NAMED` means generated code reads named properties from the module object. +- `DEFAULT` means generated code may need default interop. +- `NAMESPACE` is the combined named/default shape needed for namespace imports + and namespace re-exports. +- `STAR_EXPORT` means generated code calls the `_export_star` helper. + +When `importInterop` is `none`, namespace usage is removed before emit because +the transform must not inject interop helpers. + +## Entry Reduction + +`ModuleRecordEntryReducer` is the shared bridge from module-record-like entries +to CommonJS-like emit structures: + +- Named imports add `local -> module.importName` entries to `ImportMap`. +- Default imports add `local -> module.default`, except Node default interop can + map default-only imports directly to the module object. +- Namespace imports add `local -> module`. +- Indirect named/default exports add synthetic imported bindings to `ImportMap` + and then add export getter entries. +- Indirect namespace exports add an export getter that returns the module object. +- Star exports are emitted by the caller with `_export_star(...)`. + +Export getters are sorted by exported name before emit. A single export uses a +direct `Object.defineProperty` call, while multiple exports use the shared +`_export(exports, { ... })` helper shape. + +## CommonJS Binding Flow + +The CommonJS-like binding path can be summarized as: + +```mermaid +flowchart LR + Ast["ES module AST"] --> Collect["SourceModule::collect"] + Collect --> Strip["syntax_strip::lower"] + Strip --> Reduce["Entry reduction
ImportMap + export bindings"] + Strip --> Body["Stripped body"] + Reduce --> Emit["Emit require/export statements"] + Emit --> Assemble["Assemble statements"] + Body --> Assemble + Reduce --> Rewrite["rewrite_import_bindings"] + Assemble --> Rewrite --> Output["CommonJS module"] +``` + +## CommonJS Flow + +The CommonJS pass lives in `src/common_js.rs` and produces direct `require(...)` +calls. + +CommonJS lowers external TypeScript `import x = require("mod")` after +`syntax_strip::lower` keeps it in the executable body: + +- Non-exported `import x = require("mod")` becomes + `const x = require("mod")` or `var x = require("mod")`. +- Exported `export import x = require("mod")` becomes + `exports.x = require("mod")` and adds `x -> exports.x` to the import map. + +For each requested module, CommonJS: + +1. Creates a stable private module identifier from the request string. +2. Reduces module entries into `ImportMap` and export bindings. +3. Builds `require("mod")` through the configured path resolver. +4. Wraps the require call in `_export_star(require("mod"), exports)` for star + re-exports. +5. Applies interop helpers: + - SWC default interop uses `_interop_require_default(...)`. + - SWC namespace/default combined usage uses + `_interop_require_wildcard(...)`. + - Node namespace usage uses `_interop_require_wildcard(..., true)`. +6. Emits either a declaration for the module temporary, a lazy require wrapper, + or a side-effect-only statement. + +Before module request statements, CommonJS emits local and indirect export +getters unless the module uses `export =`. For `export = expr`, the pass appends +`module.exports = expr`. + +When `exportInteropAnnotation` is enabled, CommonJS also emits +`cjs-module-lexer`-friendly dead-code annotations such as +`0 && (exports.foo = 0)` and star re-export annotations. + +Dynamic `import()` is lowered to a `Promise.resolve(...).then(...)` shape that +calls `require(...)`. Literal dynamic import paths are resolved before emit. +`import.meta` is lowered to CommonJS equivalents such as `__filename`, +`__dirname`, `require.resolve`, or `require.main == module` unless +`preserveImportMeta` is enabled. + +## AMD Flow + +The AMD pass lives in `src/amd.rs` and emits one `define(...)` call. + +Before wrapping, AMD builds a factory body using the shared front-end flow. Each +requested module contributes: + +1. A dependency entry in `dep_list`. +2. A factory parameter identifier. +3. Import-map and export-binding entries through `ModuleRecordEntryReducer`. +4. Optional post-parameter interop assignment inside the factory body. + +External TypeScript `import x = require("mod")` also contributes a dependency +entry and factory parameter. Exported forms assign that parameter to +`exports.x`. + +The final wrapper dependency array always starts with `"require"` and a matching +`require` factory parameter. The pass adds `"exports"` only when generated code +needs the exports object, and `"module"` only when generated `import.meta` +lowering needs it. Requested modules are appended after those special AMD +dependencies. + +The call shape is: + +```javascript +define([deps...], function (params...) { + // generated body +}); +``` + +If `Config::module_id` is present, it is emitted as the first `define` argument. +If it is absent, the pass can read a TypeScript-style +`/// ` leading line comment and use that name. + +For `export = expr`, AMD appends `return expr` from the factory body instead of +using an exports object. + +Dynamic `import()` is lowered to: + +```javascript +new Promise(function (resolve, reject) { + require([arg], function (m) { + resolve(interopedModule); + }, reject); +}); +``` + +`import.meta` is lowered with AMD primitives where possible, for example +`module.uri`, `require.toUrl(...)`, and `module.id == "main"`. + +## UMD Flow + +The UMD pass lives in `src/umd.rs` and emits an adapter IIFE plus a factory. +The factory body is produced with the same collection and reduction flow as AMD. +Requested modules are stored in `dep_list` and become factory parameters. + +External TypeScript `import x = require("mod")` also becomes a factory +parameter. Exported forms assign that parameter to `exports.x`. + +The wrapper chooses among CommonJS, AMD, and global execution: + +```javascript +(function (global, factory) { + if (typeof module === "object" && typeof module.exports === "object") { + factory(exports, require("mod")); + } else if (typeof define === "function" && define.amd) { + define(["exports", "mod"], factory); + } else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) { + factory((global.lib = {}), global.mod); + } +})(this, function (exports, mod) { + // generated body +}); +``` + +When `SourceModule` records a TypeScript `export =` assignment, UMD does not +create an exports object parameter. The generated factory returns the assigned +expression, and the CommonJS branch assigns that factory result to +`module.exports`. The browser fallback assigns the same result to the inferred +global export name: + +```javascript +module.exports = factory(require("mod")); +define(["mod"], factory); +global.lib = factory(global.mod); +``` + +Some TypeScript/CommonJS syntax paths are already represented as executable +`module.exports = ...` statements in the factory body by the time the UMD wrapper +is emitted; those paths keep the normal wrapper call shape. + +UMD determines the global export name from the configured `globals` and module +name settings. It resolves dependency request strings before emitting the CJS +`require(...)`, AMD dependency string, and browser global property access. + +Unlike the CommonJS and AMD passes, the current UMD pass does not rewrite +dynamic `import()` or `import.meta` itself in this module-transform stage. + +## SystemJS Flow + +The SystemJS pass lives in `src/system_js.rs` with private implementation +modules in `src/system_js/`. Its public entry point is +`system_js(resolver, unresolved_mark, config)`, and its public `Config` type is +the shared `util::Config`. + +```mermaid +flowchart LR + Ast["Module AST"] --> Source["SourceModule::collect"] + Source --> Lower["Lower to IR"] + Lower --> Rewrite["Scoped rewrites"] + Rewrite --> Emit["Emit System.register"] +``` + +SystemJS shares only the collection stage with the CommonJS-like passes. It +lowers `RequestedModules`, `LocalExportEntries`, ordered source items, and +TypeScript `export =` assignments into a private SystemJS IR. It does not use +`syntax_strip::lower`, `ModuleRecordEntryReducer`, `ImportMap`, export getter +emission, or helper injection. + +`src/system_js.rs` owns the public pass, directive handling, strict mode, +top-level `this` rewrite, and top-level-await detection. The private +`src/system_js/` modules then own the format-specific stages: + +- `lower.rs` builds `SystemModule`: dependency slots, wrapper-scope bindings, + export announcements, and execute-time statements. +- `rewrite.rs` is the scoped visitor boundary for `import.meta`, dynamic + `import()`, `__moduleName`, and live-binding updates. +- `emit.rs` is the only layer that creates the final `System.register(...)` + call. + +Lowering keeps SystemJS timing explicit. ECMAScript module requests are merged +by `ModuleRequestRecord` in first-observed order, and each dependency slot owns +the setter operations needed for imports and re-exports. Dependency requests +from external TypeScript `import = require(...)` stay outside `RequestedModules` +and lower to independent dependency slots. Top-level function declarations stay +in wrapper scope, while variable and class initializers run from `execute`. +Import attributes stay attached to dependency slots and become the optional +metadata argument to `System.register`. + +Local exports are announced before the returned `{ setters, execute }` object: +function exports, including anonymous default functions, use their function +values, and other exports start as `void 0`. Later writes to exported locals +call `_export`; exported destructuring and loop heads use setter patterns so +local bindings and exported values stay in sync. + +After ordered source items are lowered, TypeScript `export = expr` is appended +to `execute` as a batch export update: + +```javascript +_export(expr); +``` + +## Helper Injection + +`src/import_analysis.rs` runs before module lowering to enable only the helpers +required by the module syntax in the source: + +- `_export_star` is enabled when any module request has `STAR_EXPORT`. +- `_interop_require_default` is enabled for SWC default-only interop. +- `_interop_require_wildcard` is enabled for namespace usage and, when dynamic + import is not ignored, for possible dynamic-import interop. + +The emitters assume these helpers are available when they generate the +corresponding helper calls. + +## Important Boundaries + +- `module_record.rs` owns target-neutral source module collection and the + CommonJS-like `ModuleRecordEntryReducer`. +- `syntax_strip.rs` owns the CommonJS-like module syntax stripping step. +- `common_js.rs`, `amd.rs`, and `umd.rs` own target lowering, dependency + construction, interop application, and special runtime rewrites for their + format. +- `amd/emit.rs` and `umd/emit.rs` own wrapper construction for those formats. +- `system_js.rs` owns the SystemJS facade, while `src/system_js/` owns its + private IR, lowering, rewrite traversal, and `System.register` emission. +- `module_ref_rewriter.rs` owns replacing imported local binding references with + the generated property access. +- `util.rs` owns shared helper-building code such as `define_es_module`, + `_export(...)` emission, export sorting, and property-name construction. + +Keeping these boundaries intact makes it easier to adjust interop behavior or +add module-record fields without coupling the collector to a specific output +format. diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/amd.rs b/deps/swc/crates/swc_ecma_transforms_module/src/amd.rs index 6cf649482..2f7036d66 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/amd.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/amd.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; -use anyhow::Context; use regex::Regex; +use rustc_hash::FxHashSet; use serde::{Deserialize, Serialize}; use swc_atoms::{atom, Atom}; use swc_common::{ @@ -12,24 +12,29 @@ use swc_common::{ }; use swc_ecma_ast::*; use swc_ecma_transforms_base::helper_expr; -use swc_ecma_utils::{ - member_expr, private_ident, quote_ident, quote_str, ExprFactory, FunctionFactory, IsDirective, -}; +use swc_ecma_utils::{member_expr, private_ident, quote_ident, quote_str, ExprFactory}; use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith}; pub use super::util::Config as InnerConfig; use crate::{ - module_decl_strip::{Export, Link, LinkFlag, LinkItem, LinkSpecifierReducer, ModuleDeclStrip}, + module_record::{ + exported_external_ts_import_equals_name, external_ts_import_equals_source, + LocalExportEntries, ModuleRecordEntryReducer, ModuleRequestUsage, RequestedModule, + RequestedModules, SourceModule, + }, module_ref_rewriter::{rewrite_import_bindings, ImportMap}, path::Resolver, + syntax_strip::{self, SyntaxStrippedModule}, top_level_this::top_level_this, util::{ - define_es_module, emit_export_stmts, local_name_for_src, sort_export_obj_prop_list, - use_strict, ImportInterop, VecStmtLike, + define_es_module, emit_export_stmts, local_name_for_src, sort_export_bindings, use_strict, + ImportInterop, }, SpanCtx, }; +mod emit; + #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct Config { @@ -113,54 +118,55 @@ where self.module_id = self.get_amd_module_id_from_comments(n.span); } - let mut stmts: Vec = Vec::with_capacity(n.body.len() + 4); + if !self.config.allow_top_level_this { + top_level_this(&mut n.body, *Expr::undefined(DUMMY_SP)); + } - // Collect directives - stmts.extend( - &mut n - .body - .iter_mut() - .take_while(|i| i.directive_continue()) - .map(|i| i.take()) - .map(ModuleItem::expect_stmt), - ); + let SyntaxStrippedModule { + directives, + has_use_strict, + requested_modules, + local_export_entries, + export_assign, + body, + has_module_syntax, + } = syntax_strip::lower(SourceModule::collect(n.body.take()), self.const_var_kind); + + let mut stmts: Vec = Vec::with_capacity(body.len() + 4); + stmts.extend(directives); // "use strict"; - if self.config.strict_mode && !stmts.has_use_strict() { + if self.config.strict_mode && !has_use_strict { stmts.push(use_strict()); } - if !self.config.allow_top_level_this { - top_level_this(&mut n.body, *Expr::undefined(DUMMY_SP)); - } - let import_interop = self.config.import_interop(); - let mut strip = ModuleDeclStrip::new(self.const_var_kind); - n.body.visit_mut_with(&mut strip); - - let ModuleDeclStrip { - link, - export, - export_assign, - has_module_decl, - .. - } = strip; - let is_export_assign = export_assign.is_some(); - if has_module_decl && !import_interop.is_none() && !is_export_assign { - stmts.push(define_es_module(self.exports())) + if has_module_syntax && !import_interop.is_none() && !is_export_assign { + stmts.push(define_es_module(self.exports())); } let mut import_map = Default::default(); + let ts_import_equals_exports: FxHashSet = body + .iter() + .filter_map(exported_external_ts_import_equals_name) + .cloned() + .collect(); + + stmts.extend(self.handle_import_export( + &mut import_map, + requested_modules, + local_export_entries, + &ts_import_equals_exports, + is_export_assign, + )); - stmts.extend(self.handle_import_export(&mut import_map, link, export, is_export_assign)); - - stmts.extend(n.body.take().into_iter().filter_map(|item| match item { - ModuleItem::Stmt(stmt) if !stmt.is_empty() => Some(stmt), - _ => None, - })); + stmts.extend( + body.into_iter() + .filter_map(|item| self.lower_body_item(&mut import_map, item)), + ); if let Some(export_assign) = export_assign { let return_stmt = ReturnStmt { @@ -168,7 +174,7 @@ where arg: Some(export_assign), }; - stmts.push(return_stmt.into()) + stmts.push(return_stmt.into()); } if !self.config.ignore_dynamic || !self.config.preserve_import_meta { @@ -177,75 +183,18 @@ where rewrite_import_bindings(&mut stmts, import_map, Default::default()); - // ==================== - // Emit - // ==================== - - let mut elems = vec![Some(quote_str!("require").as_arg())]; - let mut params = vec![self.require.clone().into()]; - - if let Some(exports) = self.exports.take() { - elems.push(Some(quote_str!("exports").as_arg())); - params.push(exports.into()) - } - - if let Some(module) = self.module.clone() { - elems.push(Some(quote_str!("module").as_arg())); - params.push(module.into()) - } - - self.dep_list - .take() - .into_iter() - .for_each(|(ident, src_path, src_span)| { - let src_path = match &self.resolver { - Resolver::Real { resolver, base } => resolver - .resolve_import(base, &src_path) - .with_context(|| format!("failed to resolve `{src_path}`")) - .unwrap(), - Resolver::Default => src_path, - }; - - elems.push(Some(quote_str!(src_span.0, src_path).as_arg())); - params.push(ident.into()); - }); - - let mut amd_call_args = Vec::with_capacity(3); - if let Some(module_id) = self.module_id.clone() { - amd_call_args.push(quote_str!(module_id).as_arg()); - } - amd_call_args.push( - ArrayLit { - span: DUMMY_SP, - elems, - } - .as_arg(), - ); - - amd_call_args.push( - Function { - params, - decorators: Default::default(), - span: DUMMY_SP, - body: Some(BlockStmt { - stmts, - ..Default::default() - }), - is_generator: false, - is_async: false, - ..Default::default() - } - .into_fn_expr(None) - .as_arg(), + n.body = emit::emit( + stmts, + emit::EmitModule { + module_id: self.module_id.clone(), + require: self.require.clone(), + exports: self.exports.take(), + module: self.module.clone(), + deps: self.dep_list.take(), + }, + self.unresolved_mark, + &self.resolver, ); - - n.body = vec![quote_ident!( - SyntaxContext::empty().apply_mark(self.unresolved_mark), - "define" - ) - .as_call(DUMMY_SP, amd_call_args) - .into_stmt() - .into()]; } fn visit_mut_script(&mut self, _: &mut Script) { @@ -281,6 +230,9 @@ where let mut require = self.require.clone(); require.span = *import_span; + // `import()` is specified as an ImportCall. AMD lowers it to a + // promise around async `require([arg], ...)`. + // Spec: https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-import-calls *n = amd_dynamic_import( *span, args.take(), @@ -293,9 +245,13 @@ where if !self.config.preserve_import_meta && obj .as_meta_prop() - .map(|p| p.kind == MetaPropKind::ImportMeta) - .unwrap_or_default() => + .is_some_and(|p| p.kind == MetaPropKind::ImportMeta) => { + // `import.meta` is host-populated in the spec. AMD lowers + // supported host fields to loader-specific values. + // Spec: + // - https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-hostgetimportmetaproperties + // - https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-hostfinalizeimportmeta let p = match prop { MemberProp::Ident(IdentName { sym, .. }) => Cow::Borrowed(&**sym), MemberProp::Computed(ComputedPropName { expr, .. }) => match &**expr { @@ -386,7 +342,7 @@ where n.visit_mut_with(self); return; } - }; + } n.visit_mut_children_with(self); } @@ -402,42 +358,45 @@ where fn handle_import_export( &mut self, import_map: &mut ImportMap, - link: Link, - export: Export, + requested_modules: RequestedModules, + local_export_entries: LocalExportEntries, + ts_import_equals_exports: &FxHashSet, is_export_assign: bool, ) -> impl Iterator { let import_interop = self.config.import_interop(); - let mut stmts = Vec::with_capacity(link.len()); + let mut stmts = Vec::with_capacity(requested_modules.len()); - let mut export_obj_prop_list = export.into_iter().collect(); + let mut export_bindings = local_export_entries.into_iter().collect(); - link.into_iter().for_each( - |(src, LinkItem(src_span, link_specifier_set, mut link_flag))| { - let is_node_default = !link_flag.has_named() && import_interop.is_node(); + requested_modules.into_iter().for_each( + |( + module_request, + RequestedModule { + span: src_span, + entries: module_entries, + usage: mut module_usage, + .. + }, + )| { + let src = module_request.src().clone(); + let is_node_default = !module_usage.has_named() && import_interop.is_node(); if import_interop.is_none() { - link_flag -= LinkFlag::NAMESPACE; + module_usage -= ModuleRequestUsage::NAMESPACE; } - let need_re_export = link_flag.export_star(); - let need_interop = link_flag.interop(); - let need_new_var = link_flag.need_raw_import(); + let need_re_export = module_usage.has_star_export(); + let need_interop = module_usage.needs_interop(); let mod_ident = private_ident!(local_name_for_src(&src)); - let new_var_ident = if need_new_var { - private_ident!(local_name_for_src(&src)) - } else { - mod_ident.clone() - }; self.dep_list.push((mod_ident.clone(), src, src_span)); - link_specifier_set.reduce( + module_entries.reduce( import_map, - &mut export_obj_prop_list, - &new_var_ident, - &Some(mod_ident.clone()), + &mut export_bindings, + &mod_ident, &mut false, is_node_default, ); @@ -455,52 +414,107 @@ where // _introp(mod); if need_interop { import_expr = match import_interop { - ImportInterop::Swc if link_flag.interop() => if link_flag.namespace() { - helper_expr!(interop_require_wildcard) - } else { - helper_expr!(interop_require_default) + ImportInterop::Swc if module_usage.needs_interop() => { + if module_usage.needs_namespace_object() { + helper_expr!(interop_require_wildcard) + } else { + helper_expr!(interop_require_default) + } + .as_call(PURE_SP, vec![import_expr.as_arg()]) } - .as_call(PURE_SP, vec![import_expr.as_arg()]), - ImportInterop::Node if link_flag.namespace() => { + ImportInterop::Node if module_usage.needs_namespace_object() => { helper_expr!(interop_require_wildcard) .as_call(PURE_SP, vec![import_expr.as_arg(), true.as_arg()]) } _ => import_expr, } - }; + } // mod = _introp(mod); - // var mod1 = _introp(mod); - if need_new_var { - let stmt: Stmt = import_expr - .into_var_decl(self.const_var_kind, new_var_ident.into()) - .into(); - - stmts.push(stmt) - } else if need_interop { + if need_interop { let stmt = import_expr .make_assign_to(op!("="), mod_ident.into()) .into_stmt(); stmts.push(stmt); } else if need_re_export { stmts.push(import_expr.into_stmt()); - }; + } }, ); let mut export_stmts = Default::default(); - if !export_obj_prop_list.is_empty() && !is_export_assign { - sort_export_obj_prop_list(&mut export_obj_prop_list); + export_bindings.retain(|(export_name, _)| !ts_import_equals_exports.contains(export_name)); + + if !export_bindings.is_empty() && !is_export_assign { + sort_export_bindings(&mut export_bindings); let exports = self.exports(); - export_stmts = emit_export_stmts(exports, export_obj_prop_list); + export_stmts = emit_export_stmts(exports, export_bindings); } export_stmts.into_iter().chain(stmts) } + fn lower_body_item(&mut self, import_map: &mut ImportMap, item: ModuleItem) -> Option { + match item { + ModuleItem::Stmt(stmt) if !stmt.is_empty() => Some(stmt), + ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(import)) => { + self.lower_ts_import_equals(import_map, *import) + } + _ => None, + } + } + + fn lower_ts_import_equals( + &mut self, + import_map: &mut ImportMap, + import: TsImportEqualsDecl, + ) -> Option { + let src = external_ts_import_equals_source(&import)?; + let src_span = src.span; + let request = src.value.to_atom_lossy().into_owned(); + let TsImportEqualsDecl { + id: local, + is_export, + .. + } = import; + let param = if is_export { + local.clone().into_private() + } else { + local.clone() + }; + + self.dep_list + .push((param.clone(), request, (src_span, Default::default()))); + + if !is_export { + return None; + } + + Some(self.emit_ts_import_equals(import_map, local, is_export, param.into())) + } + + fn emit_ts_import_equals( + &mut self, + import_map: &mut ImportMap, + local: Ident, + is_export: bool, + value: Expr, + ) -> Stmt { + if is_export { + import_map.insert(local.to_id(), (self.exports(), Some(local.sym.clone()))); + return value + .make_assign_to(op!("="), self.exports().make_member(local.into()).into()) + .into_stmt(); + } + + value + .into_var_decl(self.const_var_kind, local.into()) + .into() + } + fn module(&mut self) -> Ident { self.module .get_or_insert_with(|| private_ident!("module")) diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/amd/emit.rs b/deps/swc/crates/swc_ecma_transforms_module/src/amd/emit.rs new file mode 100644 index 000000000..62fb1ae24 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/amd/emit.rs @@ -0,0 +1,87 @@ +use anyhow::Context; +use swc_atoms::Atom; +use swc_common::{Mark, SyntaxContext, DUMMY_SP}; +use swc_ecma_ast::*; +use swc_ecma_utils::{quote_ident, quote_str, ExprFactory, FunctionFactory}; + +use crate::{path::Resolver, SpanCtx}; + +pub(super) struct EmitModule { + pub module_id: Option, + pub require: Ident, + pub exports: Option, + pub module: Option, + pub deps: Vec<(Ident, Atom, SpanCtx)>, +} + +pub(super) fn emit( + stmts: Vec, + mut module: EmitModule, + unresolved_mark: Mark, + resolver: &Resolver, +) -> Vec { + let mut elems = vec![Some(quote_str!("require").as_arg())]; + let mut params = vec![module.require.into()]; + + if let Some(exports) = module.exports { + elems.push(Some(quote_str!("exports").as_arg())); + params.push(exports.into()); + } + + if let Some(module) = module.module { + elems.push(Some(quote_str!("module").as_arg())); + params.push(module.into()); + } + + module + .deps + .into_iter() + .for_each(|(ident, src_path, src_span)| { + let src_path = match resolver { + Resolver::Real { resolver, base } => resolver + .resolve_import(base, &src_path) + .with_context(|| format!("failed to resolve `{src_path}`")) + .unwrap(), + Resolver::Default => src_path, + }; + + elems.push(Some(quote_str!(src_span.0, src_path).as_arg())); + params.push(ident.into()); + }); + + let mut amd_call_args = Vec::with_capacity(3); + if let Some(module_id) = module.module_id.take() { + amd_call_args.push(quote_str!(module_id).as_arg()); + } + amd_call_args.push( + ArrayLit { + span: DUMMY_SP, + elems, + } + .as_arg(), + ); + + amd_call_args.push( + Function { + params, + decorators: Default::default(), + span: DUMMY_SP, + body: Some(FunctionBody { + span: DUMMY_SP, + stmts, + }), + is_generator: false, + is_async: false, + ..Default::default() + } + .into_fn_expr(None) + .as_arg(), + ); + + vec![ + quote_ident!(SyntaxContext::empty().apply_mark(unresolved_mark), "define") + .as_call(DUMMY_SP, amd_call_args) + .into_stmt() + .into(), + ] +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/common_js.rs b/deps/swc/crates/swc_ecma_transforms_module/src/common_js.rs index d6e8c4843..b017f04c8 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/common_js.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/common_js.rs @@ -1,27 +1,31 @@ use std::borrow::Cow; use rustc_hash::FxHashSet; +use swc_atoms::Atom; use swc_common::{ source_map::PURE_SP, util::take::Take, Mark, Span, Spanned, SyntaxContext, DUMMY_SP, }; use swc_ecma_ast::*; use swc_ecma_transforms_base::helper_expr; use swc_ecma_utils::{ - member_expr, private_ident, quote_expr, quote_ident, ExprFactory, FunctionFactory, IsDirective, + member_expr, private_ident, quote_expr, quote_ident, ExprFactory, FunctionFactory, }; use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith}; pub use super::util::Config; use crate::{ - module_decl_strip::{ - Export, ExportKV, Link, LinkFlag, LinkItem, LinkSpecifierReducer, ModuleDeclStrip, + module_record::{ + exported_external_ts_import_equals_name, external_ts_import_equals_source, ExportBinding, + LocalExportEntries, ModuleRecordEntryReducer, ModuleRequestUsage, RequestedModule, + RequestedModules, SourceModule, }, module_ref_rewriter::{rewrite_import_bindings, ImportMap}, path::Resolver, + syntax_strip::{self, SyntaxStrippedModule}, top_level_this::top_level_this, util::{ - define_es_module, emit_export_stmts, local_name_for_src, prop_name, - sort_export_obj_prop_list, use_strict, ImportInterop, VecStmtLike, + define_es_module, emit_export_stmts, local_name_for_src, prop_name, sort_export_bindings, + use_strict, ImportInterop, }, }; @@ -31,6 +35,7 @@ pub struct FeatureFlag { pub support_arrow: bool, } +#[must_use] pub fn common_js( resolver: Resolver, unresolved_mark: Mark, @@ -62,22 +67,6 @@ impl VisitMut for Cjs { noop_visit_mut_type!(fail); fn visit_mut_module(&mut self, n: &mut Module) { - let mut stmts: Vec = Vec::with_capacity(n.body.len() + 6); - - // Collect directives - stmts.extend( - &mut n - .body - .iter_mut() - .take_while(|i| i.directive_continue()) - .map(|i| i.take()), - ); - - // "use strict"; - if self.config.strict_mode && !stmts.has_use_strict() { - stmts.push(use_strict().into()); - } - if !self.config.allow_top_level_this { top_level_this(&mut n.body, *Expr::undefined(DUMMY_SP)); } @@ -86,39 +75,36 @@ impl VisitMut for Cjs { let mut module_map = Default::default(); - let mut has_ts_import_equals = false; - - // handle `import foo = require("mod")` - n.body.iter_mut().for_each(|item| { - if let ModuleItem::ModuleDecl(module_decl) = item { - *item = self.handle_ts_import_equals( - module_decl.take(), - &mut module_map, - &mut has_ts_import_equals, - ); - } - }); - - let mut strip = ModuleDeclStrip::new(self.const_var_kind); - n.body.visit_mut_with(&mut strip); - - let ModuleDeclStrip { - link, - export, + let SyntaxStrippedModule { + directives, + has_use_strict, + requested_modules, + local_export_entries, export_assign, - has_module_decl, - .. - } = strip; + body, + has_module_syntax, + } = syntax_strip::lower(SourceModule::collect(n.body.take()), self.const_var_kind); + + let mut stmts: Vec = Vec::with_capacity(body.len() + 6); + stmts.extend(directives.into_iter().map(ModuleItem::from)); - let has_module_decl = has_module_decl || has_ts_import_equals; + // "use strict"; + if self.config.strict_mode && !has_use_strict { + stmts.push(use_strict().into()); + } let is_export_assign = export_assign.is_some(); - if has_module_decl && !import_interop.is_none() && !is_export_assign { - stmts.push(define_es_module(self.exports()).into()) + if has_module_syntax && !import_interop.is_none() && !is_export_assign { + stmts.push(define_es_module(self.exports()).into()); } let mut lazy_record = Default::default(); + let ts_import_equals_exports: FxHashSet = body + .iter() + .filter_map(exported_external_ts_import_equals_name) + .cloned() + .collect(); // `import` -> `require` // `export` -> `_export(exports, {});` @@ -126,17 +112,18 @@ impl VisitMut for Cjs { self.handle_import_export( &mut module_map, &mut lazy_record, - link, - export, + requested_modules, + local_export_entries, + &ts_import_equals_exports, is_export_assign, ) .map(From::from), ); - stmts.extend(n.body.take().into_iter().filter(|item| match item { - ModuleItem::Stmt(stmt) => !stmt.is_empty(), - _ => false, - })); + stmts.extend( + body.into_iter() + .filter_map(|item| self.lower_body_item(&mut module_map, item)), + ); // `export = expr;` -> `module.exports = expr;` if let Some(export_assign) = export_assign { @@ -153,7 +140,7 @@ impl VisitMut for Cjs { ) .into_stmt() .into(), - ) + ); } if !self.config.ignore_dynamic || !self.config.preserve_import_meta { @@ -201,6 +188,9 @@ impl VisitMut for Cjs { let unresolved_ctxt = SyntaxContext::empty().apply_mark(self.unresolved_mark); + // `import()` is specified as an ImportCall. CommonJS lowers it + // to a promise chain that evaluates `require(...)`. + // Spec: https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-import-calls *n = cjs_dynamic_import( *span, args.take(), @@ -214,9 +204,13 @@ impl VisitMut for Cjs { if !self.config.preserve_import_meta && obj .as_meta_prop() - .map(|p| p.kind == MetaPropKind::ImportMeta) - .unwrap_or_default() => + .is_some_and(|p| p.kind == MetaPropKind::ImportMeta) => { + // `import.meta` is host-populated in the spec. CommonJS + // lowers supported host fields to Node-like runtime values. + // Spec: + // - https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-hostgetimportmetaproperties + // - https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-hostfinalizeimportmeta let p = match prop { MemberProp::Ident(IdentName { sym, .. }) => Cow::Borrowed(&**sym), MemberProp::Computed(ComputedPropName { expr, .. }) => match &**expr { @@ -289,7 +283,7 @@ impl VisitMut for Cjs { n.visit_mut_with(self); return; } - }; + } n.visit_mut_children_with(self); } @@ -303,47 +297,57 @@ impl Cjs { &mut self, import_map: &mut ImportMap, lazy_record: &mut FxHashSet, - link: Link, - export: Export, + requested_modules: RequestedModules, + local_export_entries: LocalExportEntries, + ts_import_equals_exports: &FxHashSet, is_export_assign: bool, ) -> impl Iterator { let import_interop = self.config.import_interop(); let export_interop_annotation = self.config.export_interop_annotation(); let is_node = import_interop.is_node(); - let mut stmts = Vec::with_capacity(link.len()); + let mut stmts = Vec::with_capacity(requested_modules.len()); - let mut export_obj_prop_list = export.into_iter().collect(); + let mut export_bindings: Vec = local_export_entries.into_iter().collect(); let lexer_reexport = if export_interop_annotation { - self.emit_lexer_reexport(&link) + self.emit_lexer_reexport(&requested_modules) } else { None }; - link.into_iter().for_each( - |(src, LinkItem(src_span, link_specifier_set, mut link_flag))| { - let is_node_default = !link_flag.has_named() && is_node; + requested_modules.into_iter().for_each( + |( + module_request, + RequestedModule { + span: src_span, + entries: module_entries, + usage: mut module_usage, + .. + }, + )| { + let src = module_request.src().clone(); if import_interop.is_none() { - link_flag -= LinkFlag::NAMESPACE; + module_usage -= ModuleRequestUsage::NAMESPACE; } + let is_node_default = !module_usage.has_named() && is_node; let mod_ident = private_ident!(local_name_for_src(&src)); let mut decl_mod_ident = false; - link_specifier_set.reduce( + module_entries.reduce( import_map, - &mut export_obj_prop_list, + &mut export_bindings, &mod_ident, - &None, &mut decl_mod_ident, is_node_default, ); - let is_lazy = - decl_mod_ident && !link_flag.export_star() && self.config.lazy.is_lazy(&src); + let is_lazy = decl_mod_ident + && !module_usage.has_star_export() + && self.config.lazy.is_lazy(&src); if is_lazy { lazy_record.insert(mod_ident.to_id()); @@ -352,10 +356,10 @@ impl Cjs { // require("mod"); let import_expr = self.resolver - .make_require_call(self.unresolved_mark, src, src_span.0); + .make_require_call(self.unresolved_mark, src.clone(), src_span.0); // _export_star(require("mod"), exports); - let import_expr = if link_flag.export_star() { + let import_expr = if module_usage.has_star_export() { helper_expr!(export_star).as_call( DUMMY_SP, vec![import_expr.as_arg(), self.exports().as_arg()], @@ -367,13 +371,15 @@ impl Cjs { // _introp(require("mod")); let import_expr = { match import_interop { - ImportInterop::Swc if link_flag.interop() => if link_flag.namespace() { - helper_expr!(interop_require_wildcard) - } else { - helper_expr!(interop_require_default) + ImportInterop::Swc if module_usage.needs_interop() => { + if module_usage.needs_namespace_object() { + helper_expr!(interop_require_wildcard) + } else { + helper_expr!(interop_require_default) + } + .as_call(PURE_SP, vec![import_expr.as_arg()]) } - .as_call(PURE_SP, vec![import_expr.as_arg()]), - ImportInterop::Node if link_flag.namespace() => { + ImportInterop::Node if module_usage.needs_namespace_object() => { helper_expr!(interop_require_wildcard) .as_call(PURE_SP, vec![import_expr.as_arg(), true.as_arg()]) } @@ -399,16 +405,18 @@ impl Cjs { let mut export_stmts: Vec = Default::default(); - if !export_obj_prop_list.is_empty() && !is_export_assign { - sort_export_obj_prop_list(&mut export_obj_prop_list); + export_bindings.retain(|(export_name, _)| !ts_import_equals_exports.contains(export_name)); + + if !export_bindings.is_empty() && !is_export_assign { + sort_export_bindings(&mut export_bindings); let exports = self.exports(); - if export_interop_annotation && export_obj_prop_list.len() > 1 { - export_stmts.extend(self.emit_lexer_exports_init(&export_obj_prop_list)); + if export_interop_annotation && export_bindings.len() > 1 { + export_stmts.extend(self.emit_lexer_exports_init(&export_bindings)); } - export_stmts.extend(emit_export_stmts(exports, export_obj_prop_list)); + export_stmts.extend(emit_export_stmts(exports, export_bindings)); } export_stmts.extend(lexer_reexport); @@ -416,67 +424,48 @@ impl Cjs { export_stmts.into_iter().chain(stmts) } - fn handle_ts_import_equals( - &self, - module_decl: ModuleDecl, - module_map: &mut ImportMap, - has_ts_import_equals: &mut bool, - ) -> ModuleItem { - match module_decl { - ModuleDecl::TsImportEquals(v) - if matches!( - &*v, - TsImportEqualsDecl { - is_type_only: false, - module_ref: TsModuleRef::TsExternalModuleRef(TsExternalModuleRef { .. }), - .. - } - ) => - { - let TsImportEqualsDecl { - span, - is_export, - id, - module_ref, - .. - } = *v; - let Str { - span: src_span, - value: src, - .. - } = module_ref.expect_ts_external_module_ref().expr; - - *has_ts_import_equals = true; - - let require = self.resolver.make_require_call( - self.unresolved_mark, - src.to_atom_lossy().into_owned(), - src_span, - ); - - if is_export { - // exports.foo = require("mod") - module_map.insert(id.to_id(), (self.exports(), Some(id.sym.clone()))); + fn lower_body_item(&self, import_map: &mut ImportMap, item: ModuleItem) -> Option { + match item { + ModuleItem::Stmt(stmt) if !stmt.is_empty() => Some(stmt.into()), + ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(import)) => self + .lower_ts_import_equals(import_map, *import) + .map(From::from), + _ => None, + } + } - let assign_expr = AssignExpr { - span, - op: op!("="), - left: self.exports().make_member(id.into()).into(), - right: Box::new(require), - }; + fn lower_ts_import_equals( + &self, + import_map: &mut ImportMap, + import: TsImportEqualsDecl, + ) -> Option { + let src = external_ts_import_equals_source(&import)?; + let value = self.resolver.make_require_call( + self.unresolved_mark, + src.value.to_atom_lossy().into_owned(), + src.span, + ); - assign_expr.into_stmt() - } else { - // const foo = require("mod") - let mut var_decl = require.into_var_decl(self.const_var_kind, id.into()); - var_decl.span = span; + Some(self.emit_ts_import_equals(import_map, import.id, import.is_export, value)) + } - var_decl.into() - } - .into() - } - _ => module_decl.into(), + fn emit_ts_import_equals( + &self, + import_map: &mut ImportMap, + local: Ident, + is_export: bool, + value: Expr, + ) -> Stmt { + if is_export { + import_map.insert(local.to_id(), (self.exports(), Some(local.sym.clone()))); + return value + .make_assign_to(op!("="), self.exports().make_member(local.into()).into()) + .into_stmt(); } + + value + .into_var_decl(self.const_var_kind, local.into()) + .into() } fn exports(&self) -> Ident { @@ -491,7 +480,7 @@ impl Cjs { /// 0 && (exports.foo = 0); /// 0 && (module.exports = { foo: _, bar: _ }); /// ``` - fn emit_lexer_exports_init(&mut self, export_id_list: &[ExportKV]) -> Option { + fn emit_lexer_exports_init(&mut self, export_id_list: &[ExportBinding]) -> Option { match export_id_list.len() { 0 => None, 1 => { @@ -559,13 +548,16 @@ impl Cjs { /// ```javascript /// 0 && __export(require("foo")) && __export(require("bar")); /// ``` - fn emit_lexer_reexport(&self, link: &Link) -> Option { - link.iter() - .filter(|(.., LinkItem(.., link_flag))| link_flag.export_star()) - .map(|(src, ..)| { - let import_expr = - self.resolver - .make_require_call(self.unresolved_mark, src.clone(), DUMMY_SP); + fn emit_lexer_reexport(&self, requested_modules: &RequestedModules) -> Option { + requested_modules + .iter() + .filter(|(.., RequestedModule { usage, .. })| usage.has_star_export()) + .map(|(module_request, ..)| { + let import_expr = self.resolver.make_require_call( + self.unresolved_mark, + module_request.src().clone(), + DUMMY_SP, + ); quote_ident!("__export").as_call(DUMMY_SP, vec![import_expr.as_arg()]) }) @@ -637,7 +629,7 @@ pub(crate) fn cjs_dynamic_import( ) } -/// require('url').pathToFileURL(__filename).toString() +/// require('url').pathToFileURL(__`filename).toString()` fn cjs_import_meta_url(span: Span, require: Ident, unresolved_mark: Mark) -> Expr { require .as_call(DUMMY_SP, vec!["url".as_arg()]) @@ -663,6 +655,7 @@ fn cjs_import_meta_url(span: Span, require: Ident, unresolved_mark: Mark) -> Exp /// return data; /// } /// ``` +#[must_use] pub fn lazy_require(expr: Expr, mod_ident: Ident, var_kind: VarDeclKind) -> FnDecl { let data = private_ident!("data"); let data_decl = expr.into_var_decl(var_kind, data.clone().into()); @@ -682,10 +675,9 @@ pub fn lazy_require(expr: Expr, mod_ident: Ident, var_kind: VarDeclKind) -> FnDe params: Default::default(), decorators: Default::default(), span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![data_stmt, overwrite_stmt, return_stmt], - ..Default::default() }), is_generator: false, is_async: false, diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/import_analysis.rs b/deps/swc/crates/swc_ecma_transforms_module/src/import_analysis.rs index 994beeaa9..1cbaaa678 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/import_analysis.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/import_analysis.rs @@ -6,8 +6,9 @@ use swc_ecma_visit::{ noop_visit_mut_type, noop_visit_type, visit_mut_pass, Visit, VisitMut, VisitWith, }; -use crate::{module_decl_strip::LinkFlag, util::ImportInterop, wtf8::str_to_atom}; +use crate::{module_record::ModuleRequestUsage, util::ImportInterop, wtf8::str_to_atom}; +#[must_use] pub fn import_analyzer(import_interop: ImportInterop, ignore_dynamic: bool) -> impl Pass { visit_mut_pass(ImportAnalyzer { import_interop, @@ -21,7 +22,7 @@ pub struct ImportAnalyzer { import_interop: ImportInterop, ignore_dynamic: bool, - flag_record: FxHashMap, + flag_record: FxHashMap, dynamic_import_found: bool, } @@ -38,7 +39,7 @@ impl Visit for ImportAnalyzer { noop_visit_type!(fail); fn visit_module_items(&mut self, n: &[ModuleItem]) { - for item in n.iter() { + for item in n { if item.is_module_decl() { item.visit_with(self); } @@ -46,7 +47,10 @@ impl Visit for ImportAnalyzer { let flag_record = &self.flag_record; - if flag_record.values().any(|flag| flag.export_star()) { + if flag_record + .values() + .any(super::module_record::ModuleRequestUsage::has_star_export) + { enable_helper!(export_star); } @@ -57,17 +61,20 @@ impl Visit for ImportAnalyzer { if self.import_interop.is_swc() && flag_record .values() - .any(|flag| flag.interop() && !flag.has_named()) + .any(|flag| flag.needs_interop() && !flag.has_named()) { enable_helper!(interop_require_default); } - if flag_record.values().any(|flag| flag.namespace()) { + if flag_record + .values() + .any(super::module_record::ModuleRequestUsage::needs_namespace_object) + { enable_helper!(interop_require_wildcard); } else if !self.ignore_dynamic { // `import/export * as foo from "foo"` not found // but it may be used with dynamic import - for item in n.iter() { + for item in n { if item.is_stmt() { item.visit_with(self); } @@ -99,7 +106,7 @@ impl Visit for ImportAnalyzer { fn visit_export_all(&mut self, n: &ExportAll) { let src = str_to_atom(&n.src); - *self.flag_record.entry(src).or_default() |= LinkFlag::EXPORT_STAR; + *self.flag_record.entry(src).or_default() |= ModuleRequestUsage::STAR_EXPORT; } fn visit_import(&mut self, _: &Import) { diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/lib.rs b/deps/swc/crates/swc_ecma_transforms_module/src/lib.rs index 045f8f4c7..2531554ed 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/lib.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/lib.rs @@ -14,10 +14,11 @@ pub mod util; pub mod amd; pub mod common_js; pub mod import_analysis; -pub(crate) mod module_decl_strip; +pub(crate) mod module_record; pub(crate) mod module_ref_rewriter; pub mod path; pub mod rewriter; +pub(crate) mod syntax_strip; pub mod system_js; mod top_level_this; pub mod umd; diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/module_decl_strip.rs b/deps/swc/crates/swc_ecma_transforms_module/src/module_decl_strip.rs deleted file mode 100644 index 10552d646..000000000 --- a/deps/swc/crates/swc_ecma_transforms_module/src/module_decl_strip.rs +++ /dev/null @@ -1,812 +0,0 @@ -use indexmap::IndexMap; -use rustc_hash::{FxHashMap, FxHashSet}; -use swc_atoms::{atom, Atom}; -use swc_common::{util::take::Take, Mark, Span, SyntaxContext}; -use swc_ecma_ast::*; -use swc_ecma_utils::{find_pat_ids, private_ident, quote_ident, ExprFactory}; -use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith}; - -use crate::{module_ref_rewriter::ImportMap, SpanCtx}; - -/// key: module path -pub type Link = IndexMap; -/// key: export binding name -pub type Export = FxHashMap; - -#[derive(Debug)] -pub struct ModuleDeclStrip { - /// all imports/exports collected by path in source text order - pub link: Link, - - /// local exported binding - /// - /// `export { foo as "1", bar }` - /// -> Map("1" => foo, bar => bar) - pub export: Export, - - /// `export = ` detected - pub export_assign: Option>, - - pub has_module_decl: bool, - - /// `export default expr` - export_default: Option, - - const_var_kind: VarDeclKind, -} - -impl ModuleDeclStrip { - pub fn new(const_var_kind: VarDeclKind) -> Self { - Self { - link: Default::default(), - export: Default::default(), - export_assign: Default::default(), - has_module_decl: Default::default(), - export_default: Default::default(), - const_var_kind, - } - } -} - -impl VisitMut for ModuleDeclStrip { - noop_visit_mut_type!(fail); - - fn visit_mut_module_items(&mut self, n: &mut Vec) { - let mut list = Vec::with_capacity(n.len()); - - for item in n.drain(..) { - match item { - ModuleItem::Stmt(stmt) => list.push(stmt.into()), - - ModuleItem::ModuleDecl(mut module_decl) => { - // collect link meta - module_decl.visit_mut_with(self); - self.has_module_decl = true; - - // emit stmt - match module_decl { - ModuleDecl::Import(..) => continue, - ModuleDecl::ExportDecl(ExportDecl { decl, .. }) => { - list.push(decl.into()); - } - ModuleDecl::ExportNamed(..) => continue, - ModuleDecl::ExportDefaultDecl(ExportDefaultDecl { decl, .. }) => match decl - { - DefaultDecl::Class(class_expr) => { - list.extend(class_expr.as_class_decl().map(From::from)) - } - DefaultDecl::Fn(fn_expr) => { - list.extend(fn_expr.as_fn_decl().map(From::from)) - } - DefaultDecl::TsInterfaceDecl(_) => continue, - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }, - ModuleDecl::ExportDefaultExpr(..) => { - list.extend(self.export_default.take().map(From::from)) - } - ModuleDecl::ExportAll(..) => continue, - ModuleDecl::TsImportEquals(..) => continue, - ModuleDecl::TsExportAssignment(..) => continue, - ModuleDecl::TsNamespaceExport(..) => continue, - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }; - } - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }; - } - - *n = list; - } - - // collect all static import - fn visit_mut_import_decl(&mut self, n: &mut ImportDecl) { - if n.type_only { - return; - } - - let ImportDecl { - specifiers, src, .. - } = n.take(); - - self.link - .entry(src.value.to_atom_lossy().into_owned()) - .or_default() - .mut_dummy_span(src.span) - .extend(specifiers.into_iter().map(From::from)); - } - - /// ```javascript - /// export const foo = 1, bar = 2, { baz } = { baz: 3 }; - /// export let a = 1, [b] = [2]; - /// export function x() {} - /// export class y {} - /// ``` - /// -> - /// ```javascript - /// const foo = 1, bar = 2, { baz } = { baz: 3 }; - /// let a = 1, [b] = [2]; - /// function x() {} - /// class y {} - /// ``` - fn visit_mut_export_decl(&mut self, n: &mut ExportDecl) { - match &n.decl { - Decl::Class(ClassDecl { ident, .. }) | Decl::Fn(FnDecl { ident, .. }) => { - self.export.insert( - ident.sym.clone(), - ExportItem::new((ident.span, ident.ctxt), ident.clone()), - ); - } - - Decl::Var(v) => { - self.export.extend( - find_pat_ids::<_, Ident>(&v.decls) - .into_iter() - .map(|id| (id.sym.clone(), ExportItem::new((id.span, id.ctxt), id))), - ); - } - _ => {} - }; - } - - /// ```javascript - /// export { foo, foo as bar, foo as "baz" }; - /// export { "foo", foo as bar, "foo" as "baz" } from "mod"; - /// export * as foo from "mod"; - /// export * as "bar" from "mod"; - /// ``` - fn visit_mut_named_export(&mut self, n: &mut NamedExport) { - if n.type_only { - return; - } - - let NamedExport { - specifiers, src, .. - } = n.take(); - - if let Some(src) = src { - self.link - .entry(src.value.to_atom_lossy().into_owned()) - .or_default() - .mut_dummy_span(src.span) - .extend(specifiers.into_iter().map(From::from)); - } else { - self.export.extend(specifiers.into_iter().map(|e| match e { - ExportSpecifier::Namespace(..) => { - unreachable!("`export *` without src is invalid") - } - ExportSpecifier::Default(..) => { - unreachable!("`export foo` without src is invalid") - } - ExportSpecifier::Named(ExportNamedSpecifier { orig, exported, .. }) => { - let orig = match orig { - ModuleExportName::Ident(id) => id, - ModuleExportName::Str(_) => { - unreachable!(r#"`export {{ "foo" }}` without src is invalid"#) - } - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }; - - if let Some(exported) = exported { - let (export_name, export_name_span) = match exported { - ModuleExportName::Ident(Ident { - ctxt, span, sym, .. - }) => (sym, (span, ctxt)), - ModuleExportName::Str(Str { span, value, .. }) => ( - value.to_atom_lossy().into_owned(), - (span, Default::default()), - ), - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }; - - (export_name, ExportItem::new(export_name_span, orig)) - } else { - ( - orig.sym.clone(), - ExportItem::new((orig.span, orig.ctxt), orig), - ) - } - } - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - })) - } - } - - /// ```javascript - /// export default class foo {}; - /// export default class {}; - /// export default function bar () {}; - /// export default function () {}; - /// ``` - /// -> - /// ```javascript - /// class foo {}; - /// class _default {}; - /// function bar () {}; - /// function _default () {}; - /// ``` - fn visit_mut_export_default_decl(&mut self, n: &mut ExportDefaultDecl) { - match &mut n.decl { - DefaultDecl::Class(class_expr) => { - let ident = class_expr - .ident - .get_or_insert_with(|| private_ident!(n.span, "_default")) - .clone(); - - self.export.insert( - atom!("default"), - ExportItem::new((n.span, Default::default()), ident), - ); - } - DefaultDecl::Fn(fn_expr) => { - let ident = fn_expr - .ident - .get_or_insert_with(|| private_ident!(n.span, "_default")) - .clone(); - - self.export.insert( - atom!("default"), - ExportItem::new((n.span, Default::default()), ident), - ); - } - DefaultDecl::TsInterfaceDecl(_) => {} - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } - } - - /// ```javascript - /// export default foo; - /// export default 1 - /// ``` - /// -> - /// ```javascript - /// var _default = foo; - /// var _default = 1; - /// ``` - fn visit_mut_export_default_expr(&mut self, n: &mut ExportDefaultExpr) { - let ident = private_ident!(n.span, "_default"); - - self.export.insert( - atom!("default"), - ExportItem::new((n.span, Default::default()), ident.clone()), - ); - - self.export_default = Some( - n.expr - .take() - .into_var_decl(self.const_var_kind, ident.into()) - .into(), - ); - } - - /// ```javascript - /// export * from "mod"; - /// ``` - fn visit_mut_export_all(&mut self, n: &mut ExportAll) { - let Str { - value: src_key, - span: src_span, - .. - } = *n.take().src; - - self.link - .entry(src_key.to_atom_lossy().into_owned()) - .or_default() - .mut_dummy_span(src_span) - .insert(LinkSpecifier::ExportStar); - } - - /// ```javascript - /// import foo = require("mod"); - /// export import foo = require("mod"); - /// ``` - fn visit_mut_ts_import_equals_decl(&mut self, n: &mut TsImportEqualsDecl) { - if n.is_type_only { - return; - } - - let TsImportEqualsDecl { - id, - module_ref, - is_export, - .. - } = n; - - if let TsModuleRef::TsExternalModuleRef(TsExternalModuleRef { - expr: - Str { - span, - value: src_key, - .. - }, - .. - }) = module_ref - { - if *is_export { - self.export.insert( - id.sym.clone(), - ExportItem::new((id.span, id.ctxt), id.clone()), - ); - } - - self.link - .entry(src_key.to_atom_lossy().into_owned()) - .or_default() - .mut_dummy_span(*span) - .insert(LinkSpecifier::ImportEqual(id.to_id())); - } - } - - /// ```javascript - /// export = expr; - /// ``` - fn visit_mut_ts_export_assignment(&mut self, n: &mut TsExportAssignment) { - self.export_assign.get_or_insert(n.expr.take()); - } -} - -#[derive(Debug, PartialEq, Eq, Hash)] -pub enum LinkSpecifier { - ///```javascript - /// import "mod"; - /// import {} from "mod", - /// import { type foo } from "mod"; - /// export {} from "mod"; - /// export { type foo } from "mod"; - /// ``` - Empty, - - /// ```javascript - /// import { imported as local, local } from "mod"; - /// import { "imported" as local } from "mod"; - /// ``` - /// Note: imported will never be `default` - ImportNamed { imported: Option, local: Id }, - - /// ```javascript - /// import foo from "mod"; - /// ``` - ImportDefault(Id), - - /// ```javascript - /// import * as foo from "mod"; - /// ``` - ImportStarAs(Id), - - /// ```javascript - /// export { orig, orig as exported } from "mod"; - /// export { "orig", "orig" as "exported" } from "mod"; - /// ``` - /// Note: orig will never be `default` - ExportNamed { - orig: (Atom, SpanCtx), - exported: Option<(Atom, SpanCtx)>, - }, - - /// ```javascript - /// export { default } from "foo"; - /// export { "default" } from "foo"; - /// export { default as foo } from "mod"; - /// ``` - /// (default_span, local_sym, local_span) - ExportDefaultAs(SpanCtx, Atom, SpanCtx), - - /// ```javascript - /// export * as foo from "mod"; - /// export * as "bar" from "mod"; - /// ``` - ExportStarAs(Atom, SpanCtx), - - /// ```javascript - /// export * from "mod"; - /// ``` - ExportStar, - - /// ```javascript - /// import foo = require("foo"); - /// ``` - ImportEqual(Id), -} - -impl From for LinkSpecifier { - fn from(i: ImportSpecifier) -> Self { - match i { - ImportSpecifier::Namespace(ImportStarAsSpecifier { local, .. }) => { - Self::ImportStarAs(local.to_id()) - } - - ImportSpecifier::Default(ImportDefaultSpecifier { local, .. }) => { - Self::ImportDefault(local.to_id()) - } - ImportSpecifier::Named(ImportNamedSpecifier { - is_type_only: false, - local, - imported: Some(ModuleExportName::Ident(Ident { sym: s, .. })), - .. - }) if &*s == "default" => Self::ImportDefault(local.to_id()), - - ImportSpecifier::Named(ImportNamedSpecifier { - is_type_only: false, - local, - imported: Some(ModuleExportName::Str(Str { value: s, .. })), - .. - }) if &s == "default" => Self::ImportDefault(local.to_id()), - - ImportSpecifier::Named(ImportNamedSpecifier { - is_type_only: false, - local, - imported, - .. - }) => { - let imported = imported.and_then(|e| match e { - ModuleExportName::Ident(Ident { sym, .. }) => Some(sym), - ModuleExportName::Str(Str { value, .. }) => value.as_atom().cloned(), - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }); - - Self::ImportNamed { - local: local.to_id(), - imported, - } - } - _ => Self::Empty, - } - } -} - -impl From for LinkSpecifier { - fn from(e: ExportSpecifier) -> Self { - match e { - ExportSpecifier::Namespace(ExportNamespaceSpecifier { - name: - ModuleExportName::Str(Str { - span, value: sym, .. - }), - .. - }) => Self::ExportStarAs( - sym.to_atom_lossy().into_owned(), - (span, SyntaxContext::empty()), - ), - ExportSpecifier::Namespace(ExportNamespaceSpecifier { - name: ModuleExportName::Ident(Ident { span, sym, .. }), - .. - }) => Self::ExportStarAs(sym, (span, SyntaxContext::empty())), - - ExportSpecifier::Default(ExportDefaultSpecifier { exported }) => { - // https://github.com/tc39/proposal-export-default-from - Self::ExportDefaultAs( - (exported.span, exported.ctxt), - exported.sym, - (exported.span, exported.ctxt), - ) - } - - ExportSpecifier::Named(ExportNamedSpecifier { - is_type_only: false, - orig, - exported, - .. - }) => { - let orig = match orig { - ModuleExportName::Ident(Ident { span, sym, .. }) => { - (sym, (span, SyntaxContext::empty().apply_mark(Mark::new()))) - } - ModuleExportName::Str(Str { - span, value: sym, .. - }) => ( - sym.to_atom_lossy().into_owned(), - (span, SyntaxContext::empty().apply_mark(Mark::new())), - ), - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }; - - let exported = exported.map(|exported| match exported { - ModuleExportName::Ident(Ident { span, sym, .. }) => { - (sym, (span, SyntaxContext::empty().apply_mark(Mark::new()))) - } - ModuleExportName::Str(Str { - span, value: sym, .. - }) => ( - sym.to_atom_lossy().into_owned(), - (span, SyntaxContext::empty().apply_mark(Mark::new())), - ), - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }); - - match (&*orig.0, orig.1) { - ("default", default_span) => { - let (sym, span) = exported.unwrap_or(orig); - - Self::ExportDefaultAs(default_span, sym, span) - } - _ => Self::ExportNamed { orig, exported }, - } - } - _ => Self::Empty, - } - } -} - -#[derive(Debug, Default)] -pub struct LinkItem(pub SpanCtx, pub FxHashSet, pub LinkFlag); - -use bitflags::bitflags; - -bitflags! { - #[derive(Default, Debug)] - pub struct LinkFlag: u8 { - const NAMED = 1 << 0; - const DEFAULT = 1 << 1; - const NAMESPACE = Self::NAMED.bits() | Self::DEFAULT.bits(); - const EXPORT_STAR = 1 << 2; - const IMPORT_EQUAL = 1 << 3; - } -} - -impl LinkFlag { - pub fn interop(&self) -> bool { - self.intersects(Self::DEFAULT) - } - - pub fn has_named(&self) -> bool { - self.intersects(Self::NAMED) - } - - pub fn namespace(&self) -> bool { - self.contains(Self::NAMESPACE) - } - - pub fn need_raw_import(&self) -> bool { - self.interop() && self.intersects(Self::IMPORT_EQUAL) - } - - pub fn export_star(&self) -> bool { - self.intersects(Self::EXPORT_STAR) - } -} - -impl From<&LinkSpecifier> for LinkFlag { - fn from(s: &LinkSpecifier) -> Self { - match s { - LinkSpecifier::Empty => Self::empty(), - LinkSpecifier::ImportStarAs(..) => Self::NAMESPACE, - LinkSpecifier::ImportDefault(..) => Self::DEFAULT, - LinkSpecifier::ImportNamed { .. } => Self::NAMED, - - LinkSpecifier::ExportStarAs(..) => Self::NAMESPACE, - LinkSpecifier::ExportDefaultAs(..) => Self::DEFAULT, - LinkSpecifier::ExportNamed { .. } => Self::NAMED, - - LinkSpecifier::ImportEqual(..) => Self::IMPORT_EQUAL, - LinkSpecifier::ExportStar => Self::EXPORT_STAR, - } - } -} - -impl From<&ImportSpecifier> for LinkFlag { - fn from(i: &ImportSpecifier) -> Self { - match i { - ImportSpecifier::Namespace(..) => Self::NAMESPACE, - - ImportSpecifier::Default(ImportDefaultSpecifier { .. }) => Self::DEFAULT, - - ImportSpecifier::Named(ImportNamedSpecifier { - is_type_only: false, - imported: Some(ModuleExportName::Ident(Ident { sym: default, .. })), - .. - }) if &**default == "default" => Self::DEFAULT, - - ImportSpecifier::Named(ImportNamedSpecifier { - is_type_only: false, - imported: Some(ModuleExportName::Str(Str { value: default, .. })), - .. - }) if default == "default" => Self::DEFAULT, - - ImportSpecifier::Named(ImportNamedSpecifier { - is_type_only: false, - .. - }) => Self::NAMED, - - _ => Self::empty(), - } - } -} - -impl From<&ExportSpecifier> for LinkFlag { - fn from(e: &ExportSpecifier) -> Self { - match e { - ExportSpecifier::Namespace(..) => Self::NAMESPACE, - - // https://github.com/tc39/proposal-export-default-from - ExportSpecifier::Default(..) => Self::DEFAULT, - - ExportSpecifier::Named(ExportNamedSpecifier { - is_type_only: false, - orig: ModuleExportName::Str(Str { value: s, .. }), - .. - }) if s == "default" => Self::DEFAULT, - - ExportSpecifier::Named(ExportNamedSpecifier { - is_type_only: false, - orig: ModuleExportName::Ident(Ident { sym: s, .. }), - .. - }) if &**s == "default" => Self::DEFAULT, - - ExportSpecifier::Named(ExportNamedSpecifier { - is_type_only: false, - .. - }) => Self::NAMED, - - _ => Self::empty(), - } - } -} - -impl Extend for LinkItem { - fn extend>(&mut self, iter: T) { - iter.into_iter().for_each(|link| { - self.insert(link); - }); - } -} - -impl LinkItem { - fn mut_dummy_span(&mut self, span: Span) -> &mut Self { - if self.0 .0.is_dummy() { - self.0 .0 = span; - } - - self - } - - fn insert(&mut self, link: LinkSpecifier) -> bool { - self.2 |= (&link).into(); - self.1.insert(link) - } -} - -pub(crate) type ExportObjPropList = Vec; - -/// Reduce self to generate ImportMap and ExportObjPropList -pub(crate) trait LinkSpecifierReducer { - fn reduce( - self, - import_map: &mut ImportMap, - export_obj_prop_list: &mut ExportObjPropList, - mod_ident: &Ident, - raw_mod_ident: &Option, - ref_to_mod_ident: &mut bool, - // do not emit `mod.default`, emit `mod` instead - default_nowrap: bool, - ); -} - -impl LinkSpecifierReducer for FxHashSet { - fn reduce( - self, - import_map: &mut ImportMap, - export_obj_prop_list: &mut ExportObjPropList, - mod_ident: &Ident, - raw_mod_ident: &Option, - ref_to_mod_ident: &mut bool, - default_nowrap: bool, - ) { - self.into_iter().for_each(|s| match s { - LinkSpecifier::ImportNamed { imported, local } => { - *ref_to_mod_ident = true; - - import_map.insert( - local.clone(), - (mod_ident.clone(), imported.or(Some(local.0))), - ); - } - LinkSpecifier::ImportDefault(id) => { - *ref_to_mod_ident = true; - - import_map.insert( - id, - ( - mod_ident.clone(), - (!default_nowrap).then(|| atom!("default")), - ), - ); - } - LinkSpecifier::ImportStarAs(id) => { - *ref_to_mod_ident = true; - - import_map.insert(id, (mod_ident.clone(), None)); - } - LinkSpecifier::ExportNamed { orig, exported } => { - *ref_to_mod_ident = true; - - // ```javascript - // export { foo as bar } from "mod"; - // - // import { foo } from "mod"; - // export { foo as bar }; - // ``` - - // foo -> mod.foo - import_map.insert( - (orig.0.clone(), orig.1 .1), - (mod_ident.clone(), Some(orig.0.clone())), - ); - - let (export_name, export_name_span) = exported.unwrap_or_else(|| orig.clone()); - - // bar -> foo - export_obj_prop_list.push(( - export_name, - ExportItem::new(export_name_span, quote_ident!(orig.1 .1, orig.1 .0, orig.0)), - )) - } - LinkSpecifier::ExportDefaultAs(_, key, span) => { - *ref_to_mod_ident = true; - - // ```javascript - // export { default as foo } from "mod"; - // - // import { default as foo } from "mod"; - // export { foo }; - // ``` - - // foo -> mod.default - import_map.insert( - (key.clone(), span.1), - (mod_ident.clone(), Some(atom!("default"))), - ); - - export_obj_prop_list.push(( - key.clone(), - ExportItem::new(span, quote_ident!(span.1, span.0, key)), - )); - } - LinkSpecifier::ExportStarAs(key, span) => { - *ref_to_mod_ident = true; - - export_obj_prop_list.push((key, ExportItem::new(span, mod_ident.clone()))); - } - LinkSpecifier::ExportStar => {} - LinkSpecifier::ImportEqual(id) => { - *ref_to_mod_ident = true; - - import_map.insert( - id, - ( - raw_mod_ident.clone().unwrap_or_else(|| mod_ident.clone()), - None, - ), - ); - } - LinkSpecifier::Empty => {} - }) - } -} - -#[derive(Debug)] -pub struct ExportItem(SpanCtx, Ident); - -impl ExportItem { - pub fn new(export_name_span: SpanCtx, local_ident: Ident) -> Self { - Self(export_name_span, local_ident) - } - - pub fn export_name_span(&self) -> SpanCtx { - self.0 - } - - pub fn into_local_ident(self) -> Ident { - self.1 - } -} - -pub type ExportKV = (Atom, ExportItem); diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/module_record.rs b/deps/swc/crates/swc_ecma_transforms_module/src/module_record.rs new file mode 100644 index 000000000..5849dc6a8 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/module_record.rs @@ -0,0 +1,974 @@ +use std::cmp::Ordering; + +use indexmap::IndexMap; +use rustc_hash::{FxHashMap, FxHashSet}; +use swc_atoms::{atom, Atom, Wtf8Atom}; +use swc_common::{Mark, Span, SyntaxContext}; +use swc_ecma_ast::*; +use swc_ecma_utils::{find_pat_ids, quote_ident, IsDirective}; + +use crate::{module_ref_rewriter::ImportMap, SpanCtx}; + +/// `Source Text Module Record.[[RequestedModules]]`, kept in source order for +/// deterministic emit. +/// +/// Entries are grouped by `ModuleRequest` Record so import attributes stay +/// paired with the matching dependency slot. +/// +/// Spec: +/// - +/// - +/// - +pub(crate) type RequestedModules = IndexMap; +/// `Source Text Module Record.[[LocalExportEntries]]`, keyed by export name. +/// +/// Spec: +pub(crate) type LocalExportEntries = FxHashMap; + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub(crate) struct ModuleRequestRecord { + /// `ModuleRequest` Record [[Specifier]]. + specifier: Atom, + /// `ModuleRequest` Record [[Attributes]]. + attributes: Vec, +} + +impl ModuleRequestRecord { + pub fn src(&self) -> &Atom { + &self.specifier + } + + pub fn attributes(&self) -> &[ImportAttributeRecord] { + &self.attributes + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub(crate) struct ImportAttributeRecord { + /// `ImportAttribute` Record [[Key]]. + key: Atom, + /// `ImportAttribute` Record [[Value]]. + value: Wtf8Atom, +} + +impl ImportAttributeRecord { + pub fn key(&self) -> &Atom { + &self.key + } + + pub fn value(&self) -> &Wtf8Atom { + &self.value + } +} + +fn import_attributes(with: Option>) -> Vec { + let Some(with) = with else { + return Vec::new(); + }; + + let Some(mut attributes) = with + .props + .into_iter() + .map(|prop| import_attribute_record(&prop)) + .collect::>>() + else { + return Vec::new(); + }; + + attributes.sort_unstable_by(|a, b| { + cmp_utf16(a.key.as_str(), b.key.as_str()).then_with(|| a.value.cmp(&b.value)) + }); + + attributes +} + +fn import_attribute_record(prop: &PropOrSpread) -> Option { + let PropOrSpread::Prop(prop) = prop else { + return None; + }; + + let Prop::KeyValue(key_value) = &**prop else { + return None; + }; + + let key = match &key_value.key { + PropName::Ident(key) => key.sym.clone(), + PropName::Str(key) => key.value.as_str()?.into(), + _ => return None, + }; + + let Expr::Lit(Lit::Str(value)) = &*key_value.value else { + return None; + }; + + Some(ImportAttributeRecord { + key, + value: value.value.clone(), + }) +} + +fn cmp_utf16(a: &str, b: &str) -> Ordering { + a.encode_utf16().cmp(b.encode_utf16()) +} + +/// Source-level module syntax split into reusable module-record data and +/// ordered body items. +/// +/// This keeps extraction separate from target-specific stripping. Lowerers are +/// responsible for deciding how an exported declaration or expression becomes +/// executable code in their output format. +#[derive(Debug)] +pub(crate) struct SourceModule { + /// Directive prologue statements, preserved before generated wrapper code. + pub directives: Vec, + /// Whether the original directive prologue contained `"use strict"`. + pub has_use_strict: bool, + pub requested_modules: RequestedModules, + pub local_export_entries: LocalExportEntries, + /// TypeScript `export = expr` syntax is a source-level module record fact. + /// CJS-like lowerers consume it as an output-specific assignment. + pub ts_export_assignment: Option>, + pub body: Vec, + /// Whether the original source contained any module declaration. + /// This preserves the legacy extractor signal used for interop decisions. + pub has_module_syntax: bool, +} + +impl SourceModule { + pub fn collect(body: Vec) -> Self { + SourceModuleCollector::default().collect(body) + } +} + +/// Ordered executable source items after top-level module declarations are +/// recorded, but before any target-specific lowering removes export syntax. +#[derive(Debug)] +pub(crate) enum SourceModuleItem { + Stmt(Stmt), + ExportDecl(ExportDecl), + ExportDefaultDecl(ExportDefaultDecl), + ExportDefaultExpr(ExportDefaultExpr), + TsImportEquals(Box), +} + +pub(crate) fn external_ts_import_equals_source(import: &TsImportEqualsDecl) -> Option<&Str> { + if import.is_type_only { + return None; + } + + match &import.module_ref { + TsModuleRef::TsExternalModuleRef(TsExternalModuleRef { expr, .. }) => Some(expr), + _ => None, + } +} + +pub(crate) fn exported_external_ts_import_equals_name(item: &ModuleItem) -> Option<&Atom> { + let ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(import)) = item else { + return None; + }; + + if !import.is_export || external_ts_import_equals_source(import).is_none() { + return None; + } + + Some(&import.id.sym) +} + +#[derive(Default)] +struct SourceModuleCollector { + requested_modules: RequestedModules, + local_export_entries: LocalExportEntries, + ts_export_assignment: Option>, + has_module_syntax: bool, +} + +impl SourceModuleCollector { + fn collect(mut self, body: Vec) -> SourceModule { + let mut directives = Vec::new(); + let mut has_use_strict = false; + let mut source_items = Vec::with_capacity(body.len()); + let mut in_directive_prologue = true; + + for item in body { + if in_directive_prologue && item.directive_continue() { + let stmt = item.expect_stmt(); + if !has_use_strict { + has_use_strict = stmt.is_use_strict(); + } + directives.push(stmt); + continue; + } + + in_directive_prologue = false; + + match item { + ModuleItem::Stmt(stmt) => source_items.push(SourceModuleItem::Stmt(stmt)), + ModuleItem::ModuleDecl(module_decl) => { + if match &module_decl { + ModuleDecl::TsImportEquals(import) => { + import.is_export && external_ts_import_equals_source(import).is_some() + } + _ => true, + } { + self.has_module_syntax = true; + } + + if let Some(item) = self.collect_module_decl(module_decl) { + source_items.push(item); + } + } + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + } + } + + SourceModule { + directives, + has_use_strict, + requested_modules: self.requested_modules, + local_export_entries: self.local_export_entries, + ts_export_assignment: self.ts_export_assignment, + body: source_items, + has_module_syntax: self.has_module_syntax, + } + } + + fn collect_module_decl(&mut self, module_decl: ModuleDecl) -> Option { + match module_decl { + ModuleDecl::Import(import) => { + self.collect_import_decl(import); + None + } + ModuleDecl::ExportDecl(export) => { + self.collect_export_decl(&export); + Some(SourceModuleItem::ExportDecl(export)) + } + ModuleDecl::ExportNamed(export) => { + self.collect_named_export(export); + None + } + ModuleDecl::ExportDefaultDecl(export) => { + self.collect_export_default_decl(&export); + Some(SourceModuleItem::ExportDefaultDecl(export)) + } + ModuleDecl::ExportDefaultExpr(export) => { + Some(SourceModuleItem::ExportDefaultExpr(export)) + } + ModuleDecl::ExportAll(export) => { + self.collect_export_all(export); + None + } + ModuleDecl::TsImportEquals(import) => self.collect_ts_import_equals(import), + ModuleDecl::TsExportAssignment(export) => { + self.ts_export_assignment.get_or_insert(export.expr); + None + } + ModuleDecl::TsNamespaceExport(_) => None, + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + } + } + + fn module_request( + specifier: Atom, + attributes: &[ImportAttributeRecord], + ) -> ModuleRequestRecord { + ModuleRequestRecord { + specifier, + attributes: attributes.to_vec(), + } + } + + fn collect_import_decl(&mut self, import: ImportDecl) { + if import.type_only { + return; + } + + let ImportDecl { + specifiers, + src, + with, + .. + } = import; + + let src_key = src.value.to_atom_lossy().into_owned(); + let attributes = import_attributes(with); + let module_request = Self::module_request(src_key, &attributes); + + self.requested_modules + .entry(module_request) + .or_default() + .mut_dummy_span(src.span) + .extend(specifiers.into_iter().map(From::from)); + } + + fn collect_export_decl(&mut self, export: &ExportDecl) { + match &export.decl { + Decl::Class(ClassDecl { ident, .. }) | Decl::Fn(FnDecl { ident, .. }) => { + self.local_export_entries.insert( + ident.sym.clone(), + LocalExportEntry::new((ident.span, ident.ctxt), ident.clone()), + ); + } + + Decl::Var(v) => { + self.local_export_entries.extend( + find_pat_ids::<_, Ident>(&v.decls).into_iter().map(|id| { + ( + id.sym.clone(), + LocalExportEntry::new((id.span, id.ctxt), id), + ) + }), + ); + } + _ => {} + } + } + + fn collect_named_export(&mut self, export: NamedExport) { + if export.type_only { + return; + } + + let NamedExport { + specifiers, + src, + with, + .. + } = export; + + if let Some(src) = src { + let src_key = src.value.to_atom_lossy().into_owned(); + let attributes = import_attributes(with); + let module_request = Self::module_request(src_key, &attributes); + + self.requested_modules + .entry(module_request) + .or_default() + .mut_dummy_span(src.span) + .extend(specifiers.into_iter().map(From::from)); + } else { + self.local_export_entries + .extend(specifiers.into_iter().map(Self::local_export_entry)); + } + } + + fn local_export_entry(specifier: ExportSpecifier) -> ExportBinding { + match specifier { + ExportSpecifier::Namespace(..) => unreachable!("`export *` without src is invalid"), + ExportSpecifier::Default(..) => unreachable!("`export foo` without src is invalid"), + ExportSpecifier::Named(ExportNamedSpecifier { orig, exported, .. }) => { + let orig = match orig { + ModuleExportName::Ident(id) => id, + ModuleExportName::Str(_) => { + unreachable!(r#"`export {{ "foo" }}` without src is invalid"#) + } + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + }; + + if let Some(exported) = exported { + let (export_name, export_name_span) = match exported { + ModuleExportName::Ident(Ident { + ctxt, span, sym, .. + }) => (sym, (span, ctxt)), + ModuleExportName::Str(Str { span, value, .. }) => ( + value.to_atom_lossy().into_owned(), + (span, Default::default()), + ), + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + }; + + (export_name, LocalExportEntry::new(export_name_span, orig)) + } else { + ( + orig.sym.clone(), + LocalExportEntry::new((orig.span, orig.ctxt), orig), + ) + } + } + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + } + } + + fn collect_export_default_decl(&mut self, export: &ExportDefaultDecl) { + match &export.decl { + DefaultDecl::Class(class_expr) => { + if let Some(ident) = &class_expr.ident { + self.local_export_entries.insert( + atom!("default"), + LocalExportEntry::new((export.span, Default::default()), ident.clone()), + ); + } + } + DefaultDecl::Fn(fn_expr) => { + if let Some(ident) = &fn_expr.ident { + self.local_export_entries.insert( + atom!("default"), + LocalExportEntry::new((export.span, Default::default()), ident.clone()), + ); + } + } + DefaultDecl::TsInterfaceDecl(_) => {} + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + } + } + + fn collect_export_all(&mut self, export: ExportAll) { + let ExportAll { src, with, .. } = export; + let Str { + value: src_key, + span: src_span, + .. + } = *src; + + let attributes = import_attributes(with); + let module_request = + Self::module_request(src_key.to_atom_lossy().into_owned(), &attributes); + + self.requested_modules + .entry(module_request) + .or_default() + .mut_dummy_span(src_span) + .insert(ModuleRecordEntry::StarExport); + } + + fn collect_ts_import_equals( + &mut self, + import: Box, + ) -> Option { + external_ts_import_equals_source(&import)?; + + if import.is_export { + self.local_export_entries.insert( + import.id.sym.clone(), + LocalExportEntry::new((import.id.span, import.id.ctxt), import.id.clone()), + ); + } + + Some(SourceModuleItem::TsImportEquals(import)) + } +} + +/// `ImportEntry` and `ExportEntry` record fields used by this transform. +/// +/// Spec: +/// - +/// - +/// - +/// - +#[derive(Debug, PartialEq, Eq, Hash)] +pub enum ModuleRecordEntry { + ///```javascript + /// import "mod"; + /// import {} from "mod", + /// import { type foo } from "mod"; + /// export {} from "mod"; + /// export { type foo } from "mod"; + /// ``` + Empty, + + /// ```javascript + /// import { imported as local, local } from "mod"; + /// import { "imported" as local } from "mod"; + /// ``` + /// Note: `import_name` will never be `default`. + ImportNamed { + import_name: Option, + local_name: Id, + }, + + /// ```javascript + /// import foo from "mod"; + /// ``` + ImportDefault { local_name: Id }, + + /// ```javascript + /// import * as foo from "mod"; + /// ``` + /// The spec resolves this to a Module Namespace Exotic Object. This legacy + /// module transform emits an interop object instead. + /// Spec: + /// - + /// - + ImportNamespace { local_name: Id }, + + /// ```javascript + /// export { orig, orig as exported } from "mod"; + /// export { "orig", "orig" as "exported" } from "mod"; + /// ``` + /// Note: `import_name` will never be `default`. + IndirectExportNamed { + import_name: (Atom, SpanCtx), + export_name: Option<(Atom, SpanCtx)>, + }, + + /// ```javascript + /// export { default } from "foo"; + /// export { "default" } from "foo"; + /// export { default as foo } from "mod"; + /// ``` + IndirectExportDefault { + export_name: Atom, + export_name_span: SpanCtx, + }, + + /// ```javascript + /// export * as foo from "mod"; + /// export * as "bar" from "mod"; + /// ``` + /// The spec resolves this to a namespace export binding. This transform + /// emits a legacy interop object getter instead. + /// Spec: + /// - + /// - + IndirectExportNamespace { + export_name: Atom, + export_name_span: SpanCtx, + }, + + /// ```javascript + /// export * from "mod"; + /// ``` + /// Related spec operation: `GetExportedNames` walks + /// `[[StarExportEntries]]` and omits `default` from star-exported names. + /// + StarExport, +} + +impl From for ModuleRecordEntry { + fn from(i: ImportSpecifier) -> Self { + match i { + ImportSpecifier::Namespace(ImportStarAsSpecifier { local, .. }) => { + Self::ImportNamespace { + local_name: local.to_id(), + } + } + + ImportSpecifier::Default(ImportDefaultSpecifier { local, .. }) => Self::ImportDefault { + local_name: local.to_id(), + }, + ImportSpecifier::Named(ImportNamedSpecifier { + is_type_only: false, + local, + imported: Some(ModuleExportName::Ident(Ident { sym: s, .. })), + .. + }) if &*s == "default" => Self::ImportDefault { + local_name: local.to_id(), + }, + + ImportSpecifier::Named(ImportNamedSpecifier { + is_type_only: false, + local, + imported: Some(ModuleExportName::Str(Str { value: s, .. })), + .. + }) if &s == "default" => Self::ImportDefault { + local_name: local.to_id(), + }, + + ImportSpecifier::Named(ImportNamedSpecifier { + is_type_only: false, + local, + imported, + .. + }) => { + let import_name = imported.and_then(|e| match e { + ModuleExportName::Ident(Ident { sym, .. }) => Some(sym), + ModuleExportName::Str(Str { value, .. }) => value.as_atom().cloned(), + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + }); + + Self::ImportNamed { + local_name: local.to_id(), + import_name, + } + } + _ => Self::Empty, + } + } +} + +impl From for ModuleRecordEntry { + fn from(e: ExportSpecifier) -> Self { + match e { + ExportSpecifier::Namespace(ExportNamespaceSpecifier { + name: + ModuleExportName::Str(Str { + span, value: sym, .. + }), + .. + }) => Self::IndirectExportNamespace { + export_name: sym.to_atom_lossy().into_owned(), + export_name_span: (span, SyntaxContext::empty()), + }, + ExportSpecifier::Namespace(ExportNamespaceSpecifier { + name: ModuleExportName::Ident(Ident { span, sym, .. }), + .. + }) => Self::IndirectExportNamespace { + export_name: sym, + export_name_span: (span, SyntaxContext::empty()), + }, + + ExportSpecifier::Default(ExportDefaultSpecifier { exported }) => { + // https://github.com/tc39/proposal-export-default-from + Self::IndirectExportDefault { + export_name: exported.sym, + export_name_span: (exported.span, exported.ctxt), + } + } + + ExportSpecifier::Named(ExportNamedSpecifier { + is_type_only: false, + orig, + exported, + .. + }) => { + let orig = match orig { + ModuleExportName::Ident(Ident { span, sym, .. }) => { + (sym, (span, SyntaxContext::empty().apply_mark(Mark::new()))) + } + ModuleExportName::Str(Str { + span, value: sym, .. + }) => ( + sym.to_atom_lossy().into_owned(), + (span, SyntaxContext::empty().apply_mark(Mark::new())), + ), + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + }; + + let exported = exported.map(|exported| match exported { + ModuleExportName::Ident(Ident { span, sym, .. }) => { + (sym, (span, SyntaxContext::empty().apply_mark(Mark::new()))) + } + ModuleExportName::Str(Str { + span, value: sym, .. + }) => ( + sym.to_atom_lossy().into_owned(), + (span, SyntaxContext::empty().apply_mark(Mark::new())), + ), + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + }); + + match (&*orig.0, orig.1) { + ("default", _) => { + let (sym, span) = exported.unwrap_or(orig); + + Self::IndirectExportDefault { + export_name: sym, + export_name_span: span, + } + } + _ => Self::IndirectExportNamed { + import_name: orig, + export_name: exported, + }, + } + } + _ => Self::Empty, + } + } +} + +#[derive(Debug, Default)] +pub struct RequestedModule { + /// First useful source span for the module request. The spec tracks this as + /// a `ModuleRequest` Record; emitters keep the span for generated literals + /// and diagnostics. + /// + /// Spec: + pub span: SpanCtx, + /// `ImportEntry` and `ExportEntry` records associated with this module + /// request. + pub entries: FxHashSet, + /// Emitter-only summary of which runtime module shape is needed. + pub usage: ModuleRequestUsage, +} + +use bitflags::bitflags; + +bitflags! { + #[derive(Default, Debug)] + pub struct ModuleRequestUsage: u8 { + const NAMED = 1 << 0; + const DEFAULT = 1 << 1; + const NAMESPACE = Self::NAMED.bits() | Self::DEFAULT.bits(); + const STAR_EXPORT = 1 << 2; + } +} + +impl ModuleRequestUsage { + pub fn needs_interop(&self) -> bool { + self.intersects(Self::DEFAULT) + } + + pub fn has_named(&self) -> bool { + self.intersects(Self::NAMED) + } + + pub fn needs_namespace_object(&self) -> bool { + self.contains(Self::NAMESPACE) + } + + pub fn has_star_export(&self) -> bool { + self.intersects(Self::STAR_EXPORT) + } +} + +impl From<&ModuleRecordEntry> for ModuleRequestUsage { + fn from(s: &ModuleRecordEntry) -> Self { + match s { + ModuleRecordEntry::Empty => Self::empty(), + ModuleRecordEntry::ImportNamespace { .. } => Self::NAMESPACE, + ModuleRecordEntry::ImportDefault { .. } => Self::DEFAULT, + ModuleRecordEntry::ImportNamed { .. } => Self::NAMED, + + ModuleRecordEntry::IndirectExportNamespace { .. } => Self::NAMESPACE, + ModuleRecordEntry::IndirectExportDefault { .. } => Self::DEFAULT, + ModuleRecordEntry::IndirectExportNamed { .. } => Self::NAMED, + + ModuleRecordEntry::StarExport => Self::STAR_EXPORT, + } + } +} + +impl From<&ImportSpecifier> for ModuleRequestUsage { + fn from(i: &ImportSpecifier) -> Self { + match i { + ImportSpecifier::Namespace(..) => Self::NAMESPACE, + + ImportSpecifier::Default(ImportDefaultSpecifier { .. }) => Self::DEFAULT, + + ImportSpecifier::Named(ImportNamedSpecifier { + is_type_only: false, + imported: Some(ModuleExportName::Ident(Ident { sym: default, .. })), + .. + }) if &**default == "default" => Self::DEFAULT, + + ImportSpecifier::Named(ImportNamedSpecifier { + is_type_only: false, + imported: Some(ModuleExportName::Str(Str { value: default, .. })), + .. + }) if default == "default" => Self::DEFAULT, + + ImportSpecifier::Named(ImportNamedSpecifier { + is_type_only: false, + .. + }) => Self::NAMED, + + _ => Self::empty(), + } + } +} + +impl From<&ExportSpecifier> for ModuleRequestUsage { + fn from(e: &ExportSpecifier) -> Self { + match e { + ExportSpecifier::Namespace(..) => Self::NAMESPACE, + + // https://github.com/tc39/proposal-export-default-from + ExportSpecifier::Default(..) => Self::DEFAULT, + + ExportSpecifier::Named(ExportNamedSpecifier { + is_type_only: false, + orig: ModuleExportName::Str(Str { value: s, .. }), + .. + }) if s == "default" => Self::DEFAULT, + + ExportSpecifier::Named(ExportNamedSpecifier { + is_type_only: false, + orig: ModuleExportName::Ident(Ident { sym: s, .. }), + .. + }) if &**s == "default" => Self::DEFAULT, + + ExportSpecifier::Named(ExportNamedSpecifier { + is_type_only: false, + .. + }) => Self::NAMED, + + _ => Self::empty(), + } + } +} + +impl Extend for RequestedModule { + fn extend>(&mut self, iter: T) { + iter.into_iter().for_each(|link| { + self.insert(link); + }); + } +} + +impl RequestedModule { + fn mut_dummy_span(&mut self, span: Span) -> &mut Self { + if self.span.0.is_dummy() { + self.span.0 = span; + } + + self + } + + fn insert(&mut self, entry: ModuleRecordEntry) -> bool { + self.usage |= (&entry).into(); + self.entries.insert(entry) + } +} + +pub(crate) type ExportObjectProperties = Vec; + +/// Reduce module record entries into the import map and export object +/// properties required by CommonJS-like emitters. +/// +/// This is not a full ECMAScript module linker. It only lowers collected +/// syntactic entries to emitter-local data structures; the corresponding spec +/// operations for linked modules are `GetExportedNames` and `ResolveExport`. +/// - +/// - +pub(crate) trait ModuleRecordEntryReducer { + fn reduce( + self, + import_map: &mut ImportMap, + export_bindings: &mut ExportObjectProperties, + mod_ident: &Ident, + ref_to_mod_ident: &mut bool, + // do not emit `mod.default`, emit `mod` instead + default_nowrap: bool, + ); +} + +impl ModuleRecordEntryReducer for FxHashSet { + fn reduce( + self, + import_map: &mut ImportMap, + export_bindings: &mut ExportObjectProperties, + mod_ident: &Ident, + ref_to_mod_ident: &mut bool, + default_nowrap: bool, + ) { + self.into_iter().for_each(|s| match s { + ModuleRecordEntry::ImportNamed { + import_name, + local_name, + } => { + *ref_to_mod_ident = true; + + import_map.insert( + local_name.clone(), + (mod_ident.clone(), import_name.or(Some(local_name.0))), + ); + } + ModuleRecordEntry::ImportDefault { local_name } => { + *ref_to_mod_ident = true; + + import_map.insert( + local_name, + ( + mod_ident.clone(), + (!default_nowrap).then(|| atom!("default")), + ), + ); + } + ModuleRecordEntry::ImportNamespace { local_name } => { + *ref_to_mod_ident = true; + + import_map.insert(local_name, (mod_ident.clone(), None)); + } + ModuleRecordEntry::IndirectExportNamed { + import_name, + export_name, + } => { + *ref_to_mod_ident = true; + + // ```javascript + // export { foo as bar } from "mod"; + // + // import { foo } from "mod"; + // export { foo as bar }; + // ``` + + // foo -> mod.foo + import_map.insert( + (import_name.0.clone(), import_name.1 .1), + (mod_ident.clone(), Some(import_name.0.clone())), + ); + + let (export_name, export_name_span) = + export_name.unwrap_or_else(|| import_name.clone()); + + // bar -> foo + export_bindings.push(( + export_name, + LocalExportEntry::new( + export_name_span, + quote_ident!(import_name.1 .1, import_name.1 .0, import_name.0), + ), + )); + } + ModuleRecordEntry::IndirectExportDefault { + export_name, + export_name_span, + .. + } => { + *ref_to_mod_ident = true; + + // ```javascript + // export { default as foo } from "mod"; + // + // import { default as foo } from "mod"; + // export { foo }; + // ``` + + // foo -> mod.default + import_map.insert( + (export_name.clone(), export_name_span.1), + (mod_ident.clone(), Some(atom!("default"))), + ); + + export_bindings.push(( + export_name.clone(), + LocalExportEntry::new( + export_name_span, + quote_ident!(export_name_span.1, export_name_span.0, export_name), + ), + )); + } + ModuleRecordEntry::IndirectExportNamespace { + export_name, + export_name_span, + } => { + *ref_to_mod_ident = true; + + export_bindings.push(( + export_name, + LocalExportEntry::new(export_name_span, mod_ident.clone()), + )); + } + ModuleRecordEntry::StarExport => {} + ModuleRecordEntry::Empty => {} + }); + } +} + +#[derive(Debug)] +pub struct LocalExportEntry(SpanCtx, Ident); + +impl LocalExportEntry { + pub fn new(export_name_span: SpanCtx, local_ident: Ident) -> Self { + Self(export_name_span, local_ident) + } + + pub fn export_name_span(&self) -> SpanCtx { + self.0 + } + + pub fn into_local_ident(self) -> Ident { + self.1 + } +} + +pub type ExportBinding = (Atom, LocalExportEntry); diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/module_ref_rewriter.rs b/deps/swc/crates/swc_ecma_transforms_module/src/module_ref_rewriter.rs index b7da9ee1e..fe1a8041b 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/module_ref_rewriter.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/module_ref_rewriter.rs @@ -81,8 +81,7 @@ impl QueryRef for ImportQuery { self.import_map .get(&ident.to_id()) - .map(|(_, prop)| prop.is_some()) - .unwrap_or_default() + .is_some_and(|(_, prop)| prop.is_some()) } } @@ -100,7 +99,7 @@ pub(crate) fn rewrite_import_bindings( helper_ctxt: { HELPERS .is_set() - .then(|| HELPERS.with(|helper| helper.mark())) + .then(|| HELPERS.with(swc_ecma_transforms_base::helpers::Helpers::mark)) .map(|mark| SyntaxContext::empty().apply_mark(mark)) }, }, diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/path.rs b/deps/swc/crates/swc_ecma_transforms_module/src/path.rs index 08285710b..89c73f02c 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/path.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/path.rs @@ -73,7 +73,7 @@ pub trait ImportResolver { fn resolve_import(&self, base: &FileName, module_specifier: &str) -> Result; } -/// [ImportResolver] implementation which just uses original source. +/// [`ImportResolver`] implementation which just uses original source. #[derive(Debug, Clone, Copy, Default)] pub struct NoopImportResolver; @@ -83,11 +83,11 @@ impl ImportResolver for NoopImportResolver { } } -/// [ImportResolver] implementation for node.js +/// [`ImportResolver`] implementation for node.js /// -/// Supports [FileName::Real] and [FileName::Anon] for `base`, [FileName::Real] -/// and [FileName::Custom] for `target`. ([FileName::Custom] is used for core -/// modules) +/// Supports [`FileName::Real`] and [`FileName::Anon`] for `base`, +/// [`FileName::Real`] and [`FileName::Custom`] for `target`. +/// ([`FileName::Custom`] is used for core modules) #[derive(Debug, Clone, Default)] pub struct NodeImportResolver where @@ -335,8 +335,26 @@ where }; if base.is_absolute() != target.is_absolute() { - base = Cow::Owned(absolute_path(self.config.base_dir.as_deref(), &base)?); - target = absolute_path(self.config.base_dir.as_deref(), &target)?; + if base.is_absolute() { + base = Cow::Owned(base.to_path_buf().clean()); + } else { + base = Cow::Owned(absolute_base_path(self.config.base_dir.as_deref(), &base)?); + } + + if target.is_absolute() { + target = target.clean(); + } else { + target = absolute_path(self.config.base_dir.as_deref(), &target)?; + } + } + + #[cfg(windows)] + { + (base, target) = normalize_extended_length_path_prefixes( + self.config.base_dir.as_deref(), + base, + target, + ); } #[cfg(debug_assertions)] @@ -444,3 +462,188 @@ fn absolute_path(base_dir: Option<&Path>, path: &Path) -> io::Result { Ok(absolute_path) } + +fn absolute_base_path(base_dir: Option<&Path>, path: &Path) -> io::Result { + if path.is_absolute() { + return Ok(path.to_path_buf().clean()); + } + + let Some(base_dir) = base_dir else { + return absolute_path(None, path); + }; + + let base_dir_path = base_dir.join(path).clean(); + let cwd = match current_dir() { + Ok(path) => normalize_path_prefix_like(base_dir, path.clean()), + Err(_) => return Ok(base_dir_path), + }; + + Ok(absolute_base_path_with_cwd( + base_dir, + path, + &cwd, + base_dir_path, + )) +} + +fn absolute_base_path_with_cwd( + base_dir: &Path, + path: &Path, + cwd: &Path, + base_dir_path: PathBuf, +) -> PathBuf { + let cwd_path = cwd.join(path).clean(); + + // Relative CLI filenames are rooted at the current process directory. Other + // API callers commonly pass filenames relative to `jsc.baseUrl`, so keep + // that legacy behavior unless the cwd-rooted path visibly enters baseUrl + // from outside it. If cwd is already inside baseUrl, every relative path is + // under baseUrl and the interpretation is ambiguous. + if cwd_path.starts_with(base_dir) && !cwd.starts_with(base_dir) { + cwd_path + } else { + base_dir_path + } +} + +#[cfg(windows)] +fn normalize_path_prefix_like(reference: &Path, path: PathBuf) -> PathBuf { + let reference = reference.as_os_str().to_string_lossy(); + let path_str = path.as_os_str().to_string_lossy(); + + normalize_extended_length_path_prefix(&reference, &path_str) + .map(PathBuf::from) + .unwrap_or(path) +} + +#[cfg(not(windows))] +fn normalize_path_prefix_like(_: &Path, path: PathBuf) -> PathBuf { + path +} + +#[cfg(windows)] +fn normalize_extended_length_path_prefixes<'a>( + base_dir: Option<&Path>, + base: Cow<'a, Path>, + target: PathBuf, +) -> (Cow<'a, Path>, PathBuf) { + if !base.is_absolute() || !target.is_absolute() { + return (base, target); + } + + let reference = match base_dir { + Some(base_dir) if has_extended_length_path_prefix(base_dir) => Some(base_dir.to_path_buf()), + _ if has_extended_length_path_prefix(base.as_ref()) => Some(base.to_path_buf()), + _ if has_extended_length_path_prefix(&target) => Some(target.clone()), + _ => None, + }; + + let Some(reference) = reference else { + return (base, target); + }; + + // Windows canonicalization often returns extended-length paths (`\\?\...`). + // `pathdiff` treats those as a different prefix from ordinary absolute + // paths, so align both sides before calculating a relative import. + ( + Cow::Owned(normalize_path_prefix_like(&reference, base.into_owned())), + normalize_path_prefix_like(&reference, target), + ) +} + +#[cfg(windows)] +fn has_extended_length_path_prefix(path: &Path) -> bool { + path.as_os_str().to_string_lossy().starts_with(r"\\?\") +} + +#[cfg(any(test, windows))] +fn normalize_extended_length_path_prefix(reference: &str, path: &str) -> Option { + if !reference.starts_with(r"\\?\") || path.starts_with(r"\\?\") { + return None; + } + + if !is_windows_absolute_path(path) { + return None; + } + + if let Some(path) = path.strip_prefix(r"\\") { + if path.starts_with(r".\") { + return None; + } + + return Some(format!(r"\\?\UNC\{path}")); + } + + Some(format!(r"\\?\{path}")) +} + +#[cfg(any(test, windows))] +fn is_windows_absolute_path(path: &str) -> bool { + path.starts_with(r"\\") || has_windows_drive_prefix(path) +} + +#[cfg(any(test, windows))] +fn has_windows_drive_prefix(path: &str) -> bool { + let bytes = path.as_bytes(); + + bytes.len() >= 3 + && bytes[0].is_ascii_alphabetic() + && bytes[1] == b':' + && matches!(bytes[2], b'/' | b'\\') +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn absolute_base_path_keeps_base_dir_when_cwd_is_inside_base_dir() { + let base_dir = Path::new("/repo"); + let cwd = Path::new("/repo/packages/app"); + let path = Path::new("src"); + + assert_eq!( + absolute_base_path_with_cwd(base_dir, path, cwd, base_dir.join(path).clean()), + PathBuf::from("/repo/src") + ); + } + + #[test] + fn absolute_base_path_uses_cwd_when_relative_path_enters_base_dir() { + let base_dir = Path::new("/repo/bazel-out/foo-app"); + let cwd = Path::new("/repo"); + let path = Path::new("bazel-out/foo-app/src"); + + assert_eq!( + absolute_base_path_with_cwd(base_dir, path, cwd, base_dir.join(path).clean()), + PathBuf::from("/repo/bazel-out/foo-app/src") + ); + } + + #[test] + fn extended_unc_prefix_uses_canonical_unc_form() { + assert_eq!( + normalize_extended_length_path_prefix( + r"\\?\UNC\server\share\repo", + r"\\server\share\repo\src" + ), + Some(r"\\?\UNC\server\share\repo\src".into()) + ); + } + + #[test] + fn extended_drive_prefix_preserves_drive_form() { + assert_eq!( + normalize_extended_length_path_prefix(r"\\?\C:\repo", r"C:\repo\src"), + Some(r"\\?\C:\repo\src".into()) + ); + } + + #[test] + fn extended_drive_prefix_skips_relative_path() { + assert_eq!( + normalize_extended_length_path_prefix(r"\\?\C:\repo", r"repo\src"), + None + ); + } +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/rewriter/import_rewriter_typescript.rs b/deps/swc/crates/swc_ecma_transforms_module/src/rewriter/import_rewriter_typescript.rs index 5ce9d0c1b..5cae7a6bb 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/rewriter/import_rewriter_typescript.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/rewriter/import_rewriter_typescript.rs @@ -7,11 +7,17 @@ use swc_ecma_transforms_base::helper; use swc_ecma_visit::{visit_mut_pass, VisitMut, VisitMutWith}; /// This is the implementation of rewriteRelativeImportExtensions in TypeScript -pub fn typescript_import_rewriter() -> impl Pass { - visit_mut_pass(Rewriter) +/// +/// `jsx_preserve` corresponds to TypeScript's `jsx: "preserve"`: when set, +/// `.tsx` specifiers are rewritten to `.jsx` instead of `.js`. +#[must_use] +pub fn typescript_import_rewriter(jsx_preserve: bool) -> impl Pass { + visit_mut_pass(Rewriter { jsx_preserve }) } -struct Rewriter; +struct Rewriter { + jsx_preserve: bool, +} impl VisitMut for Rewriter { fn visit_mut_call_expr(&mut self, e: &mut CallExpr) { @@ -32,19 +38,26 @@ impl VisitMut for Rewriter { if let Some(ExprOrSpread { spread: None, expr }) = &mut e.args.get_mut(0) { if let Expr::Lit(Lit::Str(s)) = &mut **expr { - if let Some(src) = get_output_extension_wtf8(&s.value) { + if let Some(src) = get_output_extension_wtf8(&s.value, self.jsx_preserve) { s.raw = None; s.value = src; } } else { let importee = expr.take(); + let mut args = vec![ExprOrSpread { + spread: None, + expr: importee, + }]; + if self.jsx_preserve { + args.push(ExprOrSpread { + spread: None, + expr: true.into(), + }); + } **expr = Expr::Call(CallExpr { span: DUMMY_SP, callee: helper!(ts_rewrite_relative_import_extension), - args: vec![ExprOrSpread { - spread: None, - expr: importee, - }], + args, ..Default::default() }); } @@ -52,7 +65,7 @@ impl VisitMut for Rewriter { } fn visit_mut_import_decl(&mut self, i: &mut ImportDecl) { - if let Some(src) = get_output_extension_wtf8(&i.src.value) { + if let Some(src) = get_output_extension_wtf8(&i.src.value, self.jsx_preserve) { i.src.value = src; i.src.raw = None; } @@ -60,7 +73,7 @@ impl VisitMut for Rewriter { fn visit_mut_named_export(&mut self, e: &mut NamedExport) { if let Some(src) = &mut e.src { - if let Some(new_src) = get_output_extension_wtf8(&src.value) { + if let Some(new_src) = get_output_extension_wtf8(&src.value, self.jsx_preserve) { src.value = new_src; src.raw = None; } @@ -68,14 +81,14 @@ impl VisitMut for Rewriter { } fn visit_mut_export_all(&mut self, n: &mut ExportAll) { - if let Some(new_src) = get_output_extension_wtf8(&n.src.value) { + if let Some(new_src) = get_output_extension_wtf8(&n.src.value, self.jsx_preserve) { n.src.value = new_src; n.src.raw = None; } } } -fn get_output_extension(specifier: &Atom) -> Option { +fn get_output_extension(specifier: &Atom, jsx_preserve: bool) -> Option { // https://github.com/microsoft/TypeScript/blob/3eb7b6a1794a6d2cde7948a3016c57e628b104b9/src/compiler/utilities.ts#L4331 let path = Path::new(specifier.as_str()); if !(path.starts_with("./") @@ -96,7 +109,15 @@ fn get_output_extension(specifier: &Atom) -> Option { let ext = match ext { "js" | "ts" => "js", "json" => "json", - "jsx" | "tsx" => "jsx", + // `.jsx` is not rewritten: TypeScript only rewrites specifiers with a + // TS extension (`shouldRewriteModuleSpecifier` in utilities.ts). + "tsx" => { + if jsx_preserve { + "jsx" + } else { + "js" + } + } "mjs" | "mts" => "mjs", "cjs" | "cts" => "cjs", _ => return None, @@ -105,7 +126,7 @@ fn get_output_extension(specifier: &Atom) -> Option { Some(Atom::new(path.with_extension(ext).to_str()?)) } -fn get_output_extension_wtf8(specifier: &Wtf8Atom) -> Option { +fn get_output_extension_wtf8(specifier: &Wtf8Atom, jsx_preserve: bool) -> Option { let normalized = specifier.to_atom_lossy(); - get_output_extension(normalized.as_ref()).map(Into::into) + get_output_extension(normalized.as_ref(), jsx_preserve).map(Into::into) } diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/syntax_strip.rs b/deps/swc/crates/swc_ecma_transforms_module/src/syntax_strip.rs new file mode 100644 index 000000000..fc456fca0 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/syntax_strip.rs @@ -0,0 +1,119 @@ +use swc_atoms::atom; +use swc_ecma_ast::*; +use swc_ecma_utils::{private_ident, ExprFactory}; + +use crate::module_record::{ + LocalExportEntries, LocalExportEntry, RequestedModules, SourceModule, SourceModuleItem, +}; + +/// Source module after module syntax is stripped from the executable body. +#[derive(Debug)] +pub(crate) struct SyntaxStrippedModule { + pub directives: Vec, + pub has_use_strict: bool, + pub requested_modules: RequestedModules, + pub local_export_entries: LocalExportEntries, + pub export_assign: Option>, + pub body: Vec, + pub has_module_syntax: bool, +} + +pub(crate) fn lower(source: SourceModule, const_var_kind: VarDeclKind) -> SyntaxStrippedModule { + let SourceModule { + directives, + has_use_strict, + requested_modules, + mut local_export_entries, + ts_export_assignment, + body, + has_module_syntax, + } = source; + let mut lowered_body = Vec::with_capacity(body.len()); + + for item in body { + match item { + SourceModuleItem::Stmt(stmt) => lowered_body.push(stmt.into()), + SourceModuleItem::ExportDecl(export) => lowered_body.push(export.decl.into()), + SourceModuleItem::ExportDefaultDecl(export) => { + lowered_body.extend(lower_export_default_decl(export, &mut local_export_entries)); + } + SourceModuleItem::ExportDefaultExpr(export) => { + lowered_body.push(lower_export_default_expr( + export, + &mut local_export_entries, + const_var_kind, + )); + } + SourceModuleItem::TsImportEquals(import) => { + lowered_body.push(ModuleDecl::TsImportEquals(import).into()); + } + } + } + + SyntaxStrippedModule { + directives, + has_use_strict, + requested_modules, + local_export_entries, + export_assign: ts_export_assignment, + body: lowered_body, + has_module_syntax, + } +} + +fn lower_export_default_decl( + export: ExportDefaultDecl, + local_export_entries: &mut LocalExportEntries, +) -> Option { + match export.decl { + DefaultDecl::Class(mut class_expr) => { + let ident = class_expr + .ident + .get_or_insert_with(|| private_ident!(export.span, "_default")) + .clone(); + + local_export_entries.insert( + atom!("default"), + LocalExportEntry::new((export.span, Default::default()), ident), + ); + + class_expr.as_class_decl().map(From::from) + } + DefaultDecl::Fn(mut fn_expr) => { + let ident = fn_expr + .ident + .get_or_insert_with(|| private_ident!(export.span, "_default")) + .clone(); + + local_export_entries.insert( + atom!("default"), + LocalExportEntry::new((export.span, Default::default()), ident), + ); + + fn_expr.as_fn_decl().map(From::from) + } + DefaultDecl::TsInterfaceDecl(_) => None, + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + } +} + +fn lower_export_default_expr( + export: ExportDefaultExpr, + local_export_entries: &mut LocalExportEntries, + const_var_kind: VarDeclKind, +) -> ModuleItem { + let ident = private_ident!(export.span, "_default"); + + local_export_entries.insert( + atom!("default"), + LocalExportEntry::new((export.span, Default::default()), ident.clone()), + ); + + let stmt: Stmt = export + .expr + .into_var_decl(const_var_kind, ident.into()) + .into(); + + stmt.into() +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/system_js.rs b/deps/swc/crates/swc_ecma_transforms_module/src/system_js.rs index 03b682cac..394e9b546 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/system_js.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/system_js.rs @@ -1,1181 +1,95 @@ -use anyhow::Context; -use rustc_hash::FxHashMap; -use serde::{Deserialize, Serialize}; -use swc_atoms::Atom; -use swc_common::{Mark, Span, SyntaxContext, DUMMY_SP}; +use swc_common::{util::take::Take, Mark, SyntaxContext, DUMMY_SP}; use swc_ecma_ast::*; -use swc_ecma_utils::{ - member_expr, private_ident, quote_ident, quote_str, var::VarCollector, ExprFactory, -}; -use swc_ecma_visit::{fold_pass, standard_only_fold, Fold, FoldWith, VisitWith}; +use swc_ecma_utils::{contains_top_level_await, private_ident, quote_ident, ExprFactory}; +use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut}; -pub use super::util::Config as InnerConfig; +pub use super::util::Config; use crate::{ - path::Resolver, - top_level_this::top_level_this, - util::{local_name_for_src, use_strict}, - wtf8::{normalize_wtf8_atom, wtf8_to_cow_str}, + module_record::SourceModule, path::Resolver, top_level_this::top_level_this, util::use_strict, }; -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(deny_unknown_fields, rename_all = "camelCase")] -pub struct Config { - #[serde(default)] - pub allow_top_level_this: bool, - - #[serde(flatten, default)] - pub config: InnerConfig, -} -struct SystemJs { - unresolved_mark: Mark, - resolver: Resolver, - config: Config, - - declare_var_idents: Vec, - export_map: FxHashMap>, - export_names: Vec, - export_values: Vec>, - tla: bool, - enter_async_fn: u32, - root_fn_decl_idents: Vec, - module_item_meta_list: Vec, - import_idents: Vec, - export_ident: Ident, - context_ident: Ident, -} +mod emit; +mod ir; +mod lower; +mod pattern; +mod rewrite; +mod util; +#[must_use] pub fn system_js(resolver: Resolver, unresolved_mark: Mark, config: Config) -> impl Pass { - fold_pass(SystemJs { - unresolved_mark, + visit_mut_pass(SystemJs { resolver, + unresolved_mark, config, - declare_var_idents: Vec::new(), - export_map: Default::default(), - export_names: Vec::new(), - export_values: Vec::new(), - tla: false, - enter_async_fn: 0, - root_fn_decl_idents: Vec::new(), - module_item_meta_list: Vec::new(), - import_idents: Vec::new(), - export_ident: private_ident!("_export"), - context_ident: private_ident!("_context"), }) } -struct ModuleItemMeta { - export_names: Vec, - export_values: Vec>, - has_export_all: bool, - src: Atom, - setter_fn_stmts: Vec, -} - -impl SystemJs { - fn export_call(&self, name: Atom, span: Span, expr: Expr) -> CallExpr { - CallExpr { - span, - callee: self.export_ident.clone().as_callee(), - args: vec![quote_str!(name).as_arg(), expr.as_arg()], - ..Default::default() - } - } - - fn fold_module_name_ident(&mut self, ident: Ident) -> Expr { - if &*ident.sym == "__moduleName" && ident.ctxt.outer() == self.unresolved_mark { - return self - .context_ident - .clone() - .make_member(quote_ident!("id")) - .into(); - } - ident.into() - } - - fn replace_assign_expr(&mut self, assign_expr: AssignExpr) -> Expr { - match &assign_expr.left { - AssignTarget::Simple(pat_or_expr) => match pat_or_expr { - SimpleAssignTarget::Ident(ident) => { - for (k, v) in self.export_map.iter() { - if ident.ctxt == k.1 && ident.sym == k.0 { - let mut expr = assign_expr.into(); - for value in v.iter() { - expr = self.export_call(value.clone(), DUMMY_SP, expr).into(); - } - return expr; - } - } - assign_expr.into() - } - _ => assign_expr.into(), - }, - AssignTarget::Pat(pat) => { - let mut to: Vec = Vec::new(); - pat.visit_with(&mut VarCollector { to: &mut to }); - - match pat { - AssignTargetPat::Object(..) | AssignTargetPat::Array(..) => { - let mut exprs = vec![Box::new(Expr::Assign(assign_expr))]; - - for to in to { - for (k, v) in self.export_map.iter() { - if to == *k { - for _ in v.iter() { - exprs.push( - self.export_call( - to.0.clone(), - DUMMY_SP, - Ident::new(to.0.clone(), DUMMY_SP, to.1).into(), - ) - .into(), - ); - } - break; - } - } - } - SeqExpr { - span: DUMMY_SP, - exprs, - } - .into() - } - _ => assign_expr.into(), - } - } - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } - } - - fn replace_update_expr(&mut self, update_expr: UpdateExpr) -> Expr { - if !update_expr.prefix { - match &*update_expr.arg { - Expr::Ident(ident) => { - for (k, v) in self.export_map.iter() { - if ident.ctxt == k.1 && ident.sym == k.0 { - let mut expr = BinExpr { - span: DUMMY_SP, - op: op!(bin, "+"), - left: UnaryExpr { - span: DUMMY_SP, - op: op!(unary, "+"), - arg: Box::new(Expr::Ident(ident.clone())), - } - .into(), - right: 1.0.into(), - } - .into(); - for value in v.iter() { - expr = self.export_call(value.clone(), DUMMY_SP, expr).into(); - } - return SeqExpr { - span: DUMMY_SP, - exprs: vec![Box::new(expr), Box::new(Expr::Update(update_expr))], - } - .into(); - } - } - update_expr.into() - } - _ => update_expr.into(), - } - } else { - update_expr.into() - } - } - - fn add_export_name(&mut self, key: Id, value: Atom) { - let mut find = false; - for (k, v) in self.export_map.iter_mut() { - if key == *k { - v.push(value.clone()); - find = true; - break; - } - } - if !find { - self.export_map.insert(key, vec![value]); - } - } - - fn add_declare_var_idents(&mut self, ident: &Ident) { - self.declare_var_idents.push(ident.clone()); - } - - fn build_export_call( - &mut self, - export_names: &mut Vec, - export_values: &mut Vec>, - ) -> Vec { - match export_names.len() { - 0 => Vec::new(), - 1 => vec![self - .export_call(export_names.remove(0), DUMMY_SP, *export_values.remove(0)) - .into_stmt()], - _ => { - let mut props = Vec::new(); - for (sym, value) in export_names.drain(..).zip(export_values.drain(..)) { - props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { - key: match Ident::verify_symbol(&sym) { - Ok(..) => PropName::Ident(quote_ident!(sym)), - Err(..) => PropName::Str(quote_str!(sym)), - }, - value, - })))); - } - vec![CallExpr { - span: DUMMY_SP, - callee: self.export_ident.clone().as_callee(), - args: vec![ObjectLit { - span: DUMMY_SP, - props, - } - .as_arg()], - ..Default::default() - } - .into_stmt()] - } - } - } - - fn build_module_item_export_all(&mut self, mut meta: ModuleItemMeta) -> Vec { - if !meta.has_export_all { - meta.setter_fn_stmts.append( - &mut self.build_export_call(&mut meta.export_names, &mut meta.export_values), - ); - } else { - let export_obj = quote_ident!("exportObj"); - let key_ident = quote_ident!("key"); - let target = quote_ident!(local_name_for_src(&meta.src)); - meta.setter_fn_stmts.push( - VarDecl { - kind: VarDeclKind::Var, - decls: vec![VarDeclarator { - span: DUMMY_SP, - name: export_obj.clone().into(), - init: Some(Box::new(Expr::Object(ObjectLit { - span: DUMMY_SP, - props: Vec::new(), - }))), - definite: false, - }], - ..Default::default() - } - .into(), - ); - meta.setter_fn_stmts.push( - ForInStmt { - span: DUMMY_SP, - left: VarDecl { - kind: VarDeclKind::Var, - decls: vec![VarDeclarator { - span: DUMMY_SP, - name: key_ident.clone().into(), - init: None, - definite: false, - }], - ..Default::default() - } - .into(), - right: target.clone().into(), - - body: Box::new(Stmt::Block(BlockStmt { - span: DUMMY_SP, - stmts: vec![Stmt::If(IfStmt { - span: DUMMY_SP, - test: Box::new(Expr::Bin(BinExpr { - span: DUMMY_SP, - op: op!("&&"), - left: Box::new( - key_ident - .clone() - .make_bin(op!("!=="), quote_str!("default")), - ), - right: Box::new( - key_ident - .clone() - .make_bin(op!("!=="), quote_str!("__esModule")), - ), - })), - cons: Box::new(Stmt::Block(BlockStmt { - stmts: vec![AssignExpr { - span: DUMMY_SP, - op: op!("="), - left: export_obj - .clone() - .computed_member(key_ident.clone()) - .into(), - right: target.computed_member(key_ident).into(), - } - .into_stmt()], - ..Default::default() - })), - alt: None, - })], - - ..Default::default() - })), - } - .into(), - ); - for (sym, value) in meta - .export_names - .drain(..) - .zip(meta.export_values.drain(..)) - { - meta.setter_fn_stmts.push( - AssignExpr { - span: DUMMY_SP, - op: op!("="), - left: export_obj.clone().make_member(quote_ident!(sym)).into(), - right: value, - } - .into_stmt(), - ); - } - meta.setter_fn_stmts.push( - CallExpr { - span: DUMMY_SP, - callee: self.export_ident.clone().as_callee(), - args: vec![export_obj.as_arg()], - ..Default::default() - } - .into_stmt(), - ); - } - - meta.setter_fn_stmts - } - - fn add_module_item_meta(&mut self, mut m: ModuleItemMeta) { - match self - .module_item_meta_list - .iter() - .position(|i| m.src.eq(&i.src)) - { - Some(index) => { - let mut meta = self.module_item_meta_list.remove(index); - meta.setter_fn_stmts.append(&mut m.setter_fn_stmts); - meta.export_names.append(&mut m.export_names); - meta.export_values.append(&mut m.export_values); - if m.has_export_all { - meta.has_export_all = m.has_export_all; - } - self.module_item_meta_list.insert(index, meta); - } - None => { - self.module_item_meta_list.push(m); - } - } - } - - #[allow(clippy::boxed_local)] - fn hoist_var_decl(&mut self, var_decl: Box) -> Option { - let mut exprs = Vec::new(); - for var_declarator in var_decl.decls { - let mut tos: Vec = Vec::new(); - var_declarator.visit_with(&mut VarCollector { to: &mut tos }); - - for (sym, ctxt) in tos { - if var_declarator.init.is_none() { - for (k, v) in self.export_map.iter_mut() { - if (sym.clone(), ctxt) == *k { - for value in v.iter() { - self.export_names.push(value.clone()); - self.export_values.push(Expr::undefined(DUMMY_SP)); - } - break; - } - } - } - self.declare_var_idents - .push(Ident::new(sym, DUMMY_SP, ctxt)); - } - - if let Some(init) = var_declarator.init { - exprs.push( - AssignExpr { - span: DUMMY_SP, - op: op!("="), - left: var_declarator.name.try_into().unwrap(), - right: init, - } - .into(), - ); - } - } - match exprs.len() { - 0 => None, - _ => Some( - SeqExpr { - span: DUMMY_SP, - exprs, - } - .into(), - ), - } - } - - fn hoist_for_var_decl(&mut self, var_decl_or_pat: ForHead) -> ForHead { - if let ForHead::VarDecl(mut var_decl) = var_decl_or_pat { - if var_decl.kind == VarDeclKind::Var { - let var_declarator = var_decl.decls.remove(0); - let mut tos: Vec = Vec::new(); - var_declarator.visit_with(&mut VarCollector { to: &mut tos }); - - for to in tos { - if var_declarator.init.is_none() { - for (k, v) in self.export_map.iter_mut() { - if to == *k { - for value in v.iter() { - self.export_names.push(value.clone()); - self.export_values.push(Expr::undefined(DUMMY_SP)); - } - break; - } - } - } - self.declare_var_idents - .push(Ident::new(to.0, DUMMY_SP, to.1)); - } - - ForHead::Pat(var_declarator.name.into()) - } else { - ForHead::VarDecl(var_decl) - } - } else { - var_decl_or_pat - } - } - - fn hoist_variables(&mut self, stmt: Stmt) -> Stmt { - match stmt { - Stmt::Decl(decl) => { - if let Decl::Var(var_decl) = decl { - // if var_decl.kind == VarDeclKind::Var { - if let Some(expr) = self.hoist_var_decl(var_decl) { - expr.into_stmt() - } else { - EmptyStmt { span: DUMMY_SP }.into() - } - // } else { - // return Stmt::Decl(Decl::Var(var_decl)); - // } - } else { - decl.into() - } - } - Stmt::For(for_stmt) => { - if let Some(init) = for_stmt.init { - if let VarDeclOrExpr::VarDecl(var_decl) = init { - if var_decl.kind == VarDeclKind::Var { - ForStmt { - init: self - .hoist_var_decl(var_decl) - .map(|expr| VarDeclOrExpr::Expr(Box::new(expr))), - ..for_stmt - } - .into() - } else { - ForStmt { - init: Some(VarDeclOrExpr::VarDecl(var_decl)), - ..for_stmt - } - .into() - } - } else { - ForStmt { - init: Some(init), - ..for_stmt - } - .into() - } - } else { - for_stmt.into() - } - } - Stmt::ForIn(for_in_stmt) => ForInStmt { - left: self.hoist_for_var_decl(for_in_stmt.left), - ..for_in_stmt - } - .into(), - Stmt::ForOf(for_of_stmt) => ForOfStmt { - left: self.hoist_for_var_decl(for_of_stmt.left), - ..for_of_stmt - } - .into(), - _ => stmt, - } - } +struct SystemJs { + resolver: Resolver, + unresolved_mark: Mark, + config: Config, } -impl Fold for SystemJs { - standard_only_fold!(); - - fn fold_call_expr(&mut self, expr: CallExpr) -> CallExpr { - let expr = expr.fold_children_with(self); - - match expr.callee { - Callee::Import(_) => CallExpr { - callee: self - .context_ident - .clone() - .make_member(quote_ident!("import")) - .as_callee(), - ..expr - }, - _ => expr, - } - } - - fn fold_expr(&mut self, expr: Expr) -> Expr { - let expr = expr.fold_children_with(self); - - match expr { - Expr::Ident(ident) => self.fold_module_name_ident(ident), - Expr::Assign(assign) => { - let assign_expr = AssignExpr { - right: match *assign.right { - Expr::Ident(ident) => Box::new(self.fold_module_name_ident(ident)), - Expr::Assign(AssignExpr { - op: AssignOp::Assign, - .. - }) => { - return self.replace_assign_expr(AssignExpr { - right: assign.right, - ..assign - }); - } - _ => assign.right, - }, - ..assign - } - .fold_with(self); - self.replace_assign_expr(assign_expr) - } - Expr::Update(update) => self.replace_update_expr(update), - Expr::Call(call) => match call.callee { - Callee::Import(_) => CallExpr { - args: call.args.fold_with(self), - callee: self - .context_ident - .clone() - .make_member(quote_ident!("import")) - .as_callee(), - ..call - } - .into(), - _ => call.into(), - }, - Expr::MetaProp(meta_prop_expr) => match meta_prop_expr.kind { - MetaPropKind::ImportMeta => self - .context_ident - .clone() - .make_member(quote_ident!("meta")) - .into(), - _ => meta_prop_expr.into(), - }, - Expr::Await(await_expr) => { - if self.enter_async_fn == 0 { - self.tla = true; - } - - await_expr.into() - } - _ => expr, - } - } - - fn fold_fn_decl(&mut self, fn_decl: FnDecl) -> FnDecl { - let is_async = fn_decl.function.is_async; - if is_async { - self.enter_async_fn += 1; - } - let fold_fn_expr = fn_decl.fold_children_with(self); - if is_async { - self.enter_async_fn -= 1; - } - fold_fn_expr - } - - fn fold_prop(&mut self, prop: Prop) -> Prop { - let prop = prop.fold_children_with(self); - - match prop { - Prop::Shorthand(shorthand) => Prop::KeyValue(KeyValueProp { - key: PropName::Ident(shorthand.clone().into()), - value: Box::new(self.fold_module_name_ident(shorthand)), - }), - Prop::KeyValue(key_value_prop) => Prop::KeyValue(KeyValueProp { - key: key_value_prop.key, - value: match *key_value_prop.value { - Expr::Ident(ident) => Box::new(self.fold_module_name_ident(ident)), - _ => key_value_prop.value, - }, - }), - _ => prop, - } - } - - fn fold_module(&mut self, module: Module) -> Module { - let module = { - let mut module = module; - if !self.config.allow_top_level_this { - top_level_this(&mut module, *Expr::undefined(DUMMY_SP)); - } - module - }; - let mut before_body_stmts: Vec = Vec::new(); - let mut execute_stmts = Vec::new(); +impl VisitMut for SystemJs { + noop_visit_mut_type!(fail); - // collect top level fn decl - for item in &module.body { - if let ModuleItem::Stmt(Stmt::Decl(Decl::Fn(fn_decl))) = item { - self.root_fn_decl_idents.push(fn_decl.ident.clone()); - } + fn visit_mut_module(&mut self, n: &mut Module) { + if !self.config.allow_top_level_this { + top_level_this(&mut n.body, *Expr::undefined(DUMMY_SP)); } - for item in module.body { - match item { - ModuleItem::ModuleDecl(decl) => match decl { - ModuleDecl::Import(import) => { - let src = match &self.resolver { - Resolver::Real { resolver, base } => { - let spec = wtf8_to_cow_str(&import.src.value); - resolver - .resolve_import(base, &spec) - .with_context(|| { - format!( - "failed to resolve import `{}`", - import.src.value.to_string_lossy() - ) - }) - .unwrap() - } - Resolver::Default => normalize_wtf8_atom(&import.src.value), - }; - - let source_alias = local_name_for_src(&src); - - let mut setter_fn_stmts = Vec::new(); - - for specifier in import.specifiers { - match specifier { - ImportSpecifier::Default(specifier) => { - self.import_idents.push(specifier.local.to_id()); - self.add_declare_var_idents(&specifier.local); - setter_fn_stmts.push( - AssignExpr { - span: specifier.span, - op: op!("="), - left: specifier.local.into(), - right: quote_ident!(source_alias.clone()) - .make_member(quote_ident!("default")) - .into(), - } - .into_stmt(), - ); - } - ImportSpecifier::Named(specifier) => { - self.add_declare_var_idents(&specifier.local); - setter_fn_stmts.push( - AssignExpr { - span: specifier.span, - op: op!("="), - left: specifier.local.clone().into(), - right: MemberExpr { - span: DUMMY_SP, - obj: Box::new( - quote_ident!(source_alias.clone()).into(), - ), - prop: match specifier.imported { - Some(m) => get_module_export_member_prop(&m), - None => { - MemberProp::Ident(specifier.local.into()) - } - }, - } - .into(), - } - .into_stmt(), - ); - } - ImportSpecifier::Namespace(specifier) => { - self.import_idents.push(specifier.local.to_id()); - self.add_declare_var_idents(&specifier.local); - setter_fn_stmts.push( - AssignExpr { - span: specifier.span, - op: op!("="), - left: specifier.local.into(), - right: quote_ident!(source_alias.clone()).into(), - } - .into_stmt(), - ); - } - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } - } - - self.add_module_item_meta(ModuleItemMeta { - export_names: Vec::new(), - export_values: Vec::new(), - has_export_all: false, - src: src.clone(), - setter_fn_stmts, - }); - } - ModuleDecl::ExportNamed(decl) => match decl.src { - Some(s) => { - let src = match &self.resolver { - Resolver::Real { resolver, base } => { - let spec = wtf8_to_cow_str(&s.value); - resolver - .resolve_import(base, &spec) - .with_context(|| { - format!( - "failed to resolve import `{}`", - s.value.to_string_lossy() - ) - }) - .unwrap() - } - Resolver::Default => normalize_wtf8_atom(&s.value), - }; - for specifier in decl.specifiers { - let source_alias = local_name_for_src(&src); - let mut export_names = Vec::new(); - let mut export_values = Vec::new(); - - match specifier { - ExportSpecifier::Named(specifier) => { - export_names.push(match &specifier.exported { - Some(m) => get_module_export_name(m).0, - None => get_module_export_name(&specifier.orig).0, - }); - export_values.push( - MemberExpr { - span: DUMMY_SP, - obj: Box::new( - quote_ident!(source_alias.clone()).into(), - ), - prop: get_module_export_member_prop( - &specifier.orig, - ), - } - .into(), - ); - } - ExportSpecifier::Default(specifier) => { - export_names.push(specifier.exported.sym.clone()); - export_values.push( - quote_ident!(source_alias.clone()) - .make_member(quote_ident!("default")) - .into(), - ); - } - ExportSpecifier::Namespace(specifier) => { - export_names - .push(get_module_export_name(&specifier.name).0); - export_values - .push(quote_ident!(source_alias.clone()).into()); - } - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } + let mut source = SourceModule::collect(n.body.take()); + let has_use_strict = source.has_use_strict; + let mut wrapper_stmts = std::mem::take(&mut source.directives); + wrapper_stmts.reserve(8); - self.add_module_item_meta(ModuleItemMeta { - export_names, - export_values, - has_export_all: false, - src: src.clone(), - setter_fn_stmts: Vec::new(), - }); - } - } - None => { - for specifier in decl.specifiers { - if let ExportSpecifier::Named(specifier) = specifier { - let id = get_module_export_name(&specifier.orig); - - if self.root_fn_decl_idents.iter().any(|i| i.sym == id.0) { - // hoisted function export - self.export_names.push(match &specifier.exported { - Some(m) => get_module_export_name(m).0, - None => id.0.clone(), - }); - self.export_values.push(Box::new(get_module_export_expr( - &specifier.orig, - ))); - } - if self.import_idents.contains(&id) { - execute_stmts.push( - self.export_call( - id.0.clone(), - DUMMY_SP, - match &specifier.exported { - Some(m) => get_module_export_expr(m), - None => get_module_export_expr(&specifier.orig), - }, - ) - .into_stmt(), - ); - } - self.add_export_name( - id, - match specifier.exported { - Some(m) => get_module_export_name(&m).0, - None => get_module_export_name(&specifier.orig).0, - }, - ); - } - } - } - }, - ModuleDecl::ExportDecl(decl) => { - match decl.decl { - Decl::Class(class_decl) => { - let ident = class_decl.ident; - self.export_names.push(ident.sym.clone()); - self.export_values.push(Expr::undefined(DUMMY_SP)); - self.add_declare_var_idents(&ident); - self.add_export_name(ident.to_id(), ident.sym.clone()); - execute_stmts.push( - AssignExpr { - span: DUMMY_SP, - op: op!("="), - left: ident.clone().into(), - right: ClassExpr { - ident: Some(ident.clone()), - class: class_decl.class, - } - .into(), - } - .into_stmt(), - ); - } - Decl::Fn(fn_decl) => { - self.export_names.push(fn_decl.ident.sym.clone()); - self.export_values.push(fn_decl.ident.clone().into()); - self.add_export_name( - fn_decl.ident.to_id(), - fn_decl.ident.sym.clone(), - ); - before_body_stmts.push(fn_decl.into()); - } - Decl::Var(var_decl) => { - let mut decl = VarDecl { - decls: Vec::new(), - ..*var_decl - }; - for var_declarator in var_decl.decls { - let mut tos: Vec = Vec::new(); - var_declarator.visit_with(&mut VarCollector { to: &mut tos }); - for to in tos { - let ident = Ident::new(to.0.clone(), DUMMY_SP, to.1); - self.add_export_name(to, ident.sym.clone()); - } - decl.decls.push(var_declarator); - } - execute_stmts.push(decl.into()); - } - _ => {} - }; - } - ModuleDecl::ExportDefaultDecl(decl) => { - match decl.decl { - DefaultDecl::Class(class_expr) => { - if let Some(ident) = &class_expr.ident { - self.export_names.push("default".into()); - self.export_values.push(Expr::undefined(DUMMY_SP)); - self.add_declare_var_idents(ident); - self.add_export_name(ident.to_id(), "default".into()); - execute_stmts.push( - AssignExpr { - span: DUMMY_SP, - op: op!("="), - left: ident.clone().into(), - right: class_expr.into(), - } - .into_stmt(), - ); - } else { - self.export_names.push("default".into()); - self.export_values.push(class_expr.into()); - } - } - DefaultDecl::Fn(fn_expr) => { - if let Some(ident) = &fn_expr.ident { - self.export_names.push("default".into()); - self.export_values.push(ident.clone().into()); - self.add_export_name(ident.to_id(), "default".into()); - before_body_stmts.push( - FnDecl { - ident: ident.clone(), - declare: false, - function: fn_expr.function, - } - .into(), - ); - } else { - self.export_names.push("default".into()); - self.export_values.push(fn_expr.into()); - } - } - _ => {} - }; - } - ModuleDecl::ExportDefaultExpr(expr) => { - execute_stmts.push( - self.export_call("default".into(), expr.span, *expr.expr) - .into_stmt(), - ); - } - ModuleDecl::ExportAll(decl) => { - self.add_module_item_meta(ModuleItemMeta { - export_names: Vec::new(), - export_values: Vec::new(), - has_export_all: true, - src: normalize_wtf8_atom(&decl.src.value), - setter_fn_stmts: Vec::new(), - }); - } - _ => {} - }, - ModuleItem::Stmt(stmt) => match stmt { - Stmt::Decl(decl) => match decl { - Decl::Class(class_decl) => { - self.add_declare_var_idents(&class_decl.ident); - execute_stmts.push( - AssignExpr { - span: DUMMY_SP, - op: op!("="), - left: class_decl.ident.clone().into(), - right: ClassExpr { - ident: Some(class_decl.ident.clone()), - class: class_decl.class, - } - .into(), - } - .into_stmt(), - ); - } - Decl::Fn(fn_decl) => { - before_body_stmts.push(fn_decl.into()); - } - _ => execute_stmts.push(decl.into()), - }, - _ => execute_stmts.push(stmt), - }, - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } + if self.config.strict_mode && !has_use_strict { + wrapper_stmts.push(use_strict()); } - // ==================== - // fold_with function, here export_map is collected finished. - // ==================== - - before_body_stmts = before_body_stmts - .into_iter() - .map(|s| s.fold_with(self)) - .collect(); - - execute_stmts = execute_stmts - .into_iter() - .map(|s| self.hoist_variables(s).fold_with(self)) - .filter(|s| !matches!(s, Stmt::Empty(_))) - .collect(); + let export_ident = private_ident!("_export"); + let context_ident = private_ident!("_context"); + let unresolved_ctxt = SyntaxContext::empty().apply_mark(self.unresolved_mark); - // ==================== - // generate export call, here export_names is collected finished. - // ==================== - if !self.export_names.is_empty() { - let mut export_names = self.export_names.drain(..).collect(); - let mut export_values = self.export_values.drain(..).collect(); - before_body_stmts - .append(&mut self.build_export_call(&mut export_names, &mut export_values)); - } - - let mut setters = ArrayLit { - span: DUMMY_SP, - elems: Vec::new(), - }; + let mut module = lower::lower(source); - let mut dep_module_names = ArrayLit { - span: DUMMY_SP, - elems: Vec::new(), - }; + rewrite::rewrite_special_refs( + &mut module, + context_ident.clone(), + unresolved_ctxt, + &self.resolver, + self.config.ignore_dynamic, + self.config.preserve_import_meta, + ); - let module_item_meta_list: Vec = - self.module_item_meta_list.drain(..).collect(); - for meta in module_item_meta_list { - dep_module_names - .elems - .push(Some(quote_str!(meta.src.clone()).as_arg())); - setters.elems.push(Some( - Function { - params: vec![Param { - span: DUMMY_SP, - decorators: Default::default(), - pat: quote_ident!(local_name_for_src(&meta.src)).into(), - }], - span: DUMMY_SP, - body: Some(BlockStmt { - span: DUMMY_SP, - stmts: self.build_module_item_export_all(meta), - ..Default::default() - }), - is_generator: false, - is_async: false, - ..Default::default() - } - .as_arg(), - )); + let mut export_rewriter = rewrite::ExportBindingRewriter::new( + module.exports.local_exports.clone(), + export_ident.clone(), + module.export_setters.clone(), + ); + rewrite::rewrite_export_bindings(&mut module, &mut export_rewriter); + if export_rewriter.needs_old_temp() { + module.wrapper_vars.push(export_rewriter.old_temp()); } - - let execute = Box::new(Function { - params: Vec::new(), - decorators: Default::default(), - span: DUMMY_SP, - body: Some(BlockStmt { - stmts: execute_stmts, - ..Default::default() - }), - is_generator: false, - is_async: self.tla, - ..Default::default() - }); - - let return_stmt = ReturnStmt { - span: DUMMY_SP, - arg: Some( - ObjectLit { - span: DUMMY_SP, - props: vec![ - PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { - key: quote_ident!("setters").into(), - value: Box::new(Expr::Array(setters)), - }))), - PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { - key: quote_ident!("execute").into(), - value: Box::new(Expr::Fn(FnExpr { - ident: None, - function: execute, - })), - }))), - ], - } - .into(), - ), - }; - - let mut function_stmts = vec![use_strict()]; - - if !self.declare_var_idents.is_empty() { - function_stmts.push( - VarDecl { - span: DUMMY_SP, - kind: VarDeclKind::Var, - declare: false, - decls: self - .declare_var_idents - .iter() - .map(|i| VarDeclarator { - span: i.span, - name: i.clone().into(), - init: None, - definite: false, - }) - .collect(), - ..Default::default() - } - .into(), - ); + if export_rewriter.needs_export_setters() { + module.needs_export_setters = true; } - function_stmts.append(&mut before_body_stmts); - function_stmts.push(return_stmt.into()); - let function = Box::new(Function { - params: vec![ - Param { - span: DUMMY_SP, - decorators: Default::default(), - pat: self.export_ident.clone().into(), - }, - Param { - span: DUMMY_SP, - decorators: Default::default(), - pat: self.context_ident.clone().into(), - }, - ], - decorators: Default::default(), - span: DUMMY_SP, - body: Some(BlockStmt { - span: DUMMY_SP, - stmts: function_stmts, - ..Default::default() - }), - is_generator: false, - is_async: false, - ..Default::default() - }); + module.async_execute = module.execute_stmts.iter().any(contains_top_level_await); + let register_args = emit::emit( + wrapper_stmts, + module, + export_ident, + context_ident, + &self.resolver, + ); - Module { - body: vec![CallExpr { - span: DUMMY_SP, - callee: member_expr!(Default::default(), Default::default(), System.register) - .as_callee(), - args: vec![ - dep_module_names.as_arg(), - FnExpr { - ident: None, - function, - } - .as_arg(), - ], - ..Default::default() - } + n.body = vec![quote_ident!(unresolved_ctxt, "System") + .make_member(quote_ident!("register")) + .as_call(DUMMY_SP, register_args) .into_stmt() - .into()], - ..module - } + .into()]; } -} -#[inline] -fn get_module_export_name(module_export_name: &ModuleExportName) -> Id { - match &module_export_name { - ModuleExportName::Ident(ident) => ident.to_id(), - ModuleExportName::Str(s) => (s.value.to_atom_lossy().into_owned(), SyntaxContext::empty()), - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } -} - -#[inline] -fn get_module_export_expr(module_export_name: &ModuleExportName) -> Expr { - match &module_export_name { - ModuleExportName::Ident(ident) => ident.clone().into(), - ModuleExportName::Str(s) => { - Lit::Str(quote_str!(s.value.to_atom_lossy().into_owned())).into() - } - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } -} - -#[inline] -fn get_module_export_member_prop(module_export_name: &ModuleExportName) -> MemberProp { - match &module_export_name { - ModuleExportName::Ident(ident) => MemberProp::Ident(ident.clone().into()), - ModuleExportName::Str(s) => MemberProp::Computed(ComputedPropName { - span: s.span, - expr: Lit::Str(quote_str!(s.value.to_atom_lossy().into_owned())).into(), - }), - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } + fn visit_mut_script(&mut self, _: &mut Script) {} } diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/system_js/emit.rs b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/emit.rs new file mode 100644 index 000000000..2d1145068 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/emit.rs @@ -0,0 +1,517 @@ +use indexmap::{IndexMap, IndexSet}; +use swc_atoms::Atom; +use swc_common::{util::take::Take, Spanned, DUMMY_SP}; +use swc_ecma_ast::*; +use swc_ecma_utils::{ + private_ident, prop_name_from_str, quote_ident, quote_str, ExprFactory, FunctionFactory, +}; + +use super::{ + ir::{DependencySlot, ExecuteStmt, ExportInit, ExportName, SetterOp, SystemModule}, + lower::{export_call, export_names_call}, + util::{export_object_init, member_expr_for, member_for_export, object_lit_prop_name}, +}; +use crate::{module_record::ImportAttributeRecord, path::Resolver, util::prop_name}; + +enum DirectReExport { + Named(Atom), + Namespace, +} + +impl DirectReExport { + fn into_value(self, namespace: Ident) -> Expr { + match self { + Self::Named(imported) => member_for_export(namespace, &imported), + Self::Namespace => namespace.into(), + } + } +} + +pub(super) fn emit( + mut stmts: Vec, + mut module: SystemModule, + export_ident: Ident, + context_ident: Ident, + resolver: &Resolver, +) -> Vec { + let deps = emit_dependency_array(&module.dependencies, resolver); + let setters = emit_setters(&module.dependencies, &module, &export_ident); + let metadata = emit_metadata_array(&module.dependencies); + let initialized_exports = module.export_inits.take(); + let export_inits = emit_export_inits(&module, initialized_exports, &export_ident); + + emit_var_decl(&mut stmts, module.wrapper_vars.take()); + emit_export_setters(&mut stmts, &module, &export_ident); + stmts.extend( + module + .wrapper_fns + .take() + .into_iter() + .map(|f| Stmt::Decl(Decl::Fn(f))), + ); + stmts.extend(module.wrapper_stmts.take()); + stmts.extend(export_inits); + + let execute: Expr = Function { + body: Some(FunctionBody { + span: DUMMY_SP, + stmts: module + .execute_stmts + .into_iter() + .map(|execute_stmt| emit_execute_stmt(execute_stmt, &export_ident)) + .collect(), + }), + is_async: module.async_execute, + ..Default::default() + } + .into_fn_expr(None) + .into(); + + let register_body = ObjectLit { + span: DUMMY_SP, + props: vec![ + Prop::KeyValue(KeyValueProp { + key: quote_ident!("setters").into(), + value: setters.into(), + }) + .into(), + Prop::KeyValue(KeyValueProp { + key: quote_ident!("execute").into(), + value: execute.into(), + }) + .into(), + ], + }; + + stmts.push( + ReturnStmt { + span: DUMMY_SP, + arg: Some(register_body.into()), + } + .into(), + ); + + let register = Function { + params: vec![export_ident.into(), context_ident.into()], + body: Some(FunctionBody { + span: DUMMY_SP, + stmts, + }), + ..Default::default() + } + .into_fn_expr(None); + + let mut args = vec![deps.as_arg(), register.as_arg()]; + if let Some(metadata) = metadata { + args.push(metadata.as_arg()); + } + + args +} + +fn emit_execute_stmt(stmt: ExecuteStmt, export_ident: &Ident) -> Stmt { + match stmt { + ExecuteStmt::Source(stmt) => stmt, + ExecuteStmt::Assign { left, right } => AssignExpr { + span: right.span(), + op: op!("="), + left, + right, + } + .into_stmt(), + ExecuteStmt::ExportAssign { + exports, + local, + right, + } => { + let assign: Expr = AssignExpr { + span: right.span(), + op: op!("="), + left: local.into(), + right, + } + .into(); + export_call(export_ident, &exports, assign).into_stmt() + } + ExecuteStmt::ExportValue { export, value } => { + export_call(export_ident, &[export], *value).into_stmt() + } + ExecuteStmt::ExportBatch { value } => export_ident + .clone() + .as_call(value.span(), vec![value.as_arg()]) + .into_stmt(), + ExecuteStmt::ExportNames { exports, value } => { + export_names_call(export_ident, &exports, value).into_stmt() + } + } +} + +fn emit_dependency_array(deps: &[DependencySlot], resolver: &Resolver) -> Expr { + ArrayLit { + elems: deps + .iter() + .map(|dep| { + let request = resolver.resolve(dep.request.clone()); + Some( + Str { + span: dep.span.0, + value: request.into(), + raw: None, + } + .as_arg(), + ) + }) + .collect(), + ..Default::default() + } + .into() +} + +fn emit_metadata_array(deps: &[DependencySlot]) -> Option { + if !deps.iter().any(|dep| !dep.attributes.is_empty()) { + return None; + } + + let array = ArrayLit { + elems: deps.iter().map(emit_metadata_element).collect(), + ..Default::default() + }; + + Some(array.into()) +} + +fn emit_metadata_element(dep: &DependencySlot) -> Option { + let metadata = ObjectLit { + props: emit_metadata_props(&dep.attributes), + ..Default::default() + }; + + Some(metadata.as_arg()) +} + +fn emit_metadata_props(attributes: &[ImportAttributeRecord]) -> Vec { + if attributes.is_empty() { + return Vec::new(); + } + + let assert_prop = Prop::KeyValue(KeyValueProp { + key: quote_ident!("assert").into(), + value: emit_import_attributes(attributes).into(), + }); + + vec![assert_prop.into()] +} + +fn emit_import_attributes(attributes: &[ImportAttributeRecord]) -> ObjectLit { + ObjectLit { + props: attributes + .iter() + .map(|attribute| { + Prop::KeyValue(KeyValueProp { + key: prop_name_from_str(DUMMY_SP, attribute.key()), + value: attribute.value().clone().into(), + }) + .into() + }) + .collect(), + ..Default::default() + } +} + +fn emit_setters(deps: &[DependencySlot], module: &SystemModule, export_ident: &Ident) -> Expr { + ArrayLit { + elems: deps + .iter() + .map(|dep| Some(emit_setter(dep, module, export_ident).as_arg())) + .collect(), + ..Default::default() + } + .into() +} + +fn emit_setter(dep: &DependencySlot, module: &SystemModule, export_ident: &Ident) -> Expr { + let needs_namespace = !dep.setter_ops.is_empty(); + let mut stmts = Vec::new(); + let mut direct_reexports = Vec::new(); + let mut has_star = false; + + for op in &dep.setter_ops { + match op { + SetterOp::Import { local, imported } => { + let value = imported.as_ref().map_or_else( + || dep.namespace.clone().into(), + |name| member_for_export(dep.namespace.clone(), name), + ); + stmts.push( + value + .make_assign_to(op!("="), local.clone().into()) + .into_stmt(), + ); + if let Some(exports) = module.exports.exports_for(&local.to_id()) { + stmts.push(export_names_call(export_ident, exports, local.clone()).into_stmt()); + } + } + SetterOp::ReExport { export, imported } => { + direct_reexports.push((export.clone(), DirectReExport::Named(imported.clone()))); + } + SetterOp::ReExportNamespace { export } => { + direct_reexports.push((export.clone(), DirectReExport::Namespace)); + } + SetterOp::StarExport => { + has_star = true; + } + } + } + + if has_star { + let export_obj = private_ident!("exportObj"); + stmts.push( + export_object_init() + .into_var_decl(VarDeclKind::Var, export_obj.clone().into()) + .into(), + ); + stmts.push(emit_star_loop(export_obj.clone(), dep.namespace.clone())); + for (export, imported) in direct_reexports { + stmts.push( + imported + .into_value(dep.namespace.clone()) + .make_assign_to( + op!("="), + member_expr_for(export_obj.clone(), &export.name, export.span).into(), + ) + .into_stmt(), + ); + } + stmts.push( + export_ident + .clone() + .as_call(DUMMY_SP, vec![export_obj.as_arg()]) + .into_stmt(), + ); + } else if !direct_reexports.is_empty() { + let exports = direct_reexports + .into_iter() + .map(|(export, imported)| (export, imported.into_value(dep.namespace.clone()))) + .collect::>(); + stmts.push(export_values_call(export_ident, exports).into_stmt()); + } + + Function { + params: if needs_namespace { + vec![dep.namespace.clone().into()] + } else { + Default::default() + }, + body: Some(FunctionBody { + span: DUMMY_SP, + stmts, + }), + ..Default::default() + } + .into_fn_expr(None) + .into() +} + +fn emit_star_loop(export_obj: Ident, namespace: Ident) -> Stmt { + let key = quote_ident!("key"); + let test = key + .clone() + .make_bin(op!("!=="), quote_str!("default")) + .make_bin( + op!("&&"), + key.clone().make_bin(op!("!=="), quote_str!("__esModule")), + ); + let assign = namespace + .clone() + .computed_member(key.clone()) + .make_assign_to(op!("="), export_obj.computed_member(key.clone()).into()) + .into_stmt(); + + ForInStmt { + span: DUMMY_SP, + left: VarDecl { + decls: vec![VarDeclarator { + span: DUMMY_SP, + name: key.clone().into(), + init: None, + definite: false, + }], + ..Default::default() + } + .into(), + right: namespace.into(), + body: IfStmt { + span: DUMMY_SP, + test: test.into(), + cons: assign.into(), + alt: None, + } + .into(), + } + .into() +} + +fn emit_var_decl(stmts: &mut Vec, mut vars: Vec) { + vars.sort_unstable_by(|a, b| a.sym.cmp(&b.sym)); + let mut seen: IndexSet = IndexSet::default(); + let decls = vars + .into_iter() + .filter(|ident| seen.insert(ident.to_id())) + .map(|ident| VarDeclarator { + span: ident.span, + name: ident.into(), + init: None, + definite: false, + }) + .collect::>(); + + if !decls.is_empty() { + stmts.push( + VarDecl { + kind: VarDeclKind::Var, + decls, + ..Default::default() + } + .into(), + ); + } +} + +fn emit_export_setters(stmts: &mut Vec, module: &SystemModule, export_ident: &Ident) { + if !module.needs_export_setters { + return; + } + + let setters = module + .exports + .local_exports + .iter() + .filter(|(_, exports)| !exports.is_empty()) + .map(|((sym, ctxt), exports)| { + let local = Ident::new(sym.clone(), DUMMY_SP, *ctxt); + let value = private_ident!("_value"); + Prop::Setter(SetterProp { + key: prop_name(sym, Default::default()).into(), + function: Box::new(Function { + params: vec![Param::from(Pat::Ident(BindingIdent { + id: value.clone(), + type_ann: None, + }))], + body: Some(FunctionBody { + span: DUMMY_SP, + stmts: vec![ + value + .make_assign_to(op!("="), local.clone().into()) + .into_stmt(), + export_names_call(export_ident, exports, local).into_stmt(), + ], + }), + ..Default::default() + }), + span: DUMMY_SP, + }) + .into() + }) + .collect::>(); + + if setters.is_empty() { + return; + } + + stmts.push( + ObjectLit { + props: setters, + ..Default::default() + } + .into_var_decl(VarDeclKind::Var, module.export_setters.clone().into()) + .into(), + ); +} + +fn emit_export_inits( + module: &SystemModule, + initialized_exports: Vec, + export_ident: &Ident, +) -> Vec { + let mut announced = Vec::new(); + let mut seen: IndexSet = IndexSet::default(); + for export in &module.exports.announced { + if seen.insert(export.name.clone()) { + announced.push(export.clone()); + } + } + + if announced.is_empty() { + return Default::default(); + } + + let mut initial_values = module + .wrapper_fns + .iter() + .filter_map(|fn_decl| { + module + .exports + .exports_for(&fn_decl.ident.to_id()) + .map(|exports| (fn_decl.ident.clone(), exports)) + }) + .flat_map(|(ident, exports)| { + exports + .iter() + .map(move |export| (export.name.clone(), ident.clone())) + }) + .map(|(export, ident)| (export, Expr::from(ident))) + .collect::>(); + for ExportInit { export, value } in initialized_exports { + initial_values.insert(export.name, *value); + } + + let props = announced + .into_iter() + .map(|export| { + let value = initial_values + .shift_remove(&export.name) + .unwrap_or_else(|| *Expr::undefined(DUMMY_SP)); + (export, value) + }) + .collect::>(); + + vec![export_values_call(export_ident, props).into_stmt()] +} + +fn export_values_call(export_ident: &Ident, exports: Vec<(ExportName, Expr)>) -> Expr { + if exports.len() == 1 { + let (export, value) = exports.into_iter().next().unwrap(); + return export_ident.clone().as_call( + value.span(), + vec![ + Str { + span: export.span.0, + value: export.name.into(), + raw: None, + } + .as_arg(), + value.as_arg(), + ], + ); + } + + let props = exports + .into_iter() + .map(|(export, value)| { + Prop::KeyValue(KeyValueProp { + key: object_lit_prop_name(&export.name, export.span), + value: value.into(), + }) + .into() + }) + .collect(); + + export_ident.clone().as_call( + DUMMY_SP, + vec![ObjectLit { + props, + ..Default::default() + } + .as_arg()], + ) +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/system_js/ir.rs b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/ir.rs new file mode 100644 index 000000000..d02c84829 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/ir.rs @@ -0,0 +1,231 @@ +use indexmap::IndexMap; +use swc_atoms::Atom; +use swc_ecma_ast::*; +use swc_ecma_utils::private_ident; +use swc_ecma_visit::{Visit, VisitMut, VisitMutWith, VisitWith}; + +use crate::{module_record::ImportAttributeRecord, SpanCtx}; + +#[derive(Clone, Debug)] +pub(super) struct ExportName { + pub name: Atom, + pub span: SpanCtx, +} + +#[derive(Clone, Debug, Default)] +pub(super) struct ExportTable { + pub announced: Vec, + pub local_exports: IndexMap>, +} + +impl ExportTable { + pub fn add_local(&mut self, local: Id, export: ExportName) { + self.announced.push(export.clone()); + self.local_exports.entry(local).or_default().push(export); + } + + pub fn add_indirect(&mut self, export: ExportName) { + self.announced.push(export); + } + + pub fn exports_for(&self, id: &Id) -> Option<&[ExportName]> { + self.local_exports.get(id).map(Vec::as_slice) + } +} + +/// Export value initialized in the `System.register` declaration callback. +#[derive(Debug)] +pub(super) struct ExportInit { + pub export: ExportName, + pub value: Box, +} + +impl ExportInit { + pub fn new(export: ExportName, value: Box) -> Self { + Self { export, value } + } +} + +#[derive(Debug)] +pub(super) enum SetterOp { + Import { + local: Ident, + imported: Option, + }, + ReExport { + export: ExportName, + imported: Atom, + }, + ReExportNamespace { + export: ExportName, + }, + StarExport, +} + +#[derive(Debug)] +pub(super) struct DependencySlot { + pub request: Atom, + pub span: SpanCtx, + pub attributes: Vec, + pub namespace: Ident, + pub setter_ops: Vec, +} + +#[derive(Debug)] +pub(super) enum ExecuteStmt { + Source(Stmt), + Assign { + left: AssignTarget, + right: Box, + }, + ExportAssign { + exports: Vec, + local: Ident, + right: Box, + }, + ExportValue { + export: ExportName, + value: Box, + }, + /// SystemJS batch export update: `_export(value)`. + ExportBatch { + value: Box, + }, + ExportNames { + exports: Vec, + value: Ident, + }, +} + +impl ExecuteStmt { + pub fn source(stmt: Stmt) -> Self { + Self::Source(stmt) + } + + pub fn assign(left: AssignTarget, right: Box) -> Self { + Self::Assign { left, right } + } + + pub fn export_assign(exports: &[ExportName], local: Ident, right: Box) -> Self { + Self::ExportAssign { + exports: exports.to_vec(), + local, + right, + } + } + + pub fn export_value(export: ExportName, value: Box) -> Self { + Self::ExportValue { export, value } + } + + pub fn export_batch(value: Box) -> Self { + Self::ExportBatch { value } + } + + pub fn export_names(exports: &[ExportName], value: Ident) -> Self { + Self::ExportNames { + exports: exports.to_vec(), + value, + } + } +} + +impl VisitMutWith for ExecuteStmt +where + V: ?Sized + VisitMut, +{ + fn visit_mut_with(&mut self, visitor: &mut V) { + self.visit_mut_children_with(visitor); + } + + fn visit_mut_children_with(&mut self, visitor: &mut V) { + // ExecuteStmt traversal intentionally exposes only user-authored + // expressions/statements. SystemJS scaffold such as export names and + // synthetic assignment targets is emitted later. + match self { + ExecuteStmt::Source(stmt) => { + stmt.visit_mut_with(visitor); + } + ExecuteStmt::Assign { left, right } => { + left.visit_mut_with(visitor); + right.visit_mut_with(visitor); + } + ExecuteStmt::ExportAssign { right, .. } => { + right.visit_mut_with(visitor); + } + ExecuteStmt::ExportValue { value, .. } => { + value.visit_mut_with(visitor); + } + ExecuteStmt::ExportBatch { value } => { + value.visit_mut_with(visitor); + } + ExecuteStmt::ExportNames { .. } => {} + } + } +} + +impl VisitWith for ExecuteStmt +where + V: ?Sized + Visit, +{ + fn visit_with(&self, visitor: &mut V) { + self.visit_children_with(visitor); + } + + fn visit_children_with(&self, visitor: &mut V) { + match self { + ExecuteStmt::Source(stmt) => { + stmt.visit_with(visitor); + } + ExecuteStmt::Assign { left, right } => { + left.visit_with(visitor); + right.visit_with(visitor); + } + ExecuteStmt::ExportAssign { right, .. } => { + right.visit_with(visitor); + } + ExecuteStmt::ExportValue { value, .. } => { + value.visit_with(visitor); + } + ExecuteStmt::ExportBatch { value } => { + value.visit_with(visitor); + } + ExecuteStmt::ExportNames { .. } => {} + } + } +} + +#[derive(Debug)] +pub(super) struct SystemModule { + pub dependencies: Vec, + pub exports: ExportTable, + pub export_inits: Vec, + pub wrapper_vars: Vec, + pub wrapper_fns: Vec, + pub wrapper_stmts: Vec, + pub execute_stmts: Vec, + pub export_setters: Ident, + pub needs_export_setters: bool, + pub async_execute: bool, +} + +impl SystemModule { + pub fn new(exports: ExportTable) -> Self { + Self { + dependencies: Default::default(), + exports, + export_inits: Default::default(), + wrapper_vars: Default::default(), + wrapper_fns: Default::default(), + wrapper_stmts: Default::default(), + execute_stmts: Default::default(), + export_setters: private_ident!("_export_setters"), + needs_export_setters: false, + async_execute: false, + } + } +} + +pub(super) fn export_name(name: Atom, span: SpanCtx) -> ExportName { + ExportName { name, span } +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/system_js/lower.rs b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/lower.rs new file mode 100644 index 000000000..0042125d7 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/lower.rs @@ -0,0 +1,596 @@ +use swc_atoms::{atom, Atom}; +use swc_common::{util::take::Take, Spanned, DUMMY_SP}; +use swc_ecma_ast::*; +use swc_ecma_utils::{find_pat_ids, private_ident, ExprFactory}; + +use super::{ + ir::{ + export_name as make_export_name, DependencySlot, ExecuteStmt, ExportInit, ExportName, + ExportTable, SetterOp, SystemModule, + }, + pattern::replace_exported_pat, + util::object_lit_prop_name, +}; +use crate::{ + module_record::{ + external_ts_import_equals_source, LocalExportEntries, ModuleRecordEntry, RequestedModule, + RequestedModules, SourceModule, SourceModuleItem, + }, + util::local_name_for_src, +}; + +pub(super) fn lower(source: SourceModule) -> SystemModule { + let SourceModule { + directives: _directives, + has_use_strict: _has_use_strict, + requested_modules, + local_export_entries, + ts_export_assignment, + body, + has_module_syntax: _has_module_syntax, + } = source; + let default_value_exports = collect_default_value_exports(&body); + let mut exports = collect_local_exports(local_export_entries); + exports.announced.extend(default_value_exports); + exports + .announced + .sort_unstable_by(|a, b| a.name.cmp(&b.name)); + let mut module = SystemModule::new(exports.clone()); + + lower_dependencies(&mut module, &mut exports, requested_modules); + module.exports = exports; + + for item in body { + lower_source_item(&mut module, item); + } + if let Some(export_assignment) = ts_export_assignment { + module + .execute_stmts + .push(ExecuteStmt::export_batch(export_assignment)); + } + + module +} + +fn collect_default_value_exports(body: &[SourceModuleItem]) -> Vec { + let mut exports = Vec::new(); + for item in body { + match item { + SourceModuleItem::ExportDefaultExpr(export) => { + exports.push(default_export_name(export.span)); + } + SourceModuleItem::ExportDefaultDecl(export) => match &export.decl { + DefaultDecl::Class(class_expr) if class_expr.ident.is_none() => { + exports.push(default_export_name(export.span)); + } + DefaultDecl::Fn(fn_expr) if fn_expr.ident.is_none() => { + exports.push(default_export_name(export.span)); + } + _ => {} + }, + _ => {} + } + } + + exports +} + +fn collect_local_exports(local_export_entries: LocalExportEntries) -> ExportTable { + let mut entries: Vec<_> = local_export_entries.into_iter().collect(); + entries.sort_unstable_by(|a, b| a.0.cmp(&b.0)); + + let mut exports = ExportTable::default(); + for (name, entry) in entries { + let span = entry.export_name_span(); + let local = entry.into_local_ident(); + exports.add_local(local.to_id(), make_export_name(name, span)); + } + + exports +} + +fn lower_dependencies( + module: &mut SystemModule, + exports: &mut ExportTable, + requested_modules: RequestedModules, +) { + for (module_request, RequestedModule { span, entries, .. }) in requested_modules { + let request = module_request.src().clone(); + let attributes = module_request.attributes().to_vec(); + let namespace = namespace_ident_for(&request); + let mut setter_ops = Vec::with_capacity(entries.len()); + let mut entries: Vec<_> = entries.into_iter().collect(); + entries.sort_unstable_by(compare_module_entries); + + for entry in entries { + match entry { + ModuleRecordEntry::Empty => {} + ModuleRecordEntry::ImportDefault { local_name } => { + let local = ident_from_id(local_name, span.0); + module.wrapper_vars.push(local.clone()); + setter_ops.push(SetterOp::Import { + local, + imported: Some(atom!("default")), + }); + } + ModuleRecordEntry::ImportNamed { + import_name, + local_name, + } => { + let local = ident_from_id(local_name.clone(), span.0); + module.wrapper_vars.push(local.clone()); + setter_ops.push(SetterOp::Import { + local, + imported: Some(import_name.unwrap_or(local_name.0)), + }); + } + ModuleRecordEntry::ImportNamespace { local_name } => { + let local = ident_from_id(local_name, span.0); + module.wrapper_vars.push(local.clone()); + setter_ops.push(SetterOp::Import { + local, + imported: None, + }); + } + ModuleRecordEntry::IndirectExportNamed { + import_name, + export_name, + } => { + let (export_name, export_span) = + export_name.unwrap_or_else(|| import_name.clone()); + let export = make_export_name(export_name, export_span); + exports.add_indirect(export.clone()); + setter_ops.push(SetterOp::ReExport { + export, + imported: import_name.0, + }); + } + ModuleRecordEntry::IndirectExportDefault { + export_name, + export_name_span, + } => { + let export = make_export_name(export_name, export_name_span); + exports.add_indirect(export.clone()); + setter_ops.push(SetterOp::ReExport { + export, + imported: atom!("default"), + }); + } + ModuleRecordEntry::IndirectExportNamespace { + export_name, + export_name_span, + } => { + let export = make_export_name(export_name, export_name_span); + exports.add_indirect(export.clone()); + setter_ops.push(SetterOp::ReExportNamespace { export }); + } + ModuleRecordEntry::StarExport => { + setter_ops.push(SetterOp::StarExport); + } + } + } + + module.dependencies.push(DependencySlot { + request, + span, + attributes, + namespace, + setter_ops, + }); + } +} + +fn lower_source_item(module: &mut SystemModule, item: SourceModuleItem) { + match item { + SourceModuleItem::Stmt(stmt) => lower_stmt(module, stmt), + SourceModuleItem::ExportDecl(export) => lower_decl(module, export.decl), + SourceModuleItem::ExportDefaultDecl(export) => lower_default_decl(module, export), + SourceModuleItem::ExportDefaultExpr(export) => { + module.execute_stmts.push(ExecuteStmt::export_value( + default_export_name(export.span), + export.expr, + )); + } + SourceModuleItem::TsImportEquals(import) => lower_ts_import_equals(module, *import), + } +} + +fn default_export_name(span: swc_common::Span) -> ExportName { + make_export_name(atom!("default"), (span, Default::default())) +} + +fn lower_ts_import_equals(module: &mut SystemModule, import: TsImportEqualsDecl) { + let Some(src) = external_ts_import_equals_source(&import) else { + return; + }; + + let request = src.value.to_atom_lossy().into_owned(); + let span = (src.span, Default::default()); + let namespace = namespace_ident_for(&request); + let local = import.id; + + module.wrapper_vars.push(local.clone()); + module.dependencies.push(DependencySlot { + request, + span, + attributes: Vec::new(), + namespace, + setter_ops: vec![SetterOp::Import { + local, + imported: None, + }], + }); +} + +fn lower_stmt(module: &mut SystemModule, stmt: Stmt) { + if let Stmt::Decl(decl) = stmt { + lower_decl(module, decl); + } else { + let mut stmt = stmt; + lower_var_scoped_decls(module, &mut stmt); + module.execute_stmts.push(ExecuteStmt::source(stmt)); + } +} + +fn lower_decl(module: &mut SystemModule, decl: Decl) { + match decl { + Decl::Fn(fn_decl) => { + module.wrapper_fns.push(fn_decl); + } + Decl::Class(class_decl) => { + let ClassDecl { + ident, + declare: _, + class, + } = class_decl; + + module.wrapper_vars.push(ident.clone()); + module.execute_stmts.push(assign_or_export( + module, + ident.clone(), + ClassExpr { + ident: Some(ident), + class, + } + .into(), + )); + } + Decl::Var(var_decl) => { + lower_var_decl(module, *var_decl); + } + _ => module + .execute_stmts + .push(ExecuteStmt::source(Stmt::Decl(decl))), + } +} + +fn lower_default_decl(module: &mut SystemModule, export: ExportDefaultDecl) { + let export_span = export.span; + + match export.decl { + DefaultDecl::Class(class_expr) => { + let Some(ident) = class_expr.ident else { + module.execute_stmts.push(ExecuteStmt::export_value( + default_export_name(export_span), + ClassExpr { + ident: None, + class: class_expr.class, + } + .into(), + )); + return; + }; + + module.wrapper_vars.push(ident.clone()); + module.execute_stmts.push(assign_or_export( + module, + ident.clone(), + ClassExpr { + ident: Some(ident), + class: class_expr.class, + } + .into(), + )); + } + DefaultDecl::Fn(fn_expr) => { + let Some(ident) = fn_expr.ident.clone() else { + module.export_inits.push(ExportInit::new( + default_export_name(export_span), + fn_expr.into(), + )); + return; + }; + + module.wrapper_fns.push(FnDecl { + ident, + declare: false, + function: fn_expr.function, + }); + } + DefaultDecl::TsInterfaceDecl(_) => {} + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + } +} + +fn lower_var_decl(module: &mut SystemModule, var_decl: VarDecl) { + for declarator in var_decl.decls { + if let Pat::Ident(binding) = declarator.name { + let ident = binding.id; + let Some(init) = declarator.init else { + module.wrapper_vars.push(ident); + continue; + }; + + module.wrapper_vars.push(ident.clone()); + module + .execute_stmts + .push(assign_or_export(module, ident, init)); + continue; + } + + let ids = find_pat_ids::<_, Ident>(&declarator.name); + module.wrapper_vars.extend(ids.iter().cloned()); + + let Some(init) = declarator.init else { + continue; + }; + + let mut pattern = declarator.name; + let uses_export_setters = replace_exported_pat( + &mut pattern, + &module.exports.local_exports, + &module.export_setters, + ); + if uses_export_setters { + module.needs_export_setters = true; + } + + if let Ok(left) = AssignTarget::try_from(pattern) { + module.execute_stmts.push(ExecuteStmt::assign(left, init)); + if !uses_export_setters { + for ident in ids { + if let Some(exports) = module.exports.exports_for(&ident.to_id()) { + module + .execute_stmts + .push(ExecuteStmt::export_names(exports, ident)); + } + } + } + } + } +} + +fn assign_or_export(module: &SystemModule, ident: Ident, value: Box) -> ExecuteStmt { + if let Some(exports) = module.exports.exports_for(&ident.to_id()) { + ExecuteStmt::export_assign(exports, ident, value) + } else { + ExecuteStmt::assign(ident.into(), value) + } +} + +fn lower_var_scoped_decls(module: &mut SystemModule, stmt: &mut Stmt) { + // Function declarations are emitted in wrapper scope, so `var` bindings + // from the module's execution scope must live there too. Lexical + // declarations inside nested blocks keep their original scope. + match stmt { + Stmt::Block(block) => lower_var_scoped_decls_in_stmts(module, &mut block.stmts), + Stmt::With(with) => lower_var_scoped_decls(module, &mut with.body), + Stmt::Labeled(labeled) => lower_var_scoped_decls(module, &mut labeled.body), + Stmt::If(if_stmt) => { + lower_var_scoped_decls(module, &mut if_stmt.cons); + if let Some(alt) = &mut if_stmt.alt { + lower_var_scoped_decls(module, alt); + } + } + Stmt::Switch(switch) => { + for case in &mut switch.cases { + lower_var_scoped_decls_in_stmts(module, &mut case.cons); + } + } + Stmt::Try(try_stmt) => { + lower_var_scoped_decls_in_stmts(module, &mut try_stmt.block.stmts); + if let Some(handler) = &mut try_stmt.handler { + lower_var_scoped_decls_in_stmts(module, &mut handler.body.stmts); + } + if let Some(finalizer) = &mut try_stmt.finalizer { + lower_var_scoped_decls_in_stmts(module, &mut finalizer.stmts); + } + } + Stmt::While(while_stmt) => lower_var_scoped_decls(module, &mut while_stmt.body), + Stmt::DoWhile(do_while) => lower_var_scoped_decls(module, &mut do_while.body), + Stmt::For(for_stmt) => { + lower_for_init(module, &mut for_stmt.init); + lower_var_scoped_decls(module, &mut for_stmt.body); + } + Stmt::ForIn(for_in) => { + lower_for_head(module, &mut for_in.left); + lower_var_scoped_decls(module, &mut for_in.body); + } + Stmt::ForOf(for_of) => { + lower_for_head(module, &mut for_of.left); + lower_var_scoped_decls(module, &mut for_of.body); + } + Stmt::Decl(Decl::Var(var_decl)) if var_decl.kind == VarDeclKind::Var => { + *stmt = lower_var_decl_stmt(module, *var_decl.take()); + } + _ => {} + } +} + +fn lower_var_scoped_decls_in_stmts(module: &mut SystemModule, stmts: &mut [Stmt]) { + for stmt in stmts { + lower_var_scoped_decls(module, stmt); + } +} + +fn lower_for_init(module: &mut SystemModule, init: &mut Option) { + let Some(VarDeclOrExpr::VarDecl(var_decl)) = init else { + return; + }; + if var_decl.kind != VarDeclKind::Var { + return; + } + + *init = var_decl_to_assignments(module, *var_decl.take()).map(VarDeclOrExpr::Expr); +} + +fn lower_for_head(module: &mut SystemModule, head: &mut ForHead) { + let ForHead::VarDecl(var_decl) = head else { + return; + }; + if var_decl.kind != VarDeclKind::Var { + return; + } + + for declarator in &var_decl.decls { + module + .wrapper_vars + .extend(find_pat_ids::<_, Ident>(&declarator.name)); + } + + if var_decl.decls.len() == 1 { + let mut var_decl = var_decl.take(); + let declarator = var_decl.decls.pop().unwrap(); + *head = declarator.name.into(); + } +} + +fn lower_var_decl_stmt(module: &mut SystemModule, var_decl: VarDecl) -> Stmt { + var_decl_to_assignments(module, var_decl).map_or_else( + || EmptyStmt { span: DUMMY_SP }.into(), + ExprFactory::into_stmt, + ) +} + +fn var_decl_to_assignments(module: &mut SystemModule, var_decl: VarDecl) -> Option> { + let mut exprs = Vec::new(); + for declarator in var_decl.decls { + module + .wrapper_vars + .extend(find_pat_ids::<_, Ident>(&declarator.name)); + + let Some(init) = declarator.init else { + continue; + }; + let Ok(left) = AssignTarget::try_from(declarator.name) else { + continue; + }; + + exprs.push( + AssignExpr { + span: declarator.span, + op: op!("="), + left, + right: init, + } + .into(), + ); + } + + match exprs.len() { + 0 => None, + 1 => exprs.pop(), + _ => Some( + SeqExpr { + span: var_decl.span, + exprs, + } + .into(), + ), + } +} + +pub(super) fn export_call(export_ident: &Ident, exports: &[ExportName], value: Expr) -> Expr { + exports.iter().fold(value, |value, export| { + export_ident.clone().as_call( + value.span(), + vec![ + Str { + span: export.span.0, + value: export.name.clone().into(), + raw: None, + } + .as_arg(), + value.as_arg(), + ], + ) + }) +} + +pub(super) fn export_names_call( + export_ident: &Ident, + exports: &[ExportName], + value_ident: Ident, +) -> Expr { + if exports.len() == 1 { + export_call(export_ident, exports, value_ident.into()) + } else { + let props = exports + .iter() + .map(|export| { + Prop::KeyValue(KeyValueProp { + key: object_lit_prop_name(&export.name, export.span), + value: value_ident.clone().into(), + }) + .into() + }) + .collect(); + + export_ident.clone().as_call( + DUMMY_SP, + vec![ObjectLit { + span: DUMMY_SP, + props, + } + .as_arg()], + ) + } +} + +fn namespace_ident_for(src: &Atom) -> Ident { + let base = local_name_for_src(src); + private_ident!(format!("{base}_ns")) +} + +fn ident_from_id((sym, ctxt): Id, span: swc_common::Span) -> Ident { + Ident::new(sym, span, ctxt) +} + +fn compare_module_entries(a: &ModuleRecordEntry, b: &ModuleRecordEntry) -> std::cmp::Ordering { + module_entry_rank(a) + .cmp(&module_entry_rank(b)) + .then_with(|| module_entry_sort_name(a).cmp(&module_entry_sort_name(b))) +} + +fn module_entry_rank(entry: &ModuleRecordEntry) -> u8 { + match entry { + ModuleRecordEntry::Empty => 0, + ModuleRecordEntry::ImportDefault { .. } => 1, + ModuleRecordEntry::ImportNamespace { .. } => 2, + ModuleRecordEntry::ImportNamed { .. } => 3, + ModuleRecordEntry::IndirectExportDefault { .. } => 4, + ModuleRecordEntry::IndirectExportNamed { .. } => 5, + ModuleRecordEntry::IndirectExportNamespace { .. } => 6, + ModuleRecordEntry::StarExport => 7, + } +} + +fn module_entry_sort_name(entry: &ModuleRecordEntry) -> Option<&Atom> { + match entry { + ModuleRecordEntry::ImportDefault { local_name } + | ModuleRecordEntry::ImportNamespace { local_name } + | ModuleRecordEntry::ImportNamed { local_name, .. } => Some(&local_name.0), + ModuleRecordEntry::IndirectExportDefault { export_name, .. } + | ModuleRecordEntry::IndirectExportNamespace { export_name, .. } => Some(export_name), + ModuleRecordEntry::IndirectExportNamed { + export_name, + import_name, + } => Some( + export_name + .as_ref() + .map_or(&import_name.0, |export_name| &export_name.0), + ), + ModuleRecordEntry::Empty | ModuleRecordEntry::StarExport => None, + } +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/system_js/pattern.rs b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/pattern.rs new file mode 100644 index 000000000..da104d0b0 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/pattern.rs @@ -0,0 +1,74 @@ +use indexmap::IndexMap; +use swc_ecma_ast::*; + +use super::{ir::ExportName, util::export_setter_member}; + +/// Rewrites assignment patterns so writes to exported locals flow through +/// setter properties. The setter body updates the local binding and calls +/// `_export`, which keeps destructuring evaluation order compatible with live +/// bindings. +pub(super) fn replace_exported_pat( + pat: &mut Pat, + exports: &IndexMap>, + export_setters: &Ident, +) -> bool { + match pat { + Pat::Ident(binding) => { + if exports.contains_key(&binding.id.to_id()) { + *pat = export_setter_member(export_setters, &binding.id); + true + } else { + false + } + } + Pat::Array(array) => { + let mut changed = false; + for pat in array.elems.iter_mut().flatten() { + changed |= replace_exported_pat(pat, exports, export_setters); + } + changed + } + Pat::Rest(rest) => replace_exported_pat(&mut rest.arg, exports, export_setters), + Pat::Object(object) => { + let mut changed = false; + for prop in &mut object.props { + changed |= match prop { + ObjectPatProp::KeyValue(key_value) => { + replace_exported_pat(&mut key_value.value, exports, export_setters) + } + ObjectPatProp::Assign(assign) => { + if exports.contains_key(&assign.key.id.to_id()) { + let member = export_setter_member(export_setters, &assign.key.id); + let value = if let Some(default) = assign.value.take() { + Pat::Assign(AssignPat { + span: assign.span, + left: member.into(), + right: default, + }) + } else { + member + }; + *prop = ObjectPatProp::KeyValue(KeyValuePatProp { + key: PropName::Ident(assign.key.id.clone().into()), + value: value.into(), + }); + true + } else { + false + } + } + ObjectPatProp::Rest(rest) => { + replace_exported_pat(&mut rest.arg, exports, export_setters) + } + #[cfg(swc_ast_unknown)] + _ => false, + }; + } + changed + } + Pat::Assign(assign) => replace_exported_pat(&mut assign.left, exports, export_setters), + Pat::Invalid(_) | Pat::Expr(_) => false, + #[cfg(swc_ast_unknown)] + _ => false, + } +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/system_js/rewrite.rs b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/rewrite.rs new file mode 100644 index 000000000..95e215ded --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/rewrite.rs @@ -0,0 +1,308 @@ +use indexmap::IndexMap; +use swc_common::{util::take::Take, Spanned, SyntaxContext}; +use swc_ecma_ast::*; +use swc_ecma_utils::{private_ident, quote_ident, ExprFactory}; +use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith}; + +use super::{ + ir::{ExportName, SystemModule}, + lower::export_names_call, + pattern::replace_exported_pat, + util::{context_member, context_meta}, +}; +use crate::path::Resolver; + +pub(super) fn rewrite_special_refs( + module: &mut SystemModule, + context_ident: Ident, + unresolved_ctxt: SyntaxContext, + resolver: &Resolver, + ignore_dynamic: bool, + preserve_import_meta: bool, +) { + let mut rewriter = SpecialRefRewriter { + context_ident, + unresolved_ctxt, + resolver, + ignore_dynamic, + preserve_import_meta, + }; + for wrapper_fn in &mut module.wrapper_fns { + wrapper_fn.visit_mut_with(&mut rewriter); + } + for export_init in &mut module.export_inits { + export_init.value.visit_mut_with(&mut rewriter); + } + for stmt in &mut module.execute_stmts { + stmt.visit_mut_with(&mut rewriter); + } +} + +pub(super) fn rewrite_export_bindings( + module: &mut SystemModule, + rewriter: &mut ExportBindingRewriter, +) { + for wrapper_fn in &mut module.wrapper_fns { + wrapper_fn.visit_mut_with(rewriter); + } + for export_init in &mut module.export_inits { + export_init.value.visit_mut_with(rewriter); + } + for stmt in &mut module.execute_stmts { + stmt.visit_mut_with(rewriter); + } +} + +struct SpecialRefRewriter<'a> { + context_ident: Ident, + unresolved_ctxt: SyntaxContext, + resolver: &'a Resolver, + ignore_dynamic: bool, + preserve_import_meta: bool, +} + +impl VisitMut for SpecialRefRewriter<'_> { + noop_visit_mut_type!(fail); + + fn visit_mut_expr(&mut self, n: &mut Expr) { + match n { + Expr::Ident(ident) if self.is_unresolved_module_name(ident) => { + *n = self.module_name_expr(ident); + } + Expr::MetaProp(MetaPropExpr { + kind: MetaPropKind::ImportMeta, + .. + }) if !self.preserve_import_meta => { + *n = context_meta(&self.context_ident).into(); + } + Expr::Call(CallExpr { + callee: + Callee::Import(Import { + phase: ImportPhase::Evaluation, + .. + }), + args, + .. + }) if !self.ignore_dynamic => { + args.visit_mut_with(self); + if let Some(ExprOrSpread { spread: None, expr }) = args.get_mut(0) { + if let Expr::Lit(Lit::Str(Str { value, raw, .. })) = &mut **expr { + let original = value.to_atom_lossy().into_owned(); + let resolved = self.resolver.resolve(original.clone()); + if resolved != original { + *value = resolved.into(); + *raw = None; + } + } + } + + let args = std::mem::take(args); + *n = context_member(&self.context_ident, quote_ident!("import")) + .as_call(n.span(), args); + } + _ => n.visit_mut_children_with(self), + } + } + + fn visit_mut_prop(&mut self, n: &mut Prop) { + match n { + Prop::Shorthand(ident) if self.is_unresolved_module_name(ident) => { + let key = PropName::Ident(IdentName::new(ident.sym.clone(), ident.span)); + let value = self.module_name_expr(ident); + *n = KeyValueProp { + key, + value: value.into(), + } + .into(); + } + _ => n.visit_mut_children_with(self), + } + } +} + +impl SpecialRefRewriter<'_> { + fn is_unresolved_module_name(&self, ident: &Ident) -> bool { + ident.sym == *"__moduleName" && ident.ctxt == self.unresolved_ctxt + } + + fn module_name_expr(&self, ident: &Ident) -> Expr { + CondExpr { + span: ident.span, + test: context_meta(&self.context_ident).into(), + cons: context_meta(&self.context_ident) + .make_member(quote_ident!("url")) + .into(), + alt: context_member(&self.context_ident, quote_ident!("id")).into(), + } + .into() + } +} + +pub(super) struct ExportBindingRewriter { + exports: IndexMap>, + export_ident: Ident, + export_setters: Ident, + old_temp: Ident, + needs_old_temp: bool, + needs_export_setters: bool, +} + +impl ExportBindingRewriter { + pub fn new( + exports: IndexMap>, + export_ident: Ident, + export_setters: Ident, + ) -> Self { + Self { + exports, + export_ident, + export_setters, + old_temp: private_ident!("_old"), + needs_old_temp: false, + needs_export_setters: false, + } + } + + pub fn needs_old_temp(&self) -> bool { + self.needs_old_temp + } + + pub fn old_temp(&self) -> Ident { + self.old_temp.clone() + } + + pub fn needs_export_setters(&self) -> bool { + self.needs_export_setters + } +} + +impl VisitMut for ExportBindingRewriter { + noop_visit_mut_type!(fail); + + fn visit_mut_expr(&mut self, n: &mut Expr) { + match n { + Expr::Call(CallExpr { + callee: Callee::Expr(callee), + .. + }) if callee + .as_ident() + .is_some_and(|ident| ident.to_id() == self.export_ident.to_id()) => {} + Expr::Assign(assign) => { + assign.right.visit_mut_with(self); + + match &mut assign.left { + AssignTarget::Simple(SimpleAssignTarget::Ident(binding)) => { + if let Some(exports) = self.exports.get(&binding.id.to_id()) { + let ident = binding.id.clone(); + let assign_expr: Expr = AssignExpr { + span: assign.span, + op: assign.op, + left: ident.clone().into(), + right: assign.right.take(), + } + .into(); + let export = + export_names_call(&self.export_ident, exports, ident.clone()); + *n = SeqExpr { + span: assign.span, + exprs: vec![assign_expr.into(), export.into(), ident.into()], + } + .into(); + } + } + AssignTarget::Pat(pat) => { + let mut new_pat: Pat = pat.take().into(); + if replace_exported_pat(&mut new_pat, &self.exports, &self.export_setters) { + self.needs_export_setters = true; + if let Ok(new_left) = AssignTarget::try_from(new_pat) { + assign.left = new_left; + assign.left.visit_mut_with(self); + } + } else { + assign.left.visit_mut_with(self); + } + } + _ => assign.left.visit_mut_with(self), + } + } + Expr::Update(update) => { + let Expr::Ident(ident) = &*update.arg else { + update.arg.visit_mut_with(self); + return; + }; + let Some(exports) = self.exports.get(&ident.to_id()) else { + return; + }; + + let ident = ident.clone(); + let update_expr: Expr = UpdateExpr { + span: update.span, + op: update.op, + prefix: update.prefix, + arg: ident.clone().into(), + } + .into(); + let export = export_names_call(&self.export_ident, exports, ident.clone()); + + let exprs = if update.prefix { + vec![update_expr.into(), export.into(), ident.into()] + } else { + self.needs_old_temp = true; + vec![ + update_expr + .make_assign_to(op!("="), self.old_temp.clone().into()) + .into(), + export.into(), + self.old_temp.clone().into(), + ] + }; + + *n = SeqExpr { + span: update.span, + exprs, + } + .into(); + } + _ => n.visit_mut_children_with(self), + } + } + + fn visit_mut_for_in_stmt(&mut self, n: &mut ForInStmt) { + n.right.visit_mut_with(self); + self.rewrite_for_head(&mut n.left); + n.body.visit_mut_with(self); + } + + fn visit_mut_for_of_stmt(&mut self, n: &mut ForOfStmt) { + n.right.visit_mut_with(self); + self.rewrite_for_head(&mut n.left); + n.body.visit_mut_with(self); + } +} + +impl ExportBindingRewriter { + fn rewrite_for_head(&mut self, head: &mut ForHead) { + match head { + ForHead::Pat(pat) => { + if replace_exported_pat(pat, &self.exports, &self.export_setters) { + self.needs_export_setters = true; + } + pat.visit_mut_with(self); + } + ForHead::VarDecl(var_decl) => { + for decl in &mut var_decl.decls { + if replace_exported_pat(&mut decl.name, &self.exports, &self.export_setters) { + self.needs_export_setters = true; + } + decl.name.visit_mut_with(self); + if let Some(init) = &mut decl.init { + init.visit_mut_with(self); + } + } + } + ForHead::UsingDecl(_) => {} + #[cfg(swc_ast_unknown)] + _ => {} + } + } +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/system_js/util.rs b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/util.rs new file mode 100644 index 000000000..9a08d852c --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/system_js/util.rs @@ -0,0 +1,51 @@ +use swc_atoms::Atom; +use swc_common::DUMMY_SP; +use swc_ecma_ast::*; +use swc_ecma_utils::{prop_name_from_str, quote_ident, ExprFactory}; + +use crate::{util::prop_name, SpanCtx}; + +pub(super) fn context_meta(context_ident: &Ident) -> MemberExpr { + context_member(context_ident, quote_ident!("meta")) +} + +pub(super) fn context_member(context_ident: &Ident, prop: IdentName) -> MemberExpr { + context_ident.clone().make_member(prop) +} + +pub(super) fn export_object_init() -> Expr { + ObjectLit { + span: DUMMY_SP, + props: vec![Prop::KeyValue(KeyValueProp { + key: quote_ident!("__proto__").into(), + value: Lit::Null(Null { span: DUMMY_SP }).into(), + }) + .into()], + } + .into() +} + +pub(super) fn export_setter_member(export_setters: &Ident, ident: &Ident) -> Pat { + Pat::Expr( + export_setters + .clone() + .make_member(quote_ident!(ident.sym.clone())) + .into(), + ) +} + +pub(super) fn member_for_export(namespace: Ident, imported: &Atom) -> Expr { + member_expr_for(namespace, imported, Default::default()).into() +} + +pub(super) fn member_expr_for(obj: Ident, prop: &Atom, span: SpanCtx) -> MemberExpr { + MemberExpr { + span: span.0, + obj: obj.into(), + prop: prop_name(prop, span).into(), + } +} + +pub(super) fn object_lit_prop_name(prop: &Atom, (span, _): SpanCtx) -> PropName { + prop_name_from_str(span, prop) +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/umd.rs b/deps/swc/crates/swc_ecma_transforms_module/src/umd.rs index d1d910c62..ee96ad1f4 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/umd.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/umd.rs @@ -1,31 +1,32 @@ -use anyhow::Context; +use rustc_hash::FxHashSet; use swc_atoms::Atom; -use swc_common::{ - source_map::PURE_SP, sync::Lrc, util::take::Take, Mark, SourceMap, Span, SyntaxContext, - DUMMY_SP, -}; +use swc_common::{source_map::PURE_SP, sync::Lrc, util::take::Take, Mark, SourceMap, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_transforms_base::helper_expr; -use swc_ecma_utils::{ - is_valid_prop_ident, private_ident, quote_ident, quote_str, ExprFactory, IsDirective, -}; -use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith}; +use swc_ecma_utils::{private_ident, ExprFactory}; +use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut}; use self::config::BuiltConfig; pub use self::config::Config; use crate::{ - module_decl_strip::{Export, Link, LinkFlag, LinkItem, LinkSpecifierReducer, ModuleDeclStrip}, + module_record::{ + exported_external_ts_import_equals_name, external_ts_import_equals_source, + LocalExportEntries, ModuleRecordEntryReducer, ModuleRequestUsage, RequestedModule, + RequestedModules, SourceModule, + }, module_ref_rewriter::{rewrite_import_bindings, ImportMap}, path::Resolver, + syntax_strip::{self, SyntaxStrippedModule}, top_level_this::top_level_this, util::{ - define_es_module, emit_export_stmts, local_name_for_src, sort_export_obj_prop_list, - use_strict, ImportInterop, VecStmtLike, + define_es_module, emit_export_stmts, local_name_for_src, sort_export_bindings, use_strict, + ImportInterop, }, SpanCtx, }; mod config; +mod emit; #[derive(Default)] pub struct FeatureFlag { @@ -76,53 +77,58 @@ impl VisitMut for Umd { fn visit_mut_module(&mut self, module: &mut Module) { let module_items = &mut module.body; - let mut stmts: Vec = Vec::with_capacity(module_items.len() + 4); + if !self.config.config.allow_top_level_this { + top_level_this(module_items, *Expr::undefined(DUMMY_SP)); + } - // Collect directives - stmts.extend( - module_items - .iter_mut() - .take_while(|i| i.directive_continue()) - .map(|i| i.take()) - .map(ModuleItem::expect_stmt), + let SyntaxStrippedModule { + directives, + has_use_strict, + requested_modules, + local_export_entries, + export_assign, + body, + has_module_syntax, + } = syntax_strip::lower( + SourceModule::collect(module_items.take()), + self.const_var_kind, ); + let mut stmts: Vec = Vec::with_capacity(body.len() + 4); + stmts.extend(directives); + // "use strict"; - if self.config.config.strict_mode && !stmts.has_use_strict() { + if self.config.config.strict_mode && !has_use_strict { stmts.push(use_strict()); } - if !self.config.config.allow_top_level_this { - top_level_this(module_items, *Expr::undefined(DUMMY_SP)); - } - let import_interop = self.config.config.import_interop(); - let mut strip = ModuleDeclStrip::new(self.const_var_kind); - module_items.visit_mut_with(&mut strip); - - let ModuleDeclStrip { - link, - export, - export_assign, - has_module_decl, - .. - } = strip; - let is_export_assign = export_assign.is_some(); - if has_module_decl && !import_interop.is_none() && !is_export_assign { - stmts.push(define_es_module(self.exports())) + if has_module_syntax && !import_interop.is_none() && !is_export_assign { + stmts.push(define_es_module(self.exports())); } let mut import_map = Default::default(); + let ts_import_equals_exports: FxHashSet = body + .iter() + .filter_map(exported_external_ts_import_equals_name) + .cloned() + .collect(); + + stmts.extend(self.handle_import_export( + &mut import_map, + requested_modules, + local_export_entries, + &ts_import_equals_exports, + is_export_assign, + )); - stmts.extend(self.handle_import_export(&mut import_map, link, export, is_export_assign)); - - stmts.extend(module_items.take().into_iter().filter_map(|i| match i { - ModuleItem::Stmt(stmt) if !stmt.is_empty() => Some(stmt), - _ => None, - })); + stmts.extend( + body.into_iter() + .filter_map(|item| self.lower_body_item(&mut import_map, item)), + ); if let Some(export_assign) = export_assign { let return_stmt = ReturnStmt { @@ -130,41 +136,24 @@ impl VisitMut for Umd { arg: Some(export_assign), }; - stmts.push(return_stmt.into()) + stmts.push(return_stmt.into()); } rewrite_import_bindings(&mut stmts, import_map, Default::default()); - // ==================== - // Emit - // ==================== - - let (adapter_fn_expr, factory_params) = self.adapter(module.span, is_export_assign); - - let factory_fn_expr: Expr = Function { - params: factory_params, - decorators: Default::default(), - span: DUMMY_SP, - body: Some(BlockStmt { - stmts, - ..Default::default() - }), - is_generator: false, - is_async: false, - ..Default::default() - } - .into(); - - *module_items = vec![adapter_fn_expr - .as_call( - DUMMY_SP, - vec![ - ThisExpr { span: DUMMY_SP }.as_arg(), - factory_fn_expr.as_arg(), - ], - ) - .into_stmt() - .into()] + *module_items = emit::emit( + stmts, + emit::EmitModule { + span: module.span, + is_export_assign, + exports: self.exports.clone(), + deps: self.dep_list.take(), + }, + &self.cm, + &self.config, + self.unresolved_mark, + &self.resolver, + ); } } @@ -172,42 +161,45 @@ impl Umd { fn handle_import_export( &mut self, import_map: &mut ImportMap, - link: Link, - export: Export, + requested_modules: RequestedModules, + local_export_entries: LocalExportEntries, + ts_import_equals_exports: &FxHashSet, is_export_assign: bool, ) -> impl Iterator { let import_interop = self.config.config.import_interop(); - let mut stmts = Vec::with_capacity(link.len()); + let mut stmts = Vec::with_capacity(requested_modules.len()); - let mut export_obj_prop_list = export.into_iter().collect(); + let mut export_bindings = local_export_entries.into_iter().collect(); - link.into_iter().for_each( - |(src, LinkItem(src_span, link_specifier_set, mut link_flag))| { - let is_node_default = !link_flag.has_named() && import_interop.is_node(); + requested_modules.into_iter().for_each( + |( + module_request, + RequestedModule { + span: src_span, + entries: module_entries, + usage: mut module_usage, + .. + }, + )| { + let src = module_request.src().clone(); + let is_node_default = !module_usage.has_named() && import_interop.is_node(); if import_interop.is_none() { - link_flag -= LinkFlag::NAMESPACE; + module_usage -= ModuleRequestUsage::NAMESPACE; } - let need_re_export = link_flag.export_star(); - let need_interop = link_flag.interop(); - let need_new_var = link_flag.need_raw_import(); + let need_re_export = module_usage.has_star_export(); + let need_interop = module_usage.needs_interop(); let mod_ident = private_ident!(local_name_for_src(&src)); - let new_var_ident = if need_new_var { - private_ident!(local_name_for_src(&src)) - } else { - mod_ident.clone() - }; self.dep_list.push((mod_ident.clone(), src, src_span)); - link_specifier_set.reduce( + module_entries.reduce( import_map, - &mut export_obj_prop_list, - &new_var_ident, - &Some(mod_ident.clone()), + &mut export_bindings, + &mod_ident, &mut false, is_node_default, ); @@ -225,29 +217,24 @@ impl Umd { // _introp(mod); if need_interop { import_expr = match import_interop { - ImportInterop::Swc if link_flag.interop() => if link_flag.namespace() { - helper_expr!(interop_require_wildcard) - } else { - helper_expr!(interop_require_default) + ImportInterop::Swc if module_usage.needs_interop() => { + if module_usage.needs_namespace_object() { + helper_expr!(interop_require_wildcard) + } else { + helper_expr!(interop_require_default) + } + .as_call(PURE_SP, vec![import_expr.as_arg()]) } - .as_call(PURE_SP, vec![import_expr.as_arg()]), - ImportInterop::Node if link_flag.namespace() => { + ImportInterop::Node if module_usage.needs_namespace_object() => { helper_expr!(interop_require_wildcard) .as_call(PURE_SP, vec![import_expr.as_arg(), true.as_arg()]) } _ => import_expr, } - }; + } // mod = _introp(mod); - // var mod1 = _introp(mod); - if need_new_var { - let stmt: Stmt = import_expr - .into_var_decl(self.const_var_kind, new_var_ident.into()) - .into(); - - stmts.push(stmt) - } else if need_interop { + if need_interop { let stmt = import_expr .make_assign_to(op!("="), mod_ident.into()) .into_stmt(); @@ -260,234 +247,80 @@ impl Umd { let mut export_stmts = Default::default(); - if !export_obj_prop_list.is_empty() && !is_export_assign { - sort_export_obj_prop_list(&mut export_obj_prop_list); + export_bindings.retain(|(export_name, _)| !ts_import_equals_exports.contains(export_name)); + + if !export_bindings.is_empty() && !is_export_assign { + sort_export_bindings(&mut export_bindings); let exports = self.exports(); - export_stmts = emit_export_stmts(exports, export_obj_prop_list); + export_stmts = emit_export_stmts(exports, export_bindings); } export_stmts.into_iter().chain(stmts) } - fn exports(&mut self) -> Ident { - self.exports - .get_or_insert_with(|| private_ident!("exports")) - .clone() - } - - /// - Without `export =` - /// ```javascript - /// (function (global, factory) { - /// if (typeof module === "object" && typeof module.exports === "object") { - /// factory(exports, require("mod")); - /// } else if (typeof define === "function" && define.amd) { - /// define(["exports", "mod"], factory); - /// } else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) { - /// factory((global.lib = {}), global.mod); - /// } - /// })(this, function (exports, mod) { - /// ... - /// }); - /// ``` - /// - With `export =` - /// ```javascript - /// (function (global, factory) { - /// if (typeof module === "object" && typeof module.exports === "object") { - /// module.exports = factory(require("mod")); - /// } else if (typeof define === "function" && define.amd) { - /// define(["mod"], factory); - /// } else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) { - /// global.lib = factory(global.mod); - /// } - /// })(this, function (mod) { - /// ... - /// }); - /// ``` - /// Return: adapter expr and factory params - fn adapter(&mut self, module_span: Span, is_export_assign: bool) -> (FnExpr, Vec) { - macro_rules! js_typeof { - ($test:expr =>! $type:expr) => { - Expr::Unary(UnaryExpr { - span: DUMMY_SP, - op: op!("typeof"), - arg: Box::new(Expr::from($test)), - }) - .make_bin(op!("!=="), quote_str!($type)) - }; - - ($test:expr => $type:expr) => { - Expr::Unary(UnaryExpr { - span: DUMMY_SP, - op: op!("typeof"), - arg: Box::new(Expr::from($test)), - }) - .make_bin(op!("==="), quote_str!($type)) - }; + fn lower_body_item(&mut self, import_map: &mut ImportMap, item: ModuleItem) -> Option { + match item { + ModuleItem::Stmt(stmt) if !stmt.is_empty() => Some(stmt), + ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(import)) => { + self.lower_ts_import_equals(import_map, *import) + } + _ => None, } + } - // define unresolved ref - let module = quote_ident!( - SyntaxContext::empty().apply_mark(self.unresolved_mark), - "module" - ); - - let require = quote_ident!( - SyntaxContext::empty().apply_mark(self.unresolved_mark), - "require" - ); - let define = quote_ident!( - SyntaxContext::empty().apply_mark(self.unresolved_mark), - "define" - ); - let global_this = quote_ident!( - SyntaxContext::empty().apply_mark(self.unresolved_mark), - "globalThis" - ); - let js_self = quote_ident!( - SyntaxContext::empty().apply_mark(self.unresolved_mark), - "self" - ); - - // adapter arguments - let global = private_ident!("global"); - let factory = private_ident!("factory"); - - let module_exports = module.clone().make_member(quote_ident!("exports")); - let define_amd = define.clone().make_member(quote_ident!("amd")); - - let mut cjs_args = Vec::new(); - let mut amd_dep_list = Vec::new(); - let mut browser_args = Vec::new(); - - let mut factory_params = Vec::new(); - - if !is_export_assign && self.exports.is_some() { - let filename = self.cm.span_to_filename(module_span); - let exported_name = self.config.determine_export_name(filename); - let global_lib = global.clone().make_member(exported_name.into()); - - cjs_args.push(quote_ident!("exports").as_arg()); - amd_dep_list.push(Some(quote_str!("exports").as_arg())); - browser_args.push( - ObjectLit { - span: DUMMY_SP, - props: Default::default(), - } - .make_assign_to(op!("="), global_lib.into()) - .as_arg(), - ); - factory_params.push(self.exports().into()); - } + fn lower_ts_import_equals( + &mut self, + import_map: &mut ImportMap, + import: TsImportEqualsDecl, + ) -> Option { + let src = external_ts_import_equals_source(&import)?; + let src_span = src.span; + let request = src.value.to_atom_lossy().into_owned(); + let TsImportEqualsDecl { + id: local, + is_export, + .. + } = import; + let param = if is_export { + local.clone().into_private() + } else { + local.clone() + }; self.dep_list - .take() - .into_iter() - .for_each(|(ident, src_path, src_span)| { - let src_path = match &self.resolver { - Resolver::Real { resolver, base } => resolver - .resolve_import(base, &src_path) - .with_context(|| format!("failed to resolve `{src_path}`")) - .unwrap(), - Resolver::Default => src_path, - }; + .push((param.clone(), request, (src_span, Default::default()))); - cjs_args.push( - require - .clone() - .as_call( - DUMMY_SP, - vec![quote_str!(src_span.0, src_path.clone()).as_arg()], - ) - .as_arg(), - ); - amd_dep_list.push(Some(quote_str!(src_span.0, src_path.clone()).as_arg())); - - let global_dep = { - let dep_name = self.config.global_name(&src_path); - let global = global.clone(); - if is_valid_prop_ident(&dep_name) { - global.make_member(quote_ident!(dep_name)) - } else { - global.computed_member(quote_str!(dep_name)) - } - }; - browser_args.push(global_dep.as_arg()); - factory_params.push(ident.into()); - }); - - let cjs_if_test = js_typeof!(module => "object") - .make_bin(op!("&&"), js_typeof!(module_exports.clone() => "object")); - let mut cjs_if_body = factory.clone().as_call(DUMMY_SP, cjs_args); - if is_export_assign { - cjs_if_body = cjs_if_body.make_assign_to(op!("="), module_exports.clone().into()); + if !is_export { + return None; } - let amd_if_test = js_typeof!(define.clone() => "function").make_bin(op!("&&"), define_amd); - let amd_if_body = define.as_call( - DUMMY_SP, - vec![ - ArrayLit { - span: DUMMY_SP, - elems: amd_dep_list, - } - .as_arg(), - factory.clone().as_arg(), - ], - ); - - let browser_if_test = CondExpr { - span: DUMMY_SP, - test: Box::new(js_typeof!(global_this.clone() =>! "undefined")), - cons: Box::new(global_this.into()), - alt: Box::new(global.clone().make_bin(op!("||"), js_self)), - } - .make_assign_to(op!("="), global.clone().into()); + Some(self.emit_ts_import_equals(import_map, local, is_export, param.into())) + } - let mut browser_if_body = factory.clone().as_call(DUMMY_SP, browser_args); - if is_export_assign { - browser_if_body = browser_if_body.make_assign_to(op!("="), module_exports.into()); + fn emit_ts_import_equals( + &mut self, + import_map: &mut ImportMap, + local: Ident, + is_export: bool, + value: Expr, + ) -> Stmt { + if is_export { + import_map.insert(local.to_id(), (self.exports(), Some(local.sym.clone()))); + return value + .make_assign_to(op!("="), self.exports().make_member(local.into()).into()) + .into_stmt(); } - let adapter_body = BlockStmt { - span: DUMMY_SP, - stmts: vec![IfStmt { - span: DUMMY_SP, - test: Box::new(cjs_if_test), - cons: Box::new(cjs_if_body.into_stmt()), - alt: Some(Box::new( - IfStmt { - span: DUMMY_SP, - test: Box::new(amd_if_test), - cons: Box::new(amd_if_body.into_stmt()), - alt: Some(Box::new( - IfStmt { - span: DUMMY_SP, - test: Box::new(browser_if_test), - cons: Box::new(browser_if_body.into_stmt()), - alt: None, - } - .into(), - )), - } - .into(), - )), - } - .into()], - ..Default::default() - }; - - let adapter_fn_expr = Function { - params: vec![global.into(), factory.into()], - span: DUMMY_SP, - body: Some(adapter_body), - is_generator: false, - is_async: false, - ..Default::default() - } - .into(); + value + .into_var_decl(self.const_var_kind, local.into()) + .into() + } - (adapter_fn_expr, factory_params) + fn exports(&mut self) -> Ident { + self.exports + .get_or_insert_with(|| private_ident!("exports")) + .clone() } } diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/umd/config.rs b/deps/swc/crates/swc_ecma_transforms_module/src/umd/config.rs index 49fa166e9..344834b44 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/umd/config.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/umd/config.rs @@ -43,7 +43,7 @@ impl Config { ) .map_err(|e| { if HANDLER.is_set() { - HANDLER.with(|h| e.into_diagnostic(h).emit()) + HANDLER.with(|h| e.into_diagnostic(h).emit()); } }) .unwrap() diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/umd/emit.rs b/deps/swc/crates/swc_ecma_transforms_module/src/umd/emit.rs new file mode 100644 index 000000000..1eb5487d6 --- /dev/null +++ b/deps/swc/crates/swc_ecma_transforms_module/src/umd/emit.rs @@ -0,0 +1,260 @@ +use anyhow::Context; +use swc_atoms::Atom; +use swc_common::{sync::Lrc, Mark, SourceMap, Span, SyntaxContext, DUMMY_SP}; +use swc_ecma_ast::*; +use swc_ecma_utils::{is_valid_prop_ident, private_ident, quote_ident, quote_str, ExprFactory}; + +use super::config::BuiltConfig; +use crate::{path::Resolver, SpanCtx}; + +pub(super) struct EmitModule { + pub span: Span, + pub is_export_assign: bool, + pub exports: Option, + pub deps: Vec<(Ident, Atom, SpanCtx)>, +} + +pub(super) fn emit( + stmts: Vec, + module: EmitModule, + cm: &Lrc, + config: &BuiltConfig, + unresolved_mark: Mark, + resolver: &Resolver, +) -> Vec { + let (adapter_fn_expr, factory_params) = + emit_adapter(&module, cm, config, unresolved_mark, resolver); + + let factory_fn_expr: Expr = Function { + params: factory_params, + decorators: Default::default(), + span: DUMMY_SP, + body: Some(FunctionBody { + span: DUMMY_SP, + stmts, + }), + is_generator: false, + is_async: false, + ..Default::default() + } + .into(); + + vec![adapter_fn_expr + .as_call( + DUMMY_SP, + vec![ + ThisExpr { span: DUMMY_SP }.as_arg(), + factory_fn_expr.as_arg(), + ], + ) + .into_stmt() + .into()] +} + +/// Builds the UMD adapter function and returns it with the factory params. +/// +/// The adapter always emits `CommonJS`, AMD, and global-fallback branches: +/// ```javascript +/// if (typeof module === "object" && typeof module.exports === "object") { ... } +/// else if (typeof define === "function" && define.amd) { ... } +/// else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) { ... } +/// ``` +/// +/// For regular ES exports, `exports` is added as the first CommonJS/AMD +/// dependency and factory param. The global fallback creates the configured +/// export object and passes it as the first factory argument: +/// ```javascript +/// factory(exports, require("mod")); +/// define(["exports", "mod"], factory); +/// factory((global.lib = {}), global.mod); +/// function (exports, mod) { ... } +/// ``` +/// +/// For `export =`, there is no `exports` param. The factory returns the module +/// value, `CommonJS` assigns that return value to `module.exports`, AMD only +/// registers the dependency list, and the fallback branch assigns the factory +/// result to the inferred global export name: +/// ```javascript +/// module.exports = factory(require("mod")); +/// define(["mod"], factory); +/// global.lib = factory(global.mod); +/// function (mod) { ... } +/// ``` +fn emit_adapter( + module: &EmitModule, + cm: &Lrc, + config: &BuiltConfig, + unresolved_mark: Mark, + resolver: &Resolver, +) -> (FnExpr, Vec) { + macro_rules! js_typeof { + ($test:expr =>! $type:expr) => { + Expr::Unary(UnaryExpr { + span: DUMMY_SP, + op: op!("typeof"), + arg: Box::new(Expr::from($test)), + }) + .make_bin(op!("!=="), quote_str!($type)) + }; + + ($test:expr => $type:expr) => { + Expr::Unary(UnaryExpr { + span: DUMMY_SP, + op: op!("typeof"), + arg: Box::new(Expr::from($test)), + }) + .make_bin(op!("==="), quote_str!($type)) + }; + } + + let module_ident = quote_ident!(SyntaxContext::empty().apply_mark(unresolved_mark), "module"); + let require = quote_ident!( + SyntaxContext::empty().apply_mark(unresolved_mark), + "require" + ); + let define = quote_ident!(SyntaxContext::empty().apply_mark(unresolved_mark), "define"); + let global_this = quote_ident!( + SyntaxContext::empty().apply_mark(unresolved_mark), + "globalThis" + ); + let js_self = quote_ident!(SyntaxContext::empty().apply_mark(unresolved_mark), "self"); + + let global = private_ident!("global"); + let factory = private_ident!("factory"); + + let module_exports = module_ident.clone().make_member(quote_ident!("exports")); + let define_amd = define.clone().make_member(quote_ident!("amd")); + + let mut cjs_args = Vec::new(); + let mut amd_dep_list = Vec::new(); + let mut browser_args = Vec::new(); + + let mut factory_params = Vec::new(); + + if !module.is_export_assign { + if let Some(exports) = &module.exports { + cjs_args.push(quote_ident!("exports").as_arg()); + amd_dep_list.push(Some(quote_str!("exports").as_arg())); + browser_args.push( + ObjectLit::default() + .make_assign_to( + op!("="), + module_global_export_member(module.span, cm, config, &global).into(), + ) + .as_arg(), + ); + factory_params.push(exports.clone().into()); + } + } + + module.deps.iter().for_each(|(ident, src_path, src_span)| { + let src_path = match resolver { + Resolver::Real { resolver, base } => resolver + .resolve_import(base, src_path) + .with_context(|| format!("failed to resolve `{src_path}`")) + .unwrap(), + Resolver::Default => src_path.clone(), + }; + + cjs_args.push( + require + .clone() + .as_call( + DUMMY_SP, + vec![quote_str!(src_span.0, src_path.clone()).as_arg()], + ) + .as_arg(), + ); + amd_dep_list.push(Some(quote_str!(src_span.0, src_path.clone()).as_arg())); + + let global_dep = { + let dep_name = config.global_name(&src_path); + let global = global.clone(); + if is_valid_prop_ident(&dep_name) { + global.make_member(quote_ident!(dep_name)) + } else { + global.computed_member(quote_str!(dep_name)) + } + }; + browser_args.push(global_dep.as_arg()); + factory_params.push(ident.clone().into()); + }); + + let cjs_if_test = js_typeof!(module_ident.clone() => "object") + .make_bin(op!("&&"), js_typeof!(module_exports.clone() => "object")); + let mut cjs_if_body = factory.clone().as_call(DUMMY_SP, cjs_args); + if module.is_export_assign { + cjs_if_body = cjs_if_body.make_assign_to(op!("="), module_exports.clone().into()); + } + + let amd_if_test = js_typeof!(define.clone() => "function").make_bin(op!("&&"), define_amd); + let amd_if_body = define.as_call( + DUMMY_SP, + vec![ + ArrayLit { + span: DUMMY_SP, + elems: amd_dep_list, + } + .as_arg(), + factory.clone().as_arg(), + ], + ); + + let browser_if_test = CondExpr { + span: DUMMY_SP, + test: Box::new(js_typeof!(global_this.clone() =>! "undefined")), + cons: Box::new(global_this.into()), + alt: Box::new(global.clone().make_bin(op!("||"), js_self)), + } + .make_assign_to(op!("="), global.clone().into()); + + let mut browser_if_body = factory.clone().as_call(DUMMY_SP, browser_args); + if module.is_export_assign { + browser_if_body = browser_if_body.make_assign_to( + op!("="), + module_global_export_member(module.span, cm, config, &global).into(), + ); + } + + let browser_if = if_stmt(browser_if_test, browser_if_body, None); + let amd_if = if_stmt(amd_if_test, amd_if_body, Some(browser_if)); + let adapter_body = FunctionBody { + span: DUMMY_SP, + stmts: vec![if_stmt(cjs_if_test, cjs_if_body, Some(amd_if))], + }; + + let adapter_fn_expr = Function { + params: vec![global.into(), factory.into()], + span: DUMMY_SP, + body: Some(adapter_body), + is_generator: false, + is_async: false, + ..Default::default() + } + .into(); + + (adapter_fn_expr, factory_params) +} + +fn if_stmt(test: Expr, body: Expr, alt: Option) -> Stmt { + IfStmt { + span: DUMMY_SP, + test: Box::new(test), + cons: Box::new(body.into_stmt()), + alt: alt.map(Box::new), + } + .into() +} + +/// Returns the browser fallback global member for the current module. +fn module_global_export_member( + module_span: Span, + cm: &Lrc, + config: &BuiltConfig, + global: &Ident, +) -> MemberExpr { + let filename = cm.span_to_filename(module_span); + let exported_name = config.determine_export_name(filename); + + global.clone().make_member(exported_name.into()) +} diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/util.rs b/deps/swc/crates/swc_ecma_transforms_module/src/util.rs index 970af03a5..2fcc37d1b 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/util.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/util.rs @@ -6,11 +6,11 @@ use swc_config::file_pattern::FilePattern; use swc_ecma_ast::*; use swc_ecma_utils::{ is_valid_prop_ident, member_expr, private_ident, quote_ident, quote_str, ExprFactory, - FunctionFactory, IsDirective, + FunctionFactory, }; use crate::{ - module_decl_strip::{ExportItem, ExportKV}, + module_record::{ExportBinding, LocalExportEntry}, SpanCtx, }; @@ -33,7 +33,7 @@ pub struct Config { /// swc will emit `cjs-module-lexer` detectable annotation with this option /// enabled. /// - /// Defaults to `true` if import_interop is Node, else `false` + /// Defaults to `true` if `import_interop` is Node, else `false` #[serde(default)] pub export_interop_annotation: Option, #[serde(default)] @@ -52,6 +52,7 @@ pub struct Config { } impl Config { + #[must_use] pub fn default_js_ext() -> String { "js".to_string() } @@ -100,12 +101,14 @@ impl From for ImportInterop { impl Config { #[inline(always)] + #[must_use] pub fn import_interop(&self) -> ImportInterop { self.import_interop .unwrap_or_else(|| self.no_interop.into()) } #[inline(always)] + #[must_use] pub fn export_interop_annotation(&self) -> bool { self.export_interop_annotation .unwrap_or_else(|| self.import_interop == Some(ImportInterop::Node)) @@ -119,6 +122,7 @@ pub struct LazyObjectConfig { } impl LazyObjectConfig { + #[must_use] pub fn is_lazy(&self, src: &Atom) -> bool { self.patterns.iter().any(|pat| pat.is_match(src)) } @@ -133,6 +137,7 @@ pub enum Lazy { } impl Lazy { + #[must_use] pub fn is_lazy(&self, src: &Atom) -> bool { match *self { Lazy::Bool(false) => false, @@ -157,14 +162,14 @@ pub(super) fn local_name_for_src(src: &Atom) -> Atom { .unwrap_or(src); let id = match Ident::verify_symbol(src) { - Ok(_) => src.into(), + Ok(()) => src.into(), Err(err) => err, }; - if !id.starts_with('_') { - format!("_{id}").into() - } else { + if id.starts_with('_') { id.into() + } else { + format!("_{id}").into() } } @@ -209,35 +214,6 @@ pub(super) fn define_es_module(exports: Ident) -> Stmt { .into_stmt() } -pub(super) trait VecStmtLike { - type StmtLike: IsDirective; - - fn as_ref(&self) -> &[Self::StmtLike]; - - fn has_use_strict(&self) -> bool { - self.as_ref() - .iter() - .take_while(|s| s.directive_continue()) - .any(IsDirective::is_use_strict) - } -} - -impl VecStmtLike for [ModuleItem] { - type StmtLike = ModuleItem; - - fn as_ref(&self) -> &[Self::StmtLike] { - self - } -} - -impl VecStmtLike for [Stmt] { - type StmtLike = Stmt; - - fn as_ref(&self) -> &[Self::StmtLike] { - self - } -} - pub(super) fn use_strict() -> Stmt { Lit::Str(quote_str!("use strict")).into_stmt() } @@ -324,9 +300,9 @@ pub(crate) fn esm_export() -> Function { Function { params: vec![target.into(), all.into()], - body: Some(BlockStmt { + body: Some(FunctionBody { + span: DUMMY_SP, stmts: vec![for_in_stmt], - ..Default::default() }), ..Default::default() } @@ -335,11 +311,11 @@ pub(crate) fn esm_export() -> Function { /// Sort export properties by key without allocating cached keys or cloning /// `Atom`s for each entry. #[inline] -pub(crate) fn sort_export_obj_prop_list(prop_list: &mut [ExportKV]) { +pub(crate) fn sort_export_bindings(prop_list: &mut [ExportBinding]) { prop_list.sort_unstable_by(|a, b| a.0.cmp(&b.0)); } -pub(crate) fn emit_export_stmts(exports: Ident, mut prop_list: Vec) -> Vec { +pub(crate) fn emit_export_stmts(exports: Ident, mut prop_list: Vec) -> Vec { match prop_list.len() { 0 | 1 => prop_list .pop() @@ -349,7 +325,7 @@ pub(crate) fn emit_export_stmts(exports: Ident, mut prop_list: Vec) -> quote_str!(export_item.export_name_span().0, export_name).as_arg(), prop_function(( "get".into(), - ExportItem::new(Default::default(), export_item.into_local_ident()), + LocalExportEntry::new(Default::default(), export_item.into_local_ident()), )) .into(), ) @@ -423,7 +399,7 @@ impl From for MemberProp { /// }, /// } /// ``` -pub(crate) fn prop_function((key, export_item): ExportKV) -> Prop { +pub(crate) fn prop_function((key, export_item): ExportBinding) -> Prop { let key = prop_name(&key, export_item.export_name_span()).into(); KeyValueProp { @@ -447,13 +423,16 @@ pub(crate) fn prop_function((key, export_item): ExportKV) -> Prop { /// } /// ``` /// Compatibility: getter is supported in Node.js v0.10+ -fn getter_function((key, export_item): ExportKV) -> Prop { +fn getter_function((key, export_item): ExportBinding) -> Prop { let key = prop_name(&key, export_item.export_name_span()).into(); GetterProp { key, - body: Some(BlockStmt { - stmts: vec![export_item.into_local_ident().into_return_stmt().into()], + function: Box::new(Function { + body: Some(FunctionBody { + span: DUMMY_SP, + stmts: vec![export_item.into_local_ident().into_return_stmt().into()], + }), ..Default::default() }), ..Default::default() diff --git a/deps/swc/crates/swc_ecma_transforms_module/src/wtf8.rs b/deps/swc/crates/swc_ecma_transforms_module/src/wtf8.rs index e282d57fd..d01698131 100644 --- a/deps/swc/crates/swc_ecma_transforms_module/src/wtf8.rs +++ b/deps/swc/crates/swc_ecma_transforms_module/src/wtf8.rs @@ -10,8 +10,7 @@ use swc_ecma_ast::Str; pub(crate) fn normalize_wtf8_atom(value: &Wtf8Atom) -> Atom { value .as_str() - .map(Atom::from) - .unwrap_or_else(|| Atom::from(value.to_string_lossy())) + .map_or_else(|| Atom::from(value.to_string_lossy()), Atom::from) } /// Convert a [`Str`] literal into a UTF-8 [`Atom`], preserving valid UTF-8 @@ -22,8 +21,8 @@ pub(crate) fn str_to_atom(value: &Str) -> Atom { } pub(crate) fn wtf8_to_cow_str(value: &Wtf8Atom) -> Cow<'_, str> { - value - .as_str() - .map(Cow::Borrowed) - .unwrap_or_else(|| Cow::Owned(value.to_string_lossy().into_owned())) + value.as_str().map_or_else( + || Cow::Owned(value.to_string_lossy().into_owned()), + Cow::Borrowed, + ) } diff --git a/deps/swc/crates/swc_ecma_transforms_optimization/Cargo.toml b/deps/swc/crates/swc_ecma_transforms_optimization/Cargo.toml index 8956b3c34..19335c7c7 100644 --- a/deps/swc/crates/swc_ecma_transforms_optimization/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms_optimization/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_transforms_optimization" repository = { workspace = true } -version = "47.0.1" +version = "52.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] @@ -29,30 +29,31 @@ once_cell = { workspace = true } par-core = { workspace = true } petgraph = { workspace = true } rustc-hash = { workspace = true } -serde_json = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true, features = ["raw_value"] } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] par-core = { workspace = true, features = ["chili"] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base", features = [ +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base", features = [ "inline-helpers", ] } -swc_ecma_transforms_compat = { version = "52.0.1", path = "../swc_ecma_transforms_compat" } -swc_ecma_transforms_module = { version = "49.0.1", path = "../swc_ecma_transforms_module" } -swc_ecma_transforms_proposal = { version = "44.0.1", path = "../swc_ecma_transforms_proposal" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } -swc_ecma_transforms_typescript = { version = "50.0.0", path = "../swc_ecma_transforms_typescript" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_transforms_compat = { version = "57.0.0", path = "../swc_ecma_transforms_compat" } +swc_ecma_transforms_module = { version = "55.0.0", path = "../swc_ecma_transforms_module" } +swc_ecma_transforms_proposal = { version = "49.0.0", path = "../swc_ecma_transforms_proposal" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } +swc_ecma_transforms_typescript = { version = "55.0.0", path = "../swc_ecma_transforms_typescript" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_ecma_transforms_optimization/src/debug.rs b/deps/swc/crates/swc_ecma_transforms_optimization/src/debug.rs index 490aaab03..61c5ca680 100644 --- a/deps/swc/crates/swc_ecma_transforms_optimization/src/debug.rs +++ b/deps/swc/crates/swc_ecma_transforms_optimization/src/debug.rs @@ -42,16 +42,6 @@ impl Visit for AssertValid { panic!("Invalid node found"); } - #[cfg(debug_assertions)] - fn visit_number(&mut self, n: &Number) { - assert!(!n.value.is_nan(), "NaN should be an identifier"); - } - - #[cfg(debug_assertions)] - fn visit_setter_prop(&mut self, p: &SetterProp) { - p.body.visit_with(self); - } - #[cfg(debug_assertions)] fn visit_stmt(&mut self, n: &Stmt) { let ctx = Ctx { v: n }; diff --git a/deps/swc/crates/swc_ecma_transforms_optimization/src/json_parse.rs b/deps/swc/crates/swc_ecma_transforms_optimization/src/json_parse.rs index 7996cd320..353b9d581 100644 --- a/deps/swc/crates/swc_ecma_transforms_optimization/src/json_parse.rs +++ b/deps/swc/crates/swc_ecma_transforms_optimization/src/json_parse.rs @@ -1,9 +1,15 @@ -use serde_json::Value; +use std::{collections::BTreeMap, fmt::Write}; + +use serde::{ + ser::{SerializeMap, SerializeSeq}, + Serialize, Serializer, +}; +use serde_json::value::RawValue; use swc_atoms::Wtf8Atom; -use swc_common::{util::take::Take, Spanned, DUMMY_SP}; +use swc_common::{Spanned, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_transforms_base::perf::Parallel; -use swc_ecma_utils::{calc_literal_cost, member_expr, ExprFactory}; +use swc_ecma_utils::{calc_literal_cost, member_expr, number::ToJsString, ExprFactory}; use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith}; /// Transform to optimize performance of literals. @@ -65,13 +71,11 @@ impl VisitMut for JsonParse { Expr::Array(..) | Expr::Object(..) => { let (is_lit, cost) = calc_literal_cost(&*expr, false); if is_lit && cost >= self.min_cost { - let value = - serde_json::to_string(&jsonify(expr.take())).unwrap_or_else(|err| { - unreachable!("failed to serialize serde_json::Value as json: {}", err) - }); + let span = expr.span(); + let value = jsonify(expr); *expr = CallExpr { - span: expr.span(), + span, callee: member_expr!(Default::default(), DUMMY_SP, JSON.parse).as_callee(), args: vec![Lit::Str(Str { span: DUMMY_SP, @@ -109,61 +113,105 @@ fn wtf8_to_json_string(value: &Wtf8Atom) -> String { result.push(ch); } else { // Lone surrogate - escape as \uXXXX - use std::fmt::Write; write!(&mut result, "\\u{:04X}", cp.to_u32()).unwrap(); } } result } -fn jsonify(e: Expr) -> Value { - match e { - Expr::Object(obj) => Value::Object( - obj.props - .into_iter() - .map(|v| match v { - PropOrSpread::Prop(p) if p.is_key_value() => p.key_value().unwrap(), - _ => unreachable!(), - }) - .map(|p: KeyValueProp| { - let value = jsonify(*p.value); - let key = match p.key { - PropName::Str(s) => wtf8_to_json_string(&s.value), - PropName::Ident(id) => id.sym.to_string(), - PropName::Num(n) => format!("{}", n.value), - _ => unreachable!(), +/// Converts a finite ECMAScript number without using a saturating integer cast. +fn json_number(value: f64) -> serde_json::Number { + let is_i64 = value.fract() == 0.0 && value >= i64::MIN as f64 && value < i64::MAX as f64; + let preserves_zero_sign = value != 0.0 || value.is_sign_positive(); + + if is_i64 && preserves_zero_sign { + return (value as i64).into(); + } + + serde_json::Number::from_f64(value) + .unwrap_or_else(|| unreachable!("non-finite numbers require raw JSON serialization")) +} + +/// Converts a property name to the string key created by an object literal. +fn json_key(key: &PropName) -> String { + match key { + PropName::Str(s) => wtf8_to_json_string(&s.value), + PropName::Ident(id) => id.sym.to_string(), + PropName::Num(n) => n.value.to_js_string(), + _ => unreachable!(), + } +} + +/// Serializes a literal expression to JSON text while preserving ECMAScript +/// numeric values that are not representable by `serde_json::Value`. +fn jsonify(e: &Expr) -> String { + serde_json::to_string(&JsonLiteral(e)) + .unwrap_or_else(|err| unreachable!("failed to serialize literal as JSON: {err}")) +} + +/// Adapts an ECMAScript literal expression to Serde's data model. +struct JsonLiteral<'a>(&'a Expr); + +impl Serialize for JsonLiteral<'_> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self.0 { + Expr::Object(obj) => { + let mut values = BTreeMap::new(); + for prop in &obj.props { + let PropOrSpread::Prop(prop) = prop else { + unreachable!() + }; + let Prop::KeyValue(prop) = &**prop else { + unreachable!() }; - (key, value) - }) - .collect(), - ), - Expr::Array(arr) => Value::Array( - arr.elems - .into_iter() - .map(|v| jsonify(*v.unwrap().expr)) - .collect(), - ), - Expr::Lit(Lit::Str(Str { value, .. })) => Value::String(wtf8_to_json_string(&value)), - Expr::Lit(Lit::Num(Number { value, .. })) => { - if value.fract() == 0.0 { - Value::Number((value as i64).into()) - } else { - match serde_json::Number::from_f64(value) { - Some(n) => Value::Number(n), - None => Value::Number((value as i64).into()), + values.insert(json_key(&prop.key), &*prop.value); } + + let mut map = serializer.serialize_map(Some(values.len()))?; + for (key, value) in values { + map.serialize_entry(&key, &JsonLiteral(value))?; + } + map.end() + } + Expr::Array(arr) => { + let mut seq = serializer.serialize_seq(Some(arr.elems.len()))?; + for value in &arr.elems { + let value = value.as_ref().unwrap(); + seq.serialize_element(&JsonLiteral(value.expr.as_ref()))?; + } + seq.end() + } + Expr::Lit(Lit::Str(Str { value, .. })) => { + wtf8_to_json_string(value).serialize(serializer) + } + Expr::Lit(Lit::Num(Number { value, .. })) if value.is_infinite() => { + let value = if value.is_sign_positive() { + "2e308" + } else { + "-2e308" + }; + RawValue::from_string(value.into()) + .unwrap() + .serialize(serializer) + } + Expr::Lit(Lit::Num(Number { value, .. })) => json_number(*value).serialize(serializer), + Expr::Lit(Lit::Null(..)) => serializer.serialize_none(), + Expr::Lit(Lit::Bool(v)) => serializer.serialize_bool(v.value), + Expr::Tpl(Tpl { quasis, .. }) => { + let value = match quasis.first() { + Some(TplElement { + cooked: Some(value), + .. + }) => wtf8_to_json_string(value), + _ => String::new(), + }; + value.serialize(serializer) } + _ => unreachable!("jsonify: Expr {:?} cannot be converted to json", self.0), } - Expr::Lit(Lit::Null(..)) => Value::Null, - Expr::Lit(Lit::Bool(v)) => Value::Bool(v.value), - Expr::Tpl(Tpl { quasis, .. }) => Value::String(match quasis.first() { - Some(TplElement { - cooked: Some(value), - .. - }) => wtf8_to_json_string(value), - _ => String::new(), - }), - _ => unreachable!("jsonify: Expr {:?} cannot be converted to json", e), } } diff --git a/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs b/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs index 9f68b57dd..5af7b4265 100644 --- a/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs @@ -736,7 +736,7 @@ impl VisitMut for Remover { ( &Expr::Lit(Lit::Num(Number { value: test, .. })), &Expr::Lit(Lit::Num(Number { value: d, .. })), - ) => (test - d).abs() < 1e-10, + ) => test == d || (test - d).abs() < 1e-10, ( &Expr::Lit(Lit::Bool(Bool { value: test, .. })), &Expr::Lit(Lit::Bool(Bool { value: d, .. })), diff --git a/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/dce/mod.rs b/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/dce/mod.rs index a07086b06..d2b5abfa8 100644 --- a/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/dce/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/dce/mod.rs @@ -38,7 +38,7 @@ pub fn dce( changed: false, pass: 0, in_fn: false, - in_block_stmt: false, + in_non_top_level_lexical_scope: false, var_decl_kind: None, data: Default::default(), }) @@ -84,7 +84,7 @@ struct TreeShaker { pass: u16, in_fn: bool, - in_block_stmt: bool, + in_non_top_level_lexical_scope: bool, var_decl_kind: Option, data: Data, @@ -310,11 +310,27 @@ struct VarInfo { struct Analyzer<'a> { #[allow(dead_code)] config: &'a Config, + expr_ctx: ExprCtx, in_var_decl: bool, scope: Scope<'a>, data: &'a mut Data, cur_class_id: Option, cur_fn_id: Option, + /// Lexical class bindings already declared earlier in the current scope. + /// Used to tell a backward (TDZ-safe) superclass reference, which may + /// participate in a removable declaration cycle, from a forward one, which + /// must be preserved. + initialized_classes: FxHashSet, + /// Subset of the above whose declaration carries decorators. A decorated + /// class is kept observable by its decorator independently of the cycle, so + /// a subclass extending it must not collapse the cycle. + /// Lexical class bindings, among those already initialized, whose + /// declaration is NOT definition-time trivial (see `class_def_is_trivial`): + /// it evaluates decorators, computed keys, or static initializers when + /// defined. A subclass must not collapse its `extends` cycle with such a + /// superclass, since the superclass's eager evaluation may depend on the + /// cycle being intact. + nontrivial_classes: FxHashSet, } #[derive(Debug, Default)] @@ -370,6 +386,9 @@ impl Analyzer<'_> { data: self.data, cur_fn_id: self.cur_fn_id.clone(), cur_class_id: self.cur_class_id.clone(), + // A new scope starts a fresh lexical-initialization context. + initialized_classes: Default::default(), + nontrivial_classes: Default::default(), ..*self }; @@ -448,6 +467,103 @@ impl Analyzer<'_> { } } +/// A class declaration is "definition-time trivial" when evaluating it (running +/// its declaration) does nothing observable beyond resolving its `extends` +/// clause and any computed member keys (whose identifier references are pinned +/// separately by the analyzer). The eager evaluations this guards against are +/// decorators (on the class or any member) and `static` member initializers +/// (`static x = …`, `static #x = …`, and `static {}` blocks). Method and +/// constructor bodies and instance-field initializers run later (at +/// call/instantiation time), so they are not definition-time evaluations. +/// +/// Any eager evaluation may read another class still in its temporal dead zone +/// and throw. Restricting the backward-reference optimization to trivial +/// classes (on both sides of the `extends` edge) means a removable cycle can +/// only be collapsed when neither class evaluates anything at definition time +/// except the heritage reference itself — which the caller separately checks is +/// a safe backward reference. This closes the whole family of definition-time +/// TDZ hazards structurally instead of enumerating each one. The `extends` +/// expression is intentionally not inspected here; it is handled by the caller. +fn class_def_is_trivial(class: &Class) -> bool { + if !class.decorators.is_empty() { + return false; + } + class.body.iter().all(|member| match member { + ClassMember::Constructor(_) | ClassMember::TsIndexSignature(_) | ClassMember::Empty(_) => { + true + } + ClassMember::Method(m) => m.function.decorators.is_empty(), + ClassMember::PrivateMethod(m) => m.function.decorators.is_empty(), + ClassMember::ClassProp(p) => p.decorators.is_empty() && !(p.is_static && p.value.is_some()), + ClassMember::PrivateProp(p) => { + p.decorators.is_empty() && !(p.is_static && p.value.is_some()) + } + ClassMember::AutoAccessor(a) => { + a.decorators.is_empty() && !(a.is_static && a.value.is_some()) + } + ClassMember::StaticBlock(_) => false, + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + }) +} + +/// Returns true when the class definition has no observable side effects, i.e. +/// it is safe to drop when unused. Kept in sync with the `Decl::Class` arm of +/// `visit_mut_decl`'s drop predicate, which calls this. +fn class_def_is_side_effect_free(class: &Class, expr_ctx: ExprCtx) -> bool { + class + .super_class + .as_deref() + .map_or(true, |e| !e.may_have_side_effects(expr_ctx)) + && class.body.iter().all(|m| match m { + ClassMember::Method(m) => !matches!(m.key, PropName::Computed(..)), + ClassMember::ClassProp(m) => { + !matches!(m.key, PropName::Computed(..)) + && !m + .value + .as_deref() + .is_some_and(|e| e.may_have_side_effects(expr_ctx)) + } + ClassMember::AutoAccessor(m) => { + !matches!(m.key, Key::Public(PropName::Computed(..))) + && !m + .value + .as_deref() + .is_some_and(|e| e.may_have_side_effects(expr_ctx)) + } + ClassMember::PrivateProp(m) => !m + .value + .as_deref() + .is_some_and(|e| e.may_have_side_effects(expr_ctx)), + ClassMember::StaticBlock(_) => false, + ClassMember::TsIndexSignature(_) + | ClassMember::Empty(_) + | ClassMember::Constructor(_) + | ClassMember::PrivateMethod(_) => true, + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + }) +} + +/// Returns true if references in an initializer can be attributed to the +/// initialized binding instead of being treated as eager top-level references. +fn can_attribute_initializer_refs_to_binding(expr: &Expr, expr_ctx: ExprCtx) -> bool { + match expr { + Expr::Fn(_) | Expr::Arrow(_) => true, + Expr::Class(c) => { + // Class heritage is evaluated while defining the class and can throw + // even when evaluating the heritage expression itself is pure. The + // remaining checks reject decorators, computed keys, and static + // initialization, leaving only dependencies evaluated after the class + // value is used (for example, method and constructor bodies). + c.class.super_class.is_none() + && class_def_is_trivial(&c.class) + && class_def_is_side_effect_free(&c.class, expr_ctx) + } + _ => false, + } +} + impl Visit for Analyzer<'_> { noop_visit_type!(); @@ -468,12 +584,53 @@ impl Visit for Analyzer<'_> { } fn visit_class_decl(&mut self, n: &ClassDecl) { - if let Some(super_class) = &n.class.super_class { - super_class.visit_with(self); + // A superclass that is a backward reference to an already-initialized + // class can be attributed as a normal dependency edge, letting an + // unreachable `extends` cycle collapse. A forward reference, a + // non-identifier expression, or anything else is treated as a top-level + // reference (the original behavior): it pins the referent as an entry + // and preserves any cycle it belongs to. This keeps TDZ-observable + // cycles such as `class A extends B {} class B extends A {}` (which + // throws at runtime) from being eliminated. + // The backward-reference optimization (attributing the `extends` edge to + // the subclass so an unreachable cycle can collapse) is only applied when + // it is provably safe. It requires the superclass to be an identifier + // already initialized earlier in this scope, AND: + // - the subclass carries no decorators, and the superclass is not decorated + // either — a decorator runs at definition time and keeps a class observable + // independently of the cycle, so collapsing it could drop a sibling the + // decorator still needs; + // - neither class is in `top_retain`, which keeps it externally reachable. + // Anything else falls back to the original behavior (the heritage + // reference pins the referent as an entry, preserving the cycle). + // Preserving an unused cycle is always safe; dropping a live one is the bug. + let super_id = n.class.super_class.as_deref().and_then(|sc| match sc { + Expr::Ident(i) => Some(i.to_id()), + _ => None, + }); + let super_is_initialized_class_ref = class_def_is_trivial(&n.class) + && !self.config.top_retain.contains(&n.ident.sym) + && super_id.as_ref().is_some_and(|id| { + self.initialized_classes.contains(id) + && !self.nontrivial_classes.contains(id) + && !self.config.top_retain.contains(&id.0) + }); + + if !super_is_initialized_class_ref { + if let Some(super_class) = &n.class.super_class { + super_class.visit_with(self); + } } self.with_ast_path(vec![n.ident.to_id()], |v| { let old = v.cur_class_id.take(); + + if super_is_initialized_class_ref { + if let Some(super_class) = &n.class.super_class { + super_class.visit_with(v); + } + } + v.cur_class_id = Some(n.ident.to_id()); n.ident.visit_with(v); n.class.decorators.visit_with(v); @@ -483,11 +640,37 @@ impl Visit for Analyzer<'_> { if !n.class.decorators.is_empty() { v.add(n.ident.to_id(), false); } - }) + }); + + // A class that is not definition-time trivial evaluates something when + // defined (decorators, computed keys, or static initializers) that may + // read another class still in its TDZ. It is recorded so a later + // subclass extending it will not collapse their cycle, and is itself + // pinned as an entry so any cycle it participates in is kept alive. + // Independently, a class whose definition has observable side effects + // cannot be dropped either. + let is_trivial = class_def_is_trivial(&n.class); + if !is_trivial { + self.nontrivial_classes.insert(n.ident.to_id()); + } + if !is_trivial || !class_def_is_side_effect_free(&n.class, self.expr_ctx) { + let idx = self.data.node(&n.ident.to_id()); + self.data.entries.insert(idx); + } + + self.initialized_classes.insert(n.ident.to_id()); } fn visit_class_expr(&mut self, n: &ClassExpr) { - n.visit_children_with(self); + if let Some(ident) = &n.ident { + // ClassDefinitionEvaluation creates a lexical binding for a named + // class expression that is visible only inside the class definition. + let old = self.cur_class_id.replace(ident.to_id()); + n.visit_children_with(self); + self.cur_class_id = old; + } else { + n.visit_children_with(self); + } if !n.class.decorators.is_empty() { if let Some(i) = &n.ident { @@ -613,7 +796,17 @@ impl Visit for Analyzer<'_> { } fn visit_fn_expr(&mut self, n: &FnExpr) { - n.visit_children_with(self); + if let Some(ident) = &n.ident { + // `InstantiateOrdinaryFunctionExpression` creates a binding for a named + // function expression in an environment local to the function. It is + // therefore a self-reference, not a reference to an outer declaration + // with the same symbol. + let old = self.cur_fn_id.replace(ident.to_id()); + n.visit_children_with(self); + self.cur_fn_id = old; + } else { + n.visit_children_with(self); + } if !n.function.decorators.is_empty() { if let Some(i) = &n.ident { @@ -649,7 +842,19 @@ impl Visit for Analyzer<'_> { n.name.visit_with(self); self.in_var_decl = false; - n.init.visit_with(self); + match (&n.name, n.init.as_deref()) { + // When a function or a side-effect-free class directly initializes a + // variable, its deferred references are dependencies of that variable + // rather than top-level entries. Keep this limited to direct values: + // attributing an arbitrary initializer to the binding could hide its + // eager side effects or TDZ errors. + (Pat::Ident(binding), Some(init)) + if can_attribute_initializer_refs_to_binding(init, self.expr_ctx) => + { + self.with_ast_path(vec![binding.to_id()], |v| n.init.visit_with(v)); + } + _ => n.init.visit_with(self), + } self.in_var_decl = old; } @@ -699,7 +904,7 @@ impl TreeShaker { if !self.in_fn { return false; } - } else if !self.in_block_stmt { + } else if !self.in_non_top_level_lexical_scope { return false; } } @@ -720,7 +925,7 @@ impl TreeShaker { if !self.in_fn { return false; } - } else if !self.in_block_stmt { + } else if !self.in_non_top_level_lexical_scope { return false; } @@ -777,6 +982,48 @@ impl TreeShaker { } } +/// Top-level declared identifiers, without descending into function bodies. +fn push_decl_binding_ids(decl: &Decl, out: &mut Vec) { + match decl { + Decl::Class(c) => out.push(c.ident.to_id()), + Decl::Fn(f) => out.push(f.ident.to_id()), + Decl::Var(v) => { + for d in &v.decls { + out.extend(find_pat_ids::<_, Id>(&d.name)); + } + } + _ => {} + } +} + +/// Collects `var` bindings that hoist to the enclosing top-level (module or +/// script) scope: `var`s anywhere except inside a nested function scope. Used +/// alongside the immediate top-level declarations so a `var` hoisted out of a +/// top-level block (e.g. `if (c) { var x }`) stays visible to a root `eval`. +#[derive(Default)] +struct RootHoistedVars { + ids: Vec, +} + +impl Visit for RootHoistedVars { + noop_visit_type!(); + + // Nested function scopes don't hoist their `var`s to the root. + fn visit_function(&mut self, _: &Function) {} + + fn visit_arrow_expr(&mut self, _: &ArrowExpr) {} + + fn visit_constructor(&mut self, _: &Constructor) {} + + fn visit_var_decl(&mut self, n: &VarDecl) { + if n.kind == VarDeclKind::Var { + for d in &n.decls { + self.ids.extend(find_pat_ids::<_, Id>(&d.name)); + } + } + } +} + impl VisitMut for TreeShaker { noop_visit_mut_type!(); @@ -799,13 +1046,20 @@ impl VisitMut for TreeShaker { } fn visit_mut_block_stmt(&mut self, n: &mut BlockStmt) { - let old_in_block_stmt = self.in_block_stmt; - self.in_block_stmt = true; + let old_in_non_top_level_lexical_scope = self.in_non_top_level_lexical_scope; + self.in_non_top_level_lexical_scope = true; + n.visit_mut_children_with(self); + self.in_non_top_level_lexical_scope = old_in_non_top_level_lexical_scope; + } + + fn visit_mut_function_body(&mut self, n: &mut FunctionBody) { + let old_in_non_top_level_lexical_scope = self.in_non_top_level_lexical_scope; + self.in_non_top_level_lexical_scope = true; n.visit_mut_children_with(self); - self.in_block_stmt = old_in_block_stmt; + self.in_non_top_level_lexical_scope = old_in_non_top_level_lexical_scope; } - fn visit_mut_block_stmt_or_expr(&mut self, n: &mut BlockStmtOrExpr) { + fn visit_mut_arrow_function_body(&mut self, n: &mut ArrowFunctionBody) { let old_in_fn = self.in_fn; self.in_fn = true; n.visit_mut_children_with(self); @@ -831,41 +1085,7 @@ impl VisitMut for TreeShaker { } Decl::Class(c) if self.can_drop_binding(c.ident.to_id(), false) - && c.class - .super_class - .as_deref() - .map_or(true, |e| !e.may_have_side_effects(self.expr_ctx)) - && c.class.body.iter().all(|m| match m { - ClassMember::Method(m) => !matches!(m.key, PropName::Computed(..)), - ClassMember::ClassProp(m) => { - !matches!(m.key, PropName::Computed(..)) - && !m - .value - .as_deref() - .is_some_and(|e| e.may_have_side_effects(self.expr_ctx)) - } - ClassMember::AutoAccessor(m) => { - !matches!(m.key, Key::Public(PropName::Computed(..))) - && !m - .value - .as_deref() - .is_some_and(|e| e.may_have_side_effects(self.expr_ctx)) - } - - ClassMember::PrivateProp(m) => !m - .value - .as_deref() - .is_some_and(|e| e.may_have_side_effects(self.expr_ctx)), - - ClassMember::StaticBlock(_) => false, - - ClassMember::TsIndexSignature(_) - | ClassMember::Empty(_) - | ClassMember::Constructor(_) - | ClassMember::PrivateMethod(_) => true, - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }) => + && class_def_is_side_effect_free(&c.class, self.expr_ctx) => { #[cfg(debug_assertions)] debug!("Dropping class `{}` as it's not used", c.ident); @@ -1032,13 +1252,62 @@ impl VisitMut for TreeShaker { { let mut analyzer = Analyzer { config: &self.config, + expr_ctx: self.expr_ctx, in_var_decl: false, scope: Default::default(), data: &mut data, cur_class_id: Default::default(), cur_fn_id: Default::default(), + initialized_classes: Default::default(), + nontrivial_classes: Default::default(), }; m.visit_with(&mut analyzer); + + if analyzer.scope.found_direct_eval { + // A direct `eval` reaching the root can resolve any + // top-level binding by name. Pin the module's top-level + // declarations as graph entries so DCE can't drop them. + // Unlike `collect_decls`, we do NOT descend into function + // bodies: a top-level `eval` cannot observe bindings nested + // inside another scope. + let mut ids = Vec::new(); + for item in &m.body { + match item { + ModuleItem::Stmt(Stmt::Decl(d)) => push_decl_binding_ids(d, &mut ids), + ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(e)) => { + push_decl_binding_ids(&e.decl, &mut ids) + } + ModuleItem::ModuleDecl(ModuleDecl::Import(i)) => { + for spec in &i.specifiers { + ids.push(match spec { + ImportSpecifier::Named(s) => s.local.to_id(), + ImportSpecifier::Default(s) => s.local.to_id(), + ImportSpecifier::Namespace(s) => s.local.to_id(), + #[cfg(swc_ast_unknown)] + _ => continue, + }); + } + } + _ => {} + } + } + + // Also pin `var`s hoisted out of nested top-level statements + // (e.g. `if (c) { var x }`), visible to a root `eval`. + let mut hoisted = RootHoistedVars::default(); + m.visit_with(&mut hoisted); + ids.extend(hoisted.ids); + + for id in ids { + // Pin as a graph entry so `subtract_cycles` never + // subtracts it (survives Repeat passes), and bump usage + // so a lone binding — which has no in-graph references — + // isn't dropped by `can_drop_binding`. + let ix = analyzer.data.node(&id); + analyzer.data.entries.insert(ix); + analyzer.data.used_names.entry(id).or_default().usage += 1; + } + } } data.subtract_cycles(); self.data = data; @@ -1098,13 +1367,47 @@ impl VisitMut for TreeShaker { { let mut analyzer = Analyzer { config: &self.config, + expr_ctx: self.expr_ctx, in_var_decl: false, scope: Default::default(), data: &mut data, cur_class_id: Default::default(), cur_fn_id: Default::default(), + initialized_classes: Default::default(), + nontrivial_classes: Default::default(), }; m.visit_with(&mut analyzer); + + // A direct `eval` can reference any binding in its enclosing + // lexical scope chain, up to the top level. `found_direct_eval` + // is propagated to the root scope, but unlike function scopes + // (see `with_scope`), the root never consumed it, so top-level + // declarations reachable by a direct `eval` were dropped. + // Preserve them here. + if analyzer.scope.found_direct_eval { + let mut ids = Vec::new(); + for stmt in &m.body { + if let Stmt::Decl(d) = stmt { + push_decl_binding_ids(d, &mut ids); + } + } + + // Also pin `var`s hoisted out of nested top-level statements + // (e.g. `if (c) { var x }`), visible to a root `eval`. + let mut hoisted = RootHoistedVars::default(); + m.visit_with(&mut hoisted); + ids.extend(hoisted.ids); + + for id in ids { + // Pin as a graph entry so `subtract_cycles` never + // subtracts it (survives Repeat passes), and bump usage + // so a lone binding — which has no in-graph references — + // isn't dropped by `can_drop_binding`. + let ix = analyzer.data.node(&id); + analyzer.data.entries.insert(ix); + analyzer.data.used_names.entry(id).or_default().usage += 1; + } + } } data.subtract_cycles(); self.data = data; diff --git a/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs b/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs index e6f648f97..ca470d62a 100644 --- a/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs @@ -1,7 +1,6 @@ use std::{borrow::Cow, iter, iter::once}; use swc_atoms::{ - atom, wtf8::{CodePoint, Wtf8, Wtf8Buf}, Atom, }; @@ -16,8 +15,10 @@ use swc_ecma_transforms_base::{ perf::{cpu_count, Parallel, ParallelExt}, }; use swc_ecma_utils::{ - is_literal, number::JsNumber, prop_name_eq, to_int32, BoolType, ExprCtx, ExprExt, NullType, - NumberType, ObjectType, StringType, SymbolType, UndefinedType, Value, + is_literal, + number::{minify_number, parse_canonical_index, JsNumber, ToJsString}, + prop_name_eq, to_int32, BoolType, ExprCtx, ExprExt, NullType, NumberType, ObjectType, + StringType, SymbolType, UndefinedType, Value, }; use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith}; use Value::{Known, Unknown}; @@ -589,21 +590,45 @@ where } /// Gets the `idx`-th UTF-16 code unit from the given [Wtf8]. -/// Surrogate pairs are splitted into high and low surrogates and counted +/// Surrogate pairs are split into high and low surrogates and counted /// separately. -fn nth_char(s: &Wtf8, idx: usize) -> CodePoint { - match s.to_ill_formed_utf16().nth(idx) { - Some(c) => - // SAFETY: `IllFormedUtf16CodeUnits` always returns code units in the range of UTF-16. - unsafe { CodePoint::from_u32_unchecked(c as u32) }, - None => unreachable!("string is too short"), - } +fn nth_char(s: &Wtf8, idx: usize) -> Option { + s.to_ill_formed_utf16().nth(idx).map(|c| { + // SAFETY: `IllFormedUtf16CodeUnits` always returns code units in the range of + // UTF-16. + unsafe { CodePoint::from_u32_unchecked(c as u32) } + }) } fn need_zero_for_this(e: &Expr) -> bool { e.directness_matters() || e.is_seq() } +/// A statically known property key with optional metadata for literal indexing. +/// +/// `property_key` is always the exact ECMAScript property key. `index` is only +/// populated for canonical non-negative decimal keys that can index a literal +/// array or string without reinterpreting the property key. +struct KnownMemberKey { + property_key: Atom, + index: Option, +} + +impl KnownMemberKey { + fn from_number(value: f64) -> Self { + Self::from_property_key(Atom::from(value.to_js_string())) + } + + fn from_property_key(property_key: Atom) -> Self { + let index = parse_canonical_index(property_key.as_str()); + + Self { + property_key, + index, + } + } +} + /// Gets the value of the given key from the given object properties, if the key /// exists. If the key does exist, `Some` is returned and the property is /// removed from the given properties. @@ -685,24 +710,17 @@ pub fn optimize_member_expr( _ => return, }; - #[derive(Clone, PartialEq, Debug)] enum KnownOp { /// [a, b].length Len, - /// [a, b][0] - /// - /// {0.5: "bar"}[0.5] - /// Note: callers need to check `v.fract() == 0.0` in some cases. - /// ie non-integer indexes for arrays result in `undefined` - /// but not for objects (because indexing an object - /// returns the value of the key, ie `0.5` will not - /// return `undefined` if a key `0.5` exists - /// and its value is not `undefined`). - Index(f64), - - /// ({}).foo - IndexStr(Atom), + /// A known ECMAScript property key. + Key { + key: KnownMemberKey, + // Numeric keys preserve the existing object-folding eligibility; + // other keys still require a fully literal object. + requires_literal_object: bool, + }, } let op = match prop { MemberProp::Ident(IdentName { sym, .. }) if &**sym == "length" && !obj.is_object() => { @@ -713,7 +731,10 @@ pub fn optimize_member_expr( return; } - KnownOp::IndexStr(sym.clone()) + KnownOp::Key { + key: KnownMemberKey::from_property_key(sym.clone()), + requires_literal_object: true, + } } MemberProp::Computed(ComputedPropName { expr, .. }) => { if is_callee { @@ -722,17 +743,19 @@ pub fn optimize_member_expr( if let Expr::Lit(Lit::Num(Number { value, .. })) = &**expr { // x[5] - KnownOp::Index(*value) + KnownOp::Key { + key: KnownMemberKey::from_number(*value), + requires_literal_object: false, + } } else if let Known(s) = expr.as_pure_string(expr_ctx) { if s == "length" && !obj.is_object() { // Length of non-object type KnownOp::Len - } else if let Ok(n) = s.parse::() { - // x['0'] is treated as x[0] - KnownOp::Index(n) } else { - // x[''] or x[...] where ... is an expression like [], ie x[[]] - KnownOp::IndexStr(s.into()) + KnownOp::Key { + key: KnownMemberKey::from_property_key(s.into()), + requires_literal_object: true, + } } } else { return; @@ -769,14 +792,22 @@ pub fn optimize_member_expr( } // 'foo'[1] - KnownOp::Index(idx) => { - if idx.fract() != 0.0 || idx < 0.0 || idx as usize >= value.len() { - // Prototype changes affect indexing if the index is out of bounds, so we - // don't replace out-of-bound indexes. + KnownOp::Key { key, .. } => { + let Some(index) = key.index else { + return; + }; + + // WTF-8 byte length is an upper bound for UTF-16 code-unit length. + if index >= value.len() { return; } - let c = nth_char(value, idx as _); + // Prototype changes affect indexing if the index is out of bounds, so we + // don't replace out-of-bound indexes. This lookup must use UTF-16 code units, + // which are JavaScript's string indexing units, rather than WTF-8 bytes. + let Some(c) = nth_char(value, index) else { + return; + }; *changed = true; // `nth_char` always returns a code point within the UTF-16 range. @@ -790,11 +821,6 @@ pub fn optimize_member_expr( }) .into() } - - // 'foo'[''] - // - // Handled in compress - KnownOp::IndexStr(..) => {} }, // [1, 2, 3].length @@ -835,22 +861,23 @@ pub fn optimize_member_expr( .into(); } - KnownOp::Index(idx) => { - // If the fraction part is non-zero, or if the index is out of bounds, - // then we handle this in compress as Array's prototype may be modified. - if idx.fract() != 0.0 || idx < 0.0 || idx as usize >= elems.len() { + KnownOp::Key { key, .. } => { + let Some(index) = key.index else { + return; + }; + + // Out-of-bound indexes are handled in compress because Array's + // prototype may be modified. + if index >= elems.len() { return; } // Don't change if after has side effects. let after_has_side_effect = - elems - .iter() - .skip((idx as usize + 1) as _) - .any(|elem| match elem { - Some(elem) => elem.expr.may_have_side_effects(expr_ctx), - None => false, - }); + elems.iter().skip(index + 1).any(|elem| match elem { + Some(elem) => elem.expr.may_have_side_effects(expr_ctx), + None => false, + }); if after_has_side_effect { return; @@ -859,7 +886,7 @@ pub fn optimize_member_expr( *changed = true; // elements before target element - let before: Vec> = elems.drain(..(idx as usize)).collect(); + let before: Vec> = elems.drain(..index).collect(); let mut iter = elems.take().into_iter(); // element at idx let e = iter.next().flatten(); @@ -901,9 +928,6 @@ pub fn optimize_member_expr( exprs.push(val); *expr = *Expr::from_exprs(exprs); } - - // Handled in compress - KnownOp::IndexStr(..) => {} } } @@ -913,8 +937,14 @@ pub fn optimize_member_expr( Expr::Object(ObjectLit { props, span }) => { // get key let key = match op { - KnownOp::Index(i) => Atom::from(i.to_string()), - KnownOp::IndexStr(key) if key != *"yield" && is_literal(props) => key, + KnownOp::Key { + key, + requires_literal_object, + } if key.property_key != *"yield" + && (!requires_literal_object || is_literal(props)) => + { + key.property_key + } _ => return, }; @@ -976,15 +1006,11 @@ pub fn optimize_bin_expr(expr_ctx: ExprCtx, expr: &mut Expr, changed: &mut bool) Known(v) => { *changed = true; - let value_expr = if !v.is_nan() { - Expr::Lit(Lit::Num(Number { - value: v, - span: *span, - raw: None, - })) - } else { - Expr::Ident(Ident::new(atom!("NaN"), *span, expr_ctx.unresolved_ctxt)) - }; + let value_expr = Expr::Lit(Lit::Num(Number { + value: v, + span: *span, + raw: None, + })); *expr = *expr_ctx.preserve_effects(*span, value_expr.into(), { iter::once(left.take()).chain(iter::once(right.take())) @@ -1057,16 +1083,12 @@ pub fn optimize_bin_expr(expr_ctx: ExprCtx, expr: &mut Expr, changed: &mut bool) *changed = true; let span = *span; - let value_expr = if !v.is_nan() { - Lit::Num(Number { - value: v, - span, - raw: None, - }) - .into() - } else { - Ident::new(atom!("NaN"), span, expr_ctx.unresolved_ctxt).into() - }; + let value_expr = Lit::Num(Number { + value: v, + span, + raw: None, + }) + .into(); *expr = *expr_ctx.preserve_effects( span, @@ -1230,16 +1252,12 @@ pub fn optimize_bin_expr(expr_ctx: ExprCtx, expr: &mut Expr, changed: &mut bool) { if *left_op == op { if let Known(value) = perform_arithmetic_op(expr_ctx, op, left_rhs, right) { - let value_expr = if !value.is_nan() { - Lit::Num(Number { - value, - span: *span, - raw: None, - }) - .into() - } else { - Ident::new(atom!("NaN"), *span, expr_ctx.unresolved_ctxt).into() - }; + let value_expr = Lit::Num(Number { + value, + span: *span, + raw: None, + }) + .into(); *changed = true; *left = left_lhs.take(); @@ -1309,15 +1327,6 @@ pub fn optimize_unary_expr(expr_ctx: ExprCtx, expr: &mut Expr, changed: &mut boo if let Known(v) = arg.as_pure_number(expr_ctx) { *changed = true; - if v.is_nan() { - *expr = *expr_ctx.preserve_effects( - *span, - Ident::new(atom!("NaN"), *span, expr_ctx.unresolved_ctxt).into(), - iter::once(arg.take()), - ); - return; - } - *expr = *expr_ctx.preserve_effects( *span, Lit::Num(Number { @@ -1373,11 +1382,7 @@ pub fn optimize_unary_expr(expr_ctx: ExprCtx, expr: &mut Expr, changed: &mut boo *changed = true; *expr = Lit::Num(Number { span: *span, - value: if value < 0.0 { - !(value as i32 as u32) as i32 as f64 - } else { - !(value as u32) as i32 as f64 - }, + value: (!JsNumber::from(value)).into(), raw: None, }) .into(); @@ -1435,29 +1440,39 @@ fn try_fold_typeof(_expr_ctx: ExprCtx, expr: &mut Expr, changed: &mut bool) { /// Try to fold arithmetic binary operators fn perform_arithmetic_op(expr_ctx: ExprCtx, op: BinaryOp, left: &Expr, right: &Expr) -> Value { /// Replace only if it becomes shorter - macro_rules! try_replace { - ($value:expr) => {{ - let (ls, rs) = (left.span(), right.span()); - if ls.is_dummy() || rs.is_dummy() { - Known($value) - } else { - let new_len = format!("{}", $value).len(); - if right.span().hi() > left.span().lo() { - let orig_len = - right.span().hi() - right.span().lo() + left.span().hi() - left.span().lo(); - if new_len <= orig_len.0 as usize + 1 { - Known($value) - } else { - Unknown - } - } else { - Known($value) - } - } - }}; - (i32, $value:expr) => { - try_replace!($value as f64) - }; + fn try_replace(lv: f64, rv: f64, value: f64) -> Value { + if !value.is_finite() { + return Known(value); + } + + let new_len = minify_number(value, &mut false).len(); + + let orig_len = + minify_number(lv, &mut false).len() + 1 + minify_number(rv, &mut false).len(); + + if new_len <= orig_len { + Known(value) + } else { + Unknown + } + } + + fn try_replace_i32(lv: f64, rv: f64, value: i32) -> Value { + let new_len = value.to_string().len(); + + let orig_len = minify_number(lv, &mut false) + .len() + .min(to_int32(lv).to_string().len()) + + 1 + + minify_number(rv, &mut false) + .len() + .min(to_int32(rv).to_string().len()); + + if new_len <= orig_len { + Known(value as f64) + } else { + Unknown + } } let (lv, rv) = ( @@ -1476,7 +1491,7 @@ fn perform_arithmetic_op(expr_ctx: ExprCtx, op: BinaryOp, left: &Expr, right: &E match op { op!(bin, "+") => { if let (Known(lv), Known(rv)) = (lv, rv) { - return try_replace!(lv + rv); + return try_replace(lv, rv, lv + rv); } if lv == Known(0.0) { @@ -1489,7 +1504,7 @@ fn perform_arithmetic_op(expr_ctx: ExprCtx, op: BinaryOp, left: &Expr, right: &E } op!(bin, "-") => { if let (Known(lv), Known(rv)) = (lv, rv) { - return try_replace!(lv - rv); + return try_replace(lv, rv, lv - rv); } // 0 - x => -x @@ -1506,7 +1521,7 @@ fn perform_arithmetic_op(expr_ctx: ExprCtx, op: BinaryOp, left: &Expr, right: &E } op!("*") => { if let (Known(lv), Known(rv)) = (lv, rv) { - return try_replace!(lv * rv); + return try_replace(lv, rv, lv * rv); } // NOTE: 0*x != 0 for all x, if x==0, then it is NaN. So we can't take // advantage of that without some kind of non-NaN proof. So the special cases @@ -1523,10 +1538,7 @@ fn perform_arithmetic_op(expr_ctx: ExprCtx, op: BinaryOp, left: &Expr, right: &E op!("/") => { if let (Known(lv), Known(rv)) = (lv, rv) { - if rv == 0.0 { - return Unknown; - } - return try_replace!(lv / rv); + return try_replace(lv, rv, lv / rv); } // NOTE: 0/x != 0 for all x, if x==0, then it is NaN @@ -1545,10 +1557,10 @@ fn perform_arithmetic_op(expr_ctx: ExprCtx, op: BinaryOp, left: &Expr, right: &E } if let (Known(lv), Known(rv)) = (lv, rv) { - let lv: JsNumber = lv.into(); - let rv: JsNumber = rv.into(); - let result: f64 = lv.pow(rv).into(); - return try_replace!(result); + let js_lv: JsNumber = lv.into(); + let js_rv: JsNumber = rv.into(); + let result: f64 = js_lv.pow(js_rv).into(); + return try_replace(lv, rv, result); } return Unknown; @@ -1561,15 +1573,10 @@ fn perform_arithmetic_op(expr_ctx: ExprCtx, op: BinaryOp, left: &Expr, right: &E }; match op { - op!("&") => try_replace!(i32, to_int32(lv) & to_int32(rv)), - op!("|") => try_replace!(i32, to_int32(lv) | to_int32(rv)), - op!("^") => try_replace!(i32, to_int32(lv) ^ to_int32(rv)), - op!("%") => { - if rv == 0.0 { - return Unknown; - } - try_replace!(lv % rv) - } + op!("&") => try_replace_i32(lv, rv, to_int32(lv) & to_int32(rv)), + op!("|") => try_replace_i32(lv, rv, to_int32(lv) | to_int32(rv)), + op!("^") => try_replace_i32(lv, rv, to_int32(lv) ^ to_int32(rv)), + op!("%") => try_replace(lv, rv, lv % rv), _ => unreachable!("unknown binary operator: {:?}", op), } } diff --git a/deps/swc/crates/swc_ecma_transforms_proposal/Cargo.toml b/deps/swc/crates/swc_ecma_transforms_proposal/Cargo.toml index 37a8c418c..46aed341d 100644 --- a/deps/swc/crates/swc_ecma_transforms_proposal/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms_proposal/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_transforms_proposal" repository = { workspace = true } -version = "44.0.1" +version = "49.0.0" [lib] bench = false @@ -24,18 +24,18 @@ either = { workspace = true } rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_classes = { version = "44.0.0", path = "../swc_ecma_transforms_classes" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_classes = { version = "49.0.0", path = "../swc_ecma_transforms_classes" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] serde_json = { workspace = true } -swc_ecma_compat_es2022 = { version = "48.0.0", path = "../swc_ecma_compat_es2022" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_compat = { version = "52.0.1", path = "../swc_ecma_transforms_compat" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_compat_es2022 = { version = "53.0.0", path = "../swc_ecma_compat_es2022" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_compat = { version = "57.0.0", path = "../swc_ecma_transforms_compat" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_ecma_transforms_proposal/src/decorator_impl.rs b/deps/swc/crates/swc_ecma_transforms_proposal/src/decorator_impl.rs index 04fd95f65..7d546afbf 100644 --- a/deps/swc/crates/swc_ecma_transforms_proposal/src/decorator_impl.rs +++ b/deps/swc/crates/swc_ecma_transforms_proposal/src/decorator_impl.rs @@ -181,19 +181,6 @@ impl Visit for MovedStaticSuperFinder { // binding and should not trigger the rewrite. } - fn visit_getter_prop(&mut self, n: &GetterProp) { - n.key.visit_with(self); - } - - fn visit_method_prop(&mut self, n: &MethodProp) { - n.key.visit_with(self); - } - - fn visit_setter_prop(&mut self, n: &SetterProp) { - n.key.visit_with(self); - n.param.visit_with(self); - } - fn visit_super(&mut self, _: &Super) { self.found = true; } @@ -482,10 +469,9 @@ impl DecoratorPass { function: Box::new(Function { span: DUMMY_SP, params: Vec::new(), - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: Vec::new(), - ..Default::default() }), is_async: false, is_generator: false, @@ -738,13 +724,12 @@ impl DecoratorPass { let mut closure_fn = Function { span: DUMMY_SP, params: Vec::new(), - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, arg: Some(value), })], - ..Default::default() }), is_async: false, is_generator: false, @@ -1040,7 +1025,7 @@ impl DecoratorPass { ArrowExpr { span: DUMMY_SP, params: vec![arg.clone().into()], - body: Box::new(BlockStmtOrExpr::Expr( + body: Box::new(ArrowFunctionBody::Expr( BinExpr { span: DUMMY_SP, left: Expr::PrivateName(brand.clone()).into(), @@ -1148,7 +1133,7 @@ impl DecoratorPass { callee: ArrowExpr { span: DUMMY_SP, params: Vec::new(), - body: BlockStmtOrExpr::BlockStmt(BlockStmt { + body: ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts: vec![ VarDecl { @@ -1175,7 +1160,6 @@ impl DecoratorPass { } .into(), ], - ..Default::default() }) .into(), is_async: false, @@ -1565,10 +1549,9 @@ impl DecoratorPass { span: DUMMY_SP, key: PropName::Ident(atom!("constructor").into()), params: Vec::new(), - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: Vec::new(), - ..Default::default() }), ..Default::default() }), @@ -1779,10 +1762,9 @@ impl DecoratorPass { callee: ArrowExpr { span: DUMMY_SP, params: Vec::new(), - body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt { + body: Box::new(ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts: last_static_block, - ..Default::default() })), is_async: false, is_generator: false, @@ -1938,7 +1920,7 @@ impl DecoratorPass { }; p.function.params = params; - p.function.body = Some(BlockStmt { + p.function.body = Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, @@ -1960,7 +1942,6 @@ impl DecoratorPass { .into(), ), })], - ..Default::default() }); } @@ -1991,10 +1972,9 @@ impl DecoratorPass { let mut closure_fn = Function { span: DUMMY_SP, params: Vec::new(), - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: last, - ..Default::default() }), is_async: false, is_generator: false, @@ -2019,10 +1999,9 @@ impl DecoratorPass { callee: ArrowExpr { span: DUMMY_SP, params: Vec::new(), - body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt { + body: Box::new(ArrowFunctionBody::FunctionBody(FunctionBody { span: DUMMY_SP, stmts: last, - ..Default::default() })), is_async: false, is_generator: false, @@ -2576,10 +2555,9 @@ impl VisitMut for DecoratorPass { p.kind = MethodKind::Getter; p.function.is_async = false; p.function.is_generator = false; - p.function.body = Some(BlockStmt { + p.function.body = Some(FunctionBody { span: DUMMY_SP, stmts: vec![call_stmt], - ..Default::default() }); } MethodKind::Getter => { @@ -2598,10 +2576,9 @@ impl VisitMut for DecoratorPass { } .into(); - p.function.body = Some(BlockStmt { + p.function.body = Some(FunctionBody { span: DUMMY_SP, stmts: vec![call_stmt], - ..Default::default() }); } MethodKind::Setter => { @@ -2622,10 +2599,9 @@ impl VisitMut for DecoratorPass { } .into(); - p.function.body = Some(BlockStmt { + p.function.body = Some(FunctionBody { span: DUMMY_SP, stmts: vec![call_stmt], - ..Default::default() }); } #[cfg(swc_ast_unknown)] @@ -2745,7 +2721,7 @@ impl VisitMut for DecoratorPass { params: Default::default(), decorators: Default::default(), span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, @@ -2755,7 +2731,6 @@ impl VisitMut for DecoratorPass { prop: MemberProp::PrivateName(private_field.key.clone()), }))), })], - ..Default::default() }), is_generator: false, is_async: false, @@ -2772,7 +2747,7 @@ impl VisitMut for DecoratorPass { }], decorators: Default::default(), span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Expr(ExprStmt { span: DUMMY_SP, @@ -2790,7 +2765,6 @@ impl VisitMut for DecoratorPass { right: param.clone().into(), })), })], - ..Default::default() }), is_generator: false, is_async: false, @@ -2842,7 +2816,7 @@ impl VisitMut for DecoratorPass { let receiver = private_ident!("_this"); Box::new(Function { span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, @@ -2857,7 +2831,6 @@ impl VisitMut for DecoratorPass { .into(), ), })], - ..Default::default() }), is_async: false, is_generator: false, @@ -2877,7 +2850,7 @@ impl VisitMut for DecoratorPass { let setter_arg = private_ident!("_v"); Box::new(Function { span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Expr(ExprStmt { span: DUMMY_SP, @@ -2897,7 +2870,6 @@ impl VisitMut for DecoratorPass { )), })), })], - ..Default::default() }), is_async: false, is_generator: false, @@ -2958,7 +2930,7 @@ impl VisitMut for DecoratorPass { getter_function = Box::new(Function { params: Vec::new(), span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, @@ -2979,7 +2951,6 @@ impl VisitMut for DecoratorPass { ..Default::default() }))), })], - ..Default::default() }), is_generator: false, is_async: false, @@ -2996,7 +2967,7 @@ impl VisitMut for DecoratorPass { }], decorators: Default::default(), span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Expr(ExprStmt { span: DUMMY_SP, @@ -3020,7 +2991,6 @@ impl VisitMut for DecoratorPass { ..Default::default() })), })], - ..Default::default() }), is_generator: false, is_async: false, @@ -3385,6 +3355,19 @@ impl VisitMut for DecoratorPass { return; } + + let mut old_state = take(&mut self.state); + let private_id_index = old_state.private_id_index; + self.state = ClassState { + private_id_index, + ..Default::default() + }; + maybe_grow_default(|| c.visit_mut_with(self)); + let nested_state = take(&mut self.state); + old_state.private_id_index = nested_state.private_id_index; + self.state = old_state; + + return; } maybe_grow_default(|| e.visit_mut_children_with(self)); @@ -3596,7 +3579,7 @@ impl VisitMut for DecoratorPass { let getter = Box::new(Function { span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, @@ -3609,7 +3592,6 @@ impl VisitMut for DecoratorPass { .into(), ), })], - ..Default::default() }), is_async: false, is_generator: false, @@ -3624,7 +3606,7 @@ impl VisitMut for DecoratorPass { let setter = Box::new(Function { span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Expr(ExprStmt { span: DUMMY_SP, @@ -3640,7 +3622,6 @@ impl VisitMut for DecoratorPass { right: Box::new(Expr::Ident(setter_arg.clone())), })), })], - ..Default::default() }), is_async: false, is_generator: false, @@ -3670,13 +3651,12 @@ impl VisitMut for DecoratorPass { let getter = Box::new(Function { span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, arg: Some(access_expr.clone().into()), })], - ..Default::default() }), is_async: false, is_generator: false, @@ -3685,7 +3665,7 @@ impl VisitMut for DecoratorPass { let setter_arg = private_ident!("value"); let setter = Box::new(Function { span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Expr(ExprStmt { span: DUMMY_SP, @@ -3696,7 +3676,6 @@ impl VisitMut for DecoratorPass { right: Box::new(Expr::Ident(setter_arg.clone())), })), })], - ..Default::default() }), is_async: false, is_generator: false, diff --git a/deps/swc/crates/swc_ecma_transforms_proposal/src/decorators/mod.rs b/deps/swc/crates/swc_ecma_transforms_proposal/src/decorators/mod.rs index 30a2c8e88..1cd848425 100644 --- a/deps/swc/crates/swc_ecma_transforms_proposal/src/decorators/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_proposal/src/decorators/mod.rs @@ -533,13 +533,12 @@ impl Decorators { decorators: Vec::new(), params: Vec::new(), - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, arg: Some(value), })], - ..Default::default() }), ..Default::default() } @@ -581,7 +580,7 @@ impl Decorators { is_async: false, is_generator: false, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: if !self.is_in_strict { // 'use strict'; @@ -633,7 +632,6 @@ impl Decorators { .into(), )) .collect(), - ..Default::default() }), ..Default::default() } diff --git a/deps/swc/crates/swc_ecma_transforms_react/Cargo.toml b/deps/swc/crates/swc_ecma_transforms_react/Cargo.toml index 0f059a715..516d1905c 100644 --- a/deps/swc/crates/swc_ecma_transforms_react/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms_react/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ecma_transforms_react" repository = { workspace = true } -version = "50.0.0" +version = "55.0.0" [lib] bench = false @@ -31,21 +31,21 @@ serde = { workspace = true, features = ["derive"], optional = true } sha1 = { workspace = true } string_enum = { version = "1.0.2", path = "../string_enum" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_config = { version = "5.0.0", path = "../swc_config" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_hooks = { version = "0.9.0", path = "../swc_ecma_hooks" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_config = { version = "6.0.0", path = "../swc_config" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_hooks = { version = "1.0.0", path = "../swc_ecma_hooks" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_compat = { version = "52.0.1", path = "../swc_ecma_transforms_compat/", optional = true } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_compat = { version = "57.0.0", path = "../swc_ecma_transforms_compat/", optional = true } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen/" } -swc_ecma_transforms_compat = { version = "52.0.1", path = "../swc_ecma_transforms_compat/" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen/" } +swc_ecma_transforms_compat = { version = "57.0.0", path = "../swc_ecma_transforms_compat/" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_ecma_transforms_react/src/jsx/mod.rs b/deps/swc/crates/swc_ecma_transforms_react/src/jsx/mod.rs index bbc7b3dc9..bedafff67 100644 --- a/deps/swc/crates/swc_ecma_transforms_react/src/jsx/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_react/src/jsx/mod.rs @@ -30,7 +30,10 @@ use swc_ecma_utils::{ use swc_ecma_visit::VisitMut; use self::static_check::should_use_create_element; -use crate::refresh::options::{deserialize_refresh, RefreshOptions}; +use crate::{ + jsx_self::JsxSelfCtx, + refresh::options::{deserialize_refresh, RefreshOptions}, +}; mod static_check; #[cfg(test)] @@ -245,6 +248,7 @@ where .throw_if_namespace .unwrap_or_else(default_throw_if_namespace), top_level_node: true, + self_ctx: JsxSelfCtx::new(), } } @@ -295,6 +299,7 @@ where pragma_frag: Lrc>, development: bool, throw_if_namespace: bool, + self_ctx: JsxSelfCtx, } #[derive(Debug, Default, Clone, PartialEq, Eq)] @@ -489,6 +494,47 @@ impl Jsx where C: Comments, { + /// Build the JSXDEV source argument for fragments, which cannot carry + /// synthetic attributes. + fn jsx_dev_source_arg(&self, span: Span) -> ExprOrSpread { + if span == DUMMY_SP { + return Expr::undefined(DUMMY_SP).as_arg(); + } + + let loc = self.cm.lookup_char_pos(span.lo); + + ObjectLit { + span: DUMMY_SP, + props: vec![ + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(quote_ident!("fileName")), + value: Box::new(Expr::Lit(Lit::Str(Str { + span: DUMMY_SP, + raw: None, + value: loc.file.name.to_string().into(), + }))), + }))), + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(quote_ident!("lineNumber")), + value: loc.line.into(), + }))), + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(quote_ident!("columnNumber")), + value: (loc.col.0 + 1).into(), + }))), + ], + } + .as_arg() + } + + fn jsx_dev_self_arg(&self) -> ExprOrSpread { + if self.self_ctx.can_add_self() { + ThisExpr { span: DUMMY_SP }.as_arg() + } else { + Expr::undefined(DUMMY_SP).as_arg() + } + } + /// Process JSX attribute value, handling JSXElements and JSXFragments fn process_attr_value(&mut self, value: Option) -> Box { match value { @@ -636,6 +682,8 @@ where props_obj.as_arg(), Expr::undefined(DUMMY_SP).as_arg(), use_jsxs.as_arg(), + self.jsx_dev_source_arg(el.opening.span), + self.jsx_dev_self_arg(), ] } else { vec![fragment.as_arg(), props_obj.as_arg()] @@ -1160,6 +1208,86 @@ impl VisitMutHook<()> for Jsx where C: Comments, { + fn enter_class(&mut self, n: &mut Class, _ctx: &mut ()) { + self.self_ctx.enter_class(n); + } + + fn exit_class(&mut self, _n: &mut Class, _ctx: &mut ()) { + self.self_ctx.pop(); + } + + fn enter_fn_decl(&mut self, _n: &mut FnDecl, _ctx: &mut ()) { + self.self_ctx.enter_non_constructor_scope(); + } + + fn exit_fn_decl(&mut self, _n: &mut FnDecl, _ctx: &mut ()) { + self.self_ctx.pop(); + } + + fn enter_fn_expr(&mut self, _n: &mut FnExpr, _ctx: &mut ()) { + self.self_ctx.enter_non_constructor_scope(); + } + + fn exit_fn_expr(&mut self, _n: &mut FnExpr, _ctx: &mut ()) { + self.self_ctx.pop(); + } + + fn enter_getter_prop(&mut self, _n: &mut GetterProp, _ctx: &mut ()) { + self.self_ctx.enter_non_constructor_scope(); + } + + fn exit_getter_prop(&mut self, _n: &mut GetterProp, _ctx: &mut ()) { + self.self_ctx.pop(); + } + + fn enter_setter_prop(&mut self, _n: &mut SetterProp, _ctx: &mut ()) { + self.self_ctx.enter_non_constructor_scope(); + } + + fn exit_setter_prop(&mut self, _n: &mut SetterProp, _ctx: &mut ()) { + self.self_ctx.pop(); + } + + fn enter_method_prop(&mut self, _n: &mut MethodProp, _ctx: &mut ()) { + self.self_ctx.enter_non_constructor_scope(); + } + + fn exit_method_prop(&mut self, _n: &mut MethodProp, _ctx: &mut ()) { + self.self_ctx.pop(); + } + + fn enter_constructor(&mut self, _n: &mut Constructor, _ctx: &mut ()) { + self.self_ctx.enter_constructor(); + } + + fn exit_constructor(&mut self, _n: &mut Constructor, _ctx: &mut ()) { + self.self_ctx.pop(); + } + + fn enter_class_method(&mut self, _n: &mut ClassMethod, _ctx: &mut ()) { + self.self_ctx.enter_non_constructor_scope(); + } + + fn exit_class_method(&mut self, _n: &mut ClassMethod, _ctx: &mut ()) { + self.self_ctx.pop(); + } + + fn enter_private_method(&mut self, _n: &mut PrivateMethod, _ctx: &mut ()) { + self.self_ctx.enter_non_constructor_scope(); + } + + fn exit_private_method(&mut self, _n: &mut PrivateMethod, _ctx: &mut ()) { + self.self_ctx.pop(); + } + + fn enter_static_block(&mut self, _n: &mut StaticBlock, _ctx: &mut ()) { + self.self_ctx.enter_non_constructor_scope(); + } + + fn exit_static_block(&mut self, _n: &mut StaticBlock, _ctx: &mut ()) { + self.self_ctx.pop(); + } + /// Called after visiting children of an expression. /// /// This is where we transform JSX syntax to JavaScript function calls. @@ -1459,16 +1587,18 @@ fn to_prop_name(n: JSXAttrName) -> PropName { /// preserve whitespace that was explicitly encoded as HTML entities like /// ` `, ` `, ` `, ` `. #[inline] -fn jsx_text_to_str_with_raw(value: &Atom, raw: &Atom) -> Wtf8Atom { +fn jsx_text_to_str_with_raw(value: &Wtf8Atom, raw: &Atom) -> Wtf8Atom { // Fast path: if no HTML entities (raw == value), use the simple algorithm - if value.as_str() == raw.as_str() { - return jsx_text_to_str_impl(value).into(); + if let Some(value) = value.as_str() { + if value == raw.as_str() { + return jsx_text_to_str_impl(value).into(); + } } - - // Build a mask of which byte positions in value came from HTML entities + // Build a mask of which code point positions in value came from HTML + // entities. let entity_mask = build_entity_mask(value, raw); - jsx_text_to_str_with_entity_mask(value, &entity_mask).into() + jsx_text_to_str_with_entity_mask(value, &entity_mask) } /// Build a mask indicating which character positions in `value` came from HTML @@ -1476,45 +1606,76 @@ fn jsx_text_to_str_with_raw(value: &Atom, raw: &Atom) -> Wtf8Atom { /// /// Returns a Vec where true means the character at that index was from an /// entity. -fn build_entity_mask(value: &str, raw: &str) -> Vec { - let mut mask = vec![false; value.chars().count()]; +fn build_entity_mask(value: &Wtf8Atom, raw: &str) -> Vec { + let cp = value.as_wtf8().code_points(); + let mut mask = vec![false; cp.count()]; let mut value_char_idx = 0; let mut raw_chars = raw.chars().peekable(); while let Some(raw_c) = raw_chars.next() { if raw_c == '&' { - // Possible HTML entity - let mut entity_chars: Vec = vec!['&']; - let mut found_semicolon = false; - - // Collect up to 10 characters to match entity pattern - for _ in 0..10 { - if let Some(&next_c) = raw_chars.peek() { - entity_chars.push(next_c); - raw_chars.next(); - if next_c == ';' { - found_semicolon = true; - break; + let mut entity = raw_chars.clone(); + let mut s = String::new(); + let mut consumed = 0; + let mut has_prev_result = false; + let mut entity_code_points = 0; + + for _ in 0..20 { + let Some(c) = entity.next() else { + break; + }; + consumed += 1; + + if c != ';' { + s.push(c); + continue; + } + + if let Some(result) = parse_jsx_numeric_entity(&s) { + if (0xd800..=0xdfff).contains(&result) { + if result < 0xdc00 { + if has_prev_result { + entity_code_points += 1; + } + + if entity.next() == Some('&') && entity.next() == Some('#') { + consumed += 2; + has_prev_result = true; + s.clear(); + s.push('#'); + continue; + } + + entity_code_points += 1; + break; + } else if has_prev_result { + entity_code_points += 1; + break; + } + } + + if has_prev_result { + entity_code_points += 1; } + entity_code_points += 1; + break; + } else if is_known_html_entity(&s) { + entity_code_points += 1; + break; } else { break; } } - if found_semicolon && is_valid_entity(&entity_chars) { - // This was a valid entity - mark this position in value as from - // entity - if value_char_idx < mask.len() { - mask[value_char_idx] = true; - } - value_char_idx += 1; + if entity_code_points != 0 { + raw_chars.by_ref().take(consumed).count(); + + let end = value_char_idx + entity_code_points; + let mask_end = mask.len().min(end); + mask[value_char_idx..mask_end].fill(true); + value_char_idx = end; } else { - // Not a valid entity, the '&' is literal value_char_idx += 1; - // The other characters we consumed are also literal - for _ in 1..entity_chars.len() { - value_char_idx += 1; - } } } else { // Regular character @@ -1525,32 +1686,24 @@ fn build_entity_mask(value: &str, raw: &str) -> Vec { mask } -/// Check if the collected characters form a valid HTML entity -fn is_valid_entity(chars: &[char]) -> bool { - if chars.len() < 3 { - return false; - } - if chars[0] != '&' || chars[chars.len() - 1] != ';' { - return false; - } - - let inner: String = chars[1..chars.len() - 1].iter().collect(); - - if let Some(stripped) = inner.strip_prefix('#') { - // Numeric entity +fn parse_jsx_numeric_entity(s: &str) -> Option { + if let Some(stripped) = s.strip_prefix('#') { if let Some(hex) = stripped .strip_prefix('x') .or_else(|| stripped.strip_prefix('X')) { - // Hex: &#xHHHH; - !hex.is_empty() && hex.chars().all(|c| c.is_ascii_hexdigit()) + if !hex.is_empty() && hex.chars().all(|c| c.is_ascii_hexdigit()) { + u32::from_str_radix(hex, 16).ok().filter(|&v| v <= 0x10ffff) + } else { + None + } + } else if !stripped.is_empty() && stripped.chars().all(|c| c.is_ascii_digit()) { + stripped.parse::().ok().filter(|&v| v <= 0x10ffff) } else { - // Decimal: &#DDDD; - !stripped.is_empty() && stripped.chars().all(|c| c.is_ascii_digit()) + None } } else { - // Named entity - check against known entities - is_known_html_entity(&inner) + None } } @@ -1817,12 +1970,12 @@ fn is_known_html_entity(name: &str) -> bool { } /// JSX text processing with entity mask - preserves whitespace from HTML -/// entities -fn jsx_text_to_str_with_entity_mask(t: &str, entity_mask: &[bool]) -> Atom { +/// entities. +fn jsx_text_to_str_with_entity_mask(t: &Wtf8, entity_mask: &[bool]) -> Wtf8Atom { // Fast path: if no line terminators and no trimmable whitespace // (whitespace that's not from entities at the leading edge) - let chars: Vec = t.chars().collect(); - let has_line_terminator = chars.iter().any(|&c| is_line_terminator(c)); + let chars: Vec<_> = wtf8_chars(t).collect(); + let has_line_terminator = chars.iter().any(|(_, _, c)| is_line_terminator(*c)); // For single-line text, we keep all whitespace (matching original behavior) // The original jsx_text_to_str_impl preserves leading/trailing whitespace on @@ -1831,23 +1984,25 @@ fn jsx_text_to_str_with_entity_mask(t: &str, entity_mask: &[bool]) -> Atom { return t.into(); } - let mut acc: Option = None; - let mut only_line: Option = None; + let mut acc: Option = None; + let mut only_line: Option<(usize, usize)> = None; let mut line_start: Option = Some(0); let mut line_end: Option = None; // The first line preserves leading whitespace; subsequent lines trim it. let mut is_first_line = true; - for (char_idx, c) in chars.iter().enumerate() { + for (char_idx, (_, _, c)) in chars.iter().enumerate() { let is_from_entity = *entity_mask.get(char_idx).unwrap_or(&false); if is_line_terminator(*c) { // Process current line - trim both leading AND trailing (intermediate // line) if let (Some(start), Some(end)) = (line_start, line_end) { - let line_text = + let line_range = extract_line_content(&chars, start, end, entity_mask, !is_first_line, true); - add_line_of_jsx_text_owned(line_text, &mut acc, &mut only_line); + if let Some((line_start, line_end)) = line_range { + add_line_of_jsx_text_wtf8(line_start, line_end, t, &mut acc, &mut only_line); + } } is_first_line = false; line_start = None; @@ -1864,7 +2019,7 @@ fn jsx_text_to_str_with_entity_mask(t: &str, entity_mask: &[bool]) -> Atom { // Handle final line. Leading whitespace is preserved only if this is still // the first line (single-line input). if let Some(start) = line_start { - let line_text = extract_line_content( + let line_range = extract_line_content( &chars, start, chars.len(), @@ -1872,35 +2027,58 @@ fn jsx_text_to_str_with_entity_mask(t: &str, entity_mask: &[bool]) -> Atom { !is_first_line, false, ); - add_line_of_jsx_text_owned(line_text, &mut acc, &mut only_line); + if let Some((line_start, line_end)) = line_range { + add_line_of_jsx_text_wtf8(line_start, line_end, t, &mut acc, &mut only_line); + } } if let Some(acc) = acc { acc.into() - } else if let Some(only_line) = only_line { - only_line.into() + } else if let Some((start, end)) = only_line { + t.slice(start, end).into() } else { - "".into() + Wtf8Atom::default() } } +fn wtf8_chars(t: &Wtf8) -> impl Iterator + '_ { + let mut byte_pos = 0; + + t.code_points().map(move |cp| { + let start = byte_pos; + let cp_value = cp.to_u32(); + let cp_byte_len = if cp_value < 0x80 { + 1 + } else if cp_value < 0x800 { + 2 + } else if cp_value < 0x10000 { + 3 + } else { + 4 + }; + byte_pos += cp_byte_len; + + (start, byte_pos, cp.to_char_lossy()) + }) +} + /// Extract line content, optionally trimming non-entity whitespace from edges /// /// - `trim_leading`: if true, trim leading non-entity whitespace /// - `trim_trailing`: if true, trim trailing non-entity whitespace fn extract_line_content( - chars: &[char], + chars: &[(usize, usize, char)], start: usize, end: usize, entity_mask: &[bool], trim_leading: bool, trim_trailing: bool, -) -> String { +) -> Option<(usize, usize)> { // Find first non-trimmable position (if trim_leading is true) let mut actual_start = start; if trim_leading { while actual_start < end { - let c = chars[actual_start]; + let c = chars[actual_start].2; let is_from_entity = *entity_mask.get(actual_start).unwrap_or(&false); if !is_white_space_single_line(c) || is_from_entity { break; @@ -1913,7 +2091,7 @@ fn extract_line_content( let mut actual_end = end; if trim_trailing { while actual_end > actual_start { - let c = chars[actual_end - 1]; + let c = chars[actual_end - 1].2; let is_from_entity = *entity_mask.get(actual_end - 1).unwrap_or(&false); if !is_white_space_single_line(c) || is_from_entity { break; @@ -1922,30 +2100,10 @@ fn extract_line_content( } } - chars[actual_start..actual_end].iter().collect() -} - -/// Owned version of add_line_of_jsx_text for use with entity mask processing -fn add_line_of_jsx_text_owned( - line: String, - acc: &mut Option, - only_line: &mut Option, -) { - if line.is_empty() { - return; - } - - if let Some(buffer) = acc.as_mut() { - buffer.push(' '); - buffer.push_str(&line); - } else if let Some(only_line_content) = only_line.take() { - let mut buffer = String::with_capacity(line.len() * 2); - buffer.push_str(&only_line_content); - buffer.push(' '); - buffer.push_str(&line); - *acc = Some(buffer); + if actual_start == actual_end { + None } else { - *only_line = Some(line); + Some((chars[actual_start].0, chars[actual_end - 1].1)) } } diff --git a/deps/swc/crates/swc_ecma_transforms_react/src/jsx_self/mod.rs b/deps/swc/crates/swc_ecma_transforms_react/src/jsx_self/mod.rs index 42a97cad0..f210268a3 100644 --- a/deps/swc/crates/swc_ecma_transforms_react/src/jsx_self/mod.rs +++ b/deps/swc/crates/swc_ecma_transforms_react/src/jsx_self/mod.rs @@ -12,7 +12,7 @@ mod tests; pub fn hook(dev: bool) -> impl VisitMutHook<()> { JsxSelf { dev, - ctx_stack: vec![Context::default()], + ctx: JsxSelfCtx::new(), } } @@ -23,28 +23,76 @@ struct Context { in_derived_class: bool, } -struct JsxSelf { - dev: bool, +/// Tracks when JSXDEV can safely use `this` for the self argument. +/// +/// This mirrors Babel's `transform-react-jsx-self` constructor guard. Arrow +/// functions keep the surrounding `this`, so they intentionally do not enter a +/// new context. +pub(crate) struct JsxSelfCtx { ctx_stack: Vec, } -impl JsxSelf { - fn current_ctx(&self) -> Context { +impl JsxSelfCtx { + pub(crate) fn new() -> Self { + Self { + ctx_stack: vec![Context::default()], + } + } + + fn current(&self) -> Context { *self .ctx_stack .last() .expect("context stack should never be empty") } - fn push_ctx(&mut self, ctx: Context) { + fn push(&mut self, ctx: Context) { self.ctx_stack.push(ctx); } - fn pop_ctx(&mut self) { + pub(crate) fn pop(&mut self) { if self.ctx_stack.len() > 1 { self.ctx_stack.pop(); } } + + pub(crate) fn enter_class(&mut self, class: &Class) { + let mut new_ctx = self.current(); + new_ctx.in_derived_class = class.super_class.is_some(); + self.push(new_ctx); + } + + pub(crate) fn enter_constructor(&mut self) { + let mut new_ctx = self.current(); + new_ctx.in_constructor = true; + self.push(new_ctx); + } + + /// Enter a function-like scope where `this` is no longer the current + /// constructor's uninitialized `this`. + pub(crate) fn enter_non_constructor_scope(&mut self) { + let mut new_ctx = self.current(); + new_ctx.in_constructor = false; + self.push(new_ctx); + } + + /// Return whether a JSXDEV call can safely use `this` for the self + /// argument. + pub(crate) fn can_add_self(&self) -> bool { + let ctx = self.current(); + !(ctx.in_constructor && ctx.in_derived_class) + } +} + +impl Default for JsxSelfCtx { + fn default() -> Self { + Self::new() + } +} + +struct JsxSelf { + dev: bool, + ctx: JsxSelfCtx, } // For tests @@ -61,103 +109,83 @@ fn jsx_self(dev: bool) -> impl Pass { impl VisitMutHook<()> for JsxSelf { fn enter_class(&mut self, n: &mut Class, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_derived_class = n.super_class.is_some(); - self.push_ctx(new_ctx); + self.ctx.enter_class(n); } fn exit_class(&mut self, _n: &mut Class, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_fn_decl(&mut self, _n: &mut FnDecl, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_constructor = false; - self.push_ctx(new_ctx); + self.ctx.enter_non_constructor_scope(); } fn exit_fn_decl(&mut self, _n: &mut FnDecl, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_fn_expr(&mut self, _n: &mut FnExpr, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_constructor = false; - self.push_ctx(new_ctx); + self.ctx.enter_non_constructor_scope(); } fn exit_fn_expr(&mut self, _n: &mut FnExpr, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_getter_prop(&mut self, _n: &mut GetterProp, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_constructor = false; - self.push_ctx(new_ctx); + self.ctx.enter_non_constructor_scope(); } fn exit_getter_prop(&mut self, _n: &mut GetterProp, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_setter_prop(&mut self, _n: &mut SetterProp, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_constructor = false; - self.push_ctx(new_ctx); + self.ctx.enter_non_constructor_scope(); } fn exit_setter_prop(&mut self, _n: &mut SetterProp, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_method_prop(&mut self, _n: &mut MethodProp, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_constructor = false; - self.push_ctx(new_ctx); + self.ctx.enter_non_constructor_scope(); } fn exit_method_prop(&mut self, _n: &mut MethodProp, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_constructor(&mut self, _n: &mut Constructor, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_constructor = true; - self.push_ctx(new_ctx); + self.ctx.enter_constructor(); } fn exit_constructor(&mut self, _n: &mut Constructor, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_class_method(&mut self, _n: &mut ClassMethod, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_constructor = false; - self.push_ctx(new_ctx); + self.ctx.enter_non_constructor_scope(); } fn exit_class_method(&mut self, _n: &mut ClassMethod, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_private_method(&mut self, _n: &mut PrivateMethod, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_constructor = false; - self.push_ctx(new_ctx); + self.ctx.enter_non_constructor_scope(); } fn exit_private_method(&mut self, _n: &mut PrivateMethod, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_static_block(&mut self, _n: &mut StaticBlock, _ctx: &mut ()) { - let mut new_ctx = self.current_ctx(); - new_ctx.in_constructor = false; - self.push_ctx(new_ctx); + self.ctx.enter_non_constructor_scope(); } fn exit_static_block(&mut self, _n: &mut StaticBlock, _ctx: &mut ()) { - self.pop_ctx(); + self.ctx.pop(); } fn enter_jsx_opening_element(&mut self, n: &mut JSXOpeningElement, _ctx: &mut ()) { @@ -165,10 +193,8 @@ impl VisitMutHook<()> for JsxSelf { return; } - let ctx = self.current_ctx(); - // https://github.com/babel/babel/blob/1bdb1a4175ed1fc40751fb84dc4ad1900260f28f/packages/babel-plugin-transform-react-jsx-self/src/index.ts#L50 - if ctx.in_constructor && ctx.in_derived_class { + if !self.ctx.can_add_self() { return; } diff --git a/deps/swc/crates/swc_ecma_transforms_react/src/refresh/hook.rs b/deps/swc/crates/swc_ecma_transforms_react/src/refresh/hook.rs index bba9670aa..6c0eecfdf 100644 --- a/deps/swc/crates/swc_ecma_transforms_react/src/refresh/hook.rs +++ b/deps/swc/crates/swc_ecma_transforms_react/src/refresh/hook.rs @@ -168,7 +168,7 @@ impl HookRegister<'_> { params: Vec::new(), decorators: Vec::new(), span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, @@ -177,7 +177,6 @@ impl HookRegister<'_> { elems, }))), })], - ..Default::default() }), ..Default::default() } @@ -204,29 +203,25 @@ impl HookRegister<'_> { .into(), ) } -} - -impl VisitMut for HookRegister<'_> { - noop_visit_mut_type!(); - fn visit_mut_block_stmt(&mut self, b: &mut BlockStmt) { + fn visit_mut_stmt_list_with_scope(&mut self, ctxt: SyntaxContext, stmts: &mut Vec) { let old_ident = self.ident.take(); let old_stmts = self.extra_stmt.take(); - self.current_scope.push(b.ctxt); + self.current_scope.push(ctxt); - let stmt_count = b.stmts.len(); - let stmts = mem::replace(&mut b.stmts, Vec::with_capacity(stmt_count)); + let stmt_count = stmts.len(); + let original_stmts = mem::replace(stmts, Vec::with_capacity(stmt_count)); - for mut stmt in stmts { + for mut stmt in original_stmts { stmt.visit_mut_children_with(self); - b.stmts.push(stmt); - b.stmts.append(&mut self.extra_stmt); + stmts.push(stmt); + stmts.append(&mut self.extra_stmt); } if !self.ident.is_empty() { - b.stmts.insert(0, self.gen_hook_handle()) + stmts.insert(0, self.gen_hook_handle()) } self.current_scope.pop(); @@ -234,6 +229,55 @@ impl VisitMut for HookRegister<'_> { self.extra_stmt = old_stmts; } + fn visit_mut_arrow_body_with_scope( + &mut self, + ctxt: SyntaxContext, + body: &mut ArrowFunctionBody, + ) { + match body { + ArrowFunctionBody::FunctionBody(body) => { + self.visit_mut_stmt_list_with_scope(ctxt, &mut body.stmts); + } + ArrowFunctionBody::Expr(expr) => expr.visit_mut_with(self), + #[cfg(swc_ast_unknown)] + _ => body.visit_mut_children_with(self), + } + } +} + +impl VisitMut for HookRegister<'_> { + noop_visit_mut_type!(); + + fn visit_mut_block_stmt(&mut self, b: &mut BlockStmt) { + self.visit_mut_stmt_list_with_scope(b.ctxt, &mut b.stmts); + } + + fn visit_mut_function_body(&mut self, _: &mut FunctionBody) {} + + fn visit_mut_function(&mut self, function: &mut Function) { + function.visit_mut_children_with(self); + + if let Some(body) = &mut function.body { + self.visit_mut_stmt_list_with_scope(function.ctxt, &mut body.stmts); + } + } + + fn visit_mut_constructor(&mut self, constructor: &mut Constructor) { + constructor.visit_mut_children_with(self); + + if let Some(body) = &mut constructor.body { + self.visit_mut_stmt_list_with_scope(constructor.ctxt, &mut body.stmts); + } + } + + fn visit_mut_arrow_expr(&mut self, arrow: &mut ArrowExpr) { + arrow.visit_mut_children_with(self); + + if let ArrowFunctionBody::FunctionBody(body) = arrow.body.as_mut() { + self.visit_mut_stmt_list_with_scope(arrow.ctxt, &mut body.stmts); + } + } + fn visit_mut_expr(&mut self, e: &mut Expr) { e.visit_mut_children_with(self); @@ -279,7 +323,10 @@ impl VisitMut for HookRegister<'_> { ident: fn_ident, function: f, }) if f.body.is_some() => { - f.body.visit_mut_with(self); + self.visit_mut_stmt_list_with_scope( + f.ctxt, + &mut f.body.as_mut().unwrap().stmts, + ); let mut self_ids = vec![id.to_id()]; if let Some(fn_ident) = fn_ident { self_ids.push(fn_ident.to_id()); @@ -290,8 +337,8 @@ impl VisitMut for HookRegister<'_> { self.gen_hook_register_stmt(Ident::from(&*id), sig); } } - Expr::Arrow(ArrowExpr { body, .. }) => { - body.visit_mut_with(self); + Expr::Arrow(ArrowExpr { ctxt, body, .. }) => { + self.visit_mut_arrow_body_with_scope(*ctxt, body); let self_ids = [id.to_id()]; if let Some(sig) = collect_hooks_arrow(body, self.cm, &self_ids) { self.gen_hook_register_stmt(Ident::from(&*id), sig); @@ -357,13 +404,13 @@ fn collect_hooks(stmts: &mut Vec, cm: &SourceMap, self_ids: &[Id]) -> Opti } fn collect_hooks_arrow( - body: &mut BlockStmtOrExpr, + body: &mut ArrowFunctionBody, cm: &SourceMap, self_ids: &[Id], ) -> Option { match body { - BlockStmtOrExpr::BlockStmt(block) => collect_hooks(&mut block.stmts, cm, self_ids), - BlockStmtOrExpr::Expr(expr) => { + ArrowFunctionBody::FunctionBody(body) => collect_hooks(&mut body.stmts, cm, self_ids), + ArrowFunctionBody::Expr(expr) => { let mut hook = HookCollector { state: Vec::new(), cm, @@ -374,7 +421,7 @@ fn collect_hooks_arrow( if !hook.state.is_empty() { let sig = HookSig::new(hook.state); - *body = BlockStmtOrExpr::BlockStmt(BlockStmt { + *body = ArrowFunctionBody::FunctionBody(FunctionBody { span: expr.span(), stmts: vec![ make_call_stmt(sig.handle.clone()), @@ -383,7 +430,6 @@ fn collect_hooks_arrow( arg: Some(Box::new(expr.as_mut().take())), }), ], - ..Default::default() }); Some(sig) } else { @@ -495,10 +541,12 @@ impl HookCollector<'_> { impl Visit for HookCollector<'_> { noop_visit_type!(); - fn visit_block_stmt_or_expr(&mut self, _: &BlockStmtOrExpr) {} + fn visit_arrow_function_body(&mut self, _: &ArrowFunctionBody) {} fn visit_block_stmt(&mut self, _: &BlockStmt) {} + fn visit_function_body(&mut self, _: &FunctionBody) {} + fn visit_expr(&mut self, expr: &Expr) { expr.visit_children_with(self); diff --git a/deps/swc/crates/swc_ecma_transforms_react/src/refresh/util.rs b/deps/swc/crates/swc_ecma_transforms_react/src/refresh/util.rs index b75744008..4ad96295c 100644 --- a/deps/swc/crates/swc_ecma_transforms_react/src/refresh/util.rs +++ b/deps/swc/crates/swc_ecma_transforms_react/src/refresh/util.rs @@ -20,8 +20,8 @@ pub fn is_builtin_hook(name: &str) -> bool { ) } -pub fn is_body_arrow_fn(body: &BlockStmtOrExpr) -> bool { - if let BlockStmtOrExpr::Expr(body) = body { +pub fn is_body_arrow_fn(body: &ArrowFunctionBody) -> bool { + if let ArrowFunctionBody::Expr(body) = body { body.is_arrow() } else { false diff --git a/deps/swc/crates/swc_ecma_transforms_testing/Cargo.toml b/deps/swc/crates/swc_ecma_transforms_testing/Cargo.toml index 0c69c3bd7..1a0de47c1 100644 --- a/deps/swc/crates/swc_ecma_transforms_testing/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms_testing/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_transforms_testing" repository = { workspace = true } -version = "48.0.0" +version = "53.0.0" [lib] bench = false @@ -19,16 +19,16 @@ hex = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } sha2 = { workspace = true } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "sourcemap", ] } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_testing = { version = "24.0.1", path = "../swc_ecma_testing" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_testing = { version = "27.0.0", path = "../swc_ecma_testing" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } swc_sourcemap = { workspace = true } tempfile = { workspace = true } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_ecma_transforms_typescript/Cargo.toml b/deps/swc/crates/swc_ecma_transforms_typescript/Cargo.toml index 502fec69c..276331131 100644 --- a/deps/swc/crates/swc_ecma_transforms_typescript/Cargo.toml +++ b/deps/swc/crates/swc_ecma_transforms_typescript/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "examples/**/*.rs"] license = { workspace = true } name = "swc_ecma_transforms_typescript" repository = { workspace = true } -version = "50.0.0" +version = "55.0.0" [lib] bench = false @@ -24,24 +24,24 @@ bytes-str = { workspace = true } rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_react = { version = "50.0.0", path = "../swc_ecma_transforms_react" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_react = { version = "55.0.0", path = "../swc_ecma_transforms_react" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] codspeed-criterion-compat = { workspace = true } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } serde_json = { workspace = true } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", features = ["flow"] } -swc_ecma_transforms_compat = { version = "52.0.1", path = "../swc_ecma_transforms_compat" } -swc_ecma_transforms_proposal = { version = "44.0.1", path = "../swc_ecma_transforms_proposal" } -swc_ecma_transforms_testing = { version = "48.0.0", path = "../swc_ecma_transforms_testing" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", features = ["flow"] } +swc_ecma_transforms_compat = { version = "57.0.0", path = "../swc_ecma_transforms_compat" } +swc_ecma_transforms_proposal = { version = "49.0.0", path = "../swc_ecma_transforms_proposal" } +swc_ecma_transforms_testing = { version = "53.0.0", path = "../swc_ecma_transforms_testing" } +testing = { version = "27.0.0", path = "../testing" } [[bench]] harness = false diff --git a/deps/swc/crates/swc_ecma_transforms_typescript/src/semantic.rs b/deps/swc/crates/swc_ecma_transforms_typescript/src/semantic.rs index 20c105e43..8d0e138c7 100644 --- a/deps/swc/crates/swc_ecma_transforms_typescript/src/semantic.rs +++ b/deps/swc/crates/swc_ecma_transforms_typescript/src/semantic.rs @@ -6,7 +6,7 @@ use swc_ecma_visit::{noop_visit_type, Visit, VisitWith}; use crate::{ retain::{should_retain_decl, IsConcrete}, - shared::{enum_member_id_atom, get_module_ident}, + shared::{enum_member_name, get_module_ident}, ts_enum::{EnumValueComputer, TsEnumRecord, TsEnumRecordKey, TsEnumRecordValue}, }; @@ -277,7 +277,7 @@ impl SemanticAnalyzer { // name as the runtime string value. The AST does not retain // the explicit `of string` kind, so `Void` acts as the // sentinel for Flow's default string mode here. - TsEnumRecordValue::String(enum_member_id_atom(&member.id)) + TsEnumRecordValue::String(enum_member_name(&member.id)) } else { default_init.clone() } @@ -572,7 +572,7 @@ impl Visit for SemanticAnalyzer { default_init = value.inc(); - let member_name = enum_member_id_atom(&member.id); + let member_name = enum_member_name(&member.id); let key = TsEnumRecordKey { enum_id: id.to_id(), member_name, @@ -670,7 +670,7 @@ mod tests { let value = SemanticAnalyzer::transform_ts_enum_member( enum_member("A"), &id("E"), - &TsEnumRecordValue::Number(2.0.into()), + &TsEnumRecordValue::from(2.0), &Default::default(), SyntaxContext::empty(), false, @@ -679,6 +679,6 @@ mod tests { let TsEnumRecordValue::Number(value) = value else { panic!("expected defaulted TypeScript enum member to stay numeric"); }; - assert_eq!(*value, 2.0); + assert_eq!(value.value, 2.0); } } diff --git a/deps/swc/crates/swc_ecma_transforms_typescript/src/shared.rs b/deps/swc/crates/swc_ecma_transforms_typescript/src/shared.rs index eee9ddab1..2079b1621 100644 --- a/deps/swc/crates/swc_ecma_transforms_typescript/src/shared.rs +++ b/deps/swc/crates/swc_ecma_transforms_typescript/src/shared.rs @@ -1,12 +1,12 @@ -use swc_atoms::Atom; +use swc_atoms::Wtf8Atom; use swc_ecma_ast::{Ident, TsEntityName, TsEnumMemberId}; -/// Returns enum member key as an atom for record lookup. +/// Returns an enum member name without discarding lone surrogates. #[inline] -pub(crate) fn enum_member_id_atom(id: &TsEnumMemberId) -> Atom { +pub(crate) fn enum_member_name(id: &TsEnumMemberId) -> Wtf8Atom { match id { - TsEnumMemberId::Ident(ident) => ident.sym.clone(), - TsEnumMemberId::Str(str_lit) => str_lit.value.to_atom_lossy().into_owned(), + TsEnumMemberId::Ident(ident) => ident.sym.clone().into(), + TsEnumMemberId::Str(str_lit) => str_lit.value.clone(), #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), } diff --git a/deps/swc/crates/swc_ecma_transforms_typescript/src/transform.rs b/deps/swc/crates/swc_ecma_transforms_typescript/src/transform.rs index 570c46d8d..5d0dea488 100644 --- a/deps/swc/crates/swc_ecma_transforms_typescript/src/transform.rs +++ b/deps/swc/crates/swc_ecma_transforms_typescript/src/transform.rs @@ -1,7 +1,7 @@ -use std::{iter, mem}; +use std::{borrow::Borrow, iter, mem}; use rustc_hash::{FxHashMap, FxHashSet}; -use swc_atoms::Atom; +use swc_atoms::{Atom, Wtf8Atom}; use swc_common::{ errors::HANDLER, source_map::PURE_SP, util::take::Take, Mark, Span, Spanned, SyntaxContext, DUMMY_SP, @@ -21,8 +21,8 @@ use crate::{ config::TsImportExportAssignConfig, retain::{should_retain_module_item, should_retain_stmt}, semantic::SemanticInfo, - shared::enum_member_id_atom, - ts_enum::{EnumValueComputer, TsEnumRecordKey, TsEnumRecordValue}, + shared::enum_member_name, + ts_enum::{static_enum_member_name, EnumValueComputer, TsEnumRecordKey, TsEnumRecordValue}, utils::{assign_value_to_this_private_prop, assign_value_to_this_prop, Factory}, }; @@ -298,7 +298,7 @@ impl VisitMut for Transform { }); node.params.visit_mut_children_with(self); - node.body.visit_mut_children_with(self); + node.body.visit_mut_with(self); } fn visit_mut_stmts(&mut self, node: &mut Vec) { @@ -641,6 +641,11 @@ impl VisitMut for Transform { node.visit_mut_children_with(self); } + fn visit_mut_function(&mut self, node: &mut Function) { + node.this_param = None; + node.visit_mut_children_with(self); + } + fn visit_mut_private_method(&mut self, node: &mut PrivateMethod) { node.accessibility = None; node.is_abstract = false; @@ -658,11 +663,6 @@ impl VisitMut for Transform { node.visit_mut_children_with(self); } - fn visit_mut_setter_prop(&mut self, node: &mut SetterProp) { - node.this_param = None; - node.visit_mut_children_with(self); - } - fn visit_mut_ts_import_equals_decl(&mut self, _: &mut TsImportEqualsDecl) { // id should be left intact for runtime rewriting } @@ -1118,7 +1118,7 @@ impl Transform { .into_iter() .map(|m| { let span = m.span; - let name = enum_member_id_atom(&m.id); + let name = enum_member_name(&m.id); let key = TsEnumRecordKey { enum_id: id.to_id(), @@ -1643,7 +1643,7 @@ impl Transform { return; } - let Some(member_name) = get_member_key(prop) else { + let Some(member_name) = static_enum_member_name(prop) else { return; }; @@ -1901,13 +1901,13 @@ impl QueryRef for ExportQuery { struct EnumMemberRefQuery<'a> { enum_id: &'a Id, - member_names: &'a FxHashSet, + member_names: &'a FxHashSet, unresolved_ctxt: SyntaxContext, } impl QueryRef for EnumMemberRefQuery<'_> { fn query_ref(&self, ident: &Ident) -> Option> { - if ident.ctxt == self.unresolved_ctxt && self.member_names.contains(&ident.sym) { + if ident.ctxt == self.unresolved_ctxt && self.member_names.contains(ident.sym.borrow()) { Some( self.enum_id .clone() @@ -1924,7 +1924,7 @@ impl QueryRef for EnumMemberRefQuery<'_> { } fn query_jsx(&self, ident: &Ident) -> Option { - if ident.ctxt == self.unresolved_ctxt && self.member_names.contains(&ident.sym) { + if ident.ctxt == self.unresolved_ctxt && self.member_names.contains(ident.sym.borrow()) { Some( JSXMemberExpr { span: DUMMY_SP, @@ -1941,7 +1941,7 @@ impl QueryRef for EnumMemberRefQuery<'_> { struct EnumMemberItem { span: Span, - name: Atom, + name: Wtf8Atom, value: TsEnumRecordValue, } @@ -1953,20 +1953,19 @@ impl EnumMemberItem { fn build_assign(self, enum_id: &Id) -> Stmt { let is_string = self.value.is_string(); let value: Expr = self.value.into(); + let name: Expr = Str::from(self.name).into(); let inner_assign = value.make_assign_to( op!("="), Ident::from(enum_id.clone()) - .computed_member(self.name.clone()) + .computed_member(name.clone()) .into(), ); let outer_assign = if is_string { inner_assign } else { - let value: Expr = self.name.clone().into(); - - value.make_assign_to( + name.make_assign_to( op!("="), Ident::from(enum_id.clone()) .computed_member(inner_assign) @@ -2010,24 +2009,3 @@ fn get_enum_id(e: &Expr) -> Option { None } } - -fn get_member_key(prop: &MemberProp) -> Option { - match prop { - MemberProp::Ident(ident) => Some(ident.sym.clone()), - MemberProp::Computed(ComputedPropName { expr, .. }) => match &**expr { - Expr::Lit(Lit::Str(Str { value, .. })) => Some(value.to_atom_lossy().into_owned()), - Expr::Tpl(Tpl { exprs, quasis, .. }) => match (exprs.len(), quasis.len()) { - (0, 1) => quasis[0] - .cooked - .as_ref() - .map(|cooked| cooked.to_atom_lossy().into_owned()) - .or_else(|| Some(quasis[0].raw.clone())), - _ => None, - }, - _ => None, - }, - MemberProp::PrivateName(_) => None, - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - } -} diff --git a/deps/swc/crates/swc_ecma_transforms_typescript/src/ts_enum.rs b/deps/swc/crates/swc_ecma_transforms_typescript/src/ts_enum.rs index 6da0c929d..a05ef5139 100644 --- a/deps/swc/crates/swc_ecma_transforms_typescript/src/ts_enum.rs +++ b/deps/swc/crates/swc_ecma_transforms_typescript/src/ts_enum.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashMap; -use swc_atoms::{atom, Atom, Wtf8Atom}; +use swc_atoms::{wtf8::Wtf8Buf, Atom, Wtf8Atom}; use swc_common::{SyntaxContext, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_utils::{ @@ -7,34 +7,45 @@ use swc_ecma_utils::{ ExprFactory, }; -#[inline] -fn atom_from_wtf8_atom(value: &Wtf8Atom) -> Atom { - value - .as_str() - .map(Atom::from) - .unwrap_or_else(|| Atom::from(value.to_string_lossy())) -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub(crate) struct TsEnumRecordKey { pub enum_id: Id, - pub member_name: Atom, + pub member_name: Wtf8Atom, } pub(crate) type TsEnumRecord = FxHashMap; #[derive(Debug, Clone)] pub(crate) enum TsEnumRecordValue { - String(Atom), - Number(JsNumber), + String(Wtf8Atom), + Number(Number), Opaque(Box), Void, } impl TsEnumRecordValue { + /// Creates a computed number. Computations intentionally discard source + /// spelling so code generation can choose the canonical representation. + fn number(value: impl Into) -> Self { + Self::Number(Number { + span: DUMMY_SP, + value: value.into(), + raw: None, + }) + } + + /// Creates a number converted directly from an AST value. + fn converted_number(value: impl Into, raw: Option) -> Self { + Self::Number(Number { + span: DUMMY_SP, + value: value.into(), + raw, + }) + } + pub fn inc(&self) -> Self { match self { - Self::Number(num) => Self::Number((**num + 1.0).into()), + Self::Number(num) => Self::number(num.value + 1.0), _ => Self::Void, } } @@ -53,43 +64,23 @@ impl TsEnumRecordValue { pub fn has_value(&self) -> bool { !matches!(self, TsEnumRecordValue::Void) } + + fn push_to_string(&self, output: &mut Wtf8Buf) -> bool { + match self { + Self::String(value) => output.push_wtf8(value), + Self::Number(value) => output.push_str(&value.value.to_js_string()), + Self::Opaque(_) | Self::Void => return false, + } + + true + } } impl From for Expr { fn from(value: TsEnumRecordValue) -> Self { match value { TsEnumRecordValue::String(string) => Lit::Str(string.into()).into(), - TsEnumRecordValue::Number(num) if num.is_nan() => Ident { - span: DUMMY_SP, - sym: atom!("NaN"), - ..Default::default() - } - .into(), - TsEnumRecordValue::Number(num) if num.is_infinite() => { - let value: Expr = Ident { - span: DUMMY_SP, - sym: atom!("Infinity"), - ..Default::default() - } - .into(); - - if num.is_sign_negative() { - UnaryExpr { - span: DUMMY_SP, - op: op!(unary, "-"), - arg: value.into(), - } - .into() - } else { - value - } - } - TsEnumRecordValue::Number(num) => Lit::Num(Number { - span: DUMMY_SP, - value: *num, - raw: None, - }) - .into(), + TsEnumRecordValue::Number(num) => Lit::Num(num).into(), TsEnumRecordValue::Void => *Expr::undefined(DUMMY_SP), TsEnumRecordValue::Opaque(expr) => *expr, } @@ -98,7 +89,7 @@ impl From for Expr { impl From for TsEnumRecordValue { fn from(value: f64) -> Self { - Self::Number(value.into()) + Self::number(value) } } @@ -108,6 +99,24 @@ pub(crate) struct EnumValueComputer<'a> { pub record: &'a TsEnumRecord, } +/// Returns a statically known enum member key without discarding lone +/// surrogates. +pub(crate) fn static_enum_member_name(property: &MemberProp) -> Option { + match property { + MemberProp::Ident(ident) => Some(ident.sym.clone().into()), + MemberProp::Computed(ComputedPropName { expr, .. }) => match &**expr { + Expr::Lit(Lit::Str(string)) => Some(string.value.clone()), + Expr::Tpl(template) if template.exprs.is_empty() && template.quasis.len() == 1 => { + template.quasis[0].cooked.clone() + } + _ => None, + }, + MemberProp::PrivateName(_) => None, + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + } +} + /// https://github.com/microsoft/TypeScript/pull/50528 impl EnumValueComputer<'_> { pub fn compute(&self, expr: Box) -> TsEnumRecordValue { @@ -116,12 +125,12 @@ impl EnumValueComputer<'_> { fn compute_rec(&self, expr: Box) -> TsEnumRecordValue { match *expr { - Expr::Lit(Lit::Str(s)) => TsEnumRecordValue::String(atom_from_wtf8_atom(&s.value)), - Expr::Lit(Lit::Num(n)) => TsEnumRecordValue::Number(n.value.into()), + Expr::Lit(Lit::Str(s)) => TsEnumRecordValue::String(s.value), + Expr::Lit(Lit::Num(n)) => TsEnumRecordValue::Number(n), Expr::Ident(ref ident) if ident.ctxt == self.unresolved_ctxt => { if let Some(value) = self.record.get(&TsEnumRecordKey { enum_id: self.enum_id.clone(), - member_name: ident.sym.clone(), + member_name: ident.sym.clone().into(), }) { if value.is_const() { value.clone() @@ -135,8 +144,13 @@ impl EnumValueComputer<'_> { } } else { match ident.sym.as_ref() { - "Infinity" => TsEnumRecordValue::Number(f64::INFINITY.into()), - "NaN" => TsEnumRecordValue::Number(f64::NAN.into()), + "Infinity" => TsEnumRecordValue::converted_number( + f64::INFINITY, + Some(ident.sym.clone()), + ), + "NaN" => { + TsEnumRecordValue::converted_number(f64::NAN, Some(ident.sym.clone())) + } _ => TsEnumRecordValue::Opaque(expr), } } @@ -177,9 +191,9 @@ impl EnumValueComputer<'_> { }; match expr.op { - op!(unary, "+") => TsEnumRecordValue::Number(num), - op!(unary, "-") => TsEnumRecordValue::Number(-num), - op!("~") => TsEnumRecordValue::Number(!num), + op!(unary, "+") => TsEnumRecordValue::number(num.value), + op!(unary, "-") => TsEnumRecordValue::number(-num.value), + op!("~") => TsEnumRecordValue::number(!JsNumber::from(num.value)), _ => unreachable!(), } } @@ -207,8 +221,18 @@ impl EnumValueComputer<'_> { let left = self.compute_rec(expr.left); let right = self.compute_rec(expr.right); + if expr.op == BinaryOp::Add && (left.is_string() || right.is_string()) { + let mut value = Wtf8Buf::new(); + + if left.push_to_string(&mut value) && right.push_to_string(&mut value) { + return TsEnumRecordValue::String(Wtf8Atom::from(&*value)); + } + } + match (left, right, expr.op) { (TsEnumRecordValue::Number(left), TsEnumRecordValue::Number(right), op) => { + let left = JsNumber::from(left.value); + let right = JsNumber::from(right.value); let value = match op { op!(bin, "+") => left + right, op!(bin, "-") => left - right, @@ -225,20 +249,7 @@ impl EnumValueComputer<'_> { _ => unreachable!(), }; - TsEnumRecordValue::Number(value) - } - (TsEnumRecordValue::String(left), TsEnumRecordValue::String(right), op!(bin, "+")) => { - TsEnumRecordValue::String(format!("{left}{right}").into()) - } - (TsEnumRecordValue::Number(left), TsEnumRecordValue::String(right), op!(bin, "+")) => { - let left = left.to_js_string(); - - TsEnumRecordValue::String(format!("{left}{right}").into()) - } - (TsEnumRecordValue::String(left), TsEnumRecordValue::Number(right), op!(bin, "+")) => { - let right = right.to_js_string(); - - TsEnumRecordValue::String(format!("{left}{right}").into()) + TsEnumRecordValue::number(value) } (left, right, _) => { let mut origin_expr = origin_expr; @@ -257,22 +268,10 @@ impl EnumValueComputer<'_> { } fn compute_member(&self, expr: MemberExpr) -> TsEnumRecordValue { - if matches!(expr.prop, MemberProp::PrivateName(..)) { - return TsEnumRecordValue::Opaque(expr.into()); - } - let opaque_expr = TsEnumRecordValue::Opaque(expr.clone().into()); - let member_name = match expr.prop { - MemberProp::Ident(ident) => ident.sym, - MemberProp::Computed(ComputedPropName { expr, .. }) => { - let Expr::Lit(Lit::Str(s)) = *expr else { - return opaque_expr; - }; - - atom_from_wtf8_atom(&s.value) - } - _ => return opaque_expr, + let Some(member_name) = static_enum_member_name(&expr.prop) else { + return opaque_expr; }; let Expr::Ident(ident) = *expr.obj else { @@ -296,23 +295,27 @@ impl EnumValueComputer<'_> { let mut quasis_iter = quasis.into_iter(); - let Some(mut string) = quasis_iter.next().map(|q| q.raw.to_string()) else { + let Some(first_quasi) = quasis_iter.next() else { return opaque_expr; }; + let Some(first_cooked) = first_quasi.cooked.as_ref() else { + return opaque_expr; + }; + let mut string = Wtf8Buf::from(first_cooked); for (q, expr) in quasis_iter.zip(exprs) { let expr = self.compute_rec(expr); - let expr = match expr { - TsEnumRecordValue::String(s) => s.to_string(), - TsEnumRecordValue::Number(n) => n.to_js_string(), - _ => return opaque_expr, + if !expr.push_to_string(&mut string) { + return opaque_expr; + } + let Some(cooked) = q.cooked.as_ref() else { + return opaque_expr; }; - string.push_str(&expr); - string.push_str(&q.raw); + string.push_wtf8(cooked); } - TsEnumRecordValue::String(string.into()) + TsEnumRecordValue::String(Wtf8Atom::from(&*string)) } } diff --git a/deps/swc/crates/swc_ecma_transforms_typescript/src/utils.rs b/deps/swc/crates/swc_ecma_transforms_typescript/src/utils.rs index 37d562158..242060737 100644 --- a/deps/swc/crates/swc_ecma_transforms_typescript/src/utils.rs +++ b/deps/swc/crates/swc_ecma_transforms_typescript/src/utils.rs @@ -36,11 +36,13 @@ pub(crate) struct Factory; impl Factory { pub(crate) fn function(params: Vec, body: BlockStmt) -> Function { + let BlockStmt { span, stmts, .. } = body; + Function { params, decorators: Default::default(), span: DUMMY_SP, - body: Some(body), + body: Some(FunctionBody { span, stmts }), is_generator: false, is_async: false, ..Default::default() diff --git a/deps/swc/crates/swc_ecma_utils/Cargo.toml b/deps/swc/crates/swc_ecma_utils/Cargo.toml index b28c2f777..5c0274121 100644 --- a/deps/swc/crates/swc_ecma_utils/Cargo.toml +++ b/deps/swc/crates/swc_ecma_utils/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_utils" repository = { workspace = true } -version = "31.0.1" +version = "35.0.0" [package.metadata.docs.rs] all-features = true @@ -31,14 +31,14 @@ par-core = { workspace = true } rustc-hash = { workspace = true } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [target.'cfg(not(any(target_arch = "wasm32", target_arch = "arm")))'.dependencies] stacker = { version = "0.1.15", optional = true } [dev-dependencies] par-core = { workspace = true, features = ["chili"] } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } diff --git a/deps/swc/crates/swc_ecma_utils/src/constructor.rs b/deps/swc/crates/swc_ecma_utils/src/constructor.rs index aa8450bd2..27cd1749a 100644 --- a/deps/swc/crates/swc_ecma_utils/src/constructor.rs +++ b/deps/swc/crates/swc_ecma_utils/src/constructor.rs @@ -46,14 +46,6 @@ impl VisitMut for Injector { // skip } - fn visit_mut_getter_prop(&mut self, _: &mut GetterProp) { - // skip - } - - fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) { - // skip - } - fn visit_mut_expr_stmt(&mut self, node: &mut ExprStmt) { let ignore_return_value = mem::replace(&mut self.ignore_return_value, true); node.visit_mut_children_with(self); diff --git a/deps/swc/crates/swc_ecma_utils/src/factory.rs b/deps/swc/crates/swc_ecma_utils/src/factory.rs index d9e2766c3..5ff6f68e4 100644 --- a/deps/swc/crates/swc_ecma_utils/src/factory.rs +++ b/deps/swc/crates/swc_ecma_utils/src/factory.rs @@ -83,7 +83,7 @@ pub trait ExprFactory: Into> { fn into_lazy_arrow(self, params: Vec) -> ArrowExpr { ArrowExpr { params, - body: Box::new(BlockStmtOrExpr::Expr(self.into())), + body: Box::new(ArrowFunctionBody::Expr(self.into())), ..Default::default() } } @@ -96,10 +96,9 @@ pub trait ExprFactory: Into> { params, decorators: Default::default(), span: DUMMY_SP, - body: Some(BlockStmt { + body: Some(FunctionBody { span: DUMMY_SP, stmts: vec![self.into_return_stmt().into()], - ..Default::default() }), ..Default::default() } diff --git a/deps/swc/crates/swc_ecma_utils/src/function/fn_env_hoister.rs b/deps/swc/crates/swc_ecma_utils/src/function/fn_env_hoister.rs index 75f863052..689657339 100644 --- a/deps/swc/crates/swc_ecma_utils/src/function/fn_env_hoister.rs +++ b/deps/swc/crates/swc_ecma_utils/src/function/fn_env_hoister.rs @@ -279,6 +279,37 @@ impl FnEnvHoister { .get_or_insert_with(|| private_ident!(span, "_superprop_update")) .clone() } + + fn take_extra_var_decl(&mut self) -> Option { + if self.extra_ident.is_empty() { + return None; + } + + Some( + VarDecl { + kind: VarDeclKind::Var, + decls: self + .extra_ident + .take() + .into_iter() + .map(|ident| VarDeclarator { + span: DUMMY_SP, + name: ident.into(), + init: None, + definite: false, + }) + .collect(), + ..Default::default() + } + .into(), + ) + } + + fn prepend_extra_var_decl(&mut self, stmts: &mut Vec) { + if let Some(decl) = self.take_extra_var_decl() { + stmts.insert(0, decl); + } + } } impl VisitMut for FnEnvHoister { @@ -294,61 +325,34 @@ impl VisitMut for FnEnvHoister { fn visit_mut_block_stmt(&mut self, b: &mut BlockStmt) { b.visit_mut_children_with(self); - // we will not vist into fn/class so it's fine - if !self.extra_ident.is_empty() { - b.stmts.insert( - 0, - VarDecl { - kind: VarDeclKind::Var, - decls: self - .extra_ident - .take() - .into_iter() - .map(|ident| VarDeclarator { - span: DUMMY_SP, - name: ident.into(), - init: None, - definite: false, - }) - .collect(), - ..Default::default() - } - .into(), - ) - } + // We will not visit into nested functions or classes, so declarations + // collected while visiting this block belong to the current function. + self.prepend_extra_var_decl(&mut b.stmts); } - fn visit_mut_block_stmt_or_expr(&mut self, b: &mut BlockStmtOrExpr) { - b.visit_mut_children_with(self); + fn visit_mut_function_body(&mut self, body: &mut FunctionBody) { + body.visit_mut_children_with(self); - // we will not vist into fn/class so it's fine - if !self.extra_ident.is_empty() { - if let BlockStmtOrExpr::Expr(e) = b { - *b = BlockStmtOrExpr::BlockStmt(BlockStmt { - stmts: vec![ - Stmt::Decl(Decl::Var(Box::new(VarDecl { - kind: VarDeclKind::Var, - decls: self - .extra_ident - .take() - .into_iter() - .map(|ident| VarDeclarator { - span: DUMMY_SP, - name: ident.into(), - init: None, - definite: false, - }) - .collect(), - ..Default::default() - }))), - Stmt::Return(ReturnStmt { - span: e.span(), - arg: Some(e.take()), - }), - ], - ..Default::default() - }) - } + self.prepend_extra_var_decl(&mut body.stmts); + } + + fn visit_mut_arrow_function_body(&mut self, body: &mut ArrowFunctionBody) { + body.visit_mut_children_with(self); + + let Some(decl) = self.take_extra_var_decl() else { + return; + }; + if let ArrowFunctionBody::Expr(expr) = body { + *body = ArrowFunctionBody::FunctionBody(FunctionBody { + span: DUMMY_SP, + stmts: vec![ + decl, + Stmt::Return(ReturnStmt { + span: expr.span(), + arg: Some(expr.take()), + }), + ], + }); } } @@ -575,31 +579,12 @@ impl VisitMut for FnEnvHoister { /// Don't recurse into fn fn visit_mut_function(&mut self, _: &mut Function) {} - /// Don't recurse into getter/setter/method except computed key - fn visit_mut_getter_prop(&mut self, p: &mut GetterProp) { - if p.key.is_computed() { - p.key.visit_mut_with(self); - } - } - - fn visit_mut_method_prop(&mut self, p: &mut MethodProp) { - if p.key.is_computed() { - p.key.visit_mut_with(self); - } - } - fn visit_mut_pat(&mut self, n: &mut Pat) { let in_pat = self.in_pat; self.in_pat = true; n.visit_mut_children_with(self); self.in_pat = in_pat; } - - fn visit_mut_setter_prop(&mut self, p: &mut SetterProp) { - if p.key.is_computed() { - p.key.visit_mut_with(self); - } - } } pub fn init_this(stmts: &mut Vec, this_id: &Ident) { @@ -670,36 +655,40 @@ fn extend_super( Prop::Getter(GetterProp { span: DUMMY_SP, key: PropName::Ident(atom!("_").into()), - type_ann: None, - body: Some(BlockStmt { - stmts: vec![Expr::Ident( - get.ident - .get(&key) - .cloned() - .expect("getter not found") - .without_loc(), - ) - .as_call(DUMMY_SP, Default::default()) - .into_return_stmt() - .into()], + function: Box::new(Function { + body: Some(FunctionBody { + span: DUMMY_SP, + stmts: vec![Expr::Ident( + get.ident + .get(&key) + .cloned() + .expect("getter not found") + .without_loc(), + ) + .as_call(DUMMY_SP, Default::default()) + .into_return_stmt() + .into()], + }), ..Default::default() }), }), Prop::Setter(SetterProp { span: DUMMY_SP, key: PropName::Ident(atom!("_").into()), - this_param: None, - param: value.clone().into(), - body: Some(BlockStmt { - stmts: vec![Expr::Ident( - set.ident - .get(&key) - .cloned() - .expect("setter not found") - .without_loc(), - ) - .as_call(DUMMY_SP, vec![value.as_arg()]) - .into_stmt()], + function: Box::new(Function { + params: vec![Param::from(Pat::from(value.clone()))], + body: Some(FunctionBody { + span: DUMMY_SP, + stmts: vec![Expr::Ident( + set.ident + .get(&key) + .cloned() + .expect("setter not found") + .without_loc(), + ) + .as_call(DUMMY_SP, vec![value.as_arg()]) + .into_stmt()], + }), ..Default::default() }), }), @@ -725,42 +714,46 @@ fn extend_super( ArrowExpr { span: DUMMY_SP, params: vec![prop.clone().into()], - body: Box::new(BlockStmtOrExpr::Expr(Box::new( + body: Box::new(ArrowFunctionBody::Expr(Box::new( ObjectLit { span: DUMMY_SP, props: vec![ Prop::Getter(GetterProp { span: DUMMY_SP, key: PropName::Ident(atom!("_").into()), - type_ann: None, - body: Some(BlockStmt { - stmts: vec![Expr::Ident( - get.computed - .clone() - .expect("getter computed not found") - .without_loc(), - ) - .as_call(DUMMY_SP, vec![prop.clone().as_arg()]) - .into_return_stmt() - .into()], + function: Box::new(Function { + body: Some(FunctionBody { + span: DUMMY_SP, + stmts: vec![Expr::Ident( + get.computed + .clone() + .expect("getter computed not found") + .without_loc(), + ) + .as_call(DUMMY_SP, vec![prop.clone().as_arg()]) + .into_return_stmt() + .into()], + }), ..Default::default() }), }), Prop::Setter(SetterProp { span: DUMMY_SP, key: PropName::Ident(atom!("_").into()), - this_param: None, - param: value.clone().into(), - body: Some(BlockStmt { - stmts: vec![Expr::Ident( - set.computed - .clone() - .expect("setter computed not found") - .without_loc(), - ) - .as_call(DUMMY_SP, vec![prop.as_arg(), value.as_arg()]) - .into_return_stmt() - .into()], + function: Box::new(Function { + params: vec![Param::from(Pat::from(value.clone()))], + body: Some(FunctionBody { + span: DUMMY_SP, + stmts: vec![Expr::Ident( + set.computed + .clone() + .expect("setter computed not found") + .without_loc(), + ) + .as_call(DUMMY_SP, vec![prop.as_arg(), value.as_arg()]) + .into_return_stmt() + .into()], + }), ..Default::default() }), }), @@ -787,7 +780,7 @@ fn extend_super( ArrowExpr { span: DUMMY_SP, params: Vec::new(), - body: Box::new(BlockStmtOrExpr::Expr(Box::new( + body: Box::new(ArrowFunctionBody::Expr(Box::new( SuperPropExpr { obj: Super { span: DUMMY_SP }, prop: SuperProp::Ident(key.into()), @@ -811,7 +804,7 @@ fn extend_super( ArrowExpr { span: DUMMY_SP, params: vec![param.clone().into()], - body: Box::new(BlockStmtOrExpr::Expr(Box::new( + body: Box::new(ArrowFunctionBody::Expr(Box::new( SuperPropExpr { obj: Super { span: DUMMY_SP }, prop: SuperProp::Computed(ComputedPropName { @@ -838,7 +831,7 @@ fn extend_super( ArrowExpr { span: DUMMY_SP, params: vec![value.clone().into()], - body: Box::new(BlockStmtOrExpr::Expr(Box::new( + body: Box::new(ArrowFunctionBody::Expr(Box::new( AssignExpr { span: DUMMY_SP, left: SuperPropExpr { @@ -869,7 +862,7 @@ fn extend_super( ArrowExpr { span: DUMMY_SP, params: vec![prop.clone().into(), value.clone().into()], - body: Box::new(BlockStmtOrExpr::Expr(Box::new( + body: Box::new(ArrowFunctionBody::Expr(Box::new( AssignExpr { span: DUMMY_SP, left: SuperPropExpr { diff --git a/deps/swc/crates/swc_ecma_utils/src/lib.rs b/deps/swc/crates/swc_ecma_utils/src/lib.rs index 4c3b6f703..9770ae481 100644 --- a/deps/swc/crates/swc_ecma_utils/src/lib.rs +++ b/deps/swc/crates/swc_ecma_utils/src/lib.rs @@ -87,23 +87,6 @@ impl Visit for ThisVisitor { /// Don't recurse into fn fn visit_function(&mut self, _: &Function) {} - /// Don't recurse into fn - fn visit_getter_prop(&mut self, n: &GetterProp) { - n.key.visit_with(self); - } - - /// Don't recurse into fn - fn visit_method_prop(&mut self, n: &MethodProp) { - n.key.visit_with(self); - n.function.visit_with(self); - } - - /// Don't recurse into fn - fn visit_setter_prop(&mut self, n: &SetterProp) { - n.key.visit_with(self); - n.param.visit_with(self); - } - fn visit_this_expr(&mut self, _: &ThisExpr) { self.found = true; } @@ -403,6 +386,11 @@ impl IsEmpty for BlockStmt { self.stmts.is_empty() } } +impl IsEmpty for FunctionBody { + fn is_empty(&self) -> bool { + self.stmts.is_empty() + } +} impl IsEmpty for CatchClause { fn is_empty(&self) -> bool { self.body.stmts.is_empty() @@ -499,6 +487,7 @@ pub trait StmtExt { allow_break: bool, allow_throw: bool, ) -> Result { + // println!("2222 {in_switch} {allow_break} {:#?}", stmt); Ok(match stmt { Stmt::Break(_) => { if in_switch { @@ -542,7 +531,16 @@ pub trait StmtExt { let mut has_default = false; let mut has_non_empty_terminates = false; - for case in &s.cases { + // last case empty or no case at all + if s.cases + .last() + .map(|case| case.cons.is_empty()) + .unwrap_or(true) + { + return Ok(false); + } + + for case in s.cases.iter().rev() { if case.test.is_none() { has_default = true } @@ -676,8 +674,6 @@ impl Visit for Hoister { fn visit_function(&mut self, _: &Function) {} - fn visit_getter_prop(&mut self, _: &GetterProp) {} - fn visit_pat(&mut self, p: &Pat) { p.visit_children_with(self); @@ -686,8 +682,6 @@ impl Visit for Hoister { } } - fn visit_setter_prop(&mut self, _: &SetterProp) {} - fn visit_var_decl(&mut self, v: &VarDecl) { if v.kind != VarDeclKind::Var { return; @@ -1172,7 +1166,9 @@ impl Visit for LiteralVisitor { } fn visit_number(&mut self, node: &Number) { - if !self.allow_non_json_value && node.value.is_infinite() { + // JSON number syntax can express infinities as overflowed values such + // as `2e308`, but it has no representation that parses to `NaN`. + if !self.allow_non_json_value && node.value.is_nan() { self.is_lit = false; } } @@ -1514,7 +1510,8 @@ pub fn default_constructor_with_span(has_super: bool, super_call_span: Span) -> } else { Vec::new() }, - body: Some(BlockStmt { + body: Some(FunctionBody { + span: DUMMY_SP, stmts: if has_super { vec![CallExpr { span: super_call_span, @@ -1529,7 +1526,6 @@ pub fn default_constructor_with_span(has_super: bool, super_call_span: Span) -> } else { Vec::new() }, - ..Default::default() }), ..Default::default() } @@ -2051,7 +2047,7 @@ pub fn prop_name_eq(p: &PropName, key: &str) -> bool { match p { PropName::Ident(i) => i.sym == *key, PropName::Str(s) => s.value == *key, - PropName::Num(n) => n.value.to_string() == *key, + PropName::Num(n) => n.value.to_js_string() == *key, PropName::BigInt(_) => false, PropName::Computed(e) => match &*e.expr { Expr::Lit(Lit::Str(Str { value, .. })) => *value == *key, @@ -2298,6 +2294,10 @@ impl Visit for TopLevelAwait { key: PropName::Computed(computed), .. }) => computed.visit_children_with(self), + ClassMember::AutoAccessor(AutoAccessor { + key: Key::Public(PropName::Computed(computed)), + .. + }) => computed.visit_children_with(self), _ => (), }; } @@ -2306,9 +2306,16 @@ impl Visit for TopLevelAwait { match prop { Prop::KeyValue(KeyValueProp { key: PropName::Computed(computed), + value, .. - }) - | Prop::Getter(GetterProp { + }) => { + computed.visit_children_with(self); + value.visit_with(self); + } + Prop::KeyValue(KeyValueProp { value, .. }) | Prop::Assign(AssignProp { value, .. }) => { + value.visit_with(self); + } + Prop::Getter(GetterProp { key: PropName::Computed(computed), .. }) @@ -2740,8 +2747,10 @@ fn is_array_lit(expr: &Expr) -> bool { } fn is_nan(expr: &Expr) -> bool { - // NaN is special - expr.is_ident_ref_to("NaN") + match expr { + Expr::Lit(Lit::Num(number)) => number.value.is_nan(), + _ => expr.is_ident_ref_to("NaN"), + } } fn is_undefined(expr: &Expr, ctx: ExprCtx) -> bool { @@ -2779,20 +2788,26 @@ fn as_pure_bool(expr: &Expr, ctx: ExprCtx) -> BoolValue { } } +/// Returns whether a number is truthy according to ECMAScript semantics. +#[inline] +fn is_truthy_number(value: f64) -> bool { + !matches!(value.classify(), FpCategory::Nan | FpCategory::Zero) +} + fn cast_to_bool(expr: &Expr, ctx: ExprCtx) -> (Purity, BoolValue) { let Some(ctx) = ctx.consume_depth() else { return (MayBeImpure, Unknown); }; if let Expr::Ident(i) = expr { - if &*i.sym == "NaN" { - return (Pure, Known(false)); - } - if i.ctxt != ctx.unresolved_ctxt { return (Pure, Unknown); } + if &*i.sym == "NaN" { + return (Pure, Known(false)); + } + if &*i.sym == "undefined" { return (Pure, Known(false)); } @@ -2848,7 +2863,7 @@ fn cast_to_bool(expr: &Expr, ctx: ExprCtx) -> (Purity, BoolValue) { }) => { let v = arg.as_pure_number(ctx); match v { - Known(n) => Known(!matches!(n.classify(), FpCategory::Nan | FpCategory::Zero)), + Known(n) => Known(is_truthy_number(-n)), Unknown => return (MayBeImpure, Unknown), } } @@ -2875,13 +2890,7 @@ fn cast_to_bool(expr: &Expr, ctx: ExprCtx) -> (Purity, BoolValue) { return ( lp + rp, match (ln, rn) { - (Known(ln), Known(rn)) => { - if ln == rn { - Known(false) - } else { - Known(true) - } - } + (Known(ln), Known(rn)) => Known(is_truthy_number(ln - rn)), _ => Unknown, }, ); @@ -2898,17 +2907,7 @@ fn cast_to_bool(expr: &Expr, ctx: ExprCtx) -> (Purity, BoolValue) { match (lv, rv) { (Known(lv), Known(rv)) => { - // NaN is false - if lv == 0.0 && rv == 0.0 { - return (Pure, Known(false)); - } - // Infinity is true. - if rv == 0.0 { - return (Pure, Known(true)); - } - let v = lv / rv; - - return (Pure, Known(v != 0.0)); + return (Pure, Known(is_truthy_number(lv / rv))); } _ => Unknown, } @@ -3017,9 +3016,7 @@ fn cast_to_bool(expr: &Expr, ctx: ExprCtx) -> (Purity, BoolValue) { return ( Pure, Known(match *lit { - Lit::Num(Number { value: n, .. }) => { - !matches!(n.classify(), FpCategory::Nan | FpCategory::Zero) - } + Lit::Num(Number { value: n, .. }) => is_truthy_number(n), Lit::BigInt(ref v) => v .value .to_string() @@ -3818,13 +3815,44 @@ pub fn prop_name_from_ident(ident: Ident) -> PropName { } } +pub fn prop_name_from_str(span: Span, s: &str) -> PropName { + if s == "__proto__" { + PropName::Computed(ComputedPropName { + span: DUMMY_SP, + expr: Box::new(Expr::Lit(Lit::Str(Str { + span, + value: s.into(), + raw: None, + }))), + }) + } else if is_valid_prop_ident(s) { + PropName::Ident(IdentName { + span, + sym: s.into(), + }) + } else { + PropName::Str(quote_str!(span, s)) + } +} + #[cfg(test)] mod tests { - use swc_common::{input::StringInput, BytePos}; + use swc_common::{input::StringInput, BytePos, DUMMY_SP}; use swc_ecma_parser::{Parser, Syntax}; use super::*; + #[test] + fn number_literal_nan_is_recognized() { + let expr = Expr::Lit(Lit::Num(Number { + span: DUMMY_SP, + value: f64::NAN, + raw: None, + })); + + assert!(expr.is_nan()); + } + #[test] fn test_collect_decls() { run_collect_decls( @@ -3890,11 +3918,83 @@ mod tests { assert!(has_top_level_await("for await (let iter of []){}")) } + #[test] + fn top_level_await_object_property() { + assert!(has_top_level_await("const obj = { value: await test };")); + assert!(has_top_level_await("const obj = { [await key]: value };")); + assert!(!has_top_level_await( + "const obj = { async method() { await test; } };" + )); + } + + #[test] + fn top_level_await_class() { + assert!(has_top_level_await("class C extends (await base) {}")); + assert!(has_top_level_await("class C { [await key]() {} }")); + assert!(!has_top_level_await( + "class C { async method() { await test; } }" + )); + } + + #[test] + fn nested_await_is_not_top_level_await() { + assert!(!has_top_level_await("const f = async () => await test;")); + } + #[test] fn top_level_export_await() { assert!(has_top_level_await("export const foo = await 1;")); assert!(has_top_level_await("export default await 1;")); } + + #[test] + fn switch_default_before_empty_case_does_not_terminate() { + assert!(!stmt_in_function_terminates( + r#" +switch (foo) { + default: + return 1; + case "0": +} +"# + )); + } + + #[test] + fn switch_empty_case_before_default_terminates() { + assert!(stmt_in_function_terminates( + r#" +switch (foo) { + case "0": + default: + return 1; +} +"# + )); + } + + #[test] + fn switch_non_terminating_case_falls_through_to_terminating_case() { + assert!(!stmt_in_function_terminates( + r#" +switch (foo) { + case "0": + foo(); + default: + return 1; +} +"# + )); + } + + fn stmt_in_function_terminates(text: &str) -> bool { + let module = parse_module(&format!("function f() {{ {text} }}")); + let ModuleItem::Stmt(Stmt::Decl(Decl::Fn(f))) = &module.body[0] else { + unreachable!("expected a function declaration") + }; + let body = f.function.body.as_ref().unwrap(); + body.stmts[0].terminates() + } } #[cfg(test)] diff --git a/deps/swc/crates/swc_ecma_utils/src/number.rs b/deps/swc/crates/swc_ecma_utils/src/number.rs index d3c47b8a9..ca604d315 100644 --- a/deps/swc/crates/swc_ecma_utils/src/number.rs +++ b/deps/swc/crates/swc_ecma_utils/src/number.rs @@ -10,6 +10,25 @@ impl ToJsString for f64 { } } +/// Parses the canonical non-negative decimal representation of a `usize`. +/// +/// This does not apply numeric coercion, so distinct ECMAScript property keys +/// such as `"01"`, `"1.0"`, and `"+1"` are not reinterpreted as the index `1`. +pub fn parse_canonical_index(property_key: &str) -> Option { + let bytes = property_key.as_bytes(); + let is_canonical = match bytes { + [b'0'] => true, + [b'1'..=b'9', rest @ ..] => rest.iter().all(u8::is_ascii_digit), + _ => false, + }; + + if !is_canonical { + return None; + } + + property_key.parse().ok() +} + #[derive(Debug, Clone, Copy, PartialEq)] pub struct JsNumber(f64); @@ -34,6 +53,13 @@ impl std::ops::Deref for JsNumber { } impl JsNumber { + /// Applies ECMAScript `ToUint16` conversion. + /// + /// + pub fn to_uint16(self) -> u16 { + self.as_uint32() as u16 + } + // https://tc39.es/ecma262/#sec-toint32 fn as_int32(&self) -> i32 { self.as_uint32() as i32 @@ -188,10 +214,93 @@ impl std::ops::Not for JsNumber { } } +fn clz(s: &str) -> usize { + s.as_bytes().iter().take_while(|&&c| c == b'0').count() +} + +pub fn minify_number(num: f64, detect_dot: &mut bool) -> String { + // ddddd -> 0xhhhh + // len(0xhhhh) == len(ddddd) + // 10000000 <= num <= 0xffffff + 'hex: { + if num.fract() == 0.0 && num.abs() <= u64::MAX as f64 { + let int = num.abs() as u64; + + if int < 10000000 { + break 'hex; + } + + // use scientific notation + if int % 1000 == 0 { + break 'hex; + } + + *detect_dot = false; + return format!( + "{}{:#x}", + if num.is_sign_negative() { "-" } else { "" }, + int + ); + } + } + + let mut num = num.to_string(); + + if num.contains(".") { + *detect_dot = false; + } + + if let Some(num) = num.strip_prefix("0.") { + let cnt = clz(num); + if cnt > 2 { + return format!("{}e-{}", &num[cnt..], num.len()); + } + return format!(".{num}"); + } + + if let Some(num) = num.strip_prefix("-0.") { + let cnt = clz(num); + if cnt > 2 { + return format!("-{}e-{}", &num[cnt..], num.len()); + } + return format!("-.{num}"); + } + + if num.ends_with("000") { + *detect_dot = false; + + let cnt = num + .as_bytes() + .iter() + .rev() + .skip(3) + .take_while(|&&c| c == b'0') + .count() + + 3; + + num.truncate(num.len() - cnt); + num.push('e'); + num.push_str(&cnt.to_string()); + } + + num +} + #[cfg(test)] mod test_js_number { use super::*; + #[test] + fn test_parse_canonical_index() { + assert_eq!(parse_canonical_index("0"), Some(0)); + assert_eq!(parse_canonical_index("42"), Some(42)); + assert_eq!(parse_canonical_index(""), None); + assert_eq!(parse_canonical_index("01"), None); + assert_eq!(parse_canonical_index("1.0"), None); + assert_eq!(parse_canonical_index("+1"), None); + assert_eq!(parse_canonical_index("-0"), None); + } + #[test] fn test_as_int32() { assert_eq!(JsNumber(f64::NAN).as_int32(), 0); @@ -211,6 +320,20 @@ mod test_js_number { assert_eq!(JsNumber(-8.0).as_uint32(), 4294967288); } + #[test] + fn test_to_uint16() { + assert_eq!(JsNumber(65.9).to_uint16(), 65); + assert_eq!(JsNumber(-1.0).to_uint16(), 65535); + assert_eq!(JsNumber(-65535.9).to_uint16(), 1); + assert_eq!(JsNumber(65536.0).to_uint16(), 0); + assert_eq!(JsNumber(65537.0).to_uint16(), 1); + assert_eq!(JsNumber(f64::NAN).to_uint16(), 0); + assert_eq!(JsNumber(f64::INFINITY).to_uint16(), 0); + assert_eq!(JsNumber(f64::NEG_INFINITY).to_uint16(), 0); + assert_eq!(JsNumber(4294967361.0).to_uint16(), 65); + assert_eq!(JsNumber(-4294967231.0).to_uint16(), 65); + } + #[test] fn test_add() { assert_eq!(JsNumber(1.0) + JsNumber(2.0), JsNumber(3.0)); diff --git a/deps/swc/crates/swc_ecma_visit/Cargo.toml b/deps/swc/crates/swc_ecma_visit/Cargo.toml index 0e7eb802e..84eeeba09 100644 --- a/deps/swc/crates/swc_ecma_visit/Cargo.toml +++ b/deps/swc/crates/swc_ecma_visit/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecma_visit" repository = { workspace = true } -version = "25.0.0" +version = "29.0.0" [package.metadata.docs.rs] all-features = true @@ -30,7 +30,7 @@ num-bigint = { workspace = true, features = ["serde"] } serde = { workspace = true, optional = true, features = ["derive"] } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } swc_visit = { version = "2.0.1", path = "../swc_visit" } diff --git a/deps/swc/crates/swc_ecma_visit/src/generated.rs b/deps/swc/crates/swc_ecma_visit/src/generated.rs index 36f4b3771..1ee8af828 100644 --- a/deps/swc/crates/swc_ecma_visit/src/generated.rs +++ b/deps/swc/crates/swc_ecma_visit/src/generated.rs @@ -33,6 +33,13 @@ pub trait Visit { fn visit_arrow_expr(&mut self, node: &ArrowExpr) { >::visit_children_with(node, self) } + #[doc = "Visit a node of type `ArrowFunctionBody`.\n\nBy default, this method calls \ + [`ArrowFunctionBody::visit_children_with`]. If you want to recurse, you need to call \ + it manually."] + #[inline] + fn visit_arrow_function_body(&mut self, node: &ArrowFunctionBody) { + >::visit_children_with(node, self) + } #[doc = "Visit a node of type `AssignExpr`.\n\nBy default, this method calls \ [`AssignExpr::visit_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -144,13 +151,6 @@ pub trait Visit { fn visit_block_stmt(&mut self, node: &BlockStmt) { >::visit_children_with(node, self) } - #[doc = "Visit a node of type `BlockStmtOrExpr`.\n\nBy default, this method calls \ - [`BlockStmtOrExpr::visit_children_with`]. If you want to recurse, you need to call it \ - manually."] - #[inline] - fn visit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr) { - >::visit_children_with(node, self) - } #[doc = "Visit a node of type `Bool`.\n\nBy default, this method calls \ [`Bool::visit_children_with`]. If you want to recurse, you need to call it manually."] #[inline] @@ -452,6 +452,13 @@ pub trait Visit { fn visit_function(&mut self, node: &Function) { >::visit_children_with(node, self) } + #[doc = "Visit a node of type `FunctionBody`.\n\nBy default, this method calls \ + [`FunctionBody::visit_children_with`]. If you want to recurse, you need to call it \ + manually."] + #[inline] + fn visit_function_body(&mut self, node: &FunctionBody) { + >::visit_children_with(node, self) + } #[doc = "Visit a node of type `GetterProp`.\n\nBy default, this method calls \ [`GetterProp::visit_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -948,6 +955,13 @@ pub trait Visit { fn visit_opt_expr_or_spreads(&mut self, node: &Option>) { > as VisitWith>::visit_children_with(node, self) } + #[doc = "Visit a node of type `Option < FunctionBody >`.\n\nBy default, this method calls \ + [`Option < FunctionBody >::visit_children_with`]. If you want to recurse, you need to \ + call it manually."] + #[inline] + fn visit_opt_function_body(&mut self, node: &Option) { + as VisitWith>::visit_children_with(node, self) + } #[doc = "Visit a node of type `Option < Ident >`.\n\nBy default, this method calls [`Option < \ Ident >::visit_children_with`]. If you want to recurse, you need to call it manually."] #[inline] @@ -1037,6 +1051,13 @@ pub trait Visit { fn visit_opt_ts_namespace_body(&mut self, node: &Option) { as VisitWith>::visit_children_with(node, self) } + #[doc = "Visit a node of type `Option < Box < TsThisParam > >`.\n\nBy default, this method \ + calls [`Option < Box < TsThisParam > >::visit_children_with`]. If you want to \ + recurse, you need to call it manually."] + #[inline] + fn visit_opt_ts_this_param(&mut self, node: &Option>) { + > as VisitWith>::visit_children_with(node, self) + } #[doc = "Visit a node of type `Option < Box < TsType > >`.\n\nBy default, this method calls \ [`Option < Box < TsType > >::visit_children_with`]. If you want to recurse, you need \ to call it manually."] @@ -1762,6 +1783,13 @@ pub trait Visit { fn visit_ts_setter_signature(&mut self, node: &TsSetterSignature) { >::visit_children_with(node, self) } + #[doc = "Visit a node of type `TsThisParam`.\n\nBy default, this method calls \ + [`TsThisParam::visit_children_with`]. If you want to recurse, you need to call it \ + manually."] + #[inline] + fn visit_ts_this_param(&mut self, node: &TsThisParam) { + >::visit_children_with(node, self) + } #[doc = "Visit a node of type `TsThisType`.\n\nBy default, this method calls \ [`TsThisType::visit_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -2066,6 +2094,11 @@ where ::visit_arrow_expr(&mut **self, node) } + #[inline] + fn visit_arrow_function_body(&mut self, node: &ArrowFunctionBody) { + ::visit_arrow_function_body(&mut **self, node) + } + #[inline] fn visit_assign_expr(&mut self, node: &AssignExpr) { ::visit_assign_expr(&mut **self, node) @@ -2146,11 +2179,6 @@ where ::visit_block_stmt(&mut **self, node) } - #[inline] - fn visit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr) { - ::visit_block_stmt_or_expr(&mut **self, node) - } - #[inline] fn visit_bool(&mut self, node: &Bool) { ::visit_bool(&mut **self, node) @@ -2371,6 +2399,11 @@ where ::visit_function(&mut **self, node) } + #[inline] + fn visit_function_body(&mut self, node: &FunctionBody) { + ::visit_function_body(&mut **self, node) + } + #[inline] fn visit_getter_prop(&mut self, node: &GetterProp) { ::visit_getter_prop(&mut **self, node) @@ -2731,6 +2764,11 @@ where ::visit_opt_expr_or_spreads(&mut **self, node) } + #[inline] + fn visit_opt_function_body(&mut self, node: &Option) { + ::visit_opt_function_body(&mut **self, node) + } + #[inline] fn visit_opt_ident(&mut self, node: &Option) { ::visit_opt_ident(&mut **self, node) @@ -2796,6 +2834,11 @@ where ::visit_opt_ts_namespace_body(&mut **self, node) } + #[inline] + fn visit_opt_ts_this_param(&mut self, node: &Option>) { + ::visit_opt_ts_this_param(&mut **self, node) + } + #[inline] fn visit_opt_ts_type(&mut self, node: &Option>) { ::visit_opt_ts_type(&mut **self, node) @@ -3324,6 +3367,11 @@ where ::visit_ts_setter_signature(&mut **self, node) } + #[inline] + fn visit_ts_this_param(&mut self, node: &TsThisParam) { + ::visit_ts_this_param(&mut **self, node) + } + #[inline] fn visit_ts_this_type(&mut self, node: &TsThisType) { ::visit_ts_this_type(&mut **self, node) @@ -3548,6 +3596,11 @@ where ::visit_arrow_expr(&mut **self, node) } + #[inline] + fn visit_arrow_function_body(&mut self, node: &ArrowFunctionBody) { + ::visit_arrow_function_body(&mut **self, node) + } + #[inline] fn visit_assign_expr(&mut self, node: &AssignExpr) { ::visit_assign_expr(&mut **self, node) @@ -3628,11 +3681,6 @@ where ::visit_block_stmt(&mut **self, node) } - #[inline] - fn visit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr) { - ::visit_block_stmt_or_expr(&mut **self, node) - } - #[inline] fn visit_bool(&mut self, node: &Bool) { ::visit_bool(&mut **self, node) @@ -3853,6 +3901,11 @@ where ::visit_function(&mut **self, node) } + #[inline] + fn visit_function_body(&mut self, node: &FunctionBody) { + ::visit_function_body(&mut **self, node) + } + #[inline] fn visit_getter_prop(&mut self, node: &GetterProp) { ::visit_getter_prop(&mut **self, node) @@ -4213,6 +4266,11 @@ where ::visit_opt_expr_or_spreads(&mut **self, node) } + #[inline] + fn visit_opt_function_body(&mut self, node: &Option) { + ::visit_opt_function_body(&mut **self, node) + } + #[inline] fn visit_opt_ident(&mut self, node: &Option) { ::visit_opt_ident(&mut **self, node) @@ -4278,6 +4336,11 @@ where ::visit_opt_ts_namespace_body(&mut **self, node) } + #[inline] + fn visit_opt_ts_this_param(&mut self, node: &Option>) { + ::visit_opt_ts_this_param(&mut **self, node) + } + #[inline] fn visit_opt_ts_type(&mut self, node: &Option>) { ::visit_opt_ts_type(&mut **self, node) @@ -4806,6 +4869,11 @@ where ::visit_ts_setter_signature(&mut **self, node) } + #[inline] + fn visit_ts_this_param(&mut self, node: &TsThisParam) { + ::visit_ts_this_param(&mut **self, node) + } + #[inline] fn visit_ts_this_type(&mut self, node: &TsThisType) { ::visit_ts_this_type(&mut **self, node) @@ -5043,6 +5111,14 @@ where } } + #[inline] + fn visit_arrow_function_body(&mut self, node: &ArrowFunctionBody) { + match self { + swc_visit::Either::Left(visitor) => Visit::visit_arrow_function_body(visitor, node), + swc_visit::Either::Right(visitor) => Visit::visit_arrow_function_body(visitor, node), + } + } + #[inline] fn visit_assign_expr(&mut self, node: &AssignExpr) { match self { @@ -5171,14 +5247,6 @@ where } } - #[inline] - fn visit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr) { - match self { - swc_visit::Either::Left(visitor) => Visit::visit_block_stmt_or_expr(visitor, node), - swc_visit::Either::Right(visitor) => Visit::visit_block_stmt_or_expr(visitor, node), - } - } - #[inline] fn visit_bool(&mut self, node: &Bool) { match self { @@ -5539,6 +5607,14 @@ where } } + #[inline] + fn visit_function_body(&mut self, node: &FunctionBody) { + match self { + swc_visit::Either::Left(visitor) => Visit::visit_function_body(visitor, node), + swc_visit::Either::Right(visitor) => Visit::visit_function_body(visitor, node), + } + } + #[inline] fn visit_getter_prop(&mut self, node: &GetterProp) { match self { @@ -6123,6 +6199,14 @@ where } } + #[inline] + fn visit_opt_function_body(&mut self, node: &Option) { + match self { + swc_visit::Either::Left(visitor) => Visit::visit_opt_function_body(visitor, node), + swc_visit::Either::Right(visitor) => Visit::visit_opt_function_body(visitor, node), + } + } + #[inline] fn visit_opt_ident(&mut self, node: &Option) { match self { @@ -6233,6 +6317,14 @@ where } } + #[inline] + fn visit_opt_ts_this_param(&mut self, node: &Option>) { + match self { + swc_visit::Either::Left(visitor) => Visit::visit_opt_ts_this_param(visitor, node), + swc_visit::Either::Right(visitor) => Visit::visit_opt_ts_this_param(visitor, node), + } + } + #[inline] fn visit_opt_ts_type(&mut self, node: &Option>) { match self { @@ -7098,6 +7190,14 @@ where } } + #[inline] + fn visit_ts_this_param(&mut self, node: &TsThisParam) { + match self { + swc_visit::Either::Left(visitor) => Visit::visit_ts_this_param(visitor, node), + swc_visit::Either::Right(visitor) => Visit::visit_ts_this_param(visitor, node), + } + } + #[inline] fn visit_ts_this_type(&mut self, node: &TsThisType) { match self { @@ -7462,6 +7562,14 @@ where } } + #[inline] + fn visit_arrow_function_body(&mut self, node: &ArrowFunctionBody) { + if self.enabled { + ::visit_arrow_function_body(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_assign_expr(&mut self, node: &AssignExpr) { if self.enabled { @@ -7590,14 +7698,6 @@ where } } - #[inline] - fn visit_block_stmt_or_expr(&mut self, node: &BlockStmtOrExpr) { - if self.enabled { - ::visit_block_stmt_or_expr(&mut self.visitor, node) - } else { - } - } - #[inline] fn visit_bool(&mut self, node: &Bool) { if self.enabled { @@ -7950,6 +8050,14 @@ where } } + #[inline] + fn visit_function_body(&mut self, node: &FunctionBody) { + if self.enabled { + ::visit_function_body(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_getter_prop(&mut self, node: &GetterProp) { if self.enabled { @@ -8526,6 +8634,14 @@ where } } + #[inline] + fn visit_opt_function_body(&mut self, node: &Option) { + if self.enabled { + ::visit_opt_function_body(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_opt_ident(&mut self, node: &Option) { if self.enabled { @@ -8630,6 +8746,14 @@ where } } + #[inline] + fn visit_opt_ts_this_param(&mut self, node: &Option>) { + if self.enabled { + ::visit_opt_ts_this_param(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_opt_ts_type(&mut self, node: &Option>) { if self.enabled { @@ -9473,6 +9597,14 @@ where } } + #[inline] + fn visit_ts_this_param(&mut self, node: &TsThisParam) { + if self.enabled { + ::visit_ts_this_param(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_ts_this_type(&mut self, node: &TsThisType) { if self.enabled { @@ -9890,7 +10022,7 @@ impl VisitWith for ArrowExpr { as VisitWith>::visit_with(params, visitor) }; { - as VisitWith>::visit_with(body, visitor) + as VisitWith>::visit_with(body, visitor) }; { > as VisitWith>::visit_with(type_params, visitor) @@ -9902,6 +10034,25 @@ impl VisitWith for ArrowExpr { } } } +impl VisitWith for ArrowFunctionBody { + #[doc = "Calls [Visit`::visit_arrow_function_body`] with `self`."] + fn visit_with(&self, visitor: &mut V) { + ::visit_arrow_function_body(visitor, self) + } + + fn visit_children_with(&self, visitor: &mut V) { + match self { + ArrowFunctionBody::FunctionBody { 0: _field_0 } => { + >::visit_with(_field_0, visitor); + } + ArrowFunctionBody::Expr { 0: _field_0 } => { + as VisitWith>::visit_with(_field_0, visitor); + } + #[cfg(swc_ast_unknown)] + _ => (), + } + } +} impl VisitWith for AssignExpr { #[doc = "Calls [Visit`::visit_assign_expr`] with `self`."] fn visit_with(&self, visitor: &mut V) { @@ -10260,25 +10411,6 @@ impl VisitWith for BlockStmt { } } } -impl VisitWith for BlockStmtOrExpr { - #[doc = "Calls [Visit`::visit_block_stmt_or_expr`] with `self`."] - fn visit_with(&self, visitor: &mut V) { - ::visit_block_stmt_or_expr(visitor, self) - } - - fn visit_children_with(&self, visitor: &mut V) { - match self { - BlockStmtOrExpr::BlockStmt { 0: _field_0 } => { - >::visit_with(_field_0, visitor); - } - BlockStmtOrExpr::Expr { 0: _field_0 } => { - as VisitWith>::visit_with(_field_0, visitor); - } - #[cfg(swc_ast_unknown)] - _ => (), - } - } -} impl VisitWith for Bool { #[doc = "Calls [Visit`::visit_bool`] with `self`."] fn visit_with(&self, visitor: &mut V) { @@ -10688,7 +10820,7 @@ impl VisitWith for Constructor { as VisitWith>::visit_with(params, visitor) }; { - as VisitWith>::visit_with(body, visitor) + as VisitWith>::visit_with(body, visitor) }; { as VisitWith>::visit_with(accessibility, visitor) @@ -11349,6 +11481,7 @@ impl VisitWith for Function { fn visit_children_with(&self, visitor: &mut V) { match self { Function { + this_param, params, decorators, span, @@ -11359,6 +11492,9 @@ impl VisitWith for Function { type_params, return_type, } => { + { + > as VisitWith>::visit_with(this_param, visitor) + }; { as VisitWith>::visit_with(params, visitor) }; @@ -11372,7 +11508,7 @@ impl VisitWith for Function { >::visit_with(ctxt, visitor) }; { - as VisitWith>::visit_with(body, visitor) + as VisitWith>::visit_with(body, visitor) }; { > as VisitWith>::visit_with(type_params, visitor) @@ -11384,6 +11520,25 @@ impl VisitWith for Function { } } } +impl VisitWith for FunctionBody { + #[doc = "Calls [Visit`::visit_function_body`] with `self`."] + fn visit_with(&self, visitor: &mut V) { + ::visit_function_body(visitor, self) + } + + fn visit_children_with(&self, visitor: &mut V) { + match self { + FunctionBody { span, stmts } => { + { + >::visit_with(span, visitor) + }; + { + as VisitWith>::visit_with(stmts, visitor) + }; + } + } + } +} impl VisitWith for GetterProp { #[doc = "Calls [Visit`::visit_getter_prop`] with `self`."] fn visit_with(&self, visitor: &mut V) { @@ -11395,8 +11550,7 @@ impl VisitWith for GetterProp { GetterProp { span, key, - type_ann, - body, + function, } => { { >::visit_with(span, visitor) @@ -11405,10 +11559,7 @@ impl VisitWith for GetterProp { >::visit_with(key, visitor) }; { - > as VisitWith>::visit_with(type_ann, visitor) - }; - { - as VisitWith>::visit_with(body, visitor) + as VisitWith>::visit_with(function, visitor) }; } } @@ -12129,7 +12280,7 @@ impl VisitWith for JSXText { >::visit_with(span, visitor) }; { - >::visit_with(value, visitor) + >::visit_with(value, visitor) }; { >::visit_with(raw, visitor) @@ -13142,9 +13293,7 @@ impl VisitWith for SetterProp { SetterProp { span, key, - this_param, - param, - body, + function, } => { { >::visit_with(span, visitor) @@ -13153,13 +13302,7 @@ impl VisitWith for SetterProp { >::visit_with(key, visitor) }; { - as VisitWith>::visit_with(this_param, visitor) - }; - { - as VisitWith>::visit_with(param, visitor) - }; - { - as VisitWith>::visit_with(body, visitor) + as VisitWith>::visit_with(function, visitor) }; } } @@ -13430,12 +13573,16 @@ impl VisitWith for SwitchStmt { match self { SwitchStmt { span, + body_ctxt, discriminant, cases, } => { { >::visit_with(span, visitor) }; + { + >::visit_with(body_ctxt, visitor) + }; { as VisitWith>::visit_with(discriminant, visitor) }; @@ -14866,6 +15013,32 @@ impl VisitWith for TsSetterSignature { } } } +impl VisitWith for TsThisParam { + #[doc = "Calls [Visit`::visit_ts_this_param`] with `self`."] + fn visit_with(&self, visitor: &mut V) { + ::visit_ts_this_param(visitor, self) + } + + fn visit_children_with(&self, visitor: &mut V) { + match self { + TsThisParam { + span, + this_span, + type_ann, + } => { + { + >::visit_with(span, visitor) + }; + { + >::visit_with(this_span, visitor) + }; + { + > as VisitWith>::visit_with(type_ann, visitor) + }; + } + } + } +} impl VisitWith for TsThisType { #[doc = "Calls [Visit`::visit_ts_this_type`] with `self`."] fn visit_with(&self, visitor: &mut V) { @@ -15959,6 +16132,21 @@ impl VisitWith for Option> { } } } +impl VisitWith for Option { + #[doc = "Calls [Visit`::visit_opt_function_body`] with `self`. (Extra impl)"] + #[inline] + fn visit_with(&self, visitor: &mut V) { + ::visit_opt_function_body(visitor, self) + } + + #[inline] + fn visit_children_with(&self, visitor: &mut V) { + match self { + Some(inner) => >::visit_with(inner, visitor), + None => {} + } + } +} impl VisitWith for Option { #[doc = "Calls [Visit`::visit_opt_ident`] with `self`. (Extra impl)"] #[inline] @@ -16154,6 +16342,21 @@ impl VisitWith for Option { } } } +impl VisitWith for Option> { + #[doc = "Calls [Visit`::visit_opt_ts_this_param`] with `self`. (Extra impl)"] + #[inline] + fn visit_with(&self, visitor: &mut V) { + ::visit_opt_ts_this_param(visitor, self) + } + + #[inline] + fn visit_children_with(&self, visitor: &mut V) { + match self { + Some(inner) => as VisitWith>::visit_with(inner, visitor), + None => {} + } + } +} impl VisitWith for Option> { #[doc = "Calls [Visit`::visit_opt_ts_type`] with `self`. (Extra impl)"] #[inline] @@ -16587,6 +16790,19 @@ pub trait VisitAstPath { ) { >::visit_children_with_ast_path(node, self, __ast_path) } + #[doc = "Visit a node of type `ArrowFunctionBody`.\n\nBy default, this method calls \ + [`ArrowFunctionBody::visit_children_with_ast_path`]. If you want to recurse, you need \ + to call it manually."] + #[inline] + fn visit_arrow_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast ArrowFunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + >::visit_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `AssignExpr`.\n\nBy default, this method calls \ [`AssignExpr::visit_children_with_ast_path`]. If you want to recurse, you need to \ call it manually."] @@ -16777,19 +16993,6 @@ pub trait VisitAstPath { ) { >::visit_children_with_ast_path(node, self, __ast_path) } - #[doc = "Visit a node of type `BlockStmtOrExpr`.\n\nBy default, this method calls \ - [`BlockStmtOrExpr::visit_children_with_ast_path`]. If you want to recurse, you need \ - to call it manually."] - #[inline] - fn visit_block_stmt_or_expr<'ast: 'r, 'r>( - &mut self, - node: &'ast BlockStmtOrExpr, - __ast_path: &mut AstNodePath<'r>, - ) { - >::visit_children_with_ast_path( - node, self, __ast_path, - ) - } #[doc = "Visit a node of type `Bool`.\n\nBy default, this method calls \ [`Bool::visit_children_with_ast_path`]. If you want to recurse, you need to call it \ manually."] @@ -17296,6 +17499,19 @@ pub trait VisitAstPath { ) { >::visit_children_with_ast_path(node, self, __ast_path) } + #[doc = "Visit a node of type `FunctionBody`.\n\nBy default, this method calls \ + [`FunctionBody::visit_children_with_ast_path`]. If you want to recurse, you need to \ + call it manually."] + #[inline] + fn visit_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast FunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + >::visit_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `GetterProp`.\n\nBy default, this method calls \ [`GetterProp::visit_children_with_ast_path`]. If you want to recurse, you need to \ call it manually."] @@ -18148,6 +18364,19 @@ pub trait VisitAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `Option < FunctionBody >`.\n\nBy default, this method calls \ + [`Option < FunctionBody >::visit_children_with_ast_path`]. If you want to recurse, \ + you need to call it manually."] + #[inline] + fn visit_opt_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast Option, + __ast_path: &mut AstNodePath<'r>, + ) { + as VisitWithAstPath>::visit_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `Option < Ident >`.\n\nBy default, this method calls [`Option < \ Ident >::visit_children_with_ast_path`]. If you want to recurse, you need to call it \ manually."] @@ -18317,6 +18546,19 @@ pub trait VisitAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `Option < Box < TsThisParam > >`.\n\nBy default, this method \ + calls [`Option < Box < TsThisParam > >::visit_children_with_ast_path`]. If you want \ + to recurse, you need to call it manually."] + #[inline] + fn visit_opt_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast Option>, + __ast_path: &mut AstNodePath<'r>, + ) { + > as VisitWithAstPath>::visit_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `Option < Box < TsType > >`.\n\nBy default, this method calls \ [`Option < Box < TsType > >::visit_children_with_ast_path`]. If you want to recurse, \ you need to call it manually."] @@ -19565,6 +19807,19 @@ pub trait VisitAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `TsThisParam`.\n\nBy default, this method calls \ + [`TsThisParam::visit_children_with_ast_path`]. If you want to recurse, you need to \ + call it manually."] + #[inline] + fn visit_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast TsThisParam, + __ast_path: &mut AstNodePath<'r>, + ) { + >::visit_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `TsThisType`.\n\nBy default, this method calls \ [`TsThisType::visit_children_with_ast_path`]. If you want to recurse, you need to \ call it manually."] @@ -20100,6 +20355,15 @@ where ::visit_arrow_expr(&mut **self, node, __ast_path) } + #[inline] + fn visit_arrow_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast ArrowFunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_arrow_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_assign_expr<'ast: 'r, 'r>( &mut self, @@ -20244,15 +20508,6 @@ where ::visit_block_stmt(&mut **self, node, __ast_path) } - #[inline] - fn visit_block_stmt_or_expr<'ast: 'r, 'r>( - &mut self, - node: &'ast BlockStmtOrExpr, - __ast_path: &mut AstNodePath<'r>, - ) { - ::visit_block_stmt_or_expr(&mut **self, node, __ast_path) - } - #[inline] fn visit_bool<'ast: 'r, 'r>(&mut self, node: &'ast Bool, __ast_path: &mut AstNodePath<'r>) { ::visit_bool(&mut **self, node, __ast_path) @@ -20629,6 +20884,15 @@ where ::visit_function(&mut **self, node, __ast_path) } + #[inline] + fn visit_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast FunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_getter_prop<'ast: 'r, 'r>( &mut self, @@ -21249,6 +21513,15 @@ where ::visit_opt_expr_or_spreads(&mut **self, node, __ast_path) } + #[inline] + fn visit_opt_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast Option, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_opt_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_opt_ident<'ast: 'r, 'r>( &mut self, @@ -21366,6 +21639,15 @@ where ::visit_opt_ts_namespace_body(&mut **self, node, __ast_path) } + #[inline] + fn visit_opt_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast Option>, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_opt_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn visit_opt_ts_type<'ast: 'r, 'r>( &mut self, @@ -22263,6 +22545,15 @@ where ::visit_ts_setter_signature(&mut **self, node, __ast_path) } + #[inline] + fn visit_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast TsThisParam, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn visit_ts_this_type<'ast: 'r, 'r>( &mut self, @@ -22665,6 +22956,15 @@ where ::visit_arrow_expr(&mut **self, node, __ast_path) } + #[inline] + fn visit_arrow_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast ArrowFunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_arrow_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_assign_expr<'ast: 'r, 'r>( &mut self, @@ -22809,15 +23109,6 @@ where ::visit_block_stmt(&mut **self, node, __ast_path) } - #[inline] - fn visit_block_stmt_or_expr<'ast: 'r, 'r>( - &mut self, - node: &'ast BlockStmtOrExpr, - __ast_path: &mut AstNodePath<'r>, - ) { - ::visit_block_stmt_or_expr(&mut **self, node, __ast_path) - } - #[inline] fn visit_bool<'ast: 'r, 'r>(&mut self, node: &'ast Bool, __ast_path: &mut AstNodePath<'r>) { ::visit_bool(&mut **self, node, __ast_path) @@ -23194,6 +23485,15 @@ where ::visit_function(&mut **self, node, __ast_path) } + #[inline] + fn visit_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast FunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_getter_prop<'ast: 'r, 'r>( &mut self, @@ -23814,6 +24114,15 @@ where ::visit_opt_expr_or_spreads(&mut **self, node, __ast_path) } + #[inline] + fn visit_opt_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast Option, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_opt_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_opt_ident<'ast: 'r, 'r>( &mut self, @@ -23931,6 +24240,15 @@ where ::visit_opt_ts_namespace_body(&mut **self, node, __ast_path) } + #[inline] + fn visit_opt_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast Option>, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_opt_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn visit_opt_ts_type<'ast: 'r, 'r>( &mut self, @@ -24828,6 +25146,15 @@ where ::visit_ts_setter_signature(&mut **self, node, __ast_path) } + #[inline] + fn visit_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast TsThisParam, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn visit_ts_this_type<'ast: 'r, 'r>( &mut self, @@ -25259,6 +25586,22 @@ where } } + #[inline] + fn visit_arrow_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast ArrowFunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + swc_visit::Either::Left(visitor) => { + VisitAstPath::visit_arrow_function_body(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitAstPath::visit_arrow_function_body(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_assign_expr<'ast: 'r, 'r>( &mut self, @@ -25513,22 +25856,6 @@ where } } - #[inline] - fn visit_block_stmt_or_expr<'ast: 'r, 'r>( - &mut self, - node: &'ast BlockStmtOrExpr, - __ast_path: &mut AstNodePath<'r>, - ) { - match self { - swc_visit::Either::Left(visitor) => { - VisitAstPath::visit_block_stmt_or_expr(visitor, node, __ast_path) - } - swc_visit::Either::Right(visitor) => { - VisitAstPath::visit_block_stmt_or_expr(visitor, node, __ast_path) - } - } - } - #[inline] fn visit_bool<'ast: 'r, 'r>(&mut self, node: &'ast Bool, __ast_path: &mut AstNodePath<'r>) { match self { @@ -26207,6 +26534,22 @@ where } } + #[inline] + fn visit_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast FunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + swc_visit::Either::Left(visitor) => { + VisitAstPath::visit_function_body(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitAstPath::visit_function_body(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_getter_prop<'ast: 'r, 'r>( &mut self, @@ -27321,6 +27664,22 @@ where } } + #[inline] + fn visit_opt_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast Option, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + swc_visit::Either::Left(visitor) => { + VisitAstPath::visit_opt_function_body(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitAstPath::visit_opt_function_body(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_opt_ident<'ast: 'r, 'r>( &mut self, @@ -27529,6 +27888,22 @@ where } } + #[inline] + fn visit_opt_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast Option>, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + swc_visit::Either::Left(visitor) => { + VisitAstPath::visit_opt_ts_this_param(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitAstPath::visit_opt_ts_this_param(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_opt_ts_type<'ast: 'r, 'r>( &mut self, @@ -29141,6 +29516,22 @@ where } } + #[inline] + fn visit_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast TsThisParam, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + swc_visit::Either::Left(visitor) => { + VisitAstPath::visit_ts_this_param(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitAstPath::visit_ts_this_param(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_ts_this_type<'ast: 'r, 'r>( &mut self, @@ -29835,6 +30226,18 @@ where } } + #[inline] + fn visit_arrow_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast ArrowFunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + if self.enabled { + ::visit_arrow_function_body(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_assign_expr<'ast: 'r, 'r>( &mut self, @@ -30027,18 +30430,6 @@ where } } - #[inline] - fn visit_block_stmt_or_expr<'ast: 'r, 'r>( - &mut self, - node: &'ast BlockStmtOrExpr, - __ast_path: &mut AstNodePath<'r>, - ) { - if self.enabled { - ::visit_block_stmt_or_expr(&mut self.visitor, node, __ast_path) - } else { - } - } - #[inline] fn visit_bool<'ast: 'r, 'r>(&mut self, node: &'ast Bool, __ast_path: &mut AstNodePath<'r>) { if self.enabled { @@ -30551,6 +30942,18 @@ where } } + #[inline] + fn visit_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast FunctionBody, + __ast_path: &mut AstNodePath<'r>, + ) { + if self.enabled { + ::visit_function_body(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_getter_prop<'ast: 'r, 'r>( &mut self, @@ -31387,6 +31790,18 @@ where } } + #[inline] + fn visit_opt_function_body<'ast: 'r, 'r>( + &mut self, + node: &'ast Option, + __ast_path: &mut AstNodePath<'r>, + ) { + if self.enabled { + ::visit_opt_function_body(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_opt_ident<'ast: 'r, 'r>( &mut self, @@ -31547,6 +31962,18 @@ where } } + #[inline] + fn visit_opt_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast Option>, + __ast_path: &mut AstNodePath<'r>, + ) { + if self.enabled { + ::visit_opt_ts_this_param(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_opt_ts_type<'ast: 'r, 'r>( &mut self, @@ -32771,6 +33198,18 @@ where } } + #[inline] + fn visit_ts_this_param<'ast: 'r, 'r>( + &mut self, + node: &'ast TsThisParam, + __ast_path: &mut AstNodePath<'r>, + ) { + if self.enabled { + ::visit_ts_this_param(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_ts_this_type<'ast: 'r, 'r>( &mut self, @@ -33474,7 +33913,7 @@ impl VisitWithAstPath for ArrowExpr { self, self::fields::ArrowExprField::Body, )); - as VisitWithAstPath>::visit_with_ast_path( + as VisitWithAstPath>::visit_with_ast_path( body, visitor, &mut *__ast_path, @@ -33508,6 +33947,51 @@ impl VisitWithAstPath for ArrowExpr { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitWithAstPath for ArrowFunctionBody { + #[doc = "Calls [VisitAstPath`::visit_arrow_function_body`] with `self`."] + fn visit_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_arrow_function_body(visitor, self, __ast_path) + } + + fn visit_children_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + ArrowFunctionBody::FunctionBody { 0: _field_0 } => { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::ArrowFunctionBody( + self, + self::fields::ArrowFunctionBodyField::FunctionBody, + )); + >::visit_with_ast_path( + _field_0, + visitor, + &mut *__ast_path, + ); + } + ArrowFunctionBody::Expr { 0: _field_0 } => { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::ArrowFunctionBody( + self, + self::fields::ArrowFunctionBodyField::Expr, + )); + as VisitWithAstPath>::visit_with_ast_path( + _field_0, + visitor, + &mut *__ast_path, + ); + } + #[cfg(swc_ast_unknown)] + _ => (), + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitWithAstPath for AssignExpr { #[doc = "Calls [VisitAstPath`::visit_assign_expr`] with `self`."] fn visit_with_ast_path<'ast: 'r, 'r>( @@ -34310,51 +34794,6 @@ impl VisitWithAstPath for BlockStmt { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] -impl VisitWithAstPath for BlockStmtOrExpr { - #[doc = "Calls [VisitAstPath`::visit_block_stmt_or_expr`] with `self`."] - fn visit_with_ast_path<'ast: 'r, 'r>( - &'ast self, - visitor: &mut V, - __ast_path: &mut AstNodePath<'r>, - ) { - ::visit_block_stmt_or_expr(visitor, self, __ast_path) - } - - fn visit_children_with_ast_path<'ast: 'r, 'r>( - &'ast self, - visitor: &mut V, - __ast_path: &mut AstNodePath<'r>, - ) { - match self { - BlockStmtOrExpr::BlockStmt { 0: _field_0 } => { - let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::BlockStmtOrExpr( - self, - self::fields::BlockStmtOrExprField::BlockStmt, - )); - >::visit_with_ast_path( - _field_0, - visitor, - &mut *__ast_path, - ); - } - BlockStmtOrExpr::Expr { 0: _field_0 } => { - let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::BlockStmtOrExpr( - self, - self::fields::BlockStmtOrExprField::Expr, - )); - as VisitWithAstPath>::visit_with_ast_path( - _field_0, - visitor, - &mut *__ast_path, - ); - } - #[cfg(swc_ast_unknown)] - _ => (), - } - } -} -#[cfg(any(docsrs, feature = "path"))] -#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitWithAstPath for Bool { #[doc = "Calls [VisitAstPath`::visit_bool`] with `self`."] fn visit_with_ast_path<'ast: 'r, 'r>( @@ -35339,7 +35778,7 @@ impl VisitWithAstPath for Constructor { self, self::fields::ConstructorField::Body, )); - as VisitWithAstPath>::visit_with_ast_path( + as VisitWithAstPath>::visit_with_ast_path( body, visitor, &mut *__ast_path, @@ -37028,6 +37467,7 @@ impl VisitWithAstPath for Function { ) { match self { Function { + this_param, params, decorators, span, @@ -37038,6 +37478,17 @@ impl VisitWithAstPath for Function { type_params, return_type, } => { + { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::Function( + self, + self::fields::FunctionField::ThisParam, + )); + > as VisitWithAstPath>::visit_with_ast_path( + this_param, + visitor, + &mut *__ast_path, + ) + }; { let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::Function( self, @@ -37087,7 +37538,7 @@ impl VisitWithAstPath for Function { self, self::fields::FunctionField::Body, )); - as VisitWithAstPath>::visit_with_ast_path( + as VisitWithAstPath>::visit_with_ast_path( body, visitor, &mut *__ast_path, @@ -37121,6 +37572,51 @@ impl VisitWithAstPath for Function { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitWithAstPath for FunctionBody { + #[doc = "Calls [VisitAstPath`::visit_function_body`] with `self`."] + fn visit_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_function_body(visitor, self, __ast_path) + } + + fn visit_children_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + FunctionBody { span, stmts } => { + { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::FunctionBody( + self, + self::fields::FunctionBodyField::Span, + )); + >::visit_with_ast_path( + span, + visitor, + &mut *__ast_path, + ) + }; + { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::FunctionBody( + self, + self::fields::FunctionBodyField::Stmts(usize::MAX), + )); + as VisitWithAstPath>::visit_with_ast_path( + stmts, + visitor, + &mut *__ast_path, + ) + }; + } + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitWithAstPath for GetterProp { #[doc = "Calls [VisitAstPath`::visit_getter_prop`] with `self`."] fn visit_with_ast_path<'ast: 'r, 'r>( @@ -37140,8 +37636,7 @@ impl VisitWithAstPath for GetterProp { GetterProp { span, key, - type_ann, - body, + function, } => { { let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::GetterProp( @@ -37168,21 +37663,10 @@ impl VisitWithAstPath for GetterProp { { let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::GetterProp( self, - self::fields::GetterPropField::TypeAnn, - )); - > as VisitWithAstPath>::visit_with_ast_path( - type_ann, - visitor, - &mut *__ast_path, - ) - }; - { - let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::GetterProp( - self, - self::fields::GetterPropField::Body, + self::fields::GetterPropField::Function, )); - as VisitWithAstPath>::visit_with_ast_path( - body, + as VisitWithAstPath>::visit_with_ast_path( + function, visitor, &mut *__ast_path, ) @@ -38906,7 +39390,7 @@ impl VisitWithAstPath for JSXText { self, self::fields::JSXTextField::Value, )); - >::visit_with_ast_path( + >::visit_with_ast_path( value, visitor, &mut *__ast_path, @@ -41325,9 +41809,7 @@ impl VisitWithAstPath for SetterProp { SetterProp { span, key, - this_param, - param, - body, + function, } => { { let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::SetterProp( @@ -41354,32 +41836,10 @@ impl VisitWithAstPath for SetterProp { { let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::SetterProp( self, - self::fields::SetterPropField::ThisParam, - )); - as VisitWithAstPath>::visit_with_ast_path( - this_param, - visitor, - &mut *__ast_path, - ) - }; - { - let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::SetterProp( - self, - self::fields::SetterPropField::Param, - )); - as VisitWithAstPath>::visit_with_ast_path( - param, - visitor, - &mut *__ast_path, - ) - }; - { - let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::SetterProp( - self, - self::fields::SetterPropField::Body, + self::fields::SetterPropField::Function, )); - as VisitWithAstPath>::visit_with_ast_path( - body, + as VisitWithAstPath>::visit_with_ast_path( + function, visitor, &mut *__ast_path, ) @@ -42089,6 +42549,7 @@ impl VisitWithAstPath for SwitchStmt { match self { SwitchStmt { span, + body_ctxt, discriminant, cases, } => { @@ -42103,6 +42564,17 @@ impl VisitWithAstPath for SwitchStmt { &mut *__ast_path, ) }; + { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::SwitchStmt( + self, + self::fields::SwitchStmtField::BodyCtxt, + )); + >::visit_with_ast_path( + body_ctxt, + visitor, + &mut *__ast_path, + ) + }; { let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::SwitchStmt( self, @@ -45472,6 +45944,66 @@ impl VisitWithAstPath for TsSetterSignature { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitWithAstPath for TsThisParam { + #[doc = "Calls [VisitAstPath`::visit_ts_this_param`] with `self`."] + fn visit_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_ts_this_param(visitor, self, __ast_path) + } + + fn visit_children_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + TsThisParam { + span, + this_span, + type_ann, + } => { + { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::TsThisParam( + self, + self::fields::TsThisParamField::Span, + )); + >::visit_with_ast_path( + span, + visitor, + &mut *__ast_path, + ) + }; + { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::TsThisParam( + self, + self::fields::TsThisParamField::ThisSpan, + )); + >::visit_with_ast_path( + this_span, + visitor, + &mut *__ast_path, + ) + }; + { + let mut __ast_path = __ast_path.with_guard(AstParentNodeRef::TsThisParam( + self, + self::fields::TsThisParamField::TypeAnn, + )); + > as VisitWithAstPath>::visit_with_ast_path( + type_ann, + visitor, + &mut *__ast_path, + ) + }; + } + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitWithAstPath for TsThisType { #[doc = "Calls [VisitAstPath`::visit_ts_this_type`] with `self`."] fn visit_with_ast_path<'ast: 'r, 'r>( @@ -47968,6 +48500,33 @@ impl VisitWithAstPath for Option> } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitWithAstPath for Option { + #[doc = "Calls [VisitAstPath`::visit_opt_function_body`] with `self`. (Extra impl)"] + #[inline] + fn visit_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_opt_function_body(visitor, self, __ast_path) + } + + #[inline] + fn visit_children_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + Some(inner) => >::visit_with_ast_path( + inner, visitor, __ast_path, + ), + None => {} + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitWithAstPath for Option { #[doc = "Calls [VisitAstPath`::visit_opt_ident`] with `self`. (Extra impl)"] #[inline] @@ -48319,6 +48878,33 @@ impl VisitWithAstPath for Option { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitWithAstPath for Option> { + #[doc = "Calls [VisitAstPath`::visit_opt_ts_this_param`] with `self`. (Extra impl)"] + #[inline] + fn visit_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + ::visit_opt_ts_this_param(visitor, self, __ast_path) + } + + #[inline] + fn visit_children_with_ast_path<'ast: 'r, 'r>( + &'ast self, + visitor: &mut V, + __ast_path: &mut AstNodePath<'r>, + ) { + match self { + Some(inner) => as VisitWithAstPath>::visit_with_ast_path( + inner, visitor, __ast_path, + ), + None => {} + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitWithAstPath for Option> { #[doc = "Calls [VisitAstPath`::visit_opt_ts_type`] with `self`. (Extra impl)"] #[inline] @@ -49111,6 +49697,13 @@ pub trait VisitMut { fn visit_mut_arrow_expr(&mut self, node: &mut ArrowExpr) { >::visit_mut_children_with(node, self) } + #[doc = "Visit a node of type `ArrowFunctionBody`.\n\nBy default, this method calls \ + [`ArrowFunctionBody::visit_mut_children_with`]. If you want to recurse, you need to \ + call it manually."] + #[inline] + fn visit_mut_arrow_function_body(&mut self, node: &mut ArrowFunctionBody) { + >::visit_mut_children_with(node, self) + } #[doc = "Visit a node of type `AssignExpr`.\n\nBy default, this method calls \ [`AssignExpr::visit_mut_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -49223,13 +49816,6 @@ pub trait VisitMut { fn visit_mut_block_stmt(&mut self, node: &mut BlockStmt) { >::visit_mut_children_with(node, self) } - #[doc = "Visit a node of type `BlockStmtOrExpr`.\n\nBy default, this method calls \ - [`BlockStmtOrExpr::visit_mut_children_with`]. If you want to recurse, you need to \ - call it manually."] - #[inline] - fn visit_mut_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr) { - >::visit_mut_children_with(node, self) - } #[doc = "Visit a node of type `Bool`.\n\nBy default, this method calls \ [`Bool::visit_mut_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -49538,6 +50124,13 @@ pub trait VisitMut { fn visit_mut_function(&mut self, node: &mut Function) { >::visit_mut_children_with(node, self) } + #[doc = "Visit a node of type `FunctionBody`.\n\nBy default, this method calls \ + [`FunctionBody::visit_mut_children_with`]. If you want to recurse, you need to call \ + it manually."] + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody) { + >::visit_mut_children_with(node, self) + } #[doc = "Visit a node of type `GetterProp`.\n\nBy default, this method calls \ [`GetterProp::visit_mut_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -50042,6 +50635,13 @@ pub trait VisitMut { fn visit_mut_opt_expr_or_spreads(&mut self, node: &mut Option>) { > as VisitMutWith>::visit_mut_children_with(node, self) } + #[doc = "Visit a node of type `Option < FunctionBody >`.\n\nBy default, this method calls \ + [`Option < FunctionBody >::visit_mut_children_with`]. If you want to recurse, you \ + need to call it manually."] + #[inline] + fn visit_mut_opt_function_body(&mut self, node: &mut Option) { + as VisitMutWith>::visit_mut_children_with(node, self) + } #[doc = "Visit a node of type `Option < Ident >`.\n\nBy default, this method calls [`Option < \ Ident >::visit_mut_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -50133,6 +50733,13 @@ pub trait VisitMut { fn visit_mut_opt_ts_namespace_body(&mut self, node: &mut Option) { as VisitMutWith>::visit_mut_children_with(node, self) } + #[doc = "Visit a node of type `Option < Box < TsThisParam > >`.\n\nBy default, this method \ + calls [`Option < Box < TsThisParam > >::visit_mut_children_with`]. If you want to \ + recurse, you need to call it manually."] + #[inline] + fn visit_mut_opt_ts_this_param(&mut self, node: &mut Option>) { + > as VisitMutWith>::visit_mut_children_with(node, self) + } #[doc = "Visit a node of type `Option < Box < TsType > >`.\n\nBy default, this method calls \ [`Option < Box < TsType > >::visit_mut_children_with`]. If you want to recurse, you \ need to call it manually."] @@ -50870,6 +51477,13 @@ pub trait VisitMut { fn visit_mut_ts_setter_signature(&mut self, node: &mut TsSetterSignature) { >::visit_mut_children_with(node, self) } + #[doc = "Visit a node of type `TsThisParam`.\n\nBy default, this method calls \ + [`TsThisParam::visit_mut_children_with`]. If you want to recurse, you need to call it \ + manually."] + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam) { + >::visit_mut_children_with(node, self) + } #[doc = "Visit a node of type `TsThisType`.\n\nBy default, this method calls \ [`TsThisType::visit_mut_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -51175,6 +51789,11 @@ where ::visit_mut_arrow_expr(&mut **self, node) } + #[inline] + fn visit_mut_arrow_function_body(&mut self, node: &mut ArrowFunctionBody) { + ::visit_mut_arrow_function_body(&mut **self, node) + } + #[inline] fn visit_mut_assign_expr(&mut self, node: &mut AssignExpr) { ::visit_mut_assign_expr(&mut **self, node) @@ -51255,11 +51874,6 @@ where ::visit_mut_block_stmt(&mut **self, node) } - #[inline] - fn visit_mut_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr) { - ::visit_mut_block_stmt_or_expr(&mut **self, node) - } - #[inline] fn visit_mut_bool(&mut self, node: &mut Bool) { ::visit_mut_bool(&mut **self, node) @@ -51480,6 +52094,11 @@ where ::visit_mut_function(&mut **self, node) } + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody) { + ::visit_mut_function_body(&mut **self, node) + } + #[inline] fn visit_mut_getter_prop(&mut self, node: &mut GetterProp) { ::visit_mut_getter_prop(&mut **self, node) @@ -51840,6 +52459,11 @@ where ::visit_mut_opt_expr_or_spreads(&mut **self, node) } + #[inline] + fn visit_mut_opt_function_body(&mut self, node: &mut Option) { + ::visit_mut_opt_function_body(&mut **self, node) + } + #[inline] fn visit_mut_opt_ident(&mut self, node: &mut Option) { ::visit_mut_opt_ident(&mut **self, node) @@ -51905,6 +52529,11 @@ where ::visit_mut_opt_ts_namespace_body(&mut **self, node) } + #[inline] + fn visit_mut_opt_ts_this_param(&mut self, node: &mut Option>) { + ::visit_mut_opt_ts_this_param(&mut **self, node) + } + #[inline] fn visit_mut_opt_ts_type(&mut self, node: &mut Option>) { ::visit_mut_opt_ts_type(&mut **self, node) @@ -52433,6 +53062,11 @@ where ::visit_mut_ts_setter_signature(&mut **self, node) } + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam) { + ::visit_mut_ts_this_param(&mut **self, node) + } + #[inline] fn visit_mut_ts_this_type(&mut self, node: &mut TsThisType) { ::visit_mut_ts_this_type(&mut **self, node) @@ -52657,6 +53291,11 @@ where ::visit_mut_arrow_expr(&mut **self, node) } + #[inline] + fn visit_mut_arrow_function_body(&mut self, node: &mut ArrowFunctionBody) { + ::visit_mut_arrow_function_body(&mut **self, node) + } + #[inline] fn visit_mut_assign_expr(&mut self, node: &mut AssignExpr) { ::visit_mut_assign_expr(&mut **self, node) @@ -52737,11 +53376,6 @@ where ::visit_mut_block_stmt(&mut **self, node) } - #[inline] - fn visit_mut_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr) { - ::visit_mut_block_stmt_or_expr(&mut **self, node) - } - #[inline] fn visit_mut_bool(&mut self, node: &mut Bool) { ::visit_mut_bool(&mut **self, node) @@ -52962,6 +53596,11 @@ where ::visit_mut_function(&mut **self, node) } + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody) { + ::visit_mut_function_body(&mut **self, node) + } + #[inline] fn visit_mut_getter_prop(&mut self, node: &mut GetterProp) { ::visit_mut_getter_prop(&mut **self, node) @@ -53322,6 +53961,11 @@ where ::visit_mut_opt_expr_or_spreads(&mut **self, node) } + #[inline] + fn visit_mut_opt_function_body(&mut self, node: &mut Option) { + ::visit_mut_opt_function_body(&mut **self, node) + } + #[inline] fn visit_mut_opt_ident(&mut self, node: &mut Option) { ::visit_mut_opt_ident(&mut **self, node) @@ -53387,6 +54031,11 @@ where ::visit_mut_opt_ts_namespace_body(&mut **self, node) } + #[inline] + fn visit_mut_opt_ts_this_param(&mut self, node: &mut Option>) { + ::visit_mut_opt_ts_this_param(&mut **self, node) + } + #[inline] fn visit_mut_opt_ts_type(&mut self, node: &mut Option>) { ::visit_mut_opt_ts_type(&mut **self, node) @@ -53915,6 +54564,11 @@ where ::visit_mut_ts_setter_signature(&mut **self, node) } + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam) { + ::visit_mut_ts_this_param(&mut **self, node) + } + #[inline] fn visit_mut_ts_this_type(&mut self, node: &mut TsThisType) { ::visit_mut_ts_this_type(&mut **self, node) @@ -54152,6 +54806,18 @@ where } } + #[inline] + fn visit_mut_arrow_function_body(&mut self, node: &mut ArrowFunctionBody) { + match self { + swc_visit::Either::Left(visitor) => { + VisitMut::visit_mut_arrow_function_body(visitor, node) + } + swc_visit::Either::Right(visitor) => { + VisitMut::visit_mut_arrow_function_body(visitor, node) + } + } + } + #[inline] fn visit_mut_assign_expr(&mut self, node: &mut AssignExpr) { match self { @@ -54284,18 +54950,6 @@ where } } - #[inline] - fn visit_mut_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr) { - match self { - swc_visit::Either::Left(visitor) => { - VisitMut::visit_mut_block_stmt_or_expr(visitor, node) - } - swc_visit::Either::Right(visitor) => { - VisitMut::visit_mut_block_stmt_or_expr(visitor, node) - } - } - } - #[inline] fn visit_mut_bool(&mut self, node: &mut Bool) { match self { @@ -54678,6 +55332,14 @@ where } } + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody) { + match self { + swc_visit::Either::Left(visitor) => VisitMut::visit_mut_function_body(visitor, node), + swc_visit::Either::Right(visitor) => VisitMut::visit_mut_function_body(visitor, node), + } + } + #[inline] fn visit_mut_getter_prop(&mut self, node: &mut GetterProp) { match self { @@ -55346,6 +56008,18 @@ where } } + #[inline] + fn visit_mut_opt_function_body(&mut self, node: &mut Option) { + match self { + swc_visit::Either::Left(visitor) => { + VisitMut::visit_mut_opt_function_body(visitor, node) + } + swc_visit::Either::Right(visitor) => { + VisitMut::visit_mut_opt_function_body(visitor, node) + } + } + } + #[inline] fn visit_mut_opt_ident(&mut self, node: &mut Option) { match self { @@ -55478,6 +56152,18 @@ where } } + #[inline] + fn visit_mut_opt_ts_this_param(&mut self, node: &mut Option>) { + match self { + swc_visit::Either::Left(visitor) => { + VisitMut::visit_mut_opt_ts_this_param(visitor, node) + } + swc_visit::Either::Right(visitor) => { + VisitMut::visit_mut_opt_ts_this_param(visitor, node) + } + } + } + #[inline] fn visit_mut_opt_ts_type(&mut self, node: &mut Option>) { match self { @@ -56475,6 +57161,14 @@ where } } + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam) { + match self { + swc_visit::Either::Left(visitor) => VisitMut::visit_mut_ts_this_param(visitor, node), + swc_visit::Either::Right(visitor) => VisitMut::visit_mut_ts_this_param(visitor, node), + } + } + #[inline] fn visit_mut_ts_this_type(&mut self, node: &mut TsThisType) { match self { @@ -56879,6 +57573,14 @@ where } } + #[inline] + fn visit_mut_arrow_function_body(&mut self, node: &mut ArrowFunctionBody) { + if self.enabled { + ::visit_mut_arrow_function_body(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_mut_assign_expr(&mut self, node: &mut AssignExpr) { if self.enabled { @@ -57007,14 +57709,6 @@ where } } - #[inline] - fn visit_mut_block_stmt_or_expr(&mut self, node: &mut BlockStmtOrExpr) { - if self.enabled { - ::visit_mut_block_stmt_or_expr(&mut self.visitor, node) - } else { - } - } - #[inline] fn visit_mut_bool(&mut self, node: &mut Bool) { if self.enabled { @@ -57367,6 +58061,14 @@ where } } + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody) { + if self.enabled { + ::visit_mut_function_body(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_mut_getter_prop(&mut self, node: &mut GetterProp) { if self.enabled { @@ -57943,6 +58645,14 @@ where } } + #[inline] + fn visit_mut_opt_function_body(&mut self, node: &mut Option) { + if self.enabled { + ::visit_mut_opt_function_body(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_mut_opt_ident(&mut self, node: &mut Option) { if self.enabled { @@ -58047,6 +58757,14 @@ where } } + #[inline] + fn visit_mut_opt_ts_this_param(&mut self, node: &mut Option>) { + if self.enabled { + ::visit_mut_opt_ts_this_param(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_mut_opt_ts_type(&mut self, node: &mut Option>) { if self.enabled { @@ -58890,6 +59608,14 @@ where } } + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam) { + if self.enabled { + ::visit_mut_ts_this_param(&mut self.visitor, node) + } else { + } + } + #[inline] fn visit_mut_ts_this_type(&mut self, node: &mut TsThisType) { if self.enabled { @@ -59307,7 +60033,7 @@ impl VisitMutWith for ArrowExpr { as VisitMutWith>::visit_mut_with(params, visitor) }; { - as VisitMutWith>::visit_mut_with(body, visitor) + as VisitMutWith>::visit_mut_with(body, visitor) }; { > as VisitMutWith>::visit_mut_with( @@ -59325,6 +60051,25 @@ impl VisitMutWith for ArrowExpr { } } } +impl VisitMutWith for ArrowFunctionBody { + #[doc = "Calls [VisitMut`::visit_mut_arrow_function_body`] with `self`."] + fn visit_mut_with(&mut self, visitor: &mut V) { + ::visit_mut_arrow_function_body(visitor, self) + } + + fn visit_mut_children_with(&mut self, visitor: &mut V) { + match self { + ArrowFunctionBody::FunctionBody { 0: _field_0 } => { + >::visit_mut_with(_field_0, visitor); + } + ArrowFunctionBody::Expr { 0: _field_0 } => { + as VisitMutWith>::visit_mut_with(_field_0, visitor); + } + #[cfg(swc_ast_unknown)] + _ => (), + } + } +} impl VisitMutWith for AssignExpr { #[doc = "Calls [VisitMut`::visit_mut_assign_expr`] with `self`."] fn visit_mut_with(&mut self, visitor: &mut V) { @@ -59686,25 +60431,6 @@ impl VisitMutWith for BlockStmt { } } } -impl VisitMutWith for BlockStmtOrExpr { - #[doc = "Calls [VisitMut`::visit_mut_block_stmt_or_expr`] with `self`."] - fn visit_mut_with(&mut self, visitor: &mut V) { - ::visit_mut_block_stmt_or_expr(visitor, self) - } - - fn visit_mut_children_with(&mut self, visitor: &mut V) { - match self { - BlockStmtOrExpr::BlockStmt { 0: _field_0 } => { - >::visit_mut_with(_field_0, visitor); - } - BlockStmtOrExpr::Expr { 0: _field_0 } => { - as VisitMutWith>::visit_mut_with(_field_0, visitor); - } - #[cfg(swc_ast_unknown)] - _ => (), - } - } -} impl VisitMutWith for Bool { #[doc = "Calls [VisitMut`::visit_mut_bool`] with `self`."] fn visit_mut_with(&mut self, visitor: &mut V) { @@ -60125,7 +60851,7 @@ impl VisitMutWith for Constructor { as VisitMutWith>::visit_mut_with(params, visitor) }; { - as VisitMutWith>::visit_mut_with(body, visitor) + as VisitMutWith>::visit_mut_with(body, visitor) }; { as VisitMutWith>::visit_mut_with( @@ -60789,6 +61515,7 @@ impl VisitMutWith for Function { fn visit_mut_children_with(&mut self, visitor: &mut V) { match self { Function { + this_param, params, decorators, span, @@ -60799,6 +61526,11 @@ impl VisitMutWith for Function { type_params, return_type, } => { + { + > as VisitMutWith>::visit_mut_with( + this_param, visitor, + ) + }; { as VisitMutWith>::visit_mut_with(params, visitor) }; @@ -60812,7 +61544,7 @@ impl VisitMutWith for Function { >::visit_mut_with(ctxt, visitor) }; { - as VisitMutWith>::visit_mut_with(body, visitor) + as VisitMutWith>::visit_mut_with(body, visitor) }; { > as VisitMutWith>::visit_mut_with( @@ -60830,6 +61562,25 @@ impl VisitMutWith for Function { } } } +impl VisitMutWith for FunctionBody { + #[doc = "Calls [VisitMut`::visit_mut_function_body`] with `self`."] + fn visit_mut_with(&mut self, visitor: &mut V) { + ::visit_mut_function_body(visitor, self) + } + + fn visit_mut_children_with(&mut self, visitor: &mut V) { + match self { + FunctionBody { span, stmts } => { + { + >::visit_mut_with(span, visitor) + }; + { + as VisitMutWith>::visit_mut_with(stmts, visitor) + }; + } + } + } +} impl VisitMutWith for GetterProp { #[doc = "Calls [VisitMut`::visit_mut_getter_prop`] with `self`."] fn visit_mut_with(&mut self, visitor: &mut V) { @@ -60841,8 +61592,7 @@ impl VisitMutWith for GetterProp { GetterProp { span, key, - type_ann, - body, + function, } => { { >::visit_mut_with(span, visitor) @@ -60851,10 +61601,7 @@ impl VisitMutWith for GetterProp { >::visit_mut_with(key, visitor) }; { - > as VisitMutWith>::visit_mut_with(type_ann, visitor) - }; - { - as VisitMutWith>::visit_mut_with(body, visitor) + as VisitMutWith>::visit_mut_with(function, visitor) }; } } @@ -61575,7 +62322,7 @@ impl VisitMutWith for JSXText { >::visit_mut_with(span, visitor) }; { - >::visit_mut_with(value, visitor) + >::visit_mut_with(value, visitor) }; { >::visit_mut_with(raw, visitor) @@ -62594,9 +63341,7 @@ impl VisitMutWith for SetterProp { SetterProp { span, key, - this_param, - param, - body, + function, } => { { >::visit_mut_with(span, visitor) @@ -62605,13 +63350,7 @@ impl VisitMutWith for SetterProp { >::visit_mut_with(key, visitor) }; { - as VisitMutWith>::visit_mut_with(this_param, visitor) - }; - { - as VisitMutWith>::visit_mut_with(param, visitor) - }; - { - as VisitMutWith>::visit_mut_with(body, visitor) + as VisitMutWith>::visit_mut_with(function, visitor) }; } } @@ -62882,12 +63621,18 @@ impl VisitMutWith for SwitchStmt { match self { SwitchStmt { span, + body_ctxt, discriminant, cases, } => { { >::visit_mut_with(span, visitor) }; + { + >::visit_mut_with( + body_ctxt, visitor, + ) + }; { as VisitMutWith>::visit_mut_with(discriminant, visitor) }; @@ -64345,6 +65090,32 @@ impl VisitMutWith for TsSetterSignature { } } } +impl VisitMutWith for TsThisParam { + #[doc = "Calls [VisitMut`::visit_mut_ts_this_param`] with `self`."] + fn visit_mut_with(&mut self, visitor: &mut V) { + ::visit_mut_ts_this_param(visitor, self) + } + + fn visit_mut_children_with(&mut self, visitor: &mut V) { + match self { + TsThisParam { + span, + this_span, + type_ann, + } => { + { + >::visit_mut_with(span, visitor) + }; + { + >::visit_mut_with(this_span, visitor) + }; + { + > as VisitMutWith>::visit_mut_with(type_ann, visitor) + }; + } + } + } +} impl VisitMutWith for TsThisType { #[doc = "Calls [VisitMut`::visit_mut_ts_this_type`] with `self`."] fn visit_mut_with(&mut self, visitor: &mut V) { @@ -65441,6 +66212,21 @@ impl VisitMutWith for Option> { } } } +impl VisitMutWith for Option { + #[doc = "Calls [VisitMut`::visit_mut_opt_function_body`] with `self`. (Extra impl)"] + #[inline] + fn visit_mut_with(&mut self, visitor: &mut V) { + ::visit_mut_opt_function_body(visitor, self) + } + + #[inline] + fn visit_mut_children_with(&mut self, visitor: &mut V) { + match self { + Some(inner) => >::visit_mut_with(inner, visitor), + None => {} + } + } +} impl VisitMutWith for Option { #[doc = "Calls [VisitMut`::visit_mut_opt_ident`] with `self`. (Extra impl)"] #[inline] @@ -65636,6 +66422,21 @@ impl VisitMutWith for Option { } } } +impl VisitMutWith for Option> { + #[doc = "Calls [VisitMut`::visit_mut_opt_ts_this_param`] with `self`. (Extra impl)"] + #[inline] + fn visit_mut_with(&mut self, visitor: &mut V) { + ::visit_mut_opt_ts_this_param(visitor, self) + } + + #[inline] + fn visit_mut_children_with(&mut self, visitor: &mut V) { + match self { + Some(inner) => as VisitMutWith>::visit_mut_with(inner, visitor), + None => {} + } + } +} impl VisitMutWith for Option> { #[doc = "Calls [VisitMut`::visit_mut_opt_ts_type`] with `self`. (Extra impl)"] #[inline] @@ -66046,6 +66847,19 @@ pub trait VisitMutAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `ArrowFunctionBody`.\n\nBy default, this method calls \ + [`ArrowFunctionBody::visit_mut_children_with_ast_path`]. If you want to recurse, you \ + need to call it manually."] + #[inline] + fn visit_mut_arrow_function_body( + &mut self, + node: &mut ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) { + >::visit_mut_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `AssignExpr`.\n\nBy default, this method calls \ [`AssignExpr::visit_mut_children_with_ast_path`]. If you want to recurse, you need to \ call it manually."] @@ -66198,19 +67012,6 @@ pub trait VisitMutAstPath { node, self, __ast_path, ) } - #[doc = "Visit a node of type `BlockStmtOrExpr`.\n\nBy default, this method calls \ - [`BlockStmtOrExpr::visit_mut_children_with_ast_path`]. If you want to recurse, you \ - need to call it manually."] - #[inline] - fn visit_mut_block_stmt_or_expr( - &mut self, - node: &mut BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) { - >::visit_mut_children_with_ast_path( - node, self, __ast_path, - ) - } #[doc = "Visit a node of type `Bool`.\n\nBy default, this method calls \ [`Bool::visit_mut_children_with_ast_path`]. If you want to recurse, you need to call \ it manually."] @@ -66647,6 +67448,15 @@ pub trait VisitMutAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `FunctionBody`.\n\nBy default, this method calls \ + [`FunctionBody::visit_mut_children_with_ast_path`]. If you want to recurse, you need \ + to call it manually."] + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody, __ast_path: &mut AstKindPath) { + >::visit_mut_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `GetterProp`.\n\nBy default, this method calls \ [`GetterProp::visit_mut_children_with_ast_path`]. If you want to recurse, you need to \ call it manually."] @@ -67411,6 +68221,19 @@ pub trait VisitMutAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `Option < FunctionBody >`.\n\nBy default, this method calls \ + [`Option < FunctionBody >::visit_mut_children_with_ast_path`]. If you want to \ + recurse, you need to call it manually."] + #[inline] + fn visit_mut_opt_function_body( + &mut self, + node: &mut Option, + __ast_path: &mut AstKindPath, + ) { + as VisitMutWithAstPath>::visit_mut_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `Option < Ident >`.\n\nBy default, this method calls [`Option < \ Ident >::visit_mut_children_with_ast_path`]. If you want to recurse, you need to call \ it manually."] @@ -67564,6 +68387,19 @@ pub trait VisitMutAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `Option < Box < TsThisParam > >`.\n\nBy default, this method \ + calls [`Option < Box < TsThisParam > >::visit_mut_children_with_ast_path`]. If you \ + want to recurse, you need to call it manually."] + #[inline] + fn visit_mut_opt_ts_this_param( + &mut self, + node: &mut Option>, + __ast_path: &mut AstKindPath, + ) { + > as VisitMutWithAstPath>::visit_mut_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `Option < Box < TsType > >`.\n\nBy default, this method calls \ [`Option < Box < TsType > >::visit_mut_children_with_ast_path`]. If you want to \ recurse, you need to call it manually."] @@ -68704,6 +69540,15 @@ pub trait VisitMutAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `TsThisParam`.\n\nBy default, this method calls \ + [`TsThisParam::visit_mut_children_with_ast_path`]. If you want to recurse, you need \ + to call it manually."] + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam, __ast_path: &mut AstKindPath) { + >::visit_mut_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `TsThisType`.\n\nBy default, this method calls \ [`TsThisType::visit_mut_children_with_ast_path`]. If you want to recurse, you need to \ call it manually."] @@ -69163,6 +70008,15 @@ where ::visit_mut_arrow_expr(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_arrow_function_body( + &mut self, + node: &mut ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) { + ::visit_mut_arrow_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_assign_expr(&mut self, node: &mut AssignExpr, __ast_path: &mut AstKindPath) { ::visit_mut_assign_expr(&mut **self, node, __ast_path) @@ -69251,15 +70105,6 @@ where ::visit_mut_block_stmt(&mut **self, node, __ast_path) } - #[inline] - fn visit_mut_block_stmt_or_expr( - &mut self, - node: &mut BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) { - ::visit_mut_block_stmt_or_expr(&mut **self, node, __ast_path) - } - #[inline] fn visit_mut_bool(&mut self, node: &mut Bool, __ast_path: &mut AstKindPath) { ::visit_mut_bool(&mut **self, node, __ast_path) @@ -69520,6 +70365,11 @@ where ::visit_mut_function(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody, __ast_path: &mut AstKindPath) { + ::visit_mut_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_getter_prop(&mut self, node: &mut GetterProp, __ast_path: &mut AstKindPath) { ::visit_mut_getter_prop(&mut **self, node, __ast_path) @@ -70000,6 +70850,15 @@ where ::visit_mut_opt_expr_or_spreads(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_opt_function_body( + &mut self, + node: &mut Option, + __ast_path: &mut AstKindPath, + ) { + ::visit_mut_opt_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_opt_ident(&mut self, node: &mut Option, __ast_path: &mut AstKindPath) { ::visit_mut_opt_ident(&mut **self, node, __ast_path) @@ -70101,6 +70960,15 @@ where ::visit_mut_opt_ts_namespace_body(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_opt_ts_this_param( + &mut self, + node: &mut Option>, + __ast_path: &mut AstKindPath, + ) { + ::visit_mut_opt_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_opt_ts_type( &mut self, @@ -70834,6 +71702,11 @@ where ::visit_mut_ts_setter_signature(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam, __ast_path: &mut AstKindPath) { + ::visit_mut_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_ts_this_type(&mut self, node: &mut TsThisType, __ast_path: &mut AstKindPath) { ::visit_mut_ts_this_type(&mut **self, node, __ast_path) @@ -71136,6 +72009,15 @@ where ::visit_mut_arrow_expr(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_arrow_function_body( + &mut self, + node: &mut ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) { + ::visit_mut_arrow_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_assign_expr(&mut self, node: &mut AssignExpr, __ast_path: &mut AstKindPath) { ::visit_mut_assign_expr(&mut **self, node, __ast_path) @@ -71224,15 +72106,6 @@ where ::visit_mut_block_stmt(&mut **self, node, __ast_path) } - #[inline] - fn visit_mut_block_stmt_or_expr( - &mut self, - node: &mut BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) { - ::visit_mut_block_stmt_or_expr(&mut **self, node, __ast_path) - } - #[inline] fn visit_mut_bool(&mut self, node: &mut Bool, __ast_path: &mut AstKindPath) { ::visit_mut_bool(&mut **self, node, __ast_path) @@ -71493,6 +72366,11 @@ where ::visit_mut_function(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody, __ast_path: &mut AstKindPath) { + ::visit_mut_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_getter_prop(&mut self, node: &mut GetterProp, __ast_path: &mut AstKindPath) { ::visit_mut_getter_prop(&mut **self, node, __ast_path) @@ -71973,6 +72851,15 @@ where ::visit_mut_opt_expr_or_spreads(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_opt_function_body( + &mut self, + node: &mut Option, + __ast_path: &mut AstKindPath, + ) { + ::visit_mut_opt_function_body(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_opt_ident(&mut self, node: &mut Option, __ast_path: &mut AstKindPath) { ::visit_mut_opt_ident(&mut **self, node, __ast_path) @@ -72074,6 +72961,15 @@ where ::visit_mut_opt_ts_namespace_body(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_opt_ts_this_param( + &mut self, + node: &mut Option>, + __ast_path: &mut AstKindPath, + ) { + ::visit_mut_opt_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_opt_ts_type( &mut self, @@ -72807,6 +73703,11 @@ where ::visit_mut_ts_setter_signature(&mut **self, node, __ast_path) } + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam, __ast_path: &mut AstKindPath) { + ::visit_mut_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn visit_mut_ts_this_type(&mut self, node: &mut TsThisType, __ast_path: &mut AstKindPath) { ::visit_mut_ts_this_type(&mut **self, node, __ast_path) @@ -73138,6 +74039,22 @@ where } } + #[inline] + fn visit_mut_arrow_function_body( + &mut self, + node: &mut ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) { + match self { + swc_visit::Either::Left(visitor) => { + VisitMutAstPath::visit_mut_arrow_function_body(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitMutAstPath::visit_mut_arrow_function_body(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_mut_assign_expr(&mut self, node: &mut AssignExpr, __ast_path: &mut AstKindPath) { match self { @@ -73338,22 +74255,6 @@ where } } - #[inline] - fn visit_mut_block_stmt_or_expr( - &mut self, - node: &mut BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) { - match self { - swc_visit::Either::Left(visitor) => { - VisitMutAstPath::visit_mut_block_stmt_or_expr(visitor, node, __ast_path) - } - swc_visit::Either::Right(visitor) => { - VisitMutAstPath::visit_mut_block_stmt_or_expr(visitor, node, __ast_path) - } - } - } - #[inline] fn visit_mut_bool(&mut self, node: &mut Bool, __ast_path: &mut AstKindPath) { match self { @@ -73922,6 +74823,18 @@ where } } + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody, __ast_path: &mut AstKindPath) { + match self { + swc_visit::Either::Left(visitor) => { + VisitMutAstPath::visit_mut_function_body(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitMutAstPath::visit_mut_function_body(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_mut_getter_prop(&mut self, node: &mut GetterProp, __ast_path: &mut AstKindPath) { match self { @@ -74906,6 +75819,22 @@ where } } + #[inline] + fn visit_mut_opt_function_body( + &mut self, + node: &mut Option, + __ast_path: &mut AstKindPath, + ) { + match self { + swc_visit::Either::Left(visitor) => { + VisitMutAstPath::visit_mut_opt_function_body(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitMutAstPath::visit_mut_opt_function_body(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_mut_opt_ident(&mut self, node: &mut Option, __ast_path: &mut AstKindPath) { match self { @@ -75098,6 +76027,22 @@ where } } + #[inline] + fn visit_mut_opt_ts_this_param( + &mut self, + node: &mut Option>, + __ast_path: &mut AstKindPath, + ) { + match self { + swc_visit::Either::Left(visitor) => { + VisitMutAstPath::visit_mut_opt_ts_this_param(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitMutAstPath::visit_mut_opt_ts_this_param(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_mut_opt_ts_type( &mut self, @@ -76566,6 +77511,18 @@ where } } + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam, __ast_path: &mut AstKindPath) { + match self { + swc_visit::Either::Left(visitor) => { + VisitMutAstPath::visit_mut_ts_this_param(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + VisitMutAstPath::visit_mut_ts_this_param(visitor, node, __ast_path) + } + } + } + #[inline] fn visit_mut_ts_this_type(&mut self, node: &mut TsThisType, __ast_path: &mut AstKindPath) { match self { @@ -77156,6 +78113,22 @@ where } } + #[inline] + fn visit_mut_arrow_function_body( + &mut self, + node: &mut ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) { + if self.enabled { + ::visit_mut_arrow_function_body( + &mut self.visitor, + node, + __ast_path, + ) + } else { + } + } + #[inline] fn visit_mut_assign_expr(&mut self, node: &mut AssignExpr, __ast_path: &mut AstKindPath) { if self.enabled { @@ -77292,22 +78265,6 @@ where } } - #[inline] - fn visit_mut_block_stmt_or_expr( - &mut self, - node: &mut BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) { - if self.enabled { - ::visit_mut_block_stmt_or_expr( - &mut self.visitor, - node, - __ast_path, - ) - } else { - } - } - #[inline] fn visit_mut_bool(&mut self, node: &mut Bool, __ast_path: &mut AstKindPath) { if self.enabled { @@ -77724,6 +78681,14 @@ where } } + #[inline] + fn visit_mut_function_body(&mut self, node: &mut FunctionBody, __ast_path: &mut AstKindPath) { + if self.enabled { + ::visit_mut_function_body(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_mut_getter_prop(&mut self, node: &mut GetterProp, __ast_path: &mut AstKindPath) { if self.enabled { @@ -78484,6 +79449,18 @@ where } } + #[inline] + fn visit_mut_opt_function_body( + &mut self, + node: &mut Option, + __ast_path: &mut AstKindPath, + ) { + if self.enabled { + ::visit_mut_opt_function_body(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_mut_opt_ident(&mut self, node: &mut Option, __ast_path: &mut AstKindPath) { if self.enabled { @@ -78652,6 +79629,18 @@ where } } + #[inline] + fn visit_mut_opt_ts_this_param( + &mut self, + node: &mut Option>, + __ast_path: &mut AstKindPath, + ) { + if self.enabled { + ::visit_mut_opt_ts_this_param(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_mut_opt_ts_type( &mut self, @@ -79816,6 +80805,14 @@ where } } + #[inline] + fn visit_mut_ts_this_param(&mut self, node: &mut TsThisParam, __ast_path: &mut AstKindPath) { + if self.enabled { + ::visit_mut_ts_this_param(&mut self.visitor, node, __ast_path) + } else { + } + } + #[inline] fn visit_mut_ts_this_type(&mut self, node: &mut TsThisType, __ast_path: &mut AstKindPath) { if self.enabled { @@ -80397,7 +81394,7 @@ impl VisitMutWithAstPath for ArrowExpr { { let mut __ast_path = __ast_path .with_guard(AstParentKind::ArrowExpr(self::fields::ArrowExprField::Body)); - as VisitMutWithAstPath>::visit_mut_with_ast_path( + as VisitMutWithAstPath>::visit_mut_with_ast_path( body, visitor, &mut *__ast_path, @@ -80425,6 +81422,41 @@ impl VisitMutWithAstPath for ArrowExpr { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitMutWithAstPath for ArrowFunctionBody { + #[doc = "Calls [VisitMutAstPath`::visit_mut_arrow_function_body`] with `self`."] + fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + ::visit_mut_arrow_function_body(visitor, self, __ast_path) + } + + fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + match self { + ArrowFunctionBody::FunctionBody { 0: _field_0 } => { + let mut __ast_path = __ast_path.with_guard(AstParentKind::ArrowFunctionBody( + self::fields::ArrowFunctionBodyField::FunctionBody, + )); + >::visit_mut_with_ast_path( + _field_0, + visitor, + &mut *__ast_path, + ); + } + ArrowFunctionBody::Expr { 0: _field_0 } => { + let mut __ast_path = __ast_path.with_guard(AstParentKind::ArrowFunctionBody( + self::fields::ArrowFunctionBodyField::Expr, + )); + as VisitMutWithAstPath>::visit_mut_with_ast_path( + _field_0, + visitor, + &mut *__ast_path, + ); + } + #[cfg(swc_ast_unknown)] + _ => (), + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitMutWithAstPath for AssignExpr { #[doc = "Calls [VisitMutAstPath`::visit_mut_assign_expr`] with `self`."] fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { @@ -81063,41 +82095,6 @@ impl VisitMutWithAstPath for BlockStmt { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] -impl VisitMutWithAstPath for BlockStmtOrExpr { - #[doc = "Calls [VisitMutAstPath`::visit_mut_block_stmt_or_expr`] with `self`."] - fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { - ::visit_mut_block_stmt_or_expr(visitor, self, __ast_path) - } - - fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { - match self { - BlockStmtOrExpr::BlockStmt { 0: _field_0 } => { - let mut __ast_path = __ast_path.with_guard(AstParentKind::BlockStmtOrExpr( - self::fields::BlockStmtOrExprField::BlockStmt, - )); - >::visit_mut_with_ast_path( - _field_0, - visitor, - &mut *__ast_path, - ); - } - BlockStmtOrExpr::Expr { 0: _field_0 } => { - let mut __ast_path = __ast_path.with_guard(AstParentKind::BlockStmtOrExpr( - self::fields::BlockStmtOrExprField::Expr, - )); - as VisitMutWithAstPath>::visit_mut_with_ast_path( - _field_0, - visitor, - &mut *__ast_path, - ); - } - #[cfg(swc_ast_unknown)] - _ => (), - } - } -} -#[cfg(any(docsrs, feature = "path"))] -#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitMutWithAstPath for Bool { #[doc = "Calls [VisitMutAstPath`::visit_mut_bool`] with `self`."] fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { @@ -81893,7 +82890,7 @@ impl VisitMutWithAstPath for Constructor { let mut __ast_path = __ast_path.with_guard(AstParentKind::Constructor( self::fields::ConstructorField::Body, )); - as VisitMutWithAstPath>::visit_mut_with_ast_path( + as VisitMutWithAstPath>::visit_mut_with_ast_path( body, visitor, &mut *__ast_path, @@ -83254,6 +84251,7 @@ impl VisitMutWithAstPath for Function { fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { match self { Function { + this_param, params, decorators, span, @@ -83264,6 +84262,16 @@ impl VisitMutWithAstPath for Function { type_params, return_type, } => { + { + let mut __ast_path = __ast_path.with_guard(AstParentKind::Function( + self::fields::FunctionField::ThisParam, + )); + > as VisitMutWithAstPath>::visit_mut_with_ast_path( + this_param, + visitor, + &mut *__ast_path, + ) + }; { let mut __ast_path = __ast_path.with_guard(AstParentKind::Function( self::fields::FunctionField::Params(usize::MAX), @@ -83305,7 +84313,7 @@ impl VisitMutWithAstPath for Function { { let mut __ast_path = __ast_path .with_guard(AstParentKind::Function(self::fields::FunctionField::Body)); - as VisitMutWithAstPath>::visit_mut_with_ast_path( + as VisitMutWithAstPath>::visit_mut_with_ast_path( body, visitor, &mut *__ast_path, @@ -83333,6 +84341,41 @@ impl VisitMutWithAstPath for Function { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitMutWithAstPath for FunctionBody { + #[doc = "Calls [VisitMutAstPath`::visit_mut_function_body`] with `self`."] + fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + ::visit_mut_function_body(visitor, self, __ast_path) + } + + fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + match self { + FunctionBody { span, stmts } => { + { + let mut __ast_path = __ast_path.with_guard(AstParentKind::FunctionBody( + self::fields::FunctionBodyField::Span, + )); + >::visit_mut_with_ast_path( + span, + visitor, + &mut *__ast_path, + ) + }; + { + let mut __ast_path = __ast_path.with_guard(AstParentKind::FunctionBody( + self::fields::FunctionBodyField::Stmts(usize::MAX), + )); + as VisitMutWithAstPath>::visit_mut_with_ast_path( + stmts, + visitor, + &mut *__ast_path, + ) + }; + } + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitMutWithAstPath for GetterProp { #[doc = "Calls [VisitMutAstPath`::visit_mut_getter_prop`] with `self`."] fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { @@ -83344,8 +84387,7 @@ impl VisitMutWithAstPath for GetterProp { GetterProp { span, key, - type_ann, - body, + function, } => { { let mut __ast_path = __ast_path.with_guard(AstParentKind::GetterProp( @@ -83369,20 +84411,10 @@ impl VisitMutWithAstPath for GetterProp { }; { let mut __ast_path = __ast_path.with_guard(AstParentKind::GetterProp( - self::fields::GetterPropField::TypeAnn, + self::fields::GetterPropField::Function, )); - > as VisitMutWithAstPath>::visit_mut_with_ast_path( - type_ann, - visitor, - &mut *__ast_path, - ) - }; - { - let mut __ast_path = __ast_path.with_guard(AstParentKind::GetterProp( - self::fields::GetterPropField::Body, - )); - as VisitMutWithAstPath>::visit_mut_with_ast_path( - body, + as VisitMutWithAstPath>::visit_mut_with_ast_path( + function, visitor, &mut *__ast_path, ) @@ -84732,7 +85764,7 @@ impl VisitMutWithAstPath for JSXText { { let mut __ast_path = __ast_path .with_guard(AstParentKind::JSXText(self::fields::JSXTextField::Value)); - >::visit_mut_with_ast_path( + >::visit_mut_with_ast_path( value, visitor, &mut *__ast_path, @@ -86667,9 +87699,7 @@ impl VisitMutWithAstPath for SetterProp { SetterProp { span, key, - this_param, - param, - body, + function, } => { { let mut __ast_path = __ast_path.with_guard(AstParentKind::SetterProp( @@ -86693,30 +87723,10 @@ impl VisitMutWithAstPath for SetterProp { }; { let mut __ast_path = __ast_path.with_guard(AstParentKind::SetterProp( - self::fields::SetterPropField::ThisParam, - )); - as VisitMutWithAstPath>::visit_mut_with_ast_path( - this_param, - visitor, - &mut *__ast_path, - ) - }; - { - let mut __ast_path = __ast_path.with_guard(AstParentKind::SetterProp( - self::fields::SetterPropField::Param, - )); - as VisitMutWithAstPath>::visit_mut_with_ast_path( - param, - visitor, - &mut *__ast_path, - ) - }; - { - let mut __ast_path = __ast_path.with_guard(AstParentKind::SetterProp( - self::fields::SetterPropField::Body, + self::fields::SetterPropField::Function, )); - as VisitMutWithAstPath>::visit_mut_with_ast_path( - body, + as VisitMutWithAstPath>::visit_mut_with_ast_path( + function, visitor, &mut *__ast_path, ) @@ -87309,6 +88319,7 @@ impl VisitMutWithAstPath for SwitchStmt { match self { SwitchStmt { span, + body_ctxt, discriminant, cases, } => { @@ -87322,6 +88333,16 @@ impl VisitMutWithAstPath for SwitchStmt { &mut *__ast_path, ) }; + { + let mut __ast_path = __ast_path.with_guard(AstParentKind::SwitchStmt( + self::fields::SwitchStmtField::BodyCtxt, + )); + >::visit_mut_with_ast_path( + body_ctxt, + visitor, + &mut *__ast_path, + ) + }; { let mut __ast_path = __ast_path.with_guard(AstParentKind::SwitchStmt( self::fields::SwitchStmtField::Discriminant, @@ -89968,6 +90989,55 @@ impl VisitMutWithAstPath for TsSetterSignature { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl VisitMutWithAstPath for TsThisParam { + #[doc = "Calls [VisitMutAstPath`::visit_mut_ts_this_param`] with `self`."] + fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + ::visit_mut_ts_this_param(visitor, self, __ast_path) + } + + fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + match self { + TsThisParam { + span, + this_span, + type_ann, + } => { + { + let mut __ast_path = __ast_path.with_guard(AstParentKind::TsThisParam( + self::fields::TsThisParamField::Span, + )); + >::visit_mut_with_ast_path( + span, + visitor, + &mut *__ast_path, + ) + }; + { + let mut __ast_path = __ast_path.with_guard(AstParentKind::TsThisParam( + self::fields::TsThisParamField::ThisSpan, + )); + >::visit_mut_with_ast_path( + this_span, + visitor, + &mut *__ast_path, + ) + }; + { + let mut __ast_path = __ast_path.with_guard(AstParentKind::TsThisParam( + self::fields::TsThisParamField::TypeAnn, + )); + > as VisitMutWithAstPath>::visit_mut_with_ast_path( + type_ann, + visitor, + &mut *__ast_path, + ) + }; + } + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitMutWithAstPath for TsThisType { #[doc = "Calls [VisitMutAstPath`::visit_mut_ts_this_type`] with `self`."] fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { @@ -91912,6 +92982,25 @@ impl VisitMutWithAstPath for Option VisitMutWithAstPath for Option { + #[doc = "Calls [VisitMutAstPath`::visit_mut_opt_function_body`] with `self`. (Extra impl)"] + #[inline] + fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + ::visit_mut_opt_function_body(visitor, self, __ast_path) + } + + #[inline] + fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + match self { + Some(inner) => >::visit_mut_with_ast_path( + inner, visitor, __ast_path, + ), + None => {} + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitMutWithAstPath for Option { #[doc = "Calls [VisitMutAstPath`::visit_mut_opt_ident`] with `self`. (Extra impl)"] #[inline] @@ -92162,6 +93251,25 @@ impl VisitMutWithAstPath for Option VisitMutWithAstPath for Option> { + #[doc = "Calls [VisitMutAstPath`::visit_mut_opt_ts_this_param`] with `self`. (Extra impl)"] + #[inline] + fn visit_mut_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + ::visit_mut_opt_ts_this_param(visitor, self, __ast_path) + } + + #[inline] + fn visit_mut_children_with_ast_path(&mut self, visitor: &mut V, __ast_path: &mut AstKindPath) { + match self { + Some(inner) => as VisitMutWithAstPath>::visit_mut_with_ast_path( + inner, visitor, __ast_path, + ), + None => {} + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl VisitMutWithAstPath for Option> { #[doc = "Calls [VisitMutAstPath`::visit_mut_opt_ts_type`] with `self`. (Extra impl)"] #[inline] @@ -92737,6 +93845,13 @@ pub trait Fold { fn fold_arrow_expr(&mut self, node: ArrowExpr) -> ArrowExpr { >::fold_children_with(node, self) } + #[doc = "Visit a node of type `ArrowFunctionBody`.\n\nBy default, this method calls \ + [`ArrowFunctionBody::fold_children_with`]. If you want to recurse, you need to call \ + it manually."] + #[inline] + fn fold_arrow_function_body(&mut self, node: ArrowFunctionBody) -> ArrowFunctionBody { + >::fold_children_with(node, self) + } #[doc = "Visit a node of type `AssignExpr`.\n\nBy default, this method calls \ [`AssignExpr::fold_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -92847,13 +93962,6 @@ pub trait Fold { fn fold_block_stmt(&mut self, node: BlockStmt) -> BlockStmt { >::fold_children_with(node, self) } - #[doc = "Visit a node of type `BlockStmtOrExpr`.\n\nBy default, this method calls \ - [`BlockStmtOrExpr::fold_children_with`]. If you want to recurse, you need to call it \ - manually."] - #[inline] - fn fold_block_stmt_or_expr(&mut self, node: BlockStmtOrExpr) -> BlockStmtOrExpr { - >::fold_children_with(node, self) - } #[doc = "Visit a node of type `Bool`.\n\nBy default, this method calls \ [`Bool::fold_children_with`]. If you want to recurse, you need to call it manually."] #[inline] @@ -93159,6 +94267,13 @@ pub trait Fold { fn fold_function(&mut self, node: Function) -> Function { >::fold_children_with(node, self) } + #[doc = "Visit a node of type `FunctionBody`.\n\nBy default, this method calls \ + [`FunctionBody::fold_children_with`]. If you want to recurse, you need to call it \ + manually."] + #[inline] + fn fold_function_body(&mut self, node: FunctionBody) -> FunctionBody { + >::fold_children_with(node, self) + } #[doc = "Visit a node of type `GetterProp`.\n\nBy default, this method calls \ [`GetterProp::fold_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -93658,6 +94773,13 @@ pub trait Fold { ) -> Option> { > as FoldWith>::fold_children_with(node, self) } + #[doc = "Visit a node of type `Option < FunctionBody >`.\n\nBy default, this method calls \ + [`Option < FunctionBody >::fold_children_with`]. If you want to recurse, you need to \ + call it manually."] + #[inline] + fn fold_opt_function_body(&mut self, node: Option) -> Option { + as FoldWith>::fold_children_with(node, self) + } #[doc = "Visit a node of type `Option < Ident >`.\n\nBy default, this method calls [`Option < \ Ident >::fold_children_with`]. If you want to recurse, you need to call it manually."] #[inline] @@ -93759,6 +94881,16 @@ pub trait Fold { ) -> Option { as FoldWith>::fold_children_with(node, self) } + #[doc = "Visit a node of type `Option < Box < TsThisParam > >`.\n\nBy default, this method \ + calls [`Option < Box < TsThisParam > >::fold_children_with`]. If you want to recurse, \ + you need to call it manually."] + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + ) -> Option> { + > as FoldWith>::fold_children_with(node, self) + } #[doc = "Visit a node of type `Option < Box < TsType > >`.\n\nBy default, this method calls \ [`Option < Box < TsType > >::fold_children_with`]. If you want to recurse, you need \ to call it manually."] @@ -94507,6 +95639,13 @@ pub trait Fold { fn fold_ts_setter_signature(&mut self, node: TsSetterSignature) -> TsSetterSignature { >::fold_children_with(node, self) } + #[doc = "Visit a node of type `TsThisParam`.\n\nBy default, this method calls \ + [`TsThisParam::fold_children_with`]. If you want to recurse, you need to call it \ + manually."] + #[inline] + fn fold_ts_this_param(&mut self, node: TsThisParam) -> TsThisParam { + >::fold_children_with(node, self) + } #[doc = "Visit a node of type `TsThisType`.\n\nBy default, this method calls \ [`TsThisType::fold_children_with`]. If you want to recurse, you need to call it \ manually."] @@ -94815,6 +95954,11 @@ where ::fold_arrow_expr(&mut **self, node) } + #[inline] + fn fold_arrow_function_body(&mut self, node: ArrowFunctionBody) -> ArrowFunctionBody { + ::fold_arrow_function_body(&mut **self, node) + } + #[inline] fn fold_assign_expr(&mut self, node: AssignExpr) -> AssignExpr { ::fold_assign_expr(&mut **self, node) @@ -94895,11 +96039,6 @@ where ::fold_block_stmt(&mut **self, node) } - #[inline] - fn fold_block_stmt_or_expr(&mut self, node: BlockStmtOrExpr) -> BlockStmtOrExpr { - ::fold_block_stmt_or_expr(&mut **self, node) - } - #[inline] fn fold_bool(&mut self, node: Bool) -> Bool { ::fold_bool(&mut **self, node) @@ -95126,6 +96265,11 @@ where ::fold_function(&mut **self, node) } + #[inline] + fn fold_function_body(&mut self, node: FunctionBody) -> FunctionBody { + ::fold_function_body(&mut **self, node) + } + #[inline] fn fold_getter_prop(&mut self, node: GetterProp) -> GetterProp { ::fold_getter_prop(&mut **self, node) @@ -95495,6 +96639,11 @@ where ::fold_opt_expr_or_spreads(&mut **self, node) } + #[inline] + fn fold_opt_function_body(&mut self, node: Option) -> Option { + ::fold_opt_function_body(&mut **self, node) + } + #[inline] fn fold_opt_ident(&mut self, node: Option) -> Option { ::fold_opt_ident(&mut **self, node) @@ -95572,6 +96721,14 @@ where ::fold_opt_ts_namespace_body(&mut **self, node) } + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + ) -> Option> { + ::fold_opt_ts_this_param(&mut **self, node) + } + #[inline] fn fold_opt_ts_type(&mut self, node: Option>) -> Option> { ::fold_opt_ts_type(&mut **self, node) @@ -96127,6 +97284,11 @@ where ::fold_ts_setter_signature(&mut **self, node) } + #[inline] + fn fold_ts_this_param(&mut self, node: TsThisParam) -> TsThisParam { + ::fold_ts_this_param(&mut **self, node) + } + #[inline] fn fold_ts_this_type(&mut self, node: TsThisType) -> TsThisType { ::fold_ts_this_type(&mut **self, node) @@ -96357,6 +97519,11 @@ where ::fold_arrow_expr(&mut **self, node) } + #[inline] + fn fold_arrow_function_body(&mut self, node: ArrowFunctionBody) -> ArrowFunctionBody { + ::fold_arrow_function_body(&mut **self, node) + } + #[inline] fn fold_assign_expr(&mut self, node: AssignExpr) -> AssignExpr { ::fold_assign_expr(&mut **self, node) @@ -96437,11 +97604,6 @@ where ::fold_block_stmt(&mut **self, node) } - #[inline] - fn fold_block_stmt_or_expr(&mut self, node: BlockStmtOrExpr) -> BlockStmtOrExpr { - ::fold_block_stmt_or_expr(&mut **self, node) - } - #[inline] fn fold_bool(&mut self, node: Bool) -> Bool { ::fold_bool(&mut **self, node) @@ -96668,6 +97830,11 @@ where ::fold_function(&mut **self, node) } + #[inline] + fn fold_function_body(&mut self, node: FunctionBody) -> FunctionBody { + ::fold_function_body(&mut **self, node) + } + #[inline] fn fold_getter_prop(&mut self, node: GetterProp) -> GetterProp { ::fold_getter_prop(&mut **self, node) @@ -97037,6 +98204,11 @@ where ::fold_opt_expr_or_spreads(&mut **self, node) } + #[inline] + fn fold_opt_function_body(&mut self, node: Option) -> Option { + ::fold_opt_function_body(&mut **self, node) + } + #[inline] fn fold_opt_ident(&mut self, node: Option) -> Option { ::fold_opt_ident(&mut **self, node) @@ -97114,6 +98286,14 @@ where ::fold_opt_ts_namespace_body(&mut **self, node) } + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + ) -> Option> { + ::fold_opt_ts_this_param(&mut **self, node) + } + #[inline] fn fold_opt_ts_type(&mut self, node: Option>) -> Option> { ::fold_opt_ts_type(&mut **self, node) @@ -97669,6 +98849,11 @@ where ::fold_ts_setter_signature(&mut **self, node) } + #[inline] + fn fold_ts_this_param(&mut self, node: TsThisParam) -> TsThisParam { + ::fold_ts_this_param(&mut **self, node) + } + #[inline] fn fold_ts_this_type(&mut self, node: TsThisType) -> TsThisType { ::fold_ts_this_type(&mut **self, node) @@ -97912,6 +99097,14 @@ where } } + #[inline] + fn fold_arrow_function_body(&mut self, node: ArrowFunctionBody) -> ArrowFunctionBody { + match self { + swc_visit::Either::Left(visitor) => Fold::fold_arrow_function_body(visitor, node), + swc_visit::Either::Right(visitor) => Fold::fold_arrow_function_body(visitor, node), + } + } + #[inline] fn fold_assign_expr(&mut self, node: AssignExpr) -> AssignExpr { match self { @@ -98040,14 +99233,6 @@ where } } - #[inline] - fn fold_block_stmt_or_expr(&mut self, node: BlockStmtOrExpr) -> BlockStmtOrExpr { - match self { - swc_visit::Either::Left(visitor) => Fold::fold_block_stmt_or_expr(visitor, node), - swc_visit::Either::Right(visitor) => Fold::fold_block_stmt_or_expr(visitor, node), - } - } - #[inline] fn fold_bool(&mut self, node: Bool) -> Bool { match self { @@ -98410,6 +99595,14 @@ where } } + #[inline] + fn fold_function_body(&mut self, node: FunctionBody) -> FunctionBody { + match self { + swc_visit::Either::Left(visitor) => Fold::fold_function_body(visitor, node), + swc_visit::Either::Right(visitor) => Fold::fold_function_body(visitor, node), + } + } + #[inline] fn fold_getter_prop(&mut self, node: GetterProp) -> GetterProp { match self { @@ -98995,6 +100188,14 @@ where } } + #[inline] + fn fold_opt_function_body(&mut self, node: Option) -> Option { + match self { + swc_visit::Either::Left(visitor) => Fold::fold_opt_function_body(visitor, node), + swc_visit::Either::Right(visitor) => Fold::fold_opt_function_body(visitor, node), + } + } + #[inline] fn fold_opt_ident(&mut self, node: Option) -> Option { match self { @@ -99115,6 +100316,17 @@ where } } + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + ) -> Option> { + match self { + swc_visit::Either::Left(visitor) => Fold::fold_opt_ts_this_param(visitor, node), + swc_visit::Either::Right(visitor) => Fold::fold_opt_ts_this_param(visitor, node), + } + } + #[inline] fn fold_opt_ts_type(&mut self, node: Option>) -> Option> { match self { @@ -99995,6 +101207,14 @@ where } } + #[inline] + fn fold_ts_this_param(&mut self, node: TsThisParam) -> TsThisParam { + match self { + swc_visit::Either::Left(visitor) => Fold::fold_ts_this_param(visitor, node), + swc_visit::Either::Right(visitor) => Fold::fold_ts_this_param(visitor, node), + } + } + #[inline] fn fold_ts_this_type(&mut self, node: TsThisType) -> TsThisType { match self { @@ -100369,6 +101589,15 @@ where } } + #[inline] + fn fold_arrow_function_body(&mut self, node: ArrowFunctionBody) -> ArrowFunctionBody { + if self.enabled { + ::fold_arrow_function_body(&mut self.visitor, node) + } else { + node + } + } + #[inline] fn fold_assign_expr(&mut self, node: AssignExpr) -> AssignExpr { if self.enabled { @@ -100513,15 +101742,6 @@ where } } - #[inline] - fn fold_block_stmt_or_expr(&mut self, node: BlockStmtOrExpr) -> BlockStmtOrExpr { - if self.enabled { - ::fold_block_stmt_or_expr(&mut self.visitor, node) - } else { - node - } - } - #[inline] fn fold_bool(&mut self, node: Bool) -> Bool { if self.enabled { @@ -100924,6 +102144,15 @@ where } } + #[inline] + fn fold_function_body(&mut self, node: FunctionBody) -> FunctionBody { + if self.enabled { + ::fold_function_body(&mut self.visitor, node) + } else { + node + } + } + #[inline] fn fold_getter_prop(&mut self, node: GetterProp) -> GetterProp { if self.enabled { @@ -101581,6 +102810,15 @@ where } } + #[inline] + fn fold_opt_function_body(&mut self, node: Option) -> Option { + if self.enabled { + ::fold_opt_function_body(&mut self.visitor, node) + } else { + node + } + } + #[inline] fn fold_opt_ident(&mut self, node: Option) -> Option { if self.enabled { @@ -101710,6 +102948,18 @@ where } } + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + ) -> Option> { + if self.enabled { + ::fold_opt_ts_this_param(&mut self.visitor, node) + } else { + node + } + } + #[inline] fn fold_opt_ts_type(&mut self, node: Option>) -> Option> { if self.enabled { @@ -102685,6 +103935,15 @@ where } } + #[inline] + fn fold_ts_this_param(&mut self, node: TsThisParam) -> TsThisParam { + if self.enabled { + ::fold_ts_this_param(&mut self.visitor, node) + } else { + node + } + } + #[inline] fn fold_ts_this_type(&mut self, node: TsThisType) -> TsThisType { if self.enabled { @@ -103140,7 +104399,7 @@ impl FoldWith for ArrowExpr { let span = { >::fold_with(span, visitor) }; let ctxt = { >::fold_with(ctxt, visitor) }; let params = { as FoldWith>::fold_with(params, visitor) }; - let body = { as FoldWith>::fold_with(body, visitor) }; + let body = { as FoldWith>::fold_with(body, visitor) }; let type_params = { > as FoldWith>::fold_with(type_params, visitor) }; @@ -103160,6 +104419,27 @@ impl FoldWith for ArrowExpr { } } } +impl FoldWith for ArrowFunctionBody { + #[doc = "Calls [Fold`::fold_arrow_function_body`] with `self`."] + fn fold_with(self, visitor: &mut V) -> Self { + ::fold_arrow_function_body(visitor, self) + } + + fn fold_children_with(self, visitor: &mut V) -> Self { + match self { + ArrowFunctionBody::FunctionBody { 0: _field_0 } => { + let _field_0 = >::fold_with(_field_0, visitor); + ArrowFunctionBody::FunctionBody { 0: _field_0 } + } + ArrowFunctionBody::Expr { 0: _field_0 } => { + let _field_0 = as FoldWith>::fold_with(_field_0, visitor); + ArrowFunctionBody::Expr { 0: _field_0 } + } + #[cfg(swc_ast_unknown)] + _ => self, + } + } +} impl FoldWith for AssignExpr { #[doc = "Calls [Fold`::fold_assign_expr`] with `self`."] fn fold_with(self, visitor: &mut V) -> Self { @@ -103492,27 +104772,6 @@ impl FoldWith for BlockStmt { } } } -impl FoldWith for BlockStmtOrExpr { - #[doc = "Calls [Fold`::fold_block_stmt_or_expr`] with `self`."] - fn fold_with(self, visitor: &mut V) -> Self { - ::fold_block_stmt_or_expr(visitor, self) - } - - fn fold_children_with(self, visitor: &mut V) -> Self { - match self { - BlockStmtOrExpr::BlockStmt { 0: _field_0 } => { - let _field_0 = >::fold_with(_field_0, visitor); - BlockStmtOrExpr::BlockStmt { 0: _field_0 } - } - BlockStmtOrExpr::Expr { 0: _field_0 } => { - let _field_0 = as FoldWith>::fold_with(_field_0, visitor); - BlockStmtOrExpr::Expr { 0: _field_0 } - } - #[cfg(swc_ast_unknown)] - _ => self, - } - } -} impl FoldWith for Bool { #[doc = "Calls [Fold`::fold_bool`] with `self`."] fn fold_with(self, visitor: &mut V) -> Self { @@ -103919,7 +105178,7 @@ impl FoldWith for Constructor { let key = { >::fold_with(key, visitor) }; let params = { as FoldWith>::fold_with(params, visitor) }; - let body = { as FoldWith>::fold_with(body, visitor) }; + let body = { as FoldWith>::fold_with(body, visitor) }; let accessibility = { as FoldWith>::fold_with(accessibility, visitor) }; Constructor { @@ -104606,6 +105865,7 @@ impl FoldWith for Function { fn fold_children_with(self, visitor: &mut V) -> Self { match self { Function { + this_param, params, decorators, span, @@ -104616,18 +105876,21 @@ impl FoldWith for Function { type_params, return_type, } => { + let this_param = + { > as FoldWith>::fold_with(this_param, visitor) }; let params = { as FoldWith>::fold_with(params, visitor) }; let decorators = { as FoldWith>::fold_with(decorators, visitor) }; let span = { >::fold_with(span, visitor) }; let ctxt = { >::fold_with(ctxt, visitor) }; - let body = { as FoldWith>::fold_with(body, visitor) }; + let body = { as FoldWith>::fold_with(body, visitor) }; let type_params = { > as FoldWith>::fold_with(type_params, visitor) }; let return_type = { > as FoldWith>::fold_with(return_type, visitor) }; Function { + this_param, params, decorators, span, @@ -104642,6 +105905,22 @@ impl FoldWith for Function { } } } +impl FoldWith for FunctionBody { + #[doc = "Calls [Fold`::fold_function_body`] with `self`."] + fn fold_with(self, visitor: &mut V) -> Self { + ::fold_function_body(visitor, self) + } + + fn fold_children_with(self, visitor: &mut V) -> Self { + match self { + FunctionBody { span, stmts } => { + let span = { >::fold_with(span, visitor) }; + let stmts = { as FoldWith>::fold_with(stmts, visitor) }; + FunctionBody { span, stmts } + } + } + } +} impl FoldWith for GetterProp { #[doc = "Calls [Fold`::fold_getter_prop`] with `self`."] fn fold_with(self, visitor: &mut V) -> Self { @@ -104653,19 +105932,15 @@ impl FoldWith for GetterProp { GetterProp { span, key, - type_ann, - body, + function, } => { let span = { >::fold_with(span, visitor) }; let key = { >::fold_with(key, visitor) }; - let type_ann = - { > as FoldWith>::fold_with(type_ann, visitor) }; - let body = { as FoldWith>::fold_with(body, visitor) }; + let function = { as FoldWith>::fold_with(function, visitor) }; GetterProp { span, key, - type_ann, - body, + function, } } } @@ -105359,7 +106634,7 @@ impl FoldWith for JSXText { match self { JSXText { span, value, raw } => { let span = { >::fold_with(span, visitor) }; - let value = { >::fold_with(value, visitor) }; + let value = { >::fold_with(value, visitor) }; let raw = { >::fold_with(raw, visitor) }; JSXText { span, value, raw } } @@ -106384,21 +107659,15 @@ impl FoldWith for SetterProp { SetterProp { span, key, - this_param, - param, - body, + function, } => { let span = { >::fold_with(span, visitor) }; let key = { >::fold_with(key, visitor) }; - let this_param = { as FoldWith>::fold_with(this_param, visitor) }; - let param = { as FoldWith>::fold_with(param, visitor) }; - let body = { as FoldWith>::fold_with(body, visitor) }; + let function = { as FoldWith>::fold_with(function, visitor) }; SetterProp { span, key, - this_param, - param, - body, + function, } } } @@ -106680,14 +107949,18 @@ impl FoldWith for SwitchStmt { match self { SwitchStmt { span, + body_ctxt, discriminant, cases, } => { let span = { >::fold_with(span, visitor) }; + let body_ctxt = + { >::fold_with(body_ctxt, visitor) }; let discriminant = { as FoldWith>::fold_with(discriminant, visitor) }; let cases = { as FoldWith>::fold_with(cases, visitor) }; SwitchStmt { span, + body_ctxt, discriminant, cases, } @@ -108093,6 +109366,33 @@ impl FoldWith for TsSetterSignature { } } } +impl FoldWith for TsThisParam { + #[doc = "Calls [Fold`::fold_ts_this_param`] with `self`."] + fn fold_with(self, visitor: &mut V) -> Self { + ::fold_ts_this_param(visitor, self) + } + + fn fold_children_with(self, visitor: &mut V) -> Self { + match self { + TsThisParam { + span, + this_span, + type_ann, + } => { + let span = { >::fold_with(span, visitor) }; + let this_span = + { >::fold_with(this_span, visitor) }; + let type_ann = + { > as FoldWith>::fold_with(type_ann, visitor) }; + TsThisParam { + span, + this_span, + type_ann, + } + } + } + } +} impl FoldWith for TsThisType { #[doc = "Calls [Fold`::fold_ts_this_type`] with `self`."] fn fold_with(self, visitor: &mut V) -> Self { @@ -109176,6 +110476,18 @@ impl FoldWith for Option> { self.map(|inner| as FoldWith>::fold_with(inner, visitor)) } } +impl FoldWith for Option { + #[doc = "Calls [Fold`::fold_opt_function_body`] with `self`. (Extra impl)"] + #[inline] + fn fold_with(self, visitor: &mut V) -> Self { + ::fold_opt_function_body(visitor, self) + } + + #[inline] + fn fold_children_with(self, visitor: &mut V) -> Self { + self.map(|inner| >::fold_with(inner, visitor)) + } +} impl FoldWith for Option { #[doc = "Calls [Fold`::fold_opt_ident`] with `self`. (Extra impl)"] #[inline] @@ -109332,6 +110644,18 @@ impl FoldWith for Option { self.map(|inner| >::fold_with(inner, visitor)) } } +impl FoldWith for Option> { + #[doc = "Calls [Fold`::fold_opt_ts_this_param`] with `self`. (Extra impl)"] + #[inline] + fn fold_with(self, visitor: &mut V) -> Self { + ::fold_opt_ts_this_param(visitor, self) + } + + #[inline] + fn fold_children_with(self, visitor: &mut V) -> Self { + self.map(|inner| as FoldWith>::fold_with(inner, visitor)) + } +} impl FoldWith for Option> { #[doc = "Calls [Fold`::fold_opt_ts_type`] with `self`. (Extra impl)"] #[inline] @@ -109733,6 +111057,19 @@ pub trait FoldAstPath { fn fold_arrow_expr(&mut self, node: ArrowExpr, __ast_path: &mut AstKindPath) -> ArrowExpr { >::fold_children_with_ast_path(node, self, __ast_path) } + #[doc = "Visit a node of type `ArrowFunctionBody`.\n\nBy default, this method calls \ + [`ArrowFunctionBody::fold_children_with_ast_path`]. If you want to recurse, you need \ + to call it manually."] + #[inline] + fn fold_arrow_function_body( + &mut self, + node: ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) -> ArrowFunctionBody { + >::fold_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `AssignExpr`.\n\nBy default, this method calls \ [`AssignExpr::fold_children_with_ast_path`]. If you want to recurse, you need to call \ it manually."] @@ -109879,19 +111216,6 @@ pub trait FoldAstPath { fn fold_block_stmt(&mut self, node: BlockStmt, __ast_path: &mut AstKindPath) -> BlockStmt { >::fold_children_with_ast_path(node, self, __ast_path) } - #[doc = "Visit a node of type `BlockStmtOrExpr`.\n\nBy default, this method calls \ - [`BlockStmtOrExpr::fold_children_with_ast_path`]. If you want to recurse, you need to \ - call it manually."] - #[inline] - fn fold_block_stmt_or_expr( - &mut self, - node: BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) -> BlockStmtOrExpr { - >::fold_children_with_ast_path( - node, self, __ast_path, - ) - } #[doc = "Visit a node of type `Bool`.\n\nBy default, this method calls \ [`Bool::fold_children_with_ast_path`]. If you want to recurse, you need to call it \ manually."] @@ -110300,6 +111624,17 @@ pub trait FoldAstPath { fn fold_function(&mut self, node: Function, __ast_path: &mut AstKindPath) -> Function { >::fold_children_with_ast_path(node, self, __ast_path) } + #[doc = "Visit a node of type `FunctionBody`.\n\nBy default, this method calls \ + [`FunctionBody::fold_children_with_ast_path`]. If you want to recurse, you need to \ + call it manually."] + #[inline] + fn fold_function_body( + &mut self, + node: FunctionBody, + __ast_path: &mut AstKindPath, + ) -> FunctionBody { + >::fold_children_with_ast_path(node, self, __ast_path) + } #[doc = "Visit a node of type `GetterProp`.\n\nBy default, this method calls \ [`GetterProp::fold_children_with_ast_path`]. If you want to recurse, you need to call \ it manually."] @@ -111044,6 +112379,19 @@ pub trait FoldAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `Option < FunctionBody >`.\n\nBy default, this method calls \ + [`Option < FunctionBody >::fold_children_with_ast_path`]. If you want to recurse, you \ + need to call it manually."] + #[inline] + fn fold_opt_function_body( + &mut self, + node: Option, + __ast_path: &mut AstKindPath, + ) -> Option { + as FoldWithAstPath>::fold_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `Option < Ident >`.\n\nBy default, this method calls [`Option < \ Ident >::fold_children_with_ast_path`]. If you want to recurse, you need to call it \ manually."] @@ -111207,6 +112555,19 @@ pub trait FoldAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `Option < Box < TsThisParam > >`.\n\nBy default, this method \ + calls [`Option < Box < TsThisParam > >::fold_children_with_ast_path`]. If you want to \ + recurse, you need to call it manually."] + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + __ast_path: &mut AstKindPath, + ) -> Option> { + > as FoldWithAstPath>::fold_children_with_ast_path( + node, self, __ast_path, + ) + } #[doc = "Visit a node of type `Option < Box < TsType > >`.\n\nBy default, this method calls \ [`Option < Box < TsType > >::fold_children_with_ast_path`]. If you want to recurse, \ you need to call it manually."] @@ -112339,6 +113700,17 @@ pub trait FoldAstPath { node, self, __ast_path, ) } + #[doc = "Visit a node of type `TsThisParam`.\n\nBy default, this method calls \ + [`TsThisParam::fold_children_with_ast_path`]. If you want to recurse, you need to \ + call it manually."] + #[inline] + fn fold_ts_this_param( + &mut self, + node: TsThisParam, + __ast_path: &mut AstKindPath, + ) -> TsThisParam { + >::fold_children_with_ast_path(node, self, __ast_path) + } #[doc = "Visit a node of type `TsThisType`.\n\nBy default, this method calls \ [`TsThisType::fold_children_with_ast_path`]. If you want to recurse, you need to call \ it manually."] @@ -112794,6 +114166,15 @@ where ::fold_arrow_expr(&mut **self, node, __ast_path) } + #[inline] + fn fold_arrow_function_body( + &mut self, + node: ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) -> ArrowFunctionBody { + ::fold_arrow_function_body(&mut **self, node, __ast_path) + } + #[inline] fn fold_assign_expr(&mut self, node: AssignExpr, __ast_path: &mut AstKindPath) -> AssignExpr { ::fold_assign_expr(&mut **self, node, __ast_path) @@ -112902,15 +114283,6 @@ where ::fold_block_stmt(&mut **self, node, __ast_path) } - #[inline] - fn fold_block_stmt_or_expr( - &mut self, - node: BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) -> BlockStmtOrExpr { - ::fold_block_stmt_or_expr(&mut **self, node, __ast_path) - } - #[inline] fn fold_bool(&mut self, node: Bool, __ast_path: &mut AstKindPath) -> Bool { ::fold_bool(&mut **self, node, __ast_path) @@ -113207,6 +114579,15 @@ where ::fold_function(&mut **self, node, __ast_path) } + #[inline] + fn fold_function_body( + &mut self, + node: FunctionBody, + __ast_path: &mut AstKindPath, + ) -> FunctionBody { + ::fold_function_body(&mut **self, node, __ast_path) + } + #[inline] fn fold_getter_prop(&mut self, node: GetterProp, __ast_path: &mut AstKindPath) -> GetterProp { ::fold_getter_prop(&mut **self, node, __ast_path) @@ -113743,6 +115124,15 @@ where ::fold_opt_expr_or_spreads(&mut **self, node, __ast_path) } + #[inline] + fn fold_opt_function_body( + &mut self, + node: Option, + __ast_path: &mut AstKindPath, + ) -> Option { + ::fold_opt_function_body(&mut **self, node, __ast_path) + } + #[inline] fn fold_opt_ident( &mut self, @@ -113856,6 +115246,15 @@ where ::fold_opt_ts_namespace_body(&mut **self, node, __ast_path) } + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + __ast_path: &mut AstKindPath, + ) -> Option> { + ::fold_opt_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn fold_opt_ts_type( &mut self, @@ -114665,6 +116064,15 @@ where ::fold_ts_setter_signature(&mut **self, node, __ast_path) } + #[inline] + fn fold_ts_this_param( + &mut self, + node: TsThisParam, + __ast_path: &mut AstKindPath, + ) -> TsThisParam { + ::fold_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn fold_ts_this_type(&mut self, node: TsThisType, __ast_path: &mut AstKindPath) -> TsThisType { ::fold_ts_this_type(&mut **self, node, __ast_path) @@ -114999,6 +116407,15 @@ where ::fold_arrow_expr(&mut **self, node, __ast_path) } + #[inline] + fn fold_arrow_function_body( + &mut self, + node: ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) -> ArrowFunctionBody { + ::fold_arrow_function_body(&mut **self, node, __ast_path) + } + #[inline] fn fold_assign_expr(&mut self, node: AssignExpr, __ast_path: &mut AstKindPath) -> AssignExpr { ::fold_assign_expr(&mut **self, node, __ast_path) @@ -115107,15 +116524,6 @@ where ::fold_block_stmt(&mut **self, node, __ast_path) } - #[inline] - fn fold_block_stmt_or_expr( - &mut self, - node: BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) -> BlockStmtOrExpr { - ::fold_block_stmt_or_expr(&mut **self, node, __ast_path) - } - #[inline] fn fold_bool(&mut self, node: Bool, __ast_path: &mut AstKindPath) -> Bool { ::fold_bool(&mut **self, node, __ast_path) @@ -115412,6 +116820,15 @@ where ::fold_function(&mut **self, node, __ast_path) } + #[inline] + fn fold_function_body( + &mut self, + node: FunctionBody, + __ast_path: &mut AstKindPath, + ) -> FunctionBody { + ::fold_function_body(&mut **self, node, __ast_path) + } + #[inline] fn fold_getter_prop(&mut self, node: GetterProp, __ast_path: &mut AstKindPath) -> GetterProp { ::fold_getter_prop(&mut **self, node, __ast_path) @@ -115948,6 +117365,15 @@ where ::fold_opt_expr_or_spreads(&mut **self, node, __ast_path) } + #[inline] + fn fold_opt_function_body( + &mut self, + node: Option, + __ast_path: &mut AstKindPath, + ) -> Option { + ::fold_opt_function_body(&mut **self, node, __ast_path) + } + #[inline] fn fold_opt_ident( &mut self, @@ -116061,6 +117487,15 @@ where ::fold_opt_ts_namespace_body(&mut **self, node, __ast_path) } + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + __ast_path: &mut AstKindPath, + ) -> Option> { + ::fold_opt_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn fold_opt_ts_type( &mut self, @@ -116870,6 +118305,15 @@ where ::fold_ts_setter_signature(&mut **self, node, __ast_path) } + #[inline] + fn fold_ts_this_param( + &mut self, + node: TsThisParam, + __ast_path: &mut AstKindPath, + ) -> TsThisParam { + ::fold_ts_this_param(&mut **self, node, __ast_path) + } + #[inline] fn fold_ts_this_type(&mut self, node: TsThisType, __ast_path: &mut AstKindPath) -> TsThisType { ::fold_ts_this_type(&mut **self, node, __ast_path) @@ -117233,6 +118677,22 @@ where } } + #[inline] + fn fold_arrow_function_body( + &mut self, + node: ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) -> ArrowFunctionBody { + match self { + swc_visit::Either::Left(visitor) => { + FoldAstPath::fold_arrow_function_body(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + FoldAstPath::fold_arrow_function_body(visitor, node, __ast_path) + } + } + } + #[inline] fn fold_assign_expr(&mut self, node: AssignExpr, __ast_path: &mut AstKindPath) -> AssignExpr { match self { @@ -117449,22 +118909,6 @@ where } } - #[inline] - fn fold_block_stmt_or_expr( - &mut self, - node: BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) -> BlockStmtOrExpr { - match self { - swc_visit::Either::Left(visitor) => { - FoldAstPath::fold_block_stmt_or_expr(visitor, node, __ast_path) - } - swc_visit::Either::Right(visitor) => { - FoldAstPath::fold_block_stmt_or_expr(visitor, node, __ast_path) - } - } - } - #[inline] fn fold_bool(&mut self, node: Bool, __ast_path: &mut AstKindPath) -> Bool { match self { @@ -118047,6 +119491,22 @@ where } } + #[inline] + fn fold_function_body( + &mut self, + node: FunctionBody, + __ast_path: &mut AstKindPath, + ) -> FunctionBody { + match self { + swc_visit::Either::Left(visitor) => { + FoldAstPath::fold_function_body(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + FoldAstPath::fold_function_body(visitor, node, __ast_path) + } + } + } + #[inline] fn fold_getter_prop(&mut self, node: GetterProp, __ast_path: &mut AstKindPath) -> GetterProp { match self { @@ -119065,6 +120525,22 @@ where } } + #[inline] + fn fold_opt_function_body( + &mut self, + node: Option, + __ast_path: &mut AstKindPath, + ) -> Option { + match self { + swc_visit::Either::Left(visitor) => { + FoldAstPath::fold_opt_function_body(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + FoldAstPath::fold_opt_function_body(visitor, node, __ast_path) + } + } + } + #[inline] fn fold_opt_ident( &mut self, @@ -119269,6 +120745,22 @@ where } } + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + __ast_path: &mut AstKindPath, + ) -> Option> { + match self { + swc_visit::Either::Left(visitor) => { + FoldAstPath::fold_opt_ts_this_param(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + FoldAstPath::fold_opt_ts_this_param(visitor, node, __ast_path) + } + } + } + #[inline] fn fold_opt_ts_type( &mut self, @@ -120763,6 +122255,22 @@ where } } + #[inline] + fn fold_ts_this_param( + &mut self, + node: TsThisParam, + __ast_path: &mut AstKindPath, + ) -> TsThisParam { + match self { + swc_visit::Either::Left(visitor) => { + FoldAstPath::fold_ts_this_param(visitor, node, __ast_path) + } + swc_visit::Either::Right(visitor) => { + FoldAstPath::fold_ts_this_param(visitor, node, __ast_path) + } + } + } + #[inline] fn fold_ts_this_type(&mut self, node: TsThisType, __ast_path: &mut AstKindPath) -> TsThisType { match self { @@ -121393,6 +122901,19 @@ where } } + #[inline] + fn fold_arrow_function_body( + &mut self, + node: ArrowFunctionBody, + __ast_path: &mut AstKindPath, + ) -> ArrowFunctionBody { + if self.enabled { + ::fold_arrow_function_body(&mut self.visitor, node, __ast_path) + } else { + node + } + } + #[inline] fn fold_assign_expr(&mut self, node: AssignExpr, __ast_path: &mut AstKindPath) -> AssignExpr { if self.enabled { @@ -121565,19 +123086,6 @@ where } } - #[inline] - fn fold_block_stmt_or_expr( - &mut self, - node: BlockStmtOrExpr, - __ast_path: &mut AstKindPath, - ) -> BlockStmtOrExpr { - if self.enabled { - ::fold_block_stmt_or_expr(&mut self.visitor, node, __ast_path) - } else { - node - } - } - #[inline] fn fold_bool(&mut self, node: Bool, __ast_path: &mut AstKindPath) -> Bool { if self.enabled { @@ -122050,6 +123558,19 @@ where } } + #[inline] + fn fold_function_body( + &mut self, + node: FunctionBody, + __ast_path: &mut AstKindPath, + ) -> FunctionBody { + if self.enabled { + ::fold_function_body(&mut self.visitor, node, __ast_path) + } else { + node + } + } + #[inline] fn fold_getter_prop(&mut self, node: GetterProp, __ast_path: &mut AstKindPath) -> GetterProp { if self.enabled { @@ -122874,6 +124395,19 @@ where } } + #[inline] + fn fold_opt_function_body( + &mut self, + node: Option, + __ast_path: &mut AstKindPath, + ) -> Option { + if self.enabled { + ::fold_opt_function_body(&mut self.visitor, node, __ast_path) + } else { + node + } + } + #[inline] fn fold_opt_ident( &mut self, @@ -123039,6 +124573,19 @@ where } } + #[inline] + fn fold_opt_ts_this_param( + &mut self, + node: Option>, + __ast_path: &mut AstKindPath, + ) -> Option> { + if self.enabled { + ::fold_opt_ts_this_param(&mut self.visitor, node, __ast_path) + } else { + node + } + } + #[inline] fn fold_opt_ts_type( &mut self, @@ -124276,6 +125823,19 @@ where } } + #[inline] + fn fold_ts_this_param( + &mut self, + node: TsThisParam, + __ast_path: &mut AstKindPath, + ) -> TsThisParam { + if self.enabled { + ::fold_ts_this_param(&mut self.visitor, node, __ast_path) + } else { + node + } + } + #[inline] fn fold_ts_this_type(&mut self, node: TsThisType, __ast_path: &mut AstKindPath) -> TsThisType { if self.enabled { @@ -124916,7 +126476,7 @@ impl FoldWithAstPath for ArrowExpr { let body = { let mut __ast_path = __ast_path .with_guard(AstParentKind::ArrowExpr(self::fields::ArrowExprField::Body)); - as FoldWithAstPath>::fold_with_ast_path( + as FoldWithAstPath>::fold_with_ast_path( body, visitor, &mut *__ast_path, @@ -124958,6 +126518,43 @@ impl FoldWithAstPath for ArrowExpr { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl FoldWithAstPath for ArrowFunctionBody { + #[doc = "Calls [FoldAstPath`::fold_arrow_function_body`] with `self`."] + fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + ::fold_arrow_function_body(visitor, self, __ast_path) + } + + fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + match self { + ArrowFunctionBody::FunctionBody { 0: _field_0 } => { + let mut __ast_path = __ast_path.with_guard(AstParentKind::ArrowFunctionBody( + self::fields::ArrowFunctionBodyField::FunctionBody, + )); + let _field_0 = >::fold_with_ast_path( + _field_0, + visitor, + &mut *__ast_path, + ); + ArrowFunctionBody::FunctionBody { 0: _field_0 } + } + ArrowFunctionBody::Expr { 0: _field_0 } => { + let mut __ast_path = __ast_path.with_guard(AstParentKind::ArrowFunctionBody( + self::fields::ArrowFunctionBodyField::Expr, + )); + let _field_0 = as FoldWithAstPath>::fold_with_ast_path( + _field_0, + visitor, + &mut *__ast_path, + ); + ArrowFunctionBody::Expr { 0: _field_0 } + } + #[cfg(swc_ast_unknown)] + _ => self, + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl FoldWithAstPath for AssignExpr { #[doc = "Calls [FoldAstPath`::fold_assign_expr`] with `self`."] fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { @@ -125624,43 +127221,6 @@ impl FoldWithAstPath for BlockStmt { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] -impl FoldWithAstPath for BlockStmtOrExpr { - #[doc = "Calls [FoldAstPath`::fold_block_stmt_or_expr`] with `self`."] - fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { - ::fold_block_stmt_or_expr(visitor, self, __ast_path) - } - - fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { - match self { - BlockStmtOrExpr::BlockStmt { 0: _field_0 } => { - let mut __ast_path = __ast_path.with_guard(AstParentKind::BlockStmtOrExpr( - self::fields::BlockStmtOrExprField::BlockStmt, - )); - let _field_0 = >::fold_with_ast_path( - _field_0, - visitor, - &mut *__ast_path, - ); - BlockStmtOrExpr::BlockStmt { 0: _field_0 } - } - BlockStmtOrExpr::Expr { 0: _field_0 } => { - let mut __ast_path = __ast_path.with_guard(AstParentKind::BlockStmtOrExpr( - self::fields::BlockStmtOrExprField::Expr, - )); - let _field_0 = as FoldWithAstPath>::fold_with_ast_path( - _field_0, - visitor, - &mut *__ast_path, - ); - BlockStmtOrExpr::Expr { 0: _field_0 } - } - #[cfg(swc_ast_unknown)] - _ => self, - } - } -} -#[cfg(any(docsrs, feature = "path"))] -#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl FoldWithAstPath for Bool { #[doc = "Calls [FoldAstPath`::fold_bool`] with `self`."] fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { @@ -126532,7 +128092,7 @@ impl FoldWithAstPath for Constructor { let mut __ast_path = __ast_path.with_guard(AstParentKind::Constructor( self::fields::ConstructorField::Body, )); - as FoldWithAstPath>::fold_with_ast_path( + as FoldWithAstPath>::fold_with_ast_path( body, visitor, &mut *__ast_path, @@ -128007,6 +129567,7 @@ impl FoldWithAstPath for Function { fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { match self { Function { + this_param, params, decorators, span, @@ -128017,6 +129578,16 @@ impl FoldWithAstPath for Function { type_params, return_type, } => { + let this_param = { + let mut __ast_path = __ast_path.with_guard(AstParentKind::Function( + self::fields::FunctionField::ThisParam, + )); + > as FoldWithAstPath>::fold_with_ast_path( + this_param, + visitor, + &mut *__ast_path, + ) + }; let params = { let mut __ast_path = __ast_path.with_guard(AstParentKind::Function( self::fields::FunctionField::Params(usize::MAX), @@ -128058,7 +129629,7 @@ impl FoldWithAstPath for Function { let body = { let mut __ast_path = __ast_path .with_guard(AstParentKind::Function(self::fields::FunctionField::Body)); - as FoldWithAstPath>::fold_with_ast_path( + as FoldWithAstPath>::fold_with_ast_path( body, visitor, &mut *__ast_path, @@ -128085,6 +129656,7 @@ impl FoldWithAstPath for Function { ) }; Function { + this_param, params, decorators, span, @@ -128101,6 +129673,42 @@ impl FoldWithAstPath for Function { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl FoldWithAstPath for FunctionBody { + #[doc = "Calls [FoldAstPath`::fold_function_body`] with `self`."] + fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + ::fold_function_body(visitor, self, __ast_path) + } + + fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + match self { + FunctionBody { span, stmts } => { + let span = { + let mut __ast_path = __ast_path.with_guard(AstParentKind::FunctionBody( + self::fields::FunctionBodyField::Span, + )); + >::fold_with_ast_path( + span, + visitor, + &mut *__ast_path, + ) + }; + let stmts = { + let mut __ast_path = __ast_path.with_guard(AstParentKind::FunctionBody( + self::fields::FunctionBodyField::Stmts(usize::MAX), + )); + as FoldWithAstPath>::fold_with_ast_path( + stmts, + visitor, + &mut *__ast_path, + ) + }; + FunctionBody { span, stmts } + } + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl FoldWithAstPath for GetterProp { #[doc = "Calls [FoldAstPath`::fold_getter_prop`] with `self`."] fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { @@ -128112,8 +129720,7 @@ impl FoldWithAstPath for GetterProp { GetterProp { span, key, - type_ann, - body, + function, } => { let span = { let mut __ast_path = __ast_path.with_guard(AstParentKind::GetterProp( @@ -128135,22 +129742,12 @@ impl FoldWithAstPath for GetterProp { &mut *__ast_path, ) }; - let type_ann = { - let mut __ast_path = __ast_path.with_guard(AstParentKind::GetterProp( - self::fields::GetterPropField::TypeAnn, - )); - > as FoldWithAstPath>::fold_with_ast_path( - type_ann, - visitor, - &mut *__ast_path, - ) - }; - let body = { + let function = { let mut __ast_path = __ast_path.with_guard(AstParentKind::GetterProp( - self::fields::GetterPropField::Body, + self::fields::GetterPropField::Function, )); - as FoldWithAstPath>::fold_with_ast_path( - body, + as FoldWithAstPath>::fold_with_ast_path( + function, visitor, &mut *__ast_path, ) @@ -128158,8 +129755,7 @@ impl FoldWithAstPath for GetterProp { GetterProp { span, key, - type_ann, - body, + function, } } } @@ -129590,7 +131186,7 @@ impl FoldWithAstPath for JSXText { let value = { let mut __ast_path = __ast_path .with_guard(AstParentKind::JSXText(self::fields::JSXTextField::Value)); - >::fold_with_ast_path( + >::fold_with_ast_path( value, visitor, &mut *__ast_path, @@ -131668,9 +133264,7 @@ impl FoldWithAstPath for SetterProp { SetterProp { span, key, - this_param, - param, - body, + function, } => { let span = { let mut __ast_path = __ast_path.with_guard(AstParentKind::SetterProp( @@ -131692,32 +133286,12 @@ impl FoldWithAstPath for SetterProp { &mut *__ast_path, ) }; - let this_param = { - let mut __ast_path = __ast_path.with_guard(AstParentKind::SetterProp( - self::fields::SetterPropField::ThisParam, - )); - as FoldWithAstPath>::fold_with_ast_path( - this_param, - visitor, - &mut *__ast_path, - ) - }; - let param = { - let mut __ast_path = __ast_path.with_guard(AstParentKind::SetterProp( - self::fields::SetterPropField::Param, - )); - as FoldWithAstPath>::fold_with_ast_path( - param, - visitor, - &mut *__ast_path, - ) - }; - let body = { + let function = { let mut __ast_path = __ast_path.with_guard(AstParentKind::SetterProp( - self::fields::SetterPropField::Body, + self::fields::SetterPropField::Function, )); - as FoldWithAstPath>::fold_with_ast_path( - body, + as FoldWithAstPath>::fold_with_ast_path( + function, visitor, &mut *__ast_path, ) @@ -131725,9 +133299,7 @@ impl FoldWithAstPath for SetterProp { SetterProp { span, key, - this_param, - param, - body, + function, } } } @@ -132355,6 +133927,7 @@ impl FoldWithAstPath for SwitchStmt { match self { SwitchStmt { span, + body_ctxt, discriminant, cases, } => { @@ -132368,6 +133941,16 @@ impl FoldWithAstPath for SwitchStmt { &mut *__ast_path, ) }; + let body_ctxt = { + let mut __ast_path = __ast_path.with_guard(AstParentKind::SwitchStmt( + self::fields::SwitchStmtField::BodyCtxt, + )); + >::fold_with_ast_path( + body_ctxt, + visitor, + &mut *__ast_path, + ) + }; let discriminant = { let mut __ast_path = __ast_path.with_guard(AstParentKind::SwitchStmt( self::fields::SwitchStmtField::Discriminant, @@ -132390,6 +133973,7 @@ impl FoldWithAstPath for SwitchStmt { }; SwitchStmt { span, + body_ctxt, discriminant, cases, } @@ -135240,6 +136824,60 @@ impl FoldWithAstPath for TsSetterSignature { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl FoldWithAstPath for TsThisParam { + #[doc = "Calls [FoldAstPath`::fold_ts_this_param`] with `self`."] + fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + ::fold_ts_this_param(visitor, self, __ast_path) + } + + fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + match self { + TsThisParam { + span, + this_span, + type_ann, + } => { + let span = { + let mut __ast_path = __ast_path.with_guard(AstParentKind::TsThisParam( + self::fields::TsThisParamField::Span, + )); + >::fold_with_ast_path( + span, + visitor, + &mut *__ast_path, + ) + }; + let this_span = { + let mut __ast_path = __ast_path.with_guard(AstParentKind::TsThisParam( + self::fields::TsThisParamField::ThisSpan, + )); + >::fold_with_ast_path( + this_span, + visitor, + &mut *__ast_path, + ) + }; + let type_ann = { + let mut __ast_path = __ast_path.with_guard(AstParentKind::TsThisParam( + self::fields::TsThisParamField::TypeAnn, + )); + > as FoldWithAstPath>::fold_with_ast_path( + type_ann, + visitor, + &mut *__ast_path, + ) + }; + TsThisParam { + span, + this_span, + type_ann, + } + } + } + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl FoldWithAstPath for TsThisType { #[doc = "Calls [FoldAstPath`::fold_ts_this_type`] with `self`."] fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { @@ -137313,6 +138951,22 @@ impl FoldWithAstPath for Option> { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl FoldWithAstPath for Option { + #[doc = "Calls [FoldAstPath`::fold_opt_function_body`] with `self`. (Extra impl)"] + #[inline] + fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + ::fold_opt_function_body(visitor, self, __ast_path) + } + + #[inline] + fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + self.map(|inner| { + >::fold_with_ast_path(inner, visitor, __ast_path) + }) + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl FoldWithAstPath for Option { #[doc = "Calls [FoldAstPath`::fold_opt_ident`] with `self`. (Extra impl)"] #[inline] @@ -137525,6 +139179,22 @@ impl FoldWithAstPath for Option { } #[cfg(any(docsrs, feature = "path"))] #[cfg_attr(docsrs, doc(cfg(feature = "path")))] +impl FoldWithAstPath for Option> { + #[doc = "Calls [FoldAstPath`::fold_opt_ts_this_param`] with `self`. (Extra impl)"] + #[inline] + fn fold_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + ::fold_opt_ts_this_param(visitor, self, __ast_path) + } + + #[inline] + fn fold_children_with_ast_path(self, visitor: &mut V, __ast_path: &mut AstKindPath) -> Self { + self.map(|inner| { + as FoldWithAstPath>::fold_with_ast_path(inner, visitor, __ast_path) + }) + } +} +#[cfg(any(docsrs, feature = "path"))] +#[cfg_attr(docsrs, doc(cfg(feature = "path")))] impl FoldWithAstPath for Option> { #[doc = "Calls [FoldAstPath`::fold_opt_ts_type`] with `self`. (Extra impl)"] #[inline] @@ -138189,6 +139859,20 @@ pub mod fields { #[doc = "Represents [`ArrowExpr::return_type`]"] ReturnType, } + impl ArrowFunctionBodyField { + #[inline(always)] + pub(crate) fn set_index(&mut self, _: usize) { + swc_visit::wrong_ast_path(); + } + } + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] + pub enum ArrowFunctionBodyField { + #[doc = "Represents [`ArrowFunctionBody::FunctionBody`]"] + FunctionBody, + #[doc = "Represents [`ArrowFunctionBody::Expr`]"] + Expr, + } impl AssignExprField { pub(crate) fn set_index(&mut self, index: usize) { match self { @@ -138513,20 +140197,6 @@ pub mod fields { #[doc = "Represents [`BlockStmt::stmts`]"] Stmts(usize), } - impl BlockStmtOrExprField { - #[inline(always)] - pub(crate) fn set_index(&mut self, _: usize) { - swc_visit::wrong_ast_path(); - } - } - #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] - #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] - pub enum BlockStmtOrExprField { - #[doc = "Represents [`BlockStmtOrExpr::BlockStmt`]"] - BlockStmt, - #[doc = "Represents [`BlockStmtOrExpr::Expr`]"] - Expr, - } impl BoolField { pub(crate) fn set_index(&mut self, index: usize) { match self { @@ -139334,6 +141004,8 @@ pub mod fields { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] pub enum FunctionField { + #[doc = "Represents [`Function::this_param`]"] + ThisParam, #[doc = "Represents [`Function::params`]"] Params(usize), #[doc = "Represents [`Function::decorators`]"] @@ -139353,6 +141025,25 @@ pub mod fields { #[doc = "Represents [`Function::return_type`]"] ReturnType, } + impl FunctionBodyField { + pub(crate) fn set_index(&mut self, index: usize) { + match self { + Self::Stmts(idx) => { + assert_initial_index(*idx, index); + *idx = index; + } + _ => swc_visit::wrong_ast_path(), + } + } + } + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] + pub enum FunctionBodyField { + #[doc = "Represents [`FunctionBody::span`]"] + Span, + #[doc = "Represents [`FunctionBody::stmts`]"] + Stmts(usize), + } impl GetterPropField { pub(crate) fn set_index(&mut self, index: usize) { match self { @@ -139367,10 +141058,8 @@ pub mod fields { Span, #[doc = "Represents [`GetterProp::key`]"] Key, - #[doc = "Represents [`GetterProp::type_ann`]"] - TypeAnn, - #[doc = "Represents [`GetterProp::body`]"] - Body, + #[doc = "Represents [`GetterProp::function`]"] + Function, } impl IdentField { pub(crate) fn set_index(&mut self, index: usize) { @@ -140709,12 +142398,8 @@ pub mod fields { Span, #[doc = "Represents [`SetterProp::key`]"] Key, - #[doc = "Represents [`SetterProp::this_param`]"] - ThisParam, - #[doc = "Represents [`SetterProp::param`]"] - Param, - #[doc = "Represents [`SetterProp::body`]"] - Body, + #[doc = "Represents [`SetterProp::function`]"] + Function, } impl SimpleAssignTargetField { #[inline(always)] @@ -140924,6 +142609,8 @@ pub mod fields { pub enum SwitchStmtField { #[doc = "Represents [`SwitchStmt::span`]"] Span, + #[doc = "Represents [`SwitchStmt::body_ctxt`]"] + BodyCtxt, #[doc = "Represents [`SwitchStmt::discriminant`]"] Discriminant, #[doc = "Represents [`SwitchStmt::cases`]"] @@ -142020,6 +143707,23 @@ pub mod fields { #[doc = "Represents [`TsSetterSignature::param`]"] Param, } + impl TsThisParamField { + pub(crate) fn set_index(&mut self, index: usize) { + match self { + _ => swc_visit::wrong_ast_path(), + } + } + } + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] + pub enum TsThisParamField { + #[doc = "Represents [`TsThisParam::span`]"] + Span, + #[doc = "Represents [`TsThisParam::this_span`]"] + ThisSpan, + #[doc = "Represents [`TsThisParam::type_ann`]"] + TypeAnn, + } impl TsThisTypeField { pub(crate) fn set_index(&mut self, index: usize) { match self { @@ -142677,6 +144381,7 @@ pub mod fields { ArrayLit(ArrayLitField), ArrayPat(ArrayPatField), ArrowExpr(ArrowExprField), + ArrowFunctionBody(ArrowFunctionBodyField), AssignExpr(AssignExprField), AssignOp(AssignOpField), AssignPat(AssignPatField), @@ -142691,7 +144396,6 @@ pub mod fields { BinaryOp(BinaryOpField), BindingIdent(BindingIdentField), BlockStmt(BlockStmtField), - BlockStmtOrExpr(BlockStmtOrExprField), Bool(BoolField), BreakStmt(BreakStmtField), CallExpr(CallExprField), @@ -142731,6 +144435,7 @@ pub mod fields { ForOfStmt(ForOfStmtField), ForStmt(ForStmtField), Function(FunctionField), + FunctionBody(FunctionBodyField), GetterProp(GetterPropField), Ident(IdentField), IdentName(IdentNameField), @@ -142875,6 +144580,7 @@ pub mod fields { TsRestType(TsRestTypeField), TsSatisfiesExpr(TsSatisfiesExprField), TsSetterSignature(TsSetterSignatureField), + TsThisParam(TsThisParamField), TsThisType(TsThisTypeField), TsThisTypeOrIdent(TsThisTypeOrIdentField), TsTplLitType(TsTplLitTypeField), @@ -142918,6 +144624,7 @@ pub mod fields { Self::ArrayLit(v) => v.set_index(index), Self::ArrayPat(v) => v.set_index(index), Self::ArrowExpr(v) => v.set_index(index), + Self::ArrowFunctionBody(v) => v.set_index(index), Self::AssignExpr(v) => v.set_index(index), Self::AssignOp(v) => v.set_index(index), Self::AssignPat(v) => v.set_index(index), @@ -142932,7 +144639,6 @@ pub mod fields { Self::BinaryOp(v) => v.set_index(index), Self::BindingIdent(v) => v.set_index(index), Self::BlockStmt(v) => v.set_index(index), - Self::BlockStmtOrExpr(v) => v.set_index(index), Self::Bool(v) => v.set_index(index), Self::BreakStmt(v) => v.set_index(index), Self::CallExpr(v) => v.set_index(index), @@ -142972,6 +144678,7 @@ pub mod fields { Self::ForOfStmt(v) => v.set_index(index), Self::ForStmt(v) => v.set_index(index), Self::Function(v) => v.set_index(index), + Self::FunctionBody(v) => v.set_index(index), Self::GetterProp(v) => v.set_index(index), Self::Ident(v) => v.set_index(index), Self::IdentName(v) => v.set_index(index), @@ -143116,6 +144823,7 @@ pub mod fields { Self::TsRestType(v) => v.set_index(index), Self::TsSatisfiesExpr(v) => v.set_index(index), Self::TsSetterSignature(v) => v.set_index(index), + Self::TsThisParam(v) => v.set_index(index), Self::TsThisType(v) => v.set_index(index), Self::TsThisTypeOrIdent(v) => v.set_index(index), Self::TsTplLitType(v) => v.set_index(index), @@ -143159,6 +144867,7 @@ pub mod fields { ArrayLit(&'ast ArrayLit, ArrayLitField), ArrayPat(&'ast ArrayPat, ArrayPatField), ArrowExpr(&'ast ArrowExpr, ArrowExprField), + ArrowFunctionBody(&'ast ArrowFunctionBody, ArrowFunctionBodyField), AssignExpr(&'ast AssignExpr, AssignExprField), AssignOp(&'ast AssignOp, AssignOpField), AssignPat(&'ast AssignPat, AssignPatField), @@ -143173,7 +144882,6 @@ pub mod fields { BinaryOp(&'ast BinaryOp, BinaryOpField), BindingIdent(&'ast BindingIdent, BindingIdentField), BlockStmt(&'ast BlockStmt, BlockStmtField), - BlockStmtOrExpr(&'ast BlockStmtOrExpr, BlockStmtOrExprField), Bool(&'ast Bool, BoolField), BreakStmt(&'ast BreakStmt, BreakStmtField), CallExpr(&'ast CallExpr, CallExprField), @@ -143216,6 +144924,7 @@ pub mod fields { ForOfStmt(&'ast ForOfStmt, ForOfStmtField), ForStmt(&'ast ForStmt, ForStmtField), Function(&'ast Function, FunctionField), + FunctionBody(&'ast FunctionBody, FunctionBodyField), GetterProp(&'ast GetterProp, GetterPropField), Ident(&'ast Ident, IdentField), IdentName(&'ast IdentName, IdentNameField), @@ -143363,6 +145072,7 @@ pub mod fields { TsRestType(&'ast TsRestType, TsRestTypeField), TsSatisfiesExpr(&'ast TsSatisfiesExpr, TsSatisfiesExprField), TsSetterSignature(&'ast TsSetterSignature, TsSetterSignatureField), + TsThisParam(&'ast TsThisParam, TsThisParamField), TsThisType(&'ast TsThisType, TsThisTypeField), TsThisTypeOrIdent(&'ast TsThisTypeOrIdent, TsThisTypeOrIdentField), TsTplLitType(&'ast TsTplLitType, TsTplLitTypeField), @@ -143418,6 +145128,7 @@ pub mod fields { Self::ArrayLit(_, __field_kind) => __field_kind.set_index(index), Self::ArrayPat(_, __field_kind) => __field_kind.set_index(index), Self::ArrowExpr(_, __field_kind) => __field_kind.set_index(index), + Self::ArrowFunctionBody(_, __field_kind) => __field_kind.set_index(index), Self::AssignExpr(_, __field_kind) => __field_kind.set_index(index), Self::AssignOp(_, __field_kind) => __field_kind.set_index(index), Self::AssignPat(_, __field_kind) => __field_kind.set_index(index), @@ -143432,7 +145143,6 @@ pub mod fields { Self::BinaryOp(_, __field_kind) => __field_kind.set_index(index), Self::BindingIdent(_, __field_kind) => __field_kind.set_index(index), Self::BlockStmt(_, __field_kind) => __field_kind.set_index(index), - Self::BlockStmtOrExpr(_, __field_kind) => __field_kind.set_index(index), Self::Bool(_, __field_kind) => __field_kind.set_index(index), Self::BreakStmt(_, __field_kind) => __field_kind.set_index(index), Self::CallExpr(_, __field_kind) => __field_kind.set_index(index), @@ -143472,6 +145182,7 @@ pub mod fields { Self::ForOfStmt(_, __field_kind) => __field_kind.set_index(index), Self::ForStmt(_, __field_kind) => __field_kind.set_index(index), Self::Function(_, __field_kind) => __field_kind.set_index(index), + Self::FunctionBody(_, __field_kind) => __field_kind.set_index(index), Self::GetterProp(_, __field_kind) => __field_kind.set_index(index), Self::Ident(_, __field_kind) => __field_kind.set_index(index), Self::IdentName(_, __field_kind) => __field_kind.set_index(index), @@ -143616,6 +145327,7 @@ pub mod fields { Self::TsRestType(_, __field_kind) => __field_kind.set_index(index), Self::TsSatisfiesExpr(_, __field_kind) => __field_kind.set_index(index), Self::TsSetterSignature(_, __field_kind) => __field_kind.set_index(index), + Self::TsThisParam(_, __field_kind) => __field_kind.set_index(index), Self::TsThisType(_, __field_kind) => __field_kind.set_index(index), Self::TsThisTypeOrIdent(_, __field_kind) => __field_kind.set_index(index), Self::TsTplLitType(_, __field_kind) => __field_kind.set_index(index), @@ -143662,6 +145374,9 @@ pub mod fields { Self::ArrayLit(_, __field_kind) => AstParentKind::ArrayLit(*__field_kind), Self::ArrayPat(_, __field_kind) => AstParentKind::ArrayPat(*__field_kind), Self::ArrowExpr(_, __field_kind) => AstParentKind::ArrowExpr(*__field_kind), + Self::ArrowFunctionBody(_, __field_kind) => { + AstParentKind::ArrowFunctionBody(*__field_kind) + } Self::AssignExpr(_, __field_kind) => AstParentKind::AssignExpr(*__field_kind), Self::AssignOp(_, __field_kind) => AstParentKind::AssignOp(*__field_kind), Self::AssignPat(_, __field_kind) => AstParentKind::AssignPat(*__field_kind), @@ -143678,9 +145393,6 @@ pub mod fields { Self::BinaryOp(_, __field_kind) => AstParentKind::BinaryOp(*__field_kind), Self::BindingIdent(_, __field_kind) => AstParentKind::BindingIdent(*__field_kind), Self::BlockStmt(_, __field_kind) => AstParentKind::BlockStmt(*__field_kind), - Self::BlockStmtOrExpr(_, __field_kind) => { - AstParentKind::BlockStmtOrExpr(*__field_kind) - } Self::Bool(_, __field_kind) => AstParentKind::Bool(*__field_kind), Self::BreakStmt(_, __field_kind) => AstParentKind::BreakStmt(*__field_kind), Self::CallExpr(_, __field_kind) => AstParentKind::CallExpr(*__field_kind), @@ -143734,6 +145446,7 @@ pub mod fields { Self::ForOfStmt(_, __field_kind) => AstParentKind::ForOfStmt(*__field_kind), Self::ForStmt(_, __field_kind) => AstParentKind::ForStmt(*__field_kind), Self::Function(_, __field_kind) => AstParentKind::Function(*__field_kind), + Self::FunctionBody(_, __field_kind) => AstParentKind::FunctionBody(*__field_kind), Self::GetterProp(_, __field_kind) => AstParentKind::GetterProp(*__field_kind), Self::Ident(_, __field_kind) => AstParentKind::Ident(*__field_kind), Self::IdentName(_, __field_kind) => AstParentKind::IdentName(*__field_kind), @@ -143978,6 +145691,7 @@ pub mod fields { Self::TsSetterSignature(_, __field_kind) => { AstParentKind::TsSetterSignature(*__field_kind) } + Self::TsThisParam(_, __field_kind) => AstParentKind::TsThisParam(*__field_kind), Self::TsThisType(_, __field_kind) => AstParentKind::TsThisType(*__field_kind), Self::TsThisTypeOrIdent(_, __field_kind) => { AstParentKind::TsThisTypeOrIdent(*__field_kind) @@ -144058,6 +145772,11 @@ impl<'ast> From<&'ast ArrowExpr> for NodeRef<'ast> { NodeRef::ArrowExpr(node) } } +impl<'ast> From<&'ast ArrowFunctionBody> for NodeRef<'ast> { + fn from(node: &'ast ArrowFunctionBody) -> Self { + NodeRef::ArrowFunctionBody(node) + } +} impl<'ast> From<&'ast AssignExpr> for NodeRef<'ast> { fn from(node: &'ast AssignExpr) -> Self { NodeRef::AssignExpr(node) @@ -144128,11 +145847,6 @@ impl<'ast> From<&'ast BlockStmt> for NodeRef<'ast> { NodeRef::BlockStmt(node) } } -impl<'ast> From<&'ast BlockStmtOrExpr> for NodeRef<'ast> { - fn from(node: &'ast BlockStmtOrExpr) -> Self { - NodeRef::BlockStmtOrExpr(node) - } -} impl<'ast> From<&'ast Bool> for NodeRef<'ast> { fn from(node: &'ast Bool) -> Self { NodeRef::Bool(node) @@ -144328,6 +146042,11 @@ impl<'ast> From<&'ast Function> for NodeRef<'ast> { NodeRef::Function(node) } } +impl<'ast> From<&'ast FunctionBody> for NodeRef<'ast> { + fn from(node: &'ast FunctionBody) -> Self { + NodeRef::FunctionBody(node) + } +} impl<'ast> From<&'ast GetterProp> for NodeRef<'ast> { fn from(node: &'ast GetterProp) -> Self { NodeRef::GetterProp(node) @@ -145048,6 +146767,11 @@ impl<'ast> From<&'ast TsSetterSignature> for NodeRef<'ast> { NodeRef::TsSetterSignature(node) } } +impl<'ast> From<&'ast TsThisParam> for NodeRef<'ast> { + fn from(node: &'ast TsThisParam) -> Self { + NodeRef::TsThisParam(node) + } +} impl<'ast> From<&'ast TsThisType> for NodeRef<'ast> { fn from(node: &'ast TsThisType) -> Self { NodeRef::TsThisType(node) @@ -145224,6 +146948,7 @@ pub enum NodeRef<'ast> { ArrayLit(&'ast ArrayLit), ArrayPat(&'ast ArrayPat), ArrowExpr(&'ast ArrowExpr), + ArrowFunctionBody(&'ast ArrowFunctionBody), AssignExpr(&'ast AssignExpr), AssignOp(&'ast AssignOp), AssignPat(&'ast AssignPat), @@ -145238,7 +146963,6 @@ pub enum NodeRef<'ast> { BinaryOp(&'ast BinaryOp), BindingIdent(&'ast BindingIdent), BlockStmt(&'ast BlockStmt), - BlockStmtOrExpr(&'ast BlockStmtOrExpr), Bool(&'ast Bool), BreakStmt(&'ast BreakStmt), CallExpr(&'ast CallExpr), @@ -145278,6 +147002,7 @@ pub enum NodeRef<'ast> { ForOfStmt(&'ast ForOfStmt), ForStmt(&'ast ForStmt), Function(&'ast Function), + FunctionBody(&'ast FunctionBody), GetterProp(&'ast GetterProp), Ident(&'ast Ident), IdentName(&'ast IdentName), @@ -145422,6 +147147,7 @@ pub enum NodeRef<'ast> { TsRestType(&'ast TsRestType), TsSatisfiesExpr(&'ast TsSatisfiesExpr), TsSetterSignature(&'ast TsSetterSignature), + TsThisParam(&'ast TsThisParam), TsThisType(&'ast TsThisType), TsThisTypeOrIdent(&'ast TsThisTypeOrIdent), TsTplLitType(&'ast TsTplLitType), @@ -145495,7 +147221,7 @@ impl<'ast> NodeRef<'ast> { ) .chain({ let item = &*node.body; - ::std::iter::once(NodeRef::BlockStmtOrExpr(&item)) + ::std::iter::once(NodeRef::ArrowFunctionBody(&item)) }) .chain(node.type_params.iter().flat_map(|item| { let item = &*item; @@ -145507,6 +147233,13 @@ impl<'ast> NodeRef<'ast> { })); Box::new(iterator) } + NodeRef::ArrowFunctionBody(node) => match node { + ArrowFunctionBody::FunctionBody(v0) => { + Box::new(::std::iter::once(NodeRef::FunctionBody(v0))) + } + ArrowFunctionBody::Expr(v0) => Box::new(::std::iter::once(NodeRef::Expr(v0))), + _ => Box::new(::std::iter::empty::>()), + }, NodeRef::AssignExpr(node) => { let iterator = ::std::iter::empty::>() .chain(::std::iter::once(NodeRef::AssignOp(&node.op))) @@ -145630,13 +147363,6 @@ impl<'ast> NodeRef<'ast> { ); Box::new(iterator) } - NodeRef::BlockStmtOrExpr(node) => match node { - BlockStmtOrExpr::BlockStmt(v0) => { - Box::new(::std::iter::once(NodeRef::BlockStmt(v0))) - } - BlockStmtOrExpr::Expr(v0) => Box::new(::std::iter::once(NodeRef::Expr(v0))), - _ => Box::new(::std::iter::empty::>()), - }, NodeRef::Bool(node) => { let iterator = ::std::iter::empty::>(); Box::new(iterator) @@ -145827,7 +147553,7 @@ impl<'ast> NodeRef<'ast> { .chain( node.body .iter() - .flat_map(|item| ::std::iter::once(NodeRef::BlockStmt(&item))), + .flat_map(|item| ::std::iter::once(NodeRef::FunctionBody(&item))), ) .chain( node.accessibility @@ -146091,6 +147817,10 @@ impl<'ast> NodeRef<'ast> { } NodeRef::Function(node) => { let iterator = ::std::iter::empty::>() + .chain(node.this_param.iter().flat_map(|item| { + let item = &*item; + ::std::iter::once(NodeRef::TsThisParam(&item)) + })) .chain( node.params .iter() @@ -146104,7 +147834,7 @@ impl<'ast> NodeRef<'ast> { .chain( node.body .iter() - .flat_map(|item| ::std::iter::once(NodeRef::BlockStmt(&item))), + .flat_map(|item| ::std::iter::once(NodeRef::FunctionBody(&item))), ) .chain(node.type_params.iter().flat_map(|item| { let item = &*item; @@ -146116,18 +147846,21 @@ impl<'ast> NodeRef<'ast> { })); Box::new(iterator) } + NodeRef::FunctionBody(node) => { + let iterator = ::std::iter::empty::>().chain( + node.stmts + .iter() + .flat_map(|item| ::std::iter::once(NodeRef::Stmt(&item))), + ); + Box::new(iterator) + } NodeRef::GetterProp(node) => { let iterator = ::std::iter::empty::>() .chain(::std::iter::once(NodeRef::PropName(&node.key))) - .chain(node.type_ann.iter().flat_map(|item| { - let item = &*item; - ::std::iter::once(NodeRef::TsTypeAnn(&item)) - })) - .chain( - node.body - .iter() - .flat_map(|item| ::std::iter::once(NodeRef::BlockStmt(&item))), - ); + .chain({ + let item = &*node.function; + ::std::iter::once(NodeRef::Function(&item)) + }); Box::new(iterator) } NodeRef::Ident(node) => { @@ -146767,20 +148500,10 @@ impl<'ast> NodeRef<'ast> { NodeRef::SetterProp(node) => { let iterator = ::std::iter::empty::>() .chain(::std::iter::once(NodeRef::PropName(&node.key))) - .chain( - node.this_param - .iter() - .flat_map(|item| ::std::iter::once(NodeRef::Pat(&item))), - ) .chain({ - let item = &*node.param; - ::std::iter::once(NodeRef::Pat(&item)) - }) - .chain( - node.body - .iter() - .flat_map(|item| ::std::iter::once(NodeRef::BlockStmt(&item))), - ); + let item = &*node.function; + ::std::iter::once(NodeRef::Function(&item)) + }); Box::new(iterator) } NodeRef::SimpleAssignTarget(node) => match node { @@ -147471,6 +149194,15 @@ impl<'ast> NodeRef<'ast> { .chain(::std::iter::once(NodeRef::TsFnParam(&node.param))); Box::new(iterator) } + NodeRef::TsThisParam(node) => { + let iterator = ::std::iter::empty::>().chain( + node.type_ann.iter().flat_map(|item| { + let item = &*item; + ::std::iter::once(NodeRef::TsTypeAnn(&item)) + }), + ); + Box::new(iterator) + } NodeRef::TsThisType(node) => { let iterator = ::std::iter::empty::>(); Box::new(iterator) diff --git a/deps/swc/crates/swc_ecmascript/Cargo.toml b/deps/swc/crates/swc_ecmascript/Cargo.toml index 7268a1ad7..53fb51351 100644 --- a/deps/swc/crates/swc_ecmascript/Cargo.toml +++ b/deps/swc/crates/swc_ecmascript/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ecmascript" repository = { workspace = true } -version = "64.0.0" +version = "70.0.0" [package.metadata.docs.rs] all-features = true @@ -26,7 +26,6 @@ minifier = ["swc_ecma_minifier"] parser = ["swc_ecma_parser"] preset_env = ["swc_ecma_preset_env"] quote = ["swc_ecma_quote"] -rkyv-impl = ["swc_ecma_ast/rkyv-impl"] transforms = ["swc_ecma_transforms"] utils = ["swc_ecma_utils"] visit = ["swc_ecma_visit"] @@ -41,15 +40,15 @@ react = ["swc_ecma_transforms/react"] typescript = ["typescript-parser", "swc_ecma_transforms/typescript"] [dependencies] -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen", optional = true } -swc_ecma_minifier = { version = "56.0.1", path = "../swc_ecma_minifier", optional = true } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", optional = true, default-features = false } -swc_ecma_preset_env = { version = "57.0.0", path = "../swc_ecma_preset_env", optional = true } -swc_ecma_quote = { version = "41.0.0", path = "../swc_ecma_quote", optional = true } -swc_ecma_transforms = { version = "56.0.0", path = "../swc_ecma_transforms", optional = true } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils", optional = true } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit", optional = true } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen", optional = true } +swc_ecma_minifier = { version = "61.0.0", path = "../swc_ecma_minifier", optional = true } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", optional = true, default-features = false } +swc_ecma_preset_env = { version = "63.0.0", path = "../swc_ecma_preset_env", optional = true } +swc_ecma_quote = { version = "45.0.0", path = "../swc_ecma_quote", optional = true } +swc_ecma_transforms = { version = "62.0.0", path = "../swc_ecma_transforms", optional = true } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils", optional = true } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit", optional = true } [dev-dependencies] par-core = { workspace = true, features = ["chili"] } diff --git a/deps/swc/crates/swc_error_reporters/Cargo.toml b/deps/swc/crates/swc_error_reporters/Cargo.toml index be462d8bb..8b8b26288 100644 --- a/deps/swc/crates/swc_error_reporters/Cargo.toml +++ b/deps/swc/crates/swc_error_reporters/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_error_reporters" repository = { workspace = true } -version = "25.0.0" +version = "28.0.0" [lib] bench = false @@ -17,6 +17,6 @@ miette = { workspace = true, features = ["fancy-no-syscall"] } once_cell = { workspace = true } serde = { workspace = true } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "concurrent", ] } diff --git a/deps/swc/crates/swc_estree_ast/Cargo.toml b/deps/swc/crates/swc_estree_ast/Cargo.toml index a33ebe46f..9e56d35fa 100644 --- a/deps/swc/crates/swc_estree_ast/Cargo.toml +++ b/deps/swc/crates/swc_estree_ast/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" license = { workspace = true } name = "swc_estree_ast" repository = "https://github.com/swc-project/swc.git" -version = "23.0.0" +version = "26.0.0" [package.metadata.docs.rs] all-features = true @@ -26,5 +26,5 @@ serde = { workspace = true, features = ["derive"], optional = true } serde_json = { workspace = true } better_scoped_tls = { version = "1.0.1", path = "../better_scoped_tls" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } diff --git a/deps/swc/crates/swc_estree_ast/src/jsx.rs b/deps/swc/crates/swc_estree_ast/src/jsx.rs index 84663208c..75b5e05cf 100644 --- a/deps/swc/crates/swc_estree_ast/src/jsx.rs +++ b/deps/swc/crates/swc_estree_ast/src/jsx.rs @@ -1,4 +1,4 @@ -use swc_atoms::Atom; +use swc_atoms::{Atom, Wtf8Atom}; use swc_common::ast_serde; use crate::{ @@ -219,7 +219,7 @@ pub struct JSXSpreadAttribute { pub struct JSXText { #[serde(flatten)] pub base: BaseNode, - pub value: Atom, + pub value: Wtf8Atom, } #[derive(Debug, Clone, PartialEq)] diff --git a/deps/swc/crates/swc_estree_compat/Cargo.toml b/deps/swc/crates/swc_estree_compat/Cargo.toml index 52438a4e6..bf586608f 100644 --- a/deps/swc/crates/swc_estree_compat/Cargo.toml +++ b/deps/swc/crates/swc_estree_compat/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_estree_compat" repository = { workspace = true } -version = "44.0.0" +version = "48.0.0" [package.metadata.docs.rs] all-features = true @@ -26,29 +26,29 @@ copyless = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "sourcemap", "tty-emitter", ] } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } -swc_estree_ast = { version = "23.0.0", path = "../swc_estree_ast" } -swc_node_comments = { version = "24.0.0", path = "../swc_node_comments/" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } +swc_estree_ast = { version = "26.0.0", path = "../swc_estree_ast" } +swc_node_comments = { version = "27.0.0", path = "../swc_node_comments/" } [dev-dependencies] codspeed-criterion-compat = { workspace = true } pretty_assertions = { workspace = true } -swc = { version = "69.0.0", path = "../swc", default-features = false } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms = { version = "56.0.0", path = "../swc_ecma_transforms/" } -testing = { version = "24.0.1", path = "../testing" } +swc = { version = "75.0.0", path = "../swc", default-features = false } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms = { version = "62.0.0", path = "../swc_ecma_transforms/" } +testing = { version = "27.0.0", path = "../testing" } walkdir = { workspace = true } [[bench]] diff --git a/deps/swc/crates/swc_estree_compat/src/babelify/class.rs b/deps/swc/crates/swc_estree_compat/src/babelify/class.rs index f9b651254..6c654fa74 100644 --- a/deps/swc/crates/swc_estree_compat/src/babelify/class.rs +++ b/deps/swc/crates/swc_estree_compat/src/babelify/class.rs @@ -10,7 +10,9 @@ use swc_estree_ast::{ StaticBlock as BabelStaticBlock, }; -use crate::babelify::{extract_class_body_span, Babelify, Context}; +use crate::babelify::{ + extract_class_body_span, function::babelify_function_params, Babelify, Context, +}; impl Babelify for Class { type Output = ClassExpression; @@ -118,6 +120,8 @@ impl Babelify for ClassMethod { type Output = BabelClassMethod; fn babelify(self, ctx: &Context) -> Self::Output { + let params = babelify_function_params(self.function.this_param, self.function.params, ctx); + BabelClassMethod { base: ctx.base(self.span), key: self.key.babelify(ctx), @@ -127,7 +131,7 @@ impl Babelify for ClassMethod { accessibility: self.accessibility.map(|access| access.babelify(ctx)), is_abstract: Some(self.is_abstract), optional: Some(self.is_optional), - params: self.function.params.babelify(ctx), + params, body: self.function.body.unwrap().babelify(ctx), generator: Some(self.function.is_generator), is_async: Some(self.function.is_async), @@ -146,6 +150,8 @@ impl Babelify for PrivateMethod { type Output = ClassPrivateMethod; fn babelify(self, ctx: &Context) -> Self::Output { + let params = babelify_function_params(self.function.this_param, self.function.params, ctx); + ClassPrivateMethod { base: ctx.base(self.span), key: self.key.babelify(ctx), @@ -155,7 +161,7 @@ impl Babelify for PrivateMethod { accessibility: self.accessibility.map(|access| access.babelify(ctx)), is_abstract: Some(self.is_abstract), optional: Some(self.is_optional), - params: self.function.params.babelify(ctx), + params, body: self.function.body.unwrap().babelify(ctx), generator: Some(self.function.is_generator), is_async: Some(self.function.is_async), diff --git a/deps/swc/crates/swc_estree_compat/src/babelify/expr.rs b/deps/swc/crates/swc_estree_compat/src/babelify/expr.rs index 55dab6308..e72ac6789 100644 --- a/deps/swc/crates/swc_estree_compat/src/babelify/expr.rs +++ b/deps/swc/crates/swc_estree_compat/src/babelify/expr.rs @@ -3,8 +3,8 @@ use serde::{Deserialize, Serialize}; use swc_atoms::atom; use swc_common::{BytePos, Span, Spanned}; use swc_ecma_ast::{ - ArrayLit, ArrowExpr, AssignExpr, AssignTarget, AssignTargetPat, AwaitExpr, BinExpr, BinaryOp, - BlockStmtOrExpr, CallExpr, Callee, ClassExpr, CondExpr, Expr, ExprOrSpread, FnExpr, Ident, + ArrayLit, ArrowExpr, ArrowFunctionBody, AssignExpr, AssignTarget, AssignTargetPat, AwaitExpr, + BinExpr, BinaryOp, CallExpr, Callee, ClassExpr, CondExpr, Expr, ExprOrSpread, FnExpr, Ident, Import, Lit, MemberExpr, MemberProp, MetaPropExpr, MetaPropKind, NewExpr, ObjectLit, ParenExpr, PropOrSpread, SeqExpr, SimpleAssignTarget, SpreadElement, Super, SuperProp, SuperPropExpr, TaggedTpl, ThisExpr, Tpl, TplElement, UnaryExpr, UpdateExpr, YieldExpr, @@ -723,13 +723,13 @@ impl Babelify for ExprOrSpread { } } -impl Babelify for BlockStmtOrExpr { +impl Babelify for ArrowFunctionBody { type Output = ArrowFuncExprBody; fn babelify(self, ctx: &Context) -> Self::Output { match self { - BlockStmtOrExpr::BlockStmt(b) => ArrowFuncExprBody::Block(b.babelify(ctx)), - BlockStmtOrExpr::Expr(e) => { + ArrowFunctionBody::FunctionBody(b) => ArrowFuncExprBody::Block(b.babelify(ctx)), + ArrowFunctionBody::Expr(e) => { ArrowFuncExprBody::Expr(Box::alloc().init(e.babelify(ctx).into())) } #[cfg(swc_ast_unknown)] diff --git a/deps/swc/crates/swc_estree_compat/src/babelify/function.rs b/deps/swc/crates/swc_estree_compat/src/babelify/function.rs index 8dc116f1c..ce96f7d3d 100644 --- a/deps/swc/crates/swc_estree_compat/src/babelify/function.rs +++ b/deps/swc/crates/swc_estree_compat/src/babelify/function.rs @@ -1,5 +1,5 @@ use copyless::BoxHelper; -use swc_ecma_ast::{Function, Param, ParamOrTsParamProp, Pat}; +use swc_ecma_ast::{BindingIdent, Function, Ident, Param, ParamOrTsParamProp, Pat, TsThisParam}; use swc_estree_ast::{ ArrayPattern, AssignmentPattern, FunctionExpression, Identifier, ObjectPattern, Param as BabelParam, Pattern, RestElement, @@ -7,13 +7,39 @@ use swc_estree_ast::{ use crate::babelify::{Babelify, Context}; +/// Converts a `this` parameter without widening the identifier's token span. +fn babelify_ts_this_param(param: TsThisParam, ctx: &Context) -> BabelParam { + BabelParam::Id( + BindingIdent { + id: Ident::new_no_ctxt("this".into(), param.this_span), + type_ann: param.type_ann, + } + .babelify(ctx), + ) +} + +pub(super) fn babelify_function_params( + this_param: Option>, + params: Vec, + ctx: &Context, +) -> Vec { + let mut output = Vec::with_capacity(params.len() + usize::from(this_param.is_some())); + if let Some(this_param) = this_param { + output.push(babelify_ts_this_param(*this_param, ctx)); + } + output.extend(params.into_iter().map(|param| param.babelify(ctx))); + output +} + impl Babelify for Function { type Output = FunctionExpression; fn babelify(self, ctx: &Context) -> Self::Output { + let params = babelify_function_params(self.this_param, self.params, ctx); + FunctionExpression { base: ctx.base(self.span), - params: self.params.babelify(ctx), + params, body: self.body.unwrap().babelify(ctx), generator: Some(self.is_generator), is_async: Some(self.is_async), diff --git a/deps/swc/crates/swc_estree_compat/src/babelify/prop.rs b/deps/swc/crates/swc_estree_compat/src/babelify/prop.rs index d7e212899..946557c7c 100644 --- a/deps/swc/crates/swc_estree_compat/src/babelify/prop.rs +++ b/deps/swc/crates/swc_estree_compat/src/babelify/prop.rs @@ -1,7 +1,8 @@ use copyless::BoxHelper; use swc_common::Spanned; use swc_ecma_ast::{ - AssignProp, ComputedPropName, GetterProp, KeyValueProp, MethodProp, Prop, PropName, SetterProp, + AssignProp, ComputedPropName, Function, GetterProp, KeyValueProp, MethodProp, Prop, PropName, + SetterProp, }; use swc_estree_ast::{ AssignmentPattern, AssignmentPatternLeft, Expression, FunctionExpression, ObjectKey, @@ -10,6 +11,29 @@ use swc_estree_ast::{ use crate::babelify::{Babelify, Context}; +fn babelify_object_method( + key: PropName, + function: Box, + kind: ObjectMethodKind, + ctx: &Context, +) -> ObjectMethod { + let func: FunctionExpression = function.babelify(ctx); + + ObjectMethod { + base: func.base, + kind, + key: key.babelify(ctx), + params: func.params, + body: func.body, + return_type: func.return_type, + computed: Default::default(), + generator: func.generator, + is_async: func.is_async, + decorator: Default::default(), + type_parameters: func.type_parameters, + } +} + impl Babelify for Prop { type Output = ObjectMember; @@ -73,21 +97,7 @@ impl Babelify for GetterProp { type Output = ObjectMethod; fn babelify(self, ctx: &Context) -> Self::Output { - ObjectMethod { - base: ctx.base(self.span), - kind: ObjectMethodKind::Get, - key: self.key.babelify(ctx), - return_type: self - .type_ann - .map(|ann| Box::alloc().init(ann.babelify(ctx).into())), - body: self.body.unwrap().babelify(ctx), - params: Default::default(), - computed: Default::default(), - generator: Default::default(), - is_async: Default::default(), - decorator: Default::default(), - type_parameters: Default::default(), - } + babelify_object_method(self.key, self.function, ObjectMethodKind::Get, ctx) } } @@ -95,19 +105,7 @@ impl Babelify for SetterProp { type Output = ObjectMethod; fn babelify(self, ctx: &Context) -> Self::Output { - ObjectMethod { - base: ctx.base(self.span), - kind: ObjectMethodKind::Set, - key: self.key.babelify(ctx), - params: vec![self.param.babelify(ctx).into()], - body: self.body.unwrap().babelify(ctx), - return_type: Default::default(), - computed: Default::default(), - generator: Default::default(), - is_async: Default::default(), - decorator: Default::default(), - type_parameters: Default::default(), - } + babelify_object_method(self.key, self.function, ObjectMethodKind::Set, ctx) } } @@ -115,20 +113,7 @@ impl Babelify for MethodProp { type Output = ObjectMethod; fn babelify(self, ctx: &Context) -> Self::Output { - let func: FunctionExpression = self.function.babelify(ctx); - ObjectMethod { - base: func.base, - kind: ObjectMethodKind::Method, - key: self.key.babelify(ctx), - params: func.params, - body: func.body, - computed: Default::default(), - generator: func.generator, - is_async: func.is_async, - decorator: Default::default(), - return_type: func.return_type, - type_parameters: func.type_parameters, - } + babelify_object_method(self.key, self.function, ObjectMethodKind::Method, ctx) } } diff --git a/deps/swc/crates/swc_estree_compat/src/babelify/stmt.rs b/deps/swc/crates/swc_estree_compat/src/babelify/stmt.rs index 4389e4bea..7318daa1a 100644 --- a/deps/swc/crates/swc_estree_compat/src/babelify/stmt.rs +++ b/deps/swc/crates/swc_estree_compat/src/babelify/stmt.rs @@ -1,8 +1,9 @@ use copyless::BoxHelper; use swc_ecma_ast::{ BlockStmt, BreakStmt, CatchClause, ContinueStmt, DebuggerStmt, Decl, DoWhileStmt, EmptyStmt, - ExprStmt, ForHead, ForInStmt, ForOfStmt, ForStmt, IfStmt, LabeledStmt, ReturnStmt, Stmt, - SwitchCase, SwitchStmt, ThrowStmt, TryStmt, VarDeclOrExpr, WhileStmt, WithStmt, + ExprStmt, ForHead, ForInStmt, ForOfStmt, ForStmt, FunctionBody, IfStmt, LabeledStmt, + ReturnStmt, Stmt, SwitchCase, SwitchStmt, ThrowStmt, TryStmt, VarDeclOrExpr, WhileStmt, + WithStmt, }; use swc_estree_ast::{ BlockStatement, BreakStatement, CatchClause as BabelCatchClause, ContinueStatement, @@ -26,6 +27,18 @@ impl Babelify for BlockStmt { } } +impl Babelify for FunctionBody { + type Output = BlockStatement; + + fn babelify(self, ctx: &Context) -> Self::Output { + BlockStatement { + base: ctx.base(self.span), + body: self.stmts.babelify(ctx), + directives: Default::default(), + } + } +} + impl Babelify for Stmt { type Output = Statement; diff --git a/deps/swc/crates/swc_estree_compat/src/swcify/class.rs b/deps/swc/crates/swc_estree_compat/src/swcify/class.rs index 746d2d5fb..e85b2ee4b 100644 --- a/deps/swc/crates/swc_estree_compat/src/swcify/class.rs +++ b/deps/swc/crates/swc_estree_compat/src/swcify/class.rs @@ -8,7 +8,11 @@ use swc_estree_ast::{ }; use super::Context; -use crate::swcify::Swcify; +use crate::swcify::{ + function::{swcify_function_params, SwcifiedFunctionParams}, + stmt::swcify_function_body, + Swcify, +}; impl Swcify for ClassBody { type Output = Vec; @@ -40,14 +44,18 @@ impl Swcify for swc_estree_ast::ClassMethod { fn swcify(self, ctx: &Context) -> Self::Output { match self.kind.unwrap_or(ClassMethodKind::Method) { ClassMethodKind::Get | ClassMethodKind::Set | ClassMethodKind::Method => { + let SwcifiedFunctionParams { this_param, params } = + swcify_function_params(self.params, ctx); + swc_ecma_ast::ClassMethod { span: ctx.span(&self.base), key: self.key.swcify(ctx), function: Function { - params: self.params.swcify(ctx), + this_param, + params, decorators: self.decorators.swcify(ctx).unwrap_or_default(), span: ctx.span(&self.base), - body: Some(self.body.swcify(ctx)), + body: Some(swcify_function_body(self.body, ctx)), is_generator: self.generator.unwrap_or_default(), is_async: self.is_async.unwrap_or_default(), type_params: self.type_parameters.swcify(ctx).flatten().map(Box::new), @@ -83,7 +91,7 @@ impl Swcify for swc_estree_ast::ClassMethod { .map(|v| v.swcify(ctx)) .map(ParamOrTsParamProp::Param) .collect(), - body: Some(self.body.swcify(ctx)), + body: Some(swcify_function_body(self.body, ctx)), accessibility: self.accessibility.swcify(ctx), is_optional: self.optional.unwrap_or_default(), ..Default::default() @@ -97,14 +105,18 @@ impl Swcify for swc_estree_ast::ClassPrivateMethod { type Output = swc_ecma_ast::PrivateMethod; fn swcify(self, ctx: &Context) -> Self::Output { + let SwcifiedFunctionParams { this_param, params } = + swcify_function_params(self.params, ctx); + swc_ecma_ast::PrivateMethod { span: ctx.span(&self.base), key: self.key.swcify(ctx), function: Function { - params: self.params.swcify(ctx), + this_param, + params, decorators: self.decorators.swcify(ctx).unwrap_or_default(), span: ctx.span(&self.base), - body: Some(self.body.swcify(ctx)), + body: Some(swcify_function_body(self.body, ctx)), is_generator: self.generator.unwrap_or_default(), is_async: self.is_async.unwrap_or_default(), type_params: self.type_parameters.swcify(ctx).flatten().map(Box::new), diff --git a/deps/swc/crates/swc_estree_compat/src/swcify/expr.rs b/deps/swc/crates/swc_estree_compat/src/swcify/expr.rs index 3174da392..b9ccad6b0 100644 --- a/deps/swc/crates/swc_estree_compat/src/swcify/expr.rs +++ b/deps/swc/crates/swc_estree_compat/src/swcify/expr.rs @@ -1,7 +1,7 @@ use swc_common::Spanned; use swc_ecma_ast::{ - op, ArrayLit, ArrowExpr, AssignExpr, AwaitExpr, BinExpr, BinaryOp, BindingIdent, - BlockStmtOrExpr, CallExpr, Callee, ClassExpr, ComputedPropName, CondExpr, Expr, ExprOrSpread, + op, ArrayLit, ArrowExpr, ArrowFunctionBody, AssignExpr, AwaitExpr, BinExpr, BinaryOp, + BindingIdent, CallExpr, Callee, ClassExpr, ComputedPropName, CondExpr, Expr, ExprOrSpread, FnExpr, Function, Ident, Import, JSXAttr, JSXAttrOrSpread, JSXAttrValue, JSXEmptyExpr, JSXExpr, JSXExprContainer, JSXMemberExpr, JSXObject, KeyValueProp, Lit, MemberExpr, MemberProp, MetaPropExpr, MetaPropKind, MethodProp, NewExpr, ObjectLit, OptCall, OptChainBase, @@ -27,7 +27,14 @@ use swc_estree_ast::{ }; use super::Context; -use crate::{swcify::Swcify, Never}; +use crate::{ + swcify::{ + function::{swcify_function_params, SwcifiedFunctionParams}, + stmt::swcify_function_body, + Swcify, + }, + Never, +}; impl Swcify for Expression { type Output = Box; @@ -294,13 +301,17 @@ impl Swcify for FunctionExpression { type Output = FnExpr; fn swcify(self, ctx: &Context) -> Self::Output { + let SwcifiedFunctionParams { this_param, params } = + swcify_function_params(self.params, ctx); + FnExpr { ident: self.id.swcify(ctx).map(|v| v.into()), function: Box::new(Function { - params: self.params.swcify(ctx), + this_param, + params, decorators: Default::default(), span: ctx.span(&self.base), - body: Some(self.body.swcify(ctx)), + body: Some(swcify_function_body(self.body, ctx)), is_generator: self.generator.unwrap_or(false), is_async: self.is_async.unwrap_or(false), type_params: self.type_parameters.swcify(ctx).flatten().map(Box::new), @@ -458,13 +469,17 @@ impl Swcify for ObjectMethod { type Output = MethodProp; fn swcify(self, ctx: &Context) -> Self::Output { + let SwcifiedFunctionParams { this_param, params } = + swcify_function_params(self.params, ctx); + MethodProp { key: self.key.swcify(ctx), function: Box::new(Function { - params: self.params.swcify(ctx), + this_param, + params, decorators: self.decorator.swcify(ctx).unwrap_or_default(), span: ctx.span(&self.base), - body: Some(self.body.swcify(ctx)), + body: Some(swcify_function_body(self.body, ctx)), is_generator: self.generator.unwrap_or(false), is_async: self.is_async.unwrap_or(false), type_params: self.type_parameters.swcify(ctx).flatten().map(Box::new), @@ -639,12 +654,14 @@ impl Swcify for ArrowFunctionExpression { } impl Swcify for ArrowFuncExprBody { - type Output = BlockStmtOrExpr; + type Output = ArrowFunctionBody; fn swcify(self, ctx: &Context) -> Self::Output { match self { - ArrowFuncExprBody::Block(v) => BlockStmtOrExpr::BlockStmt(v.swcify(ctx)), - ArrowFuncExprBody::Expr(v) => BlockStmtOrExpr::Expr(v.swcify(ctx)), + ArrowFuncExprBody::Block(v) => { + ArrowFunctionBody::FunctionBody(swcify_function_body(v, ctx)) + } + ArrowFuncExprBody::Expr(v) => ArrowFunctionBody::Expr(v.swcify(ctx)), } } } diff --git a/deps/swc/crates/swc_estree_compat/src/swcify/function.rs b/deps/swc/crates/swc_estree_compat/src/swcify/function.rs new file mode 100644 index 000000000..a9bc21a84 --- /dev/null +++ b/deps/swc/crates/swc_estree_compat/src/swcify/function.rs @@ -0,0 +1,91 @@ +use swc_common::{Span, Spanned}; +use swc_ecma_ast::{BindingIdent, Param, TsThisParam}; +use swc_estree_ast::Param as BabelParam; + +use super::{Context, Swcify}; + +/// Function parameters converted to SWC's split type-only/runtime +/// representation. +pub(super) struct SwcifiedFunctionParams { + /// TypeScript-only `this` parameter. + pub this_param: Option>, + /// Parameters present in the emitted JavaScript function. + pub params: Vec, +} + +/// Builds a `this` parameter while preserving its token and full annotation +/// spans. +fn ts_this_param_from_binding_ident(this_span: Span, ident: BindingIdent) -> TsThisParam { + TsThisParam { + span: ident.span(), + this_span, + type_ann: ident.type_ann, + } +} + +/// Converts ESTree parameters and separates a valid leading TypeScript `this` +/// parameter. +pub(super) fn swcify_function_params( + params: Vec, + ctx: &Context, +) -> SwcifiedFunctionParams { + let mut params = params.into_iter(); + let first = params.next(); + let mut output = Vec::with_capacity(params.len() + usize::from(first.is_some())); + + let this_param = match first { + Some(BabelParam::Id(ident)) + if ident.name == "this" + && !ident.optional.unwrap_or_default() + && ident.decorators.as_ref().map_or(true, Vec::is_empty) => + { + let this_span = ctx.span(&ident.base); + let ident = ident.swcify(ctx); + Some(Box::new(ts_this_param_from_binding_ident(this_span, ident))) + } + Some(param) => { + output.push(param.swcify(ctx)); + None + } + None => None, + }; + + output.extend(params.map(|param| param.swcify(ctx))); + + SwcifiedFunctionParams { + this_param, + params: output, + } +} + +#[cfg(test)] +mod tests { + use swc_common::{BytePos, Span}; + use swc_ecma_ast::{BindingIdent, Ident, TsKeywordType, TsKeywordTypeKind, TsType, TsTypeAnn}; + + use super::ts_this_param_from_binding_ident; + + #[test] + fn builds_full_span_from_binding_ident() { + let this_span = Span::new(BytePos(10), BytePos(14)); + let type_ann_span = Span::new(BytePos(14), BytePos(23)); + let ident = BindingIdent { + id: Ident::new_no_ctxt("this".into(), this_span), + type_ann: Some(Box::new(TsTypeAnn { + span: type_ann_span, + type_ann: Box::new(TsType::TsKeywordType(TsKeywordType { + span: type_ann_span, + kind: TsKeywordTypeKind::TsStringKeyword, + })), + })), + }; + + let this_param = ts_this_param_from_binding_ident(this_span, ident); + + assert_eq!(this_param.this_span, this_span); + assert_eq!( + this_param.span, + Span::new(this_span.lo(), type_ann_span.hi()) + ); + } +} diff --git a/deps/swc/crates/swc_estree_compat/src/swcify/mod.rs b/deps/swc/crates/swc_estree_compat/src/swcify/mod.rs index 8075c3d1b..5a0ad6a2f 100644 --- a/deps/swc/crates/swc_estree_compat/src/swcify/mod.rs +++ b/deps/swc/crates/swc_estree_compat/src/swcify/mod.rs @@ -5,6 +5,7 @@ pub use self::ctx::Context; mod class; mod ctx; mod expr; +mod function; mod jsx; mod lit; mod pat; diff --git a/deps/swc/crates/swc_estree_compat/src/swcify/stmt.rs b/deps/swc/crates/swc_estree_compat/src/swcify/stmt.rs index 1bc43a167..334727e0c 100644 --- a/deps/swc/crates/swc_estree_compat/src/swcify/stmt.rs +++ b/deps/swc/crates/swc_estree_compat/src/swcify/stmt.rs @@ -2,12 +2,12 @@ use swc_common::DUMMY_SP; use swc_ecma_ast::{ BlockStmt, BreakStmt, ClassDecl, ClassExpr, ContinueStmt, DebuggerStmt, DefaultDecl, DoWhileStmt, EmptyStmt, ExportAll, ExportDecl, ExportDefaultDecl, ExportDefaultExpr, - ExportNamedSpecifier, ExprStmt, FnDecl, FnExpr, ForHead, ForInStmt, ForOfStmt, ForStmt, IfStmt, - ImportDecl, ImportNamedSpecifier, ImportSpecifier, ImportStarAsSpecifier, KeyValueProp, - LabeledStmt, Lit, ModuleDecl, ModuleItem, NamedExport, ObjectLit, Pat, Prop, PropName, - PropOrSpread, ReturnStmt, SwitchStmt, ThrowStmt, TryStmt, TsExportAssignment, TsInterfaceDecl, - TsModuleDecl, TsTypeAliasDecl, VarDecl, VarDeclKind, VarDeclOrExpr, VarDeclarator, WhileStmt, - WithStmt, + ExportNamedSpecifier, ExprStmt, FnDecl, FnExpr, ForHead, ForInStmt, ForOfStmt, ForStmt, + FunctionBody, IfStmt, ImportDecl, ImportNamedSpecifier, ImportSpecifier, ImportStarAsSpecifier, + KeyValueProp, LabeledStmt, Lit, ModuleDecl, ModuleItem, NamedExport, ObjectLit, Pat, Prop, + PropName, PropOrSpread, ReturnStmt, SwitchStmt, ThrowStmt, TryStmt, TsExportAssignment, + TsInterfaceDecl, TsModuleDecl, TsTypeAliasDecl, VarDecl, VarDeclKind, VarDeclOrExpr, + VarDeclarator, WhileStmt, WithStmt, }; use swc_estree_ast::{ BlockStatement, BreakStatement, ClassDeclaration, ContinueStatement, DebuggerStatement, @@ -23,7 +23,10 @@ use swc_estree_ast::{ }; use super::Context; -use crate::swcify::Swcify; +use crate::swcify::{ + function::{swcify_function_params, SwcifiedFunctionParams}, + Swcify, +}; impl Swcify for BlockStatement { type Output = BlockStmt; @@ -42,6 +45,12 @@ impl Swcify for BlockStatement { } } +pub(super) fn swcify_function_body(block: BlockStatement, ctx: &Context) -> FunctionBody { + let BlockStmt { span, stmts, .. } = block.swcify(ctx); + + FunctionBody { span, stmts } +} + impl Swcify for Statement { type Output = ModuleItem; @@ -206,14 +215,18 @@ impl Swcify for FunctionDeclaration { type Output = FnDecl; fn swcify(self, ctx: &Context) -> Self::Output { + let SwcifiedFunctionParams { this_param, params } = + swcify_function_params(self.params, ctx); + FnDecl { ident: self.id.swcify(ctx).map(|v| v.into()).unwrap(), declare: false, function: swc_ecma_ast::Function { - params: self.params.swcify(ctx), + this_param, + params, decorators: Default::default(), span: ctx.span(&self.base), - body: Some(self.body.swcify(ctx)), + body: Some(swcify_function_body(self.body, ctx)), is_generator: false, is_async: self.is_async.unwrap_or_default(), ..Default::default() @@ -269,6 +282,7 @@ impl Swcify for SwitchStatement { fn swcify(self, ctx: &Context) -> Self::Output { SwitchStmt { span: ctx.span(&self.base), + body_ctxt: Default::default(), discriminant: self.discriminant.swcify(ctx), cases: self.cases.swcify(ctx), } diff --git a/deps/swc/crates/swc_graph_analyzer/Cargo.toml b/deps/swc/crates/swc_graph_analyzer/Cargo.toml index 76aa935db..0ab93c592 100644 --- a/deps/swc/crates/swc_graph_analyzer/Cargo.toml +++ b/deps/swc/crates/swc_graph_analyzer/Cargo.toml @@ -18,4 +18,4 @@ rustc-hash = { workspace = true } tracing = { workspace = true } [dev-dependencies] -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_html/Cargo.toml b/deps/swc/crates/swc_html/Cargo.toml index 569f81a6f..7544469ef 100644 --- a/deps/swc/crates/swc_html/Cargo.toml +++ b/deps/swc/crates/swc_html/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" license = { workspace = true } name = "swc_html" repository = "https://github.com/swc-project/swc.git" -version = "35.0.0" +version = "38.0.0" [package.metadata.docs.rs] all-features = true @@ -22,7 +22,7 @@ bench = false minifier = [] [dependencies] -swc_html_ast = { version = "23.0.0", path = "../swc_html_ast" } -swc_html_codegen = { version = "24.0.0", path = "../swc_html_codegen" } -swc_html_parser = { version = "23.0.0", path = "../swc_html_parser" } -swc_html_visit = { version = "23.0.0", path = "../swc_html_visit" } +swc_html_ast = { version = "26.0.0", path = "../swc_html_ast" } +swc_html_codegen = { version = "27.0.0", path = "../swc_html_codegen" } +swc_html_parser = { version = "26.0.0", path = "../swc_html_parser" } +swc_html_visit = { version = "26.0.0", path = "../swc_html_visit" } diff --git a/deps/swc/crates/swc_html_ast/Cargo.toml b/deps/swc/crates/swc_html_ast/Cargo.toml index 1aa5bdded..e600559bf 100644 --- a/deps/swc/crates/swc_html_ast/Cargo.toml +++ b/deps/swc/crates/swc_html_ast/Cargo.toml @@ -9,34 +9,24 @@ edition = "2021" license = { workspace = true } name = "swc_html_ast" repository = "https://github.com/swc-project/swc.git" -version = "23.0.0" +version = "26.0.0" [lib] bench = false [features] -__rkyv = [] encoding-impl = [ "cbor4ii", "swc_atoms/encoding-impl", "swc_common/encoding-impl", ] -rkyv-impl = [ - "__rkyv", - "rkyv", - "swc_atoms/rkyv-impl", - "swc_common/rkyv-impl", - "bytecheck", -] serde-impl = ["serde"] [dependencies] -bytecheck = { workspace = true, optional = true } cbor4ii = { workspace = true, features = ["use_std"], optional = true } is-macro = { workspace = true } -rkyv = { workspace = true, optional = true } serde = { workspace = true, features = ["derive"], optional = true } string_enum = { version = "1.0.2", path = "../string_enum/" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } diff --git a/deps/swc/crates/swc_html_ast/src/base.rs b/deps/swc/crates/swc_html_ast/src/base.rs index ae218a4e1..d96283799 100644 --- a/deps/swc/crates/swc_html_ast/src/base.rs +++ b/deps/swc/crates/swc_html_ast/src/base.rs @@ -19,17 +19,6 @@ pub struct DocumentFragment { } #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -//#[cfg_attr( -// feature = "rkyv", -// archive(bound(serialize = "__S: rkyv::ser::ScratchSpace + -// rkyv::ser::Serializer")) -//)] -#[cfg_attr(feature = "rkyv", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) @@ -94,17 +83,6 @@ impl EqIgnoreSpan for DocumentType { } #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -//#[cfg_attr( -// feature = "rkyv", -// archive(bound(serialize = "__S: rkyv::ser::ScratchSpace + -// rkyv::ser::Serializer")) -//)] -#[cfg_attr(feature = "rkyv", repr(u32))] #[cfg_attr( feature = "encoding-impl", derive(::swc_common::Encode, ::swc_common::Decode) diff --git a/deps/swc/crates/swc_html_ast/src/token.rs b/deps/swc/crates/swc_html_ast/src/token.rs index 56861c4a0..b22e261dc 100644 --- a/deps/swc/crates/swc_html_ast/src/token.rs +++ b/deps/swc/crates/swc_html_ast/src/token.rs @@ -33,17 +33,6 @@ pub struct AttributeToken { } #[derive(Debug, Clone, PartialEq, Eq, Hash, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr( - feature = "rkyv", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr( feature = "encoding-impl", @@ -55,17 +44,6 @@ pub enum Raw { } #[derive(Debug, Clone, PartialEq, Eq, Hash, EqIgnoreSpan)] -#[cfg_attr( - feature = "rkyv", - derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) -)] -#[cfg_attr( - feature = "rkyv", - rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator, - __S::Error: rkyv::rancor::Source)) -)] -#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))] -#[cfg_attr(feature = "rkyv", repr(u32))] #[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr( feature = "encoding-impl", diff --git a/deps/swc/crates/swc_html_codegen/Cargo.toml b/deps/swc/crates/swc_html_codegen/Cargo.toml index 9617fc71d..bb6e9b279 100644 --- a/deps/swc/crates/swc_html_codegen/Cargo.toml +++ b/deps/swc/crates/swc_html_codegen/Cargo.toml @@ -10,7 +10,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_html_codegen" repository = "https://github.com/swc-project/swc.git" -version = "24.0.0" +version = "27.0.0" [lib] bench = false @@ -20,16 +20,16 @@ auto_impl = { workspace = true } bitflags = { workspace = true } rustc-hash = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_html_ast = { version = "23.0.0", path = "../swc_html_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_html_ast = { version = "26.0.0", path = "../swc_html_ast" } swc_html_codegen_macros = { version = "1.0.1", path = "../swc_html_codegen_macros" } -swc_html_utils = { version = "16.0.0", path = "../swc_html_utils" } +swc_html_utils = { version = "17.0.0", path = "../swc_html_utils" } [dev-dependencies] -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "sourcemap", ] } -swc_html_parser = { version = "23.0.0", path = "../swc_html_parser" } -swc_html_visit = { version = "23.0.0", path = "../swc_html_visit" } -testing = { version = "24.0.1", path = "../testing" } +swc_html_parser = { version = "26.0.0", path = "../swc_html_parser" } +swc_html_visit = { version = "26.0.0", path = "../swc_html_visit" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_html_minifier/Cargo.toml b/deps/swc/crates/swc_html_minifier/Cargo.toml index 6c7b3d842..2a7fa1b9e 100644 --- a/deps/swc/crates/swc_html_minifier/Cargo.toml +++ b/deps/swc/crates/swc_html_minifier/Cargo.toml @@ -10,7 +10,7 @@ include = ["Cargo.toml", "src/**/*.rs", "data/**/*.json"] license = { workspace = true } name = "swc_html_minifier" repository = "https://github.com/swc-project/swc.git" -version = "56.0.0" +version = "61.0.0" [lib] bench = false @@ -34,36 +34,36 @@ rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_config = { version = "5.0.0", path = "../swc_config", features = ["regex"] } -swc_css_ast = { version = "23.0.0", path = "../swc_css_ast", optional = true } -swc_css_codegen = { version = "23.0.0", path = "../swc_css_codegen", optional = true } -swc_css_minifier = { version = "23.0.0", path = "../swc_css_minifier", optional = true } -swc_css_parser = { version = "23.0.0", path = "../swc_css_parser", optional = true } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_config = { version = "6.0.0", path = "../swc_config", features = ["regex"] } +swc_css_ast = { version = "26.0.0", path = "../swc_css_ast", optional = true } +swc_css_codegen = { version = "26.0.0", path = "../swc_css_codegen", optional = true } +swc_css_minifier = { version = "26.0.0", path = "../swc_css_minifier", optional = true } +swc_css_parser = { version = "26.0.0", path = "../swc_css_parser", optional = true } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen", features = [ "serde-impl", ] } -swc_ecma_minifier = { version = "56.0.1", path = "../swc_ecma_minifier", features = [ +swc_ecma_minifier = { version = "61.0.0", path = "../swc_ecma_minifier", features = [ "extra-serde", ] } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } -swc_html_ast = { version = "23.0.0", path = "../swc_html_ast" } -swc_html_codegen = { version = "24.0.0", path = "../swc_html_codegen" } -swc_html_parser = { version = "23.0.0", path = "../swc_html_parser" } -swc_html_utils = { version = "16.0.0", path = "../swc_html_utils" } -swc_html_visit = { version = "23.0.0", path = "../swc_html_visit" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } +swc_html_ast = { version = "26.0.0", path = "../swc_html_ast" } +swc_html_codegen = { version = "27.0.0", path = "../swc_html_codegen" } +swc_html_parser = { version = "26.0.0", path = "../swc_html_parser" } +swc_html_utils = { version = "17.0.0", path = "../swc_html_utils" } +swc_html_visit = { version = "26.0.0", path = "../swc_html_visit" } [dev-dependencies] codspeed-criterion-compat = { workspace = true } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } [[bench]] harness = false diff --git a/deps/swc/crates/swc_html_minifier/src/lib.rs b/deps/swc/crates/swc_html_minifier/src/lib.rs index d952d23d3..4f3ff1e03 100644 --- a/deps/swc/crates/swc_html_minifier/src/lib.rs +++ b/deps/swc/crates/swc_html_minifier/src/lib.rs @@ -1789,6 +1789,20 @@ impl Minifier<'_, C> { result.ok() } + /// Escapes serialized JSON so it cannot terminate its containing HTML + /// `script` element. + /// + /// HTML tokenization recognizes ` String { + if json.contains('<') { + json.replace('<', "\\u003C") + } else { + json + } + } + fn need_minify_js(&self) -> bool { match self.options.minify_js { MinifyJsOption::Bool(value) => value, @@ -2742,7 +2756,7 @@ impl VisitMut for Minifier<'_, C> { None => return, }; - n.data = minified.into(); + n.data = Self::escape_json_for_html_script(minified).into(); } Some(MinifierType::Css) => { let minified = diff --git a/deps/swc/crates/swc_html_parser/Cargo.toml b/deps/swc/crates/swc_html_parser/Cargo.toml index b84211772..abadd7fde 100644 --- a/deps/swc/crates/swc_html_parser/Cargo.toml +++ b/deps/swc/crates/swc_html_parser/Cargo.toml @@ -10,7 +10,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/**/*.json"] license = { workspace = true } name = "swc_html_parser" repository = "https://github.com/swc-project/swc.git" -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -21,22 +21,22 @@ debug = [] [dependencies] rustc-hash = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_html_ast = { version = "23.0.0", path = "../swc_html_ast" } -swc_html_utils = { version = "16.0.0", path = "../swc_html_utils" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_html_ast = { version = "26.0.0", path = "../swc_html_ast" } +swc_html_utils = { version = "17.0.0", path = "../swc_html_utils" } [dev-dependencies] codspeed-criterion-compat = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } -swc_html_ast = { version = "23.0.0", path = "../swc_html_ast", features = [ +swc_html_ast = { version = "26.0.0", path = "../swc_html_ast", features = [ "serde-impl", ] } -swc_html_visit = { version = "23.0.0", path = "../swc_html_visit" } +swc_html_visit = { version = "26.0.0", path = "../swc_html_visit" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } [[bench]] harness = false diff --git a/deps/swc/crates/swc_html_utils/Cargo.toml b/deps/swc/crates/swc_html_utils/Cargo.toml index 3bf37d099..b1989297e 100644 --- a/deps/swc/crates/swc_html_utils/Cargo.toml +++ b/deps/swc/crates/swc_html_utils/Cargo.toml @@ -10,7 +10,7 @@ include = ["Cargo.toml", "src/**/*.rs", "data/**/*.json"] license = { workspace = true } name = "swc_html_utils" repository = "https://github.com/swc-project/swc.git" -version = "16.0.0" +version = "17.0.0" [lib] bench = false @@ -21,4 +21,4 @@ rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } diff --git a/deps/swc/crates/swc_html_visit/Cargo.toml b/deps/swc/crates/swc_html_visit/Cargo.toml index f715c0c72..6926cafd1 100644 --- a/deps/swc/crates/swc_html_visit/Cargo.toml +++ b/deps/swc/crates/swc_html_visit/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" license = { workspace = true } name = "swc_html_visit" repository = "https://github.com/swc-project/swc.git" -version = "23.0.0" +version = "26.0.0" [package.metadata.docs.rs] all-features = true @@ -26,7 +26,7 @@ serde-impl = ["serde"] [dependencies] serde = { workspace = true, optional = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_html_ast = { version = "23.0.0", path = "../swc_html_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_html_ast = { version = "26.0.0", path = "../swc_html_ast" } swc_visit = { version = "2.0.1", path = "../swc_visit" } diff --git a/deps/swc/crates/swc_node_bundler/Cargo.toml b/deps/swc/crates/swc_node_bundler/Cargo.toml index 0f108a8fe..db67cd327 100644 --- a/deps/swc/crates/swc_node_bundler/Cargo.toml +++ b/deps/swc/crates/swc_node_bundler/Cargo.toml @@ -7,7 +7,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_node_bundler" repository = { workspace = true } -version = "70.0.0" +version = "76.0.0" [lib] bench = false @@ -25,27 +25,27 @@ serde = { workspace = true, features = ["derive"], optional = true } tracing = { workspace = true } string_enum = { version = "1.0.2", path = "../string_enum" } -swc = { version = "69.0.0", path = "../swc" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_bundler = { version = "51.0.1", path = "../swc_bundler", features = [ +swc = { version = "75.0.0", path = "../swc" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_bundler = { version = "56.0.0", path = "../swc_bundler", features = [ "concurrent", ] } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "concurrent", ] } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_loader = { version = "24.0.1", path = "../swc_ecma_loader" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_loader = { version = "27.0.0", path = "../swc_ecma_loader" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", ] } -swc_ecma_transforms = { version = "56.0.0", path = "../swc_ecma_transforms" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } +swc_ecma_transforms = { version = "62.0.0", path = "../swc_ecma_transforms" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } [dev-dependencies] -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base", features = [ +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base", features = [ "inline-helpers", ] } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_node_comments/Cargo.toml b/deps/swc/crates/swc_node_comments/Cargo.toml index 83073905c..1ae863205 100644 --- a/deps/swc/crates/swc_node_comments/Cargo.toml +++ b/deps/swc/crates/swc_node_comments/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" license = { workspace = true } name = "swc_node_comments" repository = "https://github.com/swc-project/swc.git" -version = "24.0.0" +version = "27.0.0" [lib] bench = false @@ -18,5 +18,5 @@ bench = false dashmap = { workspace = true } rustc-hash = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } diff --git a/deps/swc/crates/swc_plugin_backend_tests/Cargo.toml b/deps/swc/crates/swc_plugin_backend_tests/Cargo.toml index 0f3df6d7c..4e46b5ab4 100644 --- a/deps/swc/crates/swc_plugin_backend_tests/Cargo.toml +++ b/deps/swc/crates/swc_plugin_backend_tests/Cargo.toml @@ -13,10 +13,7 @@ bench = false doctest = false [features] -# for ast_node macro default = ["encoding-impl"] -__rkyv = [] -rkyv-impl = [] serde-impl = [] encoding-impl = [] @@ -33,21 +30,21 @@ tokio = { workspace = true, features = ["rt"] } tracing = { workspace = true } cbor4ii = { workspace = true, features = [ "use_std" ] } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "concurrent", ] } -swc_plugin_runner = { version = "30.0.0", path = "../swc_plugin_runner", features = ["encoding-impl", "plugin_transform_schema_v1"] } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast", features = [ +swc_plugin_runner = { version = "34.0.0", path = "../swc_plugin_runner", features = ["encoding-impl", "plugin_transform_schema_v1"] } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast", features = [ "encoding-impl", ] } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } -swc_transform_common = { version = "17.0.0", path = "../swc_transform_common" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } +swc_transform_common = { version = "20.0.0", path = "../swc_transform_common" } swc_malloc = { version = "1.2.5", path = "../swc_malloc" } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } -swc_plugin_backend_wasmer = { version = "13.0", path = "../swc_plugin_backend_wasmer" } -swc_plugin_backend_wasmtime = { version = "12.0", path = "../swc_plugin_backend_wasmtime" } +swc_plugin_backend_wasmer = { version = "17.0", path = "../swc_plugin_backend_wasmer" } +swc_plugin_backend_wasmtime = { version = "16.0", path = "../swc_plugin_backend_wasmtime" } [[bench]] harness = false diff --git a/deps/swc/crates/swc_plugin_backend_wasmer/Cargo.toml b/deps/swc/crates/swc_plugin_backend_wasmer/Cargo.toml index 6151617aa..424c72d43 100644 --- a/deps/swc/crates/swc_plugin_backend_wasmer/Cargo.toml +++ b/deps/swc/crates/swc_plugin_backend_wasmer/Cargo.toml @@ -5,7 +5,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_plugin_backend_wasmer" repository = { workspace = true } -version = "13.0.0" +version = "17.0.0" [lib] bench = false @@ -33,10 +33,13 @@ parking_lot = { workspace = true } wasmer = { workspace = true } wasmer-wasix = { workspace = true } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "concurrent", ] } -swc_plugin_runner = { version = "30.0.0", path = "../swc_plugin_runner" } +swc_plugin_runner = { version = "34.0.0", path = "../swc_plugin_runner" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] wasmer-compiler-cranelift = { version = "6.1.0-rc.3", default-features = false } + +[dev-dependencies] +tempfile = { workspace = true } diff --git a/deps/swc/crates/swc_plugin_backend_wasmer/src/filesystem_cache.rs b/deps/swc/crates/swc_plugin_backend_wasmer/src/filesystem_cache.rs new file mode 100644 index 000000000..73b7ca0fb --- /dev/null +++ b/deps/swc/crates/swc_plugin_backend_wasmer/src/filesystem_cache.rs @@ -0,0 +1,106 @@ +use std::{ + fs::{File, OpenOptions}, + io::{self, ErrorKind, Write}, + path::{Path, PathBuf}, + sync::atomic::{AtomicU64, Ordering}, +}; + +static TEMP_FILE_COUNTER: AtomicU64 = AtomicU64::new(0); + +/// Writes a serialized module without exposing a partially-written cache file. +/// +/// Jest and other parallel runners can load the same plugin from multiple +/// processes. Writing directly to the final path allows one process to observe +/// another process's incomplete Wasmer artifact. A temporary file in the same +/// directory keeps the final rename atomic. +pub(crate) fn write_atomic(path: &Path, data: &[u8]) -> io::Result<()> { + let (temporary_path, mut file) = create_temporary_file(path)?; + + if let Err(err) = file.write_all(data) { + drop(file); + let _ = std::fs::remove_file(&temporary_path); + return Err(err); + } + drop(file); + + match std::fs::rename(&temporary_path, path) { + Ok(()) => Ok(()), + // Windows does not replace an existing file with rename. Another process + // publishing the same content first is a successful cache write for us. + Err(_) if path.is_file() => { + let _ = std::fs::remove_file(&temporary_path); + Ok(()) + } + Err(err) => { + let _ = std::fs::remove_file(&temporary_path); + Err(err) + } + } +} + +fn create_temporary_file(path: &Path) -> io::Result<(PathBuf, File)> { + loop { + let id = TEMP_FILE_COUNTER.fetch_add(1, Ordering::Relaxed); + let mut temporary_path = path.as_os_str().to_os_string(); + temporary_path.push(format!(".{}.{}.tmp", std::process::id(), id)); + let temporary_path = PathBuf::from(temporary_path); + + match OpenOptions::new() + .create_new(true) + .write(true) + .open(&temporary_path) + { + Ok(file) => return Ok((temporary_path, file)), + Err(err) if err.kind() == ErrorKind::AlreadyExists => continue, + Err(err) => return Err(err), + } + } +} + +#[cfg(test)] +mod tests { + use std::sync::{Arc, Barrier}; + + use super::*; + + #[test] + fn concurrent_writers_only_publish_complete_cache_files() { + const WRITER_COUNT: usize = 8; + const PAYLOAD_SIZE: usize = 2 * 1024 * 1024; + + let directory = tempfile::tempdir().unwrap(); + let cache_path = directory.path().join("plugin.wasmer"); + let barrier = Arc::new(Barrier::new(WRITER_COUNT + 1)); + let payloads: Vec<_> = (0..WRITER_COUNT) + .map(|index| Arc::new(vec![index as u8; PAYLOAD_SIZE])) + .collect(); + + let handles: Vec<_> = payloads + .iter() + .map(|payload| { + let barrier = barrier.clone(); + let cache_path = cache_path.clone(); + let payload = payload.clone(); + std::thread::spawn(move || { + barrier.wait(); + write_atomic(&cache_path, &payload) + }) + }) + .collect(); + + barrier.wait(); + while handles.iter().any(|handle| !handle.is_finished()) { + if let Ok(data) = std::fs::read(&cache_path) { + assert!(payloads.iter().any(|payload| payload.as_slice() == data)); + } + } + + for handle in handles { + handle.join().unwrap().unwrap(); + } + + let data = std::fs::read(&cache_path).unwrap(); + assert!(payloads.iter().any(|payload| payload.as_slice() == data)); + assert_eq!(std::fs::read_dir(directory.path()).unwrap().count(), 1); + } +} diff --git a/deps/swc/crates/swc_plugin_backend_wasmer/src/lib.rs b/deps/swc/crates/swc_plugin_backend_wasmer/src/lib.rs index 241508dad..67b9935a5 100644 --- a/deps/swc/crates/swc_plugin_backend_wasmer/src/lib.rs +++ b/deps/swc/crates/swc_plugin_backend_wasmer/src/lib.rs @@ -9,6 +9,9 @@ use swc_plugin_runner::runtime; use wasmer::{AsStoreMut, Store}; use wasmer_wasix::{default_fs_backing, Runtime}; +#[cfg(not(target_arch = "wasm32"))] +mod filesystem_cache; + /// Identifier for bytecode cache stored in local filesystem. /// /// This MUST be updated when bump up wasmer. @@ -304,7 +307,16 @@ impl runtime::Runtime for WasmerRuntime { fn store_cache(&self, path: &Path, cache: &runtime::ModuleCache) -> anyhow::Result<()> { let cache = cache.0.downcast_ref::().unwrap(); + + #[cfg(not(target_arch = "wasm32"))] + { + let data = cache.module.serialize()?; + filesystem_cache::write_atomic(path, &data)?; + } + + #[cfg(target_arch = "wasm32")] cache.module.serialize_to_file(path)?; + Ok(()) } } diff --git a/deps/swc/crates/swc_plugin_backend_wasmtime/Cargo.toml b/deps/swc/crates/swc_plugin_backend_wasmtime/Cargo.toml index 36a4e41ce..02e24d72d 100644 --- a/deps/swc/crates/swc_plugin_backend_wasmtime/Cargo.toml +++ b/deps/swc/crates/swc_plugin_backend_wasmtime/Cargo.toml @@ -5,14 +5,14 @@ edition = { workspace = true } license = { workspace = true } name = "swc_plugin_backend_wasmtime" repository = { workspace = true } -version = "12.0.0" +version = "16.0.0" [dependencies] anyhow = { workspace = true } wasi-common = { workspace = true, features = ["sync", "wasmtime"] } wasmtime = { workspace = true, features = ["runtime", "cranelift", "threads"] } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "concurrent", ] } -swc_plugin_runner = { version = "30.0.0", path = "../swc_plugin_runner" } +swc_plugin_runner = { version = "34.0.0", path = "../swc_plugin_runner" } diff --git a/deps/swc/crates/swc_plugin_macro/Cargo.toml b/deps/swc/crates/swc_plugin_macro/Cargo.toml index 1f3828974..eb1ccbc7a 100644 --- a/deps/swc/crates/swc_plugin_macro/Cargo.toml +++ b/deps/swc/crates/swc_plugin_macro/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = { workspace = true } name = "swc_plugin_macro" repository = { workspace = true } -version = "1.1.1" +version = "2.0.0" [lib] bench = false diff --git a/deps/swc/crates/swc_plugin_macro/src/lib.rs b/deps/swc/crates/swc_plugin_macro/src/lib.rs index eaf62f294..4d86fe64b 100644 --- a/deps/swc/crates/swc_plugin_macro/src/lib.rs +++ b/deps/swc/crates/swc_plugin_macro/src/lib.rs @@ -112,13 +112,33 @@ fn handle_func(func: ItemFn, ast_type: Ident) -> TokenStream { // There are some cases error won't be wrapped up however - for example, we expect // serialization of PluginError itself should succeed. #[no_mangle] - #[allow(clippy::not_unsafe_ptr_arg_deref)] - pub fn #transform_process_impl_ident( + /// Runs the plugin transform for a program serialized by the SWC host. + /// + /// # Safety + /// + /// `ast_ptr` must be non-null and properly aligned, including when + /// `ast_ptr_len` is zero. It must point to `ast_ptr_len` initialized, + /// readable bytes in one guest allocation which remains valid for the + /// duration of this call. The byte range must not exceed `isize::MAX` + /// or wrap around the address space. + pub unsafe fn #transform_process_impl_ident( ast_ptr: *const u8, ast_ptr_len: u32, unresolved_mark: u32, should_enable_comments_proxy: i32) -> u32 { // Reconstruct `Program` & config string from serialized program - // Host (SWC) should allocate memory, copy bytes and pass ptr to plugin. - let program = swc_core::common::plugin::serialized::PluginSerializedBytes::from_raw_ptr(ast_ptr, ast_ptr_len.try_into().expect("Should able to convert ptr length")).deserialize(); + // Host (SWC) allocates guest memory, copies bytes and passes the + // allocation's pointer to the plugin. + // SAFETY: The exported function's contract requires a valid pointer + // and length. The SWC host ABI upholds it by allocating exactly + // `ast_ptr_len` bytes in guest memory and initializing them with the + // serialized program before invoking this function. The host retains + // the allocation until this function returns. + let serialized_program = unsafe { + swc_core::common::plugin::serialized::PluginSerializedBytes::from_raw_ptr( + ast_ptr, + ast_ptr_len.try_into().expect("Should able to convert ptr length"), + ) + }; + let program = serialized_program.deserialize(); if program.is_err() { let err = swc_core::common::plugin::serialized::PluginError::Deserialize("Failed to deserialize program received from host".to_string()); return construct_error_ptr(err); diff --git a/deps/swc/crates/swc_plugin_proxy/Cargo.toml b/deps/swc/crates/swc_plugin_proxy/Cargo.toml index 613df997e..aa1515e02 100644 --- a/deps/swc/crates/swc_plugin_proxy/Cargo.toml +++ b/deps/swc/crates/swc_plugin_proxy/Cargo.toml @@ -5,7 +5,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_plugin_proxy" repository = { workspace = true } -version = "26.0.0" +version = "30.0.0" [lib] bench = false @@ -25,5 +25,5 @@ tracing = { workspace = true } cbor4ii = { workspace = true, features = [ "use_std" ], optional = true } better_scoped_tls = { version = "1.0.1", path = "../better_scoped_tls" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } diff --git a/deps/swc/crates/swc_plugin_proxy/src/memory_interop/read_returned_result_from_host.rs b/deps/swc/crates/swc_plugin_proxy/src/memory_interop/read_returned_result_from_host.rs index 49cc8d907..6b7024bda 100644 --- a/deps/swc/crates/swc_plugin_proxy/src/memory_interop/read_returned_result_from_host.rs +++ b/deps/swc/crates/swc_plugin_proxy/src/memory_interop/read_returned_result_from_host.rs @@ -98,15 +98,24 @@ where // Using AllocatedBytesPtr's value, reconstruct actual return value allocated_returned_value_ptr.map(|allocated_returned_value_ptr| { - PluginSerializedBytes::from_raw_ptr( - allocated_returned_value_ptr.0 as _, - allocated_returned_value_ptr - .1 - .try_into() - .expect("Should able to convert ptr length"), - ) - .deserialize() - .expect("Returned value should be serializable") - .into_inner() + // SAFETY: On a successful return, the host ABI allocated + // `allocated_returned_value_ptr.1` bytes in guest memory through + // `__alloc`, initialized all of them with the serialized result, and + // returned the allocation's non-null pointer. `allocated_returned_value_ptr` + // owns that allocation until this closure returns, so it remains readable + // for the duration of the copy. + let serialized = unsafe { + PluginSerializedBytes::from_raw_ptr( + allocated_returned_value_ptr.0 as _, + allocated_returned_value_ptr + .1 + .try_into() + .expect("Should able to convert ptr length"), + ) + }; + serialized + .deserialize() + .expect("Returned value should be serializable") + .into_inner() }) } diff --git a/deps/swc/crates/swc_plugin_runner/Cargo.toml b/deps/swc/crates/swc_plugin_runner/Cargo.toml index e8b88fc68..e5d7b0954 100644 --- a/deps/swc/crates/swc_plugin_runner/Cargo.toml +++ b/deps/swc/crates/swc_plugin_runner/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_plugin_runner" repository = { workspace = true } -version = "30.0.0" +version = "34.0.0" [lib] bench = false @@ -26,10 +26,6 @@ ecma = ["swc_ecma_ast/encoding-impl"] encoding-impl = ["swc_common/plugin-rt", "swc_plugin_proxy/plugin-rt"] -[build-dependencies] -vergen = { workspace = true, features = ["build", "cargo"] } - - [dependencies] anyhow = { workspace = true } parking_lot = { workspace = true } @@ -38,13 +34,13 @@ serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } tracing = { workspace = true } -swc_atoms = { version = "9.0.3", path = '../swc_atoms' } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_atoms = { version = "10.0.0", path = '../swc_atoms' } +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "concurrent", ] } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast", optional = true } -swc_plugin_proxy = { version = "26.0.0", path = "../swc_plugin_proxy" } -swc_transform_common = { version = "17.0.0", path = "../swc_transform_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast", optional = true } +swc_plugin_proxy = { version = "30.0.0", path = "../swc_plugin_proxy" } +swc_transform_common = { version = "20.0.0", path = "../swc_transform_common" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] blake3 = { workspace = true, optional = true } diff --git a/deps/swc/crates/swc_plugin_runner/build.rs b/deps/swc/crates/swc_plugin_runner/build.rs deleted file mode 100644 index bb189fc6f..000000000 --- a/deps/swc/crates/swc_plugin_runner/build.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::error::Error; - -use vergen::{BuildBuilder, CargoBuilder, Emitter}; - -fn main() -> Result<(), Box> { - let build = BuildBuilder::all_build()?; - let cargo = CargoBuilder::default() - .dependencies(true) - .name_filter("*_ast") - .build()?; - - Emitter::default() - .add_instructions(&build)? - .add_instructions(&cargo)? - .emit()?; - - Ok(()) -} diff --git a/deps/swc/crates/swc_plugin_runner/src/transform_executor.rs b/deps/swc/crates/swc_plugin_runner/src/transform_executor.rs index 7364b7e3c..3ea3e06a6 100644 --- a/deps/swc/crates/swc_plugin_runner/src/transform_executor.rs +++ b/deps/swc/crates/swc_plugin_runner/src/transform_executor.rs @@ -274,20 +274,12 @@ impl TransformExecutor { See https://plugins.swc.rs/versions/from-plugin-runner/{PKG_VERSION} for the list of the compatible versions. - Build info: - Date: {BUILD_DATE} - Timestamp: {BUILD_TIMESTAMP} - Version info: swc_plugin_runner: {PKG_VERSION} - Dependencies: {PKG_DEPS} " ) }) } } -const BUILD_DATE: &str = env!("VERGEN_BUILD_DATE"); -const BUILD_TIMESTAMP: &str = env!("VERGEN_BUILD_TIMESTAMP"); const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); -const PKG_DEPS: &str = env!("VERGEN_CARGO_DEPENDENCIES"); diff --git a/deps/swc/crates/swc_transform_common/Cargo.toml b/deps/swc/crates/swc_transform_common/Cargo.toml index b8ed235b7..06463cc5e 100644 --- a/deps/swc/crates/swc_transform_common/Cargo.toml +++ b/deps/swc/crates/swc_transform_common/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_transform_common" repository = { workspace = true } -version = "17.0.0" +version = "20.0.0" [package.metadata.docs.rs] all-features = true @@ -20,4 +20,4 @@ rustc-hash = { workspace = true } serde = { workspace = true } better_scoped_tls = { version = "1.0.1", path = "../better_scoped_tls" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_common = { version = "26.0.0", path = "../swc_common" } diff --git a/deps/swc/crates/swc_ts_fast_strip/Cargo.toml b/deps/swc/crates/swc_ts_fast_strip/Cargo.toml index b69b0a970..e35904da2 100644 --- a/deps/swc/crates/swc_ts_fast_strip/Cargo.toml +++ b/deps/swc/crates/swc_ts_fast_strip/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_ts_fast_strip" repository = { workspace = true } -version = "53.0.0" +version = "58.0.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } @@ -20,25 +20,25 @@ nightly = [] anyhow = { workspace = true } bytes-str = { workspace = true } serde = { workspace = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "sourcemap", ] } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser", default-features = false, features = [ +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser", default-features = false, features = [ "typescript", "unstable", ] } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -swc_ecma_transforms_react = { version = "50.0.0", path = "../swc_ecma_transforms_react" } -swc_ecma_transforms_typescript = { version = "50.0.0", path = "../swc_ecma_transforms_typescript" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +swc_ecma_transforms_react = { version = "55.0.0", path = "../swc_ecma_transforms_react" } +swc_ecma_transforms_typescript = { version = "55.0.0", path = "../swc_ecma_transforms_typescript" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } wasm-bindgen = { workspace = true, optional = true } [dev-dependencies] codspeed-criterion-compat = { workspace = true } -testing = { version = "24.0.1", path = "../testing" } +testing = { version = "27.0.0", path = "../testing" } [[bench]] harness = false diff --git a/deps/swc/crates/swc_ts_fast_strip/benches/assets.rs b/deps/swc/crates/swc_ts_fast_strip/benches/assets.rs index 5d102a946..e0c1b5ef2 100644 --- a/deps/swc/crates/swc_ts_fast_strip/benches/assets.rs +++ b/deps/swc/crates/swc_ts_fast_strip/benches/assets.rs @@ -1,22 +1,50 @@ use codspeed_criterion_compat::{black_box, criterion_group, criterion_main, Bencher, Criterion}; use swc_ts_fast_strip::{operate, Options}; -static SOURCE: &str = include_str!("assets/test.ts"); +const CASES: &[(&str, &str)] = &[ + ("typescript/fast-strip", include_str!("assets/test.ts")), + ( + "typescript/fast-strip/docusaurus-config", + include_str!("assets/docusaurus.config.ts"), + ), + ( + "typescript/fast-strip/ant-design-config", + include_str!("assets/ant-design.vitest.config.ts"), + ), + ( + "typescript/fast-strip/typescript-eslint-generate-configs", + include_str!("assets/typescript-eslint.generate-configs.mts"), + ), + ( + "typescript/fast-strip/graphile-config", + include_str!("assets/graphile.config.ts"), + ), + ( + "typescript/fast-strip/hono-types-test", + include_str!("assets/hono.types.test.ts"), + ), +]; fn fast_ts(c: &mut Criterion) { - c.bench_function("typescript/fast-strip", fast_typescript); + for &(name, source) in CASES { + c.bench_function(name, |b| fast_typescript(b, source)); + } } -fn fast_typescript(b: &mut Bencher) { + +fn fast_typescript(b: &mut Bencher, source: &str) { b.iter(|| { ::testing::run_test(false, |cm, handler| { - let _result = black_box(operate( + let result = operate( &cm, handler, - black_box(SOURCE.to_string()), + black_box(source.to_string()), Options { ..Default::default() }, - )); + ) + .expect("benchmark source should be valid erasable TypeScript"); + + black_box(result); Ok(()) }) diff --git a/deps/swc/crates/swc_ts_fast_strip/benches/assets/README.md b/deps/swc/crates/swc_ts_fast_strip/benches/assets/README.md new file mode 100644 index 000000000..83cc11d4e --- /dev/null +++ b/deps/swc/crates/swc_ts_fast_strip/benches/assets/README.md @@ -0,0 +1,12 @@ +# Real-world benchmark sources + +These files are copied unchanged from pinned upstream revisions. They are used +only as inputs for the `swc_ts_fast_strip` benchmarks. + +| Local file | Upstream source | License | +| --- | --- | --- | +| `docusaurus.config.ts` | [facebook/docusaurus@a0bc322](https://github.com/facebook/docusaurus/blob/a0bc32214436d52a5ac9de9be1a515d872987366/website/docusaurus.config.ts) | [MIT](https://github.com/facebook/docusaurus/blob/a0bc32214436d52a5ac9de9be1a515d872987366/LICENSE) | +| `ant-design.vitest.config.ts` | [ant-design/ant-design@afe2c19](https://github.com/ant-design/ant-design/blob/afe2c19fc03442ded9675a1260126bbda1108ca8/vitest.config.ts) | [MIT](https://github.com/ant-design/ant-design/blob/afe2c19fc03442ded9675a1260126bbda1108ca8/LICENSE) | +| `typescript-eslint.generate-configs.mts` | [typescript-eslint/typescript-eslint@c8cafa4](https://github.com/typescript-eslint/typescript-eslint/blob/c8cafa4ae9a0b57a64ba23659eba25a01301684a/tools/scripts/generate-configs.mts) | [MIT](https://github.com/typescript-eslint/typescript-eslint/blob/c8cafa4ae9a0b57a64ba23659eba25a01301684a/LICENSE) | +| `graphile.config.ts` | [graphile/crystal@33f239b](https://github.com/graphile/crystal/blob/33f239b494f43df2d11ee7264832ea8c732311f1/postgraphile/postgraphile/graphile.config.ts) | [MIT](https://github.com/graphile/crystal/blob/33f239b494f43df2d11ee7264832ea8c732311f1/LICENSE.md) | +| `hono.types.test.ts` | [honojs/hono@971106d](https://github.com/honojs/hono/blob/971106d132ec8a989be12ec5c8e63cfaf597cd4f/src/types.test.ts) | [MIT](https://github.com/honojs/hono/blob/971106d132ec8a989be12ec5c8e63cfaf597cd4f/LICENSE) | diff --git a/deps/swc/crates/swc_ts_fast_strip/benches/assets/ant-design.vitest.config.ts b/deps/swc/crates/swc_ts_fast_strip/benches/assets/ant-design.vitest.config.ts new file mode 100644 index 000000000..e624080cd --- /dev/null +++ b/deps/swc/crates/swc_ts_fast_strip/benches/assets/ant-design.vitest.config.ts @@ -0,0 +1,195 @@ +import { resolve } from 'node:path'; +import { defineConfig } from 'vitest/config'; + +// POC: 对标 .jest.js 的 moduleNameMapper / LIB_DIR 机制。 +// LIB_DIR=es|lib 时让 antd 指向对应产物目录,否则指向源码 components。 +// 注:dist/dist-min(UMD 产物 dist/antd.js、dist/antd.min.js)的映射与源码不同, +// 本 POC 未验证,故不纳入;仅支持 es/lib 与默认 components。 +const LIB_DIR = process.env.LIB_DIR || 'components'; +const baseDir = ['es', 'lib'].includes(LIB_DIR) ? LIB_DIR : 'components'; + +const r = (p: string) => resolve(__dirname, p); + +export default defineConfig({ + // JSX 走 automatic runtime(方案 A:丢弃 babel)。Vitest 4 默认转换器为 oxc, + // 其 jsx.runtime 默认即 'automatic',无需再像 esbuild 时代那样显式声明。 + resolve: { + alias: [ + // 对标 jest moduleNameMapper,并接入 LIB_DIR 切换 + { find: /^antd$/, replacement: r(`${baseDir}/index`) }, + { find: /^antd\/es\/(.*)$/, replacement: r(`${baseDir}/$1`) }, + { find: /^antd\/lib\/(.*)$/, replacement: r(`${baseDir}/$1`) }, + { find: /^antd\/locale\/(.*)$/, replacement: r(`${baseDir}/locale/$1`) }, + // 部分 antd 生态包默认解析到 CJS lib/(内部 require('antd') 绕过 alias); + // 强制走各自 ESM es/,其 import 'antd' 可命中上面的 antd alias。 + { find: /^antd-style$/, replacement: r('node_modules/antd-style/es/index.js') }, + { + find: /^@ant-design\/happy-work-theme$/, + replacement: r('node_modules/@ant-design/happy-work-theme/es/index.js'), + }, + // css/less → identity-obj-proxy(CSS-in-JS,测试不需要真实样式) + { find: /\.(css|less)$/, replacement: 'identity-obj-proxy' }, + ], + }, + test: { + globals: true, + environment: 'jsdom', + setupFiles: [r('vitest.setup.ts')], + // POC:Vitest 的 snapshot key 格式与 Jest 不同(`A > B` vs `A B`)。将 Vitest 基线放在 + // 测试同目录的 __snapshots__/vitest/ 子目录,与组件就近存放;Jest 通过 + // modulePathIgnorePatterns 忽略该子目录,避免在 --ci 下把它判为 obsolete 而报错。 + resolveSnapshotPath: (testPath, snapExtension) => { + const normalized = testPath.replace(/\\/g, '/'); + const dir = normalized.slice(0, normalized.lastIndexOf('/')); + const file = normalized.slice(normalized.lastIndexOf('/') + 1); + return `${dir}/__snapshots__/vitest/${file}${snapExtension}`; + }, + // include 覆盖全组件;exclude 是当前 Vitest 迁移进度的显式 manifest。 + // 维护规则: + // - 每次从 exclude 移除文件,都要先单跑该文件,再跑 npm run test:vitest。 + // - 只提交当前 collected test files 对应的 __snapshots__/vitest/*.snap。 + // - CI 的覆盖统计使用 vitest list --filesOnly;不要用普通 vitest list 统计文件数。 + // + // exclude 分四类: + // (A) 非 jsdom 环境 / 需独立配置的测试类型 + // (B) demo 测试——依赖 jest.requireActual 同步 shim,且 antd-style 的 style-class.tsx + // demo 在 Vitest 中因模块状态冲突无法加载(57 个组件受影响) + // (C) jest.mock() 提升问题——通过垫片间接调用不会被 Vitest 提升 + // (D) 其他兼容性问题(Tooltip popup 时序、requireActual 相对路径等) + include: ['components/**/__tests__/**/*.test.{ts,tsx}'], + exclude: [ + '**/node_modules/**', + // (A) 非 jsdom 环境测试 + '**/image.test.*', + '**/node.test.*', + '**/demo-semantic.test.*', + '**/a11y.test.*', + '**/type.test.*', + // (B) demo 测试(jest.requireActual shim + antd-style 模块冲突) + '**/demo.test.*', + '**/demo-extend.test.*', + // (C) jest.mock() 提升 / requireActual 相对路径 / ResizeObserver 兼容性等 + 'components/affix/__tests__/Affix.test.tsx', + 'components/__tests__/index.test.ts', + 'components/__tests__/17.test.ts', + 'components/__tests__/node.test.tsx', + 'components/_util/__tests__/useZIndex.test.tsx', + 'components/_util/__tests__/wave.test.tsx', + 'components/_util/__tests__/wave-util.test.tsx', + 'components/anchor/__tests__/Anchor.test.tsx', + 'components/auto-complete/__tests__/index.test.tsx', + 'components/auto-complete/__tests__/semantic.test.tsx', + 'components/avatar/__tests__/Avatar.test.tsx', + 'components/breadcrumb/__tests__/Breadcrumb.test.tsx', + 'components/button/__tests__/delay-timer.test.tsx', + 'components/button/__tests__/index.test.tsx', + 'components/button/__tests__/wave.test.tsx', + 'components/calendar/__tests__/index.test.tsx', + 'components/cascader/__tests__/index.test.tsx', + 'components/cascader/__tests__/semantic.test.tsx', + 'components/collapse/__tests__/index.test.tsx', + 'components/color-picker/__tests__/gradient.test.tsx', + 'components/color-picker/__tests__/index.test.tsx', + 'components/color-picker/__tests__/semantic.test.tsx', + 'components/config-provider/__tests__/components.test.tsx', + 'components/config-provider/__tests__/cssinjs.test.tsx', + 'components/config-provider/__tests__/form.test.tsx', + 'components/config-provider/__tests__/index.test.tsx', + 'components/config-provider/__tests__/locale.test.tsx', + 'components/config-provider/__tests__/motion.test.tsx', + 'components/config-provider/__tests__/nonce.test.tsx', + 'components/config-provider/__tests__/popup.test.tsx', + 'components/config-provider/__tests__/style.test.tsx', + 'components/config-provider/__tests__/wave.test.tsx', + 'components/date-picker/__tests__/DatePicker.test.tsx', + 'components/date-picker/__tests__/RangePicker.test.tsx', + 'components/descriptions/__tests__/index.test.tsx', + 'components/dropdown/__tests__/dropdown-button.test.tsx', + 'components/dropdown/__tests__/index.test.tsx', + 'components/dropdown/__tests__/semantic.test.tsx', + 'components/flex/__tests__/index.test.tsx', + 'components/float-button/__tests__/index.test.tsx', + 'components/form/__tests__/index.test.tsx', + 'components/grid/__tests__/gap.test.tsx', + 'components/grid/__tests__/index.test.tsx', + 'components/grid/__tests__/server.test.tsx', + 'components/input/__tests__/textarea.test.tsx', + 'components/layout/__tests__/index.test.tsx', + 'components/locale/__tests__/config.test.tsx', + 'components/masonry/__tests__/index.test.tsx', + 'components/mentions/__tests__/index.test.tsx', + 'components/menu/__tests__/index.test.tsx', + 'components/message/__tests__/config.test.tsx', + 'components/message/__tests__/hooks.test.tsx', + 'components/message/__tests__/immediately.test.tsx', + 'components/message/__tests__/index.test.tsx', + 'components/message/__tests__/semantic.test.tsx', + 'components/message/__tests__/static-warning.test.tsx', + 'components/message/__tests__/type.test.tsx', + 'components/modal/__tests__/confirm.test.tsx', + 'components/modal/__tests__/hook.test.tsx', + 'components/modal/__tests__/Modal.test.tsx', + 'components/modal/__tests__/static-warning.test.tsx', + 'components/notification/__tests__/config.test.tsx', + 'components/notification/__tests__/index.test.tsx', + 'components/notification/__tests__/placement.test.tsx', + 'components/notification/__tests__/semantic.test.tsx', + 'components/notification/__tests__/static-warning.test.tsx', + 'components/popconfirm/__tests__/index.test.tsx', + 'components/popconfirm/__tests__/semantic.test.tsx', + 'components/popover/__tests__/index.test.tsx', + 'components/popover/__tests__/semantic.test.tsx', + 'components/progress/__tests__/index.test.tsx', + 'components/progress/__tests__/placement.test.tsx', + 'components/segmented/__tests__/index.test.tsx', + 'components/select/__tests__/index.test.tsx', + 'components/select/__tests__/semantic.test.tsx', + 'components/slider/__tests__/index.test.tsx', + 'components/slider/__tests__/SliderTooltip.test.tsx', + 'components/slider/__tests__/tooltip.test.tsx', + 'components/space/__tests__/gap.test.tsx', + 'components/spin/__tests__/delay.test.tsx', + 'components/splitter/__tests__/index.test.tsx', + 'components/splitter/__tests__/lazy.test.tsx', + 'components/switch/__tests__/index.test.tsx', + 'components/switch/__tests__/semantic.test.tsx', + 'components/table/__tests__/semantic.test.tsx', + 'components/table/__tests__/Table.filter.test.tsx', + 'components/table/__tests__/Table.IE.test.tsx', + 'components/table/__tests__/Table.pagination.test.tsx', + 'components/table/__tests__/Table.rowSelection.test.tsx', + 'components/table/__tests__/Table.sorter.test.tsx', + 'components/table/__tests__/Table.test.tsx', + 'components/tabs/__tests__/index.test.tsx', + 'components/tag/__tests__/index.test.tsx', + 'components/time-picker/__tests__/index.test.tsx', + 'components/time-picker/__tests__/semantic.test.tsx', + 'components/tooltip/__tests__/semantic.test.tsx', + 'components/tooltip/__tests__/tooltip.test.tsx', + 'components/tour/__tests__/index.test.tsx', + 'components/transfer/__tests__/dropdown.test.tsx', + 'components/transfer/__tests__/index.test.tsx', + 'components/tree/__tests__/directory.test.tsx', + 'components/tree-select/__tests__/index.test.tsx', + 'components/typography/__tests__/copy.test.tsx', + 'components/typography/__tests__/editable.test.tsx', + 'components/typography/__tests__/ellipsis.test.tsx', + 'components/typography/__tests__/index.test.tsx', + 'components/upload/__tests__/upload.test.tsx', + 'components/upload/__tests__/uploadlist.test.tsx', + 'components/watermark/__tests__/index.test.tsx', + ], + environmentOptions: { + jsdom: { url: 'http://localhost' }, + }, + // 与 jest maxWorkers:'50%' 对齐,保证性能对比公平 + pool: 'threads', + server: { + deps: { + // 这些依赖内部 import 'antd',需经 Vite 处理才能命中 alias; + // 同时强制内联 ESM 依赖(对标 jest transformIgnorePatterns)。 + inline: [/@rc-component/, /rc-/, /@ant-design/, /antd-style/, /@emotion/], + }, + }, + }, +}); diff --git a/deps/swc/crates/swc_ts_fast_strip/benches/assets/docusaurus.config.ts b/deps/swc/crates/swc_ts_fast_strip/benches/assets/docusaurus.config.ts new file mode 100644 index 000000000..8c00701ef --- /dev/null +++ b/deps/swc/crates/swc_ts_fast_strip/benches/assets/docusaurus.config.ts @@ -0,0 +1,908 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import path from 'path'; +// eslint-disable-next-line import/default +import npm2yarn from '@docusaurus/remark-plugin-npm2yarn'; +import remarkMath from 'remark-math'; +import rehypeKatex from 'rehype-katex'; +import configTabs from './src/remark/configTabs'; + +import versions from './versions.json'; +import VersionsArchived from './versionsArchived.json'; +import { + dogfoodingPluginInstances, + dogfoodingThemeInstances, + dogfoodingRedirects, + dogfoodingTransformFrontMatter, + isArgosBuild, +} from './_dogfooding/dogfooding.config'; + +import ConfigLocalized from './docusaurus.config.localized.json'; + +import PrismLight from './src/utils/prismLight'; +import PrismDark from './src/utils/prismDark'; + +import type {Config, DocusaurusConfig, VcsPreset} from '@docusaurus/types'; + +import type * as Preset from '@docusaurus/preset-classic'; +import type {Options as DocsOptions} from '@docusaurus/plugin-content-docs'; +import type {Options as BlogOptions} from '@docusaurus/plugin-content-blog'; +import type {Options as PageOptions} from '@docusaurus/plugin-content-pages'; +import type {Options as IdealImageOptions} from '@docusaurus/plugin-ideal-image'; +import type {Options as ClientRedirectsOptions} from '@docusaurus/plugin-client-redirects'; +import type {ThemeConfig as LiveCodeBlockThemeConfig} from '@docusaurus/theme-live-codeblock'; + +type ThemeConfig = Preset.ThemeConfig & LiveCodeBlockThemeConfig; + +const ArchivedVersionsDropdownItems = Object.entries(VersionsArchived).splice( + 0, + 5, +); + +function isPrerelease(version: string) { + return ( + version.includes('-') || + version.includes('alpha') || + version.includes('beta') || + version.includes('rc') + ); +} + +function getLastStableVersion() { + const lastStableVersion = versions.find((version) => !isPrerelease(version)); + if (!lastStableVersion) { + throw new Error('unexpected, no stable Docusaurus version?'); + } + return lastStableVersion; +} +const announcedVersion = getAnnouncedVersion(); + +function getLastStableVersionTuple(): [string, string, string] { + const lastStableVersion = getLastStableVersion(); + const parts = lastStableVersion.split('.'); + if (parts.length !== 3) { + throw new Error(`Unexpected stable version name: ${lastStableVersion}`); + } + return [parts[0]!, parts[1]!, parts[2]!]; +} + +// The version announced on the homepage hero and announcement banner +// 3.3.2 => 3.3 +// 3.0.5 => 3.0 +function getAnnouncedVersion() { + const [major, minor] = getLastStableVersionTuple(); + return `${major}.${minor}`; +} + +// This probably only makes sense for the alpha/beta/rc phase, temporary +function getNextVersionName() { + return 'Canary'; + /* + const expectedPrefix = '2.0.0-rc.'; + + const lastReleasedVersion = versions[0]; + if (!lastReleasedVersion || !lastReleasedVersion.includes(expectedPrefix)) { + throw new Error( + 'this code is only meant to be used during the 2.0 alpha/beta/rc phase.', + ); + } + const version = parseInt(lastReleasedVersion.replace(expectedPrefix, ''), 10); + return `${expectedPrefix}${version + 1}`; + + */ +} + +// Artificial way to crash the SSR rendering and test errors +// See website/_dogfooding/_pages tests/crashTest.tsx +// Test with: DOCUSAURUS_CRASH_TEST=true pnpm build:website:fast +const crashTest = process.env.DOCUSAURUS_CRASH_TEST === 'true'; + +// By default, we use Docusaurus Faster +// DOCUSAURUS_SLOWER=true is useful for benchmarking faster against slower +// hyperfine --prepare 'pnpm clear:website' --runs 3 'DOCUSAURUS_SLOWER=true pnpm build:website:fast' 'pnpm build:website:fast' +const isSlower = process.env.DOCUSAURUS_SLOWER === 'true'; +if (isSlower) { + console.log('🐢 Using slower Docusaurus build'); +} + +const router = process.env + .DOCUSAURUS_ROUTER as DocusaurusConfig['future']['experimental_router']; + +const vcs = process.env.DOCUSAURUS_SITE_VCS as VcsPreset; + +const isDev = process.env.NODE_ENV === 'development'; + +// See https://docs.netlify.com/configure-builds/environment-variables/ +const isProductionDeployment = + !!process.env.NETLIFY && process.env.CONTEXT === 'production'; + +const isDeployPreview = + !!process.env.NETLIFY && process.env.CONTEXT === 'deploy-preview'; + +// Netlify branch deploy like "docusaurus-v2" +const isBranchDeploy = + !!process.env.NETLIFY && process.env.CONTEXT === 'branch-deploy'; + +// Used to debug production build issues faster +const isBuildFast = !!process.env.BUILD_FAST; + +const baseUrl = process.env.BASE_URL ?? '/'; + +// Special deployment for staging locales until they get enough translations +// https://app.netlify.com/sites/docusaurus-i18n-staging +// https://docusaurus-i18n-staging.netlify.app/ +const isI18nStaging = process.env.I18N_STAGING === 'true'; + +const isVersioningDisabled = !!process.env.DISABLE_VERSIONING || isI18nStaging; + +const isRsdoctor = process.env.RSDOCTOR === 'true'; + +/* +const TwitterSvg = + ''; +*/ + +const defaultLocale = 'en'; + +function getLocalizedConfigValue(key: keyof typeof ConfigLocalized) { + const currentLocale = process.env.DOCUSAURUS_CURRENT_LOCALE ?? defaultLocale; + const values = ConfigLocalized[key]; + if (!values) { + throw new Error(`Localized config key=${key} not found`); + } + const value = values[currentLocale] ?? values[defaultLocale]; + if (!value) { + throw new Error( + `Localized value for config key=${key} not found for both currentLocale=${currentLocale} or defaultLocale=${defaultLocale}`, + ); + } + return value; +} + +// By default, we don't want to run "git log" commands on i18n sites +// This makes localized sites build much slower on Netlify +// See also https://github.com/facebook/docusaurus/issues/11208 +// const showLastUpdate = process.env.DOCUSAURUS_CURRENT_LOCALE === defaultLocale; +const showLastUpdate = true; + +export default async function createConfigAsync() { + return { + title: 'Docusaurus', + tagline: getLocalizedConfigValue('tagline'), + organizationName: 'facebook', + projectName: 'docusaurus', + baseUrl, + baseUrlIssueBanner: true, + url: 'https://docusaurus.io', + future: { + v4: !isSlower, // Not accurate, but good enough + faster: isSlower + ? false + : { + // Verbose object: easier to independently test single attributes + swcJsLoader: true, + swcJsMinimizer: true, + swcHtmlMinimizer: true, + lightningCssMinimizer: true, + mdxCrossCompilerCache: true, + rspackBundler: true, + rspackPersistentCache: true, + ssgWorkerThreads: true, + gitEagerVcs: true, + }, + experimental_vcs: vcs, + experimental_router: router, + }, + // Dogfood both settings: + // - force trailing slashes for deploy previews + // - avoid trailing slashes in prod + trailingSlash: isDeployPreview, + stylesheets: [ + { + href: '/katex/katex.min.css', + type: 'text/css', + }, + ], + i18n: { + defaultLocale, + + localeConfigs: { + [defaultLocale]: { + // Forces the translation process to run for default locale + // Permits to dogfood translation key conflicts detection + translate: true, + }, + }, + + locales: + isDeployPreview || isBranchDeploy + ? // Deploy preview and branch deploys: keep them fast! + [defaultLocale] + : isI18nStaging + ? // Staging locales: https://docusaurus-i18n-staging.netlify.app/ + [defaultLocale, 'ja'] + : // Production locales + [defaultLocale, 'fr', 'pt-BR', 'ko', 'zh-CN'], + }, + markdown: { + format: 'detect', + mermaid: true, + hooks: { + onBrokenMarkdownLinks: 'warn', + }, + mdx1Compat: { + // Needed for us until Crowdin improves support + // See https://github.com/facebook/docusaurus/pull/11847#issuecomment-4183213345 + admonitions: true, + }, + remarkRehypeOptions: { + footnoteLabel: getLocalizedConfigValue('remarkRehypeOptions_footnotes'), + }, + parseFrontMatter: async (params) => { + const result = await params.defaultParseFrontMatter(params); + return { + ...result, + frontMatter: dogfoodingTransformFrontMatter(result.frontMatter), + }; + }, + preprocessor: ({filePath, fileContent}) => { + let result = fileContent; + + // This fixes Crowdin bug altering MDX comments on i18n sites... + // https://github.com/facebook/docusaurus/pull/9220 + result = result.replaceAll('{/_', '{/*'); + result = result.replaceAll('_/}', '*/}'); + + const showDevLink = false; + + if (isDev && showDevLink) { + const isPartial = path.basename(filePath).startsWith('_'); + if (!isPartial) { + // "vscode://file/${projectPath}${filePath}:${line}:${column}", + // "webstorm://open?file=${projectPath}${filePath}&line=${line}&column=${column}", + const vscodeLink = `vscode://file/${filePath}`; + const webstormLink = `webstorm://open?file=${filePath}`; + const intellijLink = `idea://open?file=${filePath}`; + result = `${result}\n\n---\n\n**DEV**: open this file in [VSCode](<${vscodeLink}>) | [WebStorm](<${webstormLink}>) | [IntelliJ](<${intellijLink}>)\n`; + } + } + + return result; + }, + }, + onBrokenLinks: + isVersioningDisabled || + process.env.DOCUSAURUS_CURRENT_LOCALE !== defaultLocale + ? 'warn' + : 'throw', + onBrokenAnchors: + isVersioningDisabled || + process.env.DOCUSAURUS_CURRENT_LOCALE !== defaultLocale + ? 'warn' + : 'throw', + favicon: 'img/docusaurus.ico', + customFields: { + crashTest, + isDeployPreview, + description: + 'An optimized site generator in React. Docusaurus helps you to move fast and write content. Build documentation websites, blogs, marketing pages, and more.', + announcedVersion, + }, + staticDirectories: [ + 'static', + path.join(__dirname, '_dogfooding/_asset-tests'), + // Adding a non-existent static directory. If user deleted `static` + // without specifying `staticDirectories: []`, build should still work + path.join(__dirname, '_dogfooding/non-existent'), + ], + themes: ['live-codeblock', ...dogfoodingThemeInstances], + plugins: [ + function disableExpensiveBundlerOptimizationPlugin() { + return { + name: 'disable-expensive-bundler-optimizations', + configureWebpack(_config, isServer) { + // This optimization is expensive and only reduces by 3% the JS + // Let's skip it for local and deploy preview builds + // See also https://github.com/facebook/docusaurus/discussions/11199 + return { + optimization: { + concatenateModules: isProductionDeployment ? !isServer : false, + }, + }; + }, + }; + }, + isRsdoctor && [ + 'rsdoctor', + { + rsdoctorOptions: { + disableTOSUpload: true, + supports: { + // https://rsdoctor.dev/config/options/options#generatetilegraph + generateTileGraph: true, + }, + linter: { + // See https://rsdoctor.dev/guide/usage/rule-config + rules: { + 'ecma-version-check': 'off', + 'duplicate-package': 'off', + }, + }, + }, + }, + ], + [ + './src/plugins/changelog/index.ts', + { + blogTitle: 'Docusaurus changelog', + // Not useful, but permits to run git commands earlier + // Otherwise the sitemap plugin will run them in postBuild() + showLastUpdateAuthor: showLastUpdate, + showLastUpdateTime: showLastUpdate, + blogDescription: + 'Keep yourself up-to-date about new features in every release', + blogSidebarCount: 'ALL', + blogSidebarTitle: 'Changelog', + routeBasePath: '/changelog', + showReadingTime: false, + postsPerPage: 20, + archiveBasePath: null, + authorsMapPath: 'authors.json', + feedOptions: { + type: 'all', + title: 'Docusaurus changelog', + description: + 'Keep yourself up-to-date about new features in every release', + copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`, + language: defaultLocale, + }, + onInlineAuthors: 'warn', + }, + ], + [ + 'content-docs', + { + id: 'community', + path: 'community', + routeBasePath: 'community', + editUrl: ({locale, versionDocsDirPath, docPath}) => { + if (locale !== defaultLocale) { + return `https://crowdin.com/project/docusaurus-v2/${locale}`; + } + return `https://github.com/facebook/docusaurus/edit/main/website/${versionDocsDirPath}/${docPath}`; + }, + remarkPlugins: [npm2yarn], + editCurrentVersion: true, + sidebarPath: './sidebarsCommunity.js', + showLastUpdateAuthor: showLastUpdate, + showLastUpdateTime: showLastUpdate, + } satisfies DocsOptions, + ], + !process.env.DOCUSAURUS_SKIP_BUNDLING && [ + 'client-redirects', + { + fromExtensions: ['html'], + createRedirects(routePath) { + // Redirect to /docs from /docs/introduction (now docs root doc) + if (routePath === '/docs' || routePath === '/docs/') { + return [`${routePath}/introduction`]; + } + return []; + }, + redirects: [ + { + from: ['/docs/support', '/docs/next/support'], + to: '/community/support', + }, + { + from: ['/docs/team', '/docs/next/team'], + to: '/community/team', + }, + { + from: ['/docs/resources', '/docs/next/resources'], + to: '/community/resources', + }, + { + from: '/docs/api/misc/docusaurus-init', + to: '/docs/api/misc/create-docusaurus', + }, + ...dogfoodingRedirects, + ], + } satisfies ClientRedirectsOptions, + ], + [ + 'ideal-image', + { + quality: 70, + max: 1030, + min: 640, + steps: 2, + // Use false to debug, but it incurs huge perf costs + disableInDev: true, + } satisfies IdealImageOptions, + ], + [ + 'pwa', + { + // debug: isDeployPreview, + offlineModeActivationStrategies: [ + 'appInstalled', + 'standalone', + 'queryString', + ], + // swRegister: false, + swCustom: require.resolve('./src/sw.js'), // TODO make it possible to use relative path + pwaHead: [ + { + tagName: 'link', + rel: 'icon', + href: 'img/docusaurus.png', + }, + { + tagName: 'link', + rel: 'manifest', + href: 'manifest.json', + }, + { + tagName: 'meta', + name: 'theme-color', + content: 'rgb(37, 194, 160)', + }, + { + tagName: 'meta', + name: 'apple-mobile-web-app-capable', + content: 'yes', + }, + { + tagName: 'meta', + name: 'apple-mobile-web-app-status-bar-style', + content: '#000', + }, + { + tagName: 'link', + rel: 'apple-touch-icon', + href: 'img/docusaurus.png', + }, + { + tagName: 'link', + rel: 'mask-icon', + href: 'img/docusaurus.png', + color: 'rgb(62, 204, 94)', + }, + { + tagName: 'meta', + name: 'msapplication-TileImage', + content: 'img/docusaurus.png', + }, + { + tagName: 'meta', + name: 'msapplication-TileColor', + content: '#000', + }, + ], + }, + ], + '@docusaurus/theme-mermaid', + './src/plugins/featureRequests/FeatureRequestsPlugin.js', + ...dogfoodingPluginInstances, + ], + presets: [ + [ + 'classic', + { + debug: true, // force debug plugin usage + docs: { + // routeBasePath: '/', + path: 'docs', + sidebarPath: 'sidebars.ts', + // sidebarCollapsible: false, + // sidebarCollapsed: true, + editUrl: ({locale, docPath}) => { + if (locale !== defaultLocale) { + return `https://crowdin.com/project/docusaurus-v2/${locale}`; + } + // We want users to submit updates to the upstream/next version! + // Otherwise we risk losing the update on the next release. + const nextVersionDocsDirPath = 'docs'; + return `https://github.com/facebook/docusaurus/edit/main/website/${nextVersionDocsDirPath}/${docPath}`; + }, + admonitions: { + keywords: ['my-custom-admonition'], + }, + showLastUpdateAuthor: showLastUpdate, + showLastUpdateTime: showLastUpdate, + remarkPlugins: [[npm2yarn, {sync: true}], remarkMath, configTabs], + rehypePlugins: [rehypeKatex], + disableVersioning: isVersioningDisabled, + lastVersion: + isDev || + isVersioningDisabled || + isDeployPreview || + isBranchDeploy || + isBuildFast + ? 'current' + : getLastStableVersion(), + + onlyIncludeVersions: (() => { + if (isBuildFast) { + return ['current']; + } else if ( + !isVersioningDisabled && + (isDev || isDeployPreview || isBranchDeploy) + ) { + return ['current', ...versions.slice(0, 2)]; + } + return undefined; + })(), + versions: { + current: { + label: `${getNextVersionName()} 🚧`, + }, + }, + }, + blog: { + // routeBasePath: '/', + path: 'blog', + showLastUpdateAuthor: showLastUpdate, + showLastUpdateTime: showLastUpdate, + editUrl: ({locale, blogDirPath, blogPath}) => { + if (locale !== defaultLocale) { + return `https://crowdin.com/project/docusaurus-v2/${locale}`; + } + return `https://github.com/facebook/docusaurus/edit/main/website/${blogDirPath}/${blogPath}`; + }, + remarkPlugins: [npm2yarn], + postsPerPage: 5, + feedOptions: { + type: 'all', + description: + 'Keep up to date with upcoming Docusaurus releases and articles by following our feed!', + copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`, + xslt: true, + }, + blogTitle: 'Docusaurus blog', + blogDescription: 'Read blog posts about Docusaurus from the team', + blogSidebarCount: 'ALL', + blogSidebarTitle: 'All our posts', + onUntruncatedBlogPosts: + process.env.DOCUSAURUS_CURRENT_LOCALE !== defaultLocale + ? 'warn' + : 'throw', + onInlineTags: + process.env.DOCUSAURUS_CURRENT_LOCALE !== defaultLocale + ? 'warn' + : 'throw', + } satisfies BlogOptions, + pages: { + remarkPlugins: [npm2yarn], + editUrl: ({locale, pagesPath}) => { + if (locale !== defaultLocale) { + return `https://crowdin.com/project/docusaurus-v2/${locale}`; + } + return `https://github.com/facebook/docusaurus/edit/main/website/src/pages/${pagesPath}`; + }, + showLastUpdateAuthor: showLastUpdate, + showLastUpdateTime: showLastUpdate, + } satisfies PageOptions, + theme: { + customCss: [ + './src/css/custom.css', + // relative paths are relative to site dir + './_dogfooding/dogfooding.css', + ], + }, + gtag: !(isDeployPreview || isBranchDeploy) + ? { + trackingID: ['G-E5CR2Q1NRE'], + } + : undefined, + sitemap: { + ignorePatterns: isArgosBuild + ? undefined + : // Note: /tests/docs already has noIndex: true + ['/tests/{blog,pages}/**'], + lastmod: showLastUpdate ? 'date' : null, + priority: null, + changefreq: null, + }, + svgr: { + svgrConfig: { + svgoConfig: undefined, // Use .svgo.config.js + }, + }, + } satisfies Preset.Options, + ], + ], + + themeConfig: { + liveCodeBlock: { + playgroundPosition: 'bottom', + }, + docs: { + sidebar: { + hideable: true, + autoCollapseCategories: true, + }, + }, + colorMode: { + defaultMode: 'light', + disableSwitch: false, + respectPrefersColorScheme: true, + }, + announcementBar: { + id: `announcementBar-v${announcedVersion}`, + // content: `⭐️ If you like Docusaurus, give it a star on GitHub and follow us on X ${TwitterSvg}`, + content: `🎉️ Docusaurus v${announcedVersion} is out! 🥳️`, + }, + prism: { + additionalLanguages: [ + 'java', + 'latex', + 'haskell', + 'matlab', + 'PHp', + 'powershell', + 'bash', + 'diff', + 'json', + 'scss', + ], + magicComments: [ + { + className: 'theme-code-block-highlighted-line', + line: 'highlight-next-line', + block: {start: 'highlight-start', end: 'highlight-end'}, + }, + { + className: 'code-block-error-line', + line: 'This will error', + }, + ], + theme: PrismLight, + darkTheme: PrismDark, + }, + image: 'img/docusaurus-social-card.jpg', + // metadata: [{name: 'twitter:card', content: 'summary'}], + algolia: { + appId: 'X1Z85QJPUV', + apiKey: 'bf7211c161e8205da2f933a02534105a', + indexName: 'docusaurus-2', + + // TODO Docusaurus v4: remove after we drop DocSearch v3 + // temporary, for DocSearch v3/v4 conditional Ask AI integration + // see https://github.com/facebook/docusaurus/pull/11327 + ...(require('@docsearch/react').version.startsWith('4.') + ? { + askAi: { + // cSpell:ignore IMYF + assistantId: 'RgIMYFUmTfrN', + indexName: 'docusaurus-markdown', + suggestedQuestions: true, + }, + } + : {}), + + replaceSearchResultPathname: + isDev || isDeployPreview + ? { + from: /^\/docs\/next/g.source, + to: '/docs', + } + : undefined, + }, + navbar: { + hideOnScroll: true, + title: 'Docusaurus', + logo: { + alt: '', + src: 'img/docusaurus.svg', + srcDark: 'img/docusaurus_keytar.svg', + width: 32, + height: 32, + }, + items: [ + { + type: 'doc', + position: 'left', + docId: 'introduction', + label: 'Docs', + }, + { + type: 'docSidebar', + position: 'left', + sidebarId: 'api', + label: 'API', + }, + {to: 'blog', label: 'Blog', position: 'left'}, + {to: 'showcase', label: 'Showcase', position: 'left'}, + { + to: '/community/support', + label: 'Community', + position: 'left', + activeBaseRegex: `/community/`, + }, + // This item links to a draft doc: only displayed in dev + { + type: 'doc', + docId: 'index', + label: 'Tests', + docsPluginId: 'docs-tests', + }, + isDev && {to: '/__docusaurus/debug', label: 'Debug'}, + // Custom item for dogfooding: only displayed in /tests/ routes + { + type: 'custom-dogfood-navbar-item', + content: '😉', + }, + // Right + { + type: 'docsVersionDropdown', + position: 'right', + dropdownActiveClassDisabled: true, + dropdownItemsAfter: [ + { + type: 'html', + value: '', + }, + { + type: 'html', + className: 'dropdown-archived-versions', + value: 'Archived versions', + }, + ...ArchivedVersionsDropdownItems.map( + ([versionName, versionUrl]) => ({ + label: versionName, + href: versionUrl, + }), + ), + { + href: 'https://v1.docusaurus.io', + label: '1.x.x', + }, + { + type: 'html', + value: '', + }, + { + to: '/versions', + label: 'All versions', + }, + ], + }, + { + type: 'localeDropdown', + position: 'right', + dropdownItemsAfter: [ + { + type: 'html', + value: '
', + }, + { + href: 'https://github.com/facebook/docusaurus/issues/3526', + label: 'Help Us Translate', + }, + ], + }, + { + href: 'https://github.com/facebook/docusaurus', + position: 'right', + className: 'header-github-link', + 'aria-label': 'GitHub repository', + }, + ] + // TODO fix type + .filter(Boolean) as NonNullable< + Preset.ThemeConfig['navbar'] + >['items'], + }, + footer: { + style: 'dark', + links: [ + { + title: 'Learn', + items: [ + { + label: 'Introduction', + to: 'docs', + }, + { + label: 'Installation', + to: 'docs/installation', + }, + { + label: 'Migration from v1 to v2', + to: 'docs/migration', + }, + ], + }, + { + title: 'Community', + items: [ + { + label: 'Stack Overflow', + href: 'https://stackoverflow.com/questions/tagged/docusaurus', + }, + { + label: 'Feature Requests', + to: '/feature-requests', + }, + { + label: 'Discord', + href: 'https://discordapp.com/invite/docusaurus', + }, + { + label: 'Help', + to: '/community/support', + }, + ], + }, + { + title: 'More', + items: [ + { + label: 'Blog', + to: 'blog', + }, + { + label: 'Changelog', + to: '/changelog', + }, + { + label: 'GitHub', + href: 'https://github.com/facebook/docusaurus', + }, + { + label: 'X', + href: 'https://x.com/docusaurus', + }, + { + html: ` + + Deploys by Netlify + + `, + }, + { + html: ` + + Covered by Argos + + `, + }, + ], + }, + { + title: 'Legal', + className: 'footer-column-legal', + // Don't remove the privacy and terms, it's a legal requirement. + items: [ + { + label: 'Privacy', + className: 'footer-item-privacy', + href: 'https://opensource.facebook.com/legal/privacy/', + }, + { + label: 'Terms', + href: 'https://opensource.facebook.com/legal/terms/', + }, + { + label: 'Cookie Policy', + href: 'https://opensource.facebook.com/legal/cookie-policy/', + }, + ], + }, + ], + logo: { + alt: 'Meta Open Source Logo', + src: '/img/meta_opensource_logo_negative.svg', + href: 'https://opensource.fb.com', + }, + copyright: `Copyright © ${new Date().getFullYear()} Meta Platforms, Inc. Built with Docusaurus.`, + }, + } satisfies ThemeConfig, + } satisfies Config; +} diff --git a/deps/swc/crates/swc_ts_fast_strip/benches/assets/graphile.config.ts b/deps/swc/crates/swc_ts_fast_strip/benches/assets/graphile.config.ts new file mode 100644 index 000000000..1ec76f7d7 --- /dev/null +++ b/deps/swc/crates/swc_ts_fast_strip/benches/assets/graphile.config.ts @@ -0,0 +1,747 @@ +/* eslint-disable import/no-unresolved */ +import type { PgSelectSingleStep } from "@dataplan/pg"; +import PersistedPlugin from "@grafserv/persisted"; +import { EXPORTABLE, exportSchema } from "graphile-export"; +import { extendSchema, wrapPlans } from "graphile-utils"; +import * as jsonwebtoken from "jsonwebtoken"; +import type {} from "postgraphile"; +import { jsonParse } from "postgraphile/@dataplan/json"; +import { makePgService } from "postgraphile/adaptors/pg"; +import type { EdgeStep, ObjectStep } from "postgraphile/grafast"; +import { + connection, + constant, + context, + error, + isAsyncIterable, + lambda, + list, + listen, + object, + sideEffect, +} from "postgraphile/grafast"; +import { defaultMaskError } from "postgraphile/grafserv"; +import type {} from "postgraphile/grafserv/node"; +import { StreamDeferPlugin } from "postgraphile/graphile-build"; +import { PostGraphileAmberPreset } from "postgraphile/presets/amber"; +import { PgLazyJWTPreset } from "postgraphile/presets/lazy-jwt"; +import { PostGraphileRelayPreset } from "postgraphile/presets/relay"; +import { makeV4Preset } from "postgraphile/presets/v4"; + +// import { PgManyToManyPreset } from "../../contrib/pg-many-to-many/dist/index.js"; +// import { PostGraphileConnectionFilterPreset } from "../../contrib/postgraphile-plugin-connection-filter/dist/index.js"; + +// Every field plan is wrapped in a side effect; should this side effect log the results? +const LOG_RESULTS = false; + +const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +declare global { + namespace Grafast { + interface Context { + mol?: number; + number?: number; + } + } +} + +/* +const PrimaryKeyMutationsOnlyPlugin: GraphileConfig.Plugin = { + name: "PrimaryKeyMutationsOnlyPlugin", + version: "0.0.0", + + gather: { + hooks: { + pgIntrospection_introspection(info, event) { + const { introspection } = event; + for (const pgConstraint of introspection.constraints) { + if (pgConstraint.contype === "u") { + const tags = pgConstraint.getTags(); + const newBehavior = ["-update", "-delete"]; + if (typeof tags.behavior === "string") { + newBehavior.push(tags.behavior); + } else if (Array.isArray(tags.behavior)) { + newBehavior.push(...tags.behavior); + } + tags.behavior = newBehavior; + console.log(pgConstraint.getClass().relname, newBehavior); + } + } + }, + }, + }, +}; +*/ + +const HTML_ESCAPES = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", +}; +function escapeHTML(rawText: string): string { + return rawText.replace( + /[&<>"']/g, + (l) => HTML_ESCAPES[l as keyof typeof HTML_ESCAPES], + ); +} + +function ruruTitle(title: string): GraphileConfig.Plugin { + return { + name: "RuruTitlePlugin", + version: "0.0.0", + + grafserv: { + middleware: { + ruruHTML(next, event) { + const { htmlParts, request } = event; + htmlParts.titleTag = `${escapeHTML( + title + " | " + request.getHeader("host"), + )}`; + return next(); + }, + }, + }, + }; +} + +const RuruQueryParamsPlugin: GraphileConfig.Plugin = { + name: "RuruQueryParamsPlugin", + version: "0.0.0", + + grafserv: { + middleware: { + ruruHTML(next, event) { + const { htmlParts } = event; + htmlParts.headerScripts += ` + +`; + return next(); + }, + }, + }, +}; + +/** + * Update the URL search params with the current query and variables + */ +const RuruQueryParamsUpdatePlugin: GraphileConfig.Plugin = { + name: "RuruQueryParamsUpdatePlugin", + version: "0.0.0", + + grafserv: { + middleware: { + ruruHTML(next, event) { + const { htmlParts } = event; + htmlParts.headerScripts += ` + +`; + return next(); + }, + }, + }, +}; + +const ExportSchemaPlugin: GraphileConfig.Plugin = { + name: "ExportSchemaPlugin", + version: "0.0.0", + + schema: { + hooks: { + finalize(schema) { + exportSchema(schema, `${__dirname}/exported-schema.mjs`, { + mode: "typeDefs", + modules: { + jsonwebtoken, + }, + }).catch((e) => { + console.error(e); + }); + return schema; + }, + }, + }, +}; + +const NonNullRelationsPlugin: GraphileConfig.Plugin = { + name: "NonNullRelationsPlugin", + description: + "Makes foreign key fields non-nullable if their columns are all `not null`", + version: "0.0.0", + + schema: { + hooks: { + // Hook a field that has already been defined + GraphQLObjectType_fields_field(field, build, context) { + const { + graphql: { GraphQLNonNull, getNullableType }, + input: { pgRegistry }, + } = build; + // Extract details about why this field was defined. + const { isPgSingleRelationField, pgRelationDetails } = context.scope; + // See if the field was defined for a singular relation + if (isPgSingleRelationField && pgRelationDetails) { + // If so, extract details about the relation + const { codec, relationName } = pgRelationDetails; + // Look up the relation in the registry + const relation = pgRegistry.pgRelations[codec.name][relationName]; + // Determine if every column is non-null + const everyColumnIsNonNull = relation.localAttributes.every( + (attrName) => codec.attributes[attrName].notNull, + ); + if (!relation.isReferencee && everyColumnIsNonNull) { + // If so, change the type of the field to be non-nullable + field.type = new GraphQLNonNull(getNullableType(field.type)); + } + } + return field; + }, + }, + }, +}; + +const LeftArmPlugin = extendSchema((build) => { + const { left_arm } = build.input.pgRegistry.pgResources; + return { + typeDefs: /* GraphQL */ ` + extend type Person { + allArms: PersonRelatedArmConnection + } + type PersonRelatedArmConnection { + edges: [PersonRelatedArmEdge] + } + type PersonRelatedArmEdge { + node: LeftArm + isTheirs: Boolean + } + `, + objects: { + Person: { + plans: { + allArms: EXPORTABLE( + (connection, left_arm, object) => ($person) => { + const $arms = left_arm.find(); + + return connection($arms, { + edgeDataPlan($arm) { + return object({ arm: $arm, person: $person }); + }, + }); + }, + [connection, left_arm, object], + ), + }, + }, + PersonRelatedArmEdge: { + plans: { + isTheirs: EXPORTABLE( + (aEqualsB, lambda) => + ( + $edge: EdgeStep< + any, + any, + ObjectStep<{ + arm: PgSelectSingleStep; + person: PgSelectSingleStep; + }> + >, + ) => { + const $obj = $edge.data(); + const $arm = $obj.get("arm"); + const $armPersonId = $arm.get("person_id"); + const $person = $obj.get("person"); + const $personId = $person.get("id"); + return lambda([$personId, $armPersonId], aEqualsB); + }, + [aEqualsB, lambda], + ), + }, + }, + }, + }; +}); + +const testResolver = EXPORTABLE( + (context, sideEffect) => + function () { + const $context = context(); + sideEffect($context, (context) => (context.number = 3)); + sideEffect($context, (context) => context.number!++); + sideEffect($context, (_context) => { + throw new Error("Side effect 3 failed"); + }); + sideEffect($context, (context) => context.number!++); + sideEffect($context, (context) => context.number!++); + return $context.get("number"); + }, + [context, sideEffect], +); + +const TestSideEffectCancellingPlugin = extendSchema({ + typeDefs: /* GraphQL */ ` + extend type Query { + testSideEffectCancelling: Int + } + extend type Mutation { + testSideEffectCancelling: Int + } + `, + objects: { + Mutation: { + plans: { + testSideEffectCancelling: testResolver, + }, + }, + Query: { + plans: { + testSideEffectCancelling: testResolver, + }, + }, + }, +}); + +const AddToResponseExtensionsPropertyPlugin: GraphileConfig.Plugin = { + name: "AddToResponseExtensionsPropertyPlugin", + + grafast: { + middleware: { + execute(next, event) { + return next.callback((error, result) => { + if (error) throw error; + const context = (event.args.contextValue ?? + Object.create(null)) as Grafast.Context; + if (!isAsyncIterable(result)) { + if (!result.extensions) result.extensions = Object.create(null); + result.extensions!.number = context.number; + } + return result; + }); + }, + }, + }, +}; + +const preset: GraphileConfig.Preset = { + plugins: [ + StreamDeferPlugin, + extendSchema((build) => { + const { + dataplanPg: { TYPES }, + } = build; + return { + typeDefs: /* GraphQL */ ` + extend type Person { + greet( + greeting: String! = "Hello" @deprecated(reason: "TESTING") + ): String + query: Query + } + extend type Query { + throw: Int + wrapMe: Int + } + `, + objects: { + Query: { + plans: { + wrapMe: EXPORTABLE((constant) => () => constant(42), [constant]), + throw: EXPORTABLE( + (error) => () => { + return error( + Object.assign( + new Error( + "You've requested the 'throw' field... which throws!", + ), + { + metadata: true, + mol: 42, + }, + ), + ); + }, + [error], + ), + }, + }, + Person: { + plans: { + greet: EXPORTABLE( + (TYPES) => + ($user: PgSelectSingleStep, { $greeting }) => { + const placeholderSql = $user.placeholder( + $greeting, + TYPES.text, + ); + return $user.select( + (sql) => sql`${placeholderSql} || ', ' || ${$user}.name`, + TYPES.text, + ); + }, + [TYPES], + ), + query: EXPORTABLE( + (constant) => () => { + return constant(true); + }, + [constant], + ), + }, + }, + }, + }; + }), + wrapPlans({ + Query: { + wrapMe(plan) { + return plan(); + }, + }, + Mutation: { + updatePost(plan) { + return plan(); + }, + }, + }), + extendSchema({ + typeDefs: /* GraphQL */ ` + extend type Query { + mol: Int + } + extend type Subscription { + sub(topic: String!): Int + gql(max: Int! = 10): Int + slow: String + } + `, + objects: { + Query: { + plans: { + mol: EXPORTABLE( + (context) => () => { + return context().get("mol"); + }, + [context], + ), + }, + }, + Subscription: { + plans: { + // Test via SQL: `NOTIFY test, '{"a":40}';` + sub: EXPORTABLE( + (context, jsonParse, listen, object) => (_$root, args) => { + const $topic = args.getRaw("topic"); + const $pgSubscriber = context().get("pgSubscriber"); + return listen($pgSubscriber, $topic, ($payload) => + object({ sub: jsonParse($payload).get("a" as never) }), + ); + }, + [context, jsonParse, listen, object], + ), + gql: { + resolve: EXPORTABLE( + () => + function resolve(e) { + return e; + }, + [], + ), + subscribe: EXPORTABLE( + (sleep) => + async function* subscribe(_, { max }) { + for (let i = 1; i <= max; i++) { + yield i; + await sleep(300); + } + }, + [sleep], + ), + }, + slow: { + resolve: EXPORTABLE( + () => + function resolve(e) { + return e; + }, + [], + ), + subscribe: EXPORTABLE( + (sleep) => + async function* subscribe() { + while (true) { + yield new Date().toISOString(); + // Wait two minutes between ticks + await sleep(120000); + } + }, + [sleep], + ), + }, + }, + }, + }, + }), + extendSchema({ + typeDefs: /* GraphQL */ ` + extend type Subscription { + error: Int + errorAfter(n: Int! = 3): Int + } + `, + objects: { + Subscription: { + plans: { + error: { + subscribePlan: EXPORTABLE( + (constant, lambda) => + function subscribePlan() { + return lambda(constant(3), () => { + throw new Error("Testing error"); + }); + }, + [constant, lambda], + ), + }, + errorAfter: { + subscribe: EXPORTABLE( + (sleep) => + async function* subscribe(_, { n }) { + for (let i = 0; i < n; i++) { + yield i; + await sleep(1000); + } + throw new Error(`Error after ${n}`); + }, + [sleep], + ), + resolve: EXPORTABLE( + () => + function resolve(i) { + return i; + }, + [], + ), + }, + }, + }, + }, + }), + // Testing errors + extendSchema({ + typeDefs: /* GraphQL */ ` + extend type Query { + errorTests: ErrorTests + } + extend type Subscription { + errorTests: ErrorTests + } + type ErrorTests { + nested: ErrorTests + nestedList: [ErrorTests] + index: Int + errorOnOddNumbers: Int! + fourtyTwo: Int! + nonNullableReturningNull: Int! + coercionFailure: Int + planningError: Int + } + `, + objects: { + Query: { + plans: { + errorTests: EXPORTABLE( + (constant) => () => constant({}), + [constant], + ), + }, + }, + Subscription: { + plans: { + errorTests: { + subscribePlan: EXPORTABLE( + (lambda, sleep) => () => { + return lambda(null, () => { + return (async function* () { + for (let index = 0; ; index++) { + yield { index }; + await sleep(1000); + } + })(); + }); + }, + [lambda, sleep], + ), + plan: EXPORTABLE( + () => + function plan($event) { + return $event; + }, + [], + ), + }, + }, + }, + ErrorTests: { + plans: { + planningError: EXPORTABLE( + () => () => { + throw new Error(`This error occurred during planning!`); + }, + [], + ), + nested: EXPORTABLE(() => ($test) => $test, []), + nestedList: EXPORTABLE((list) => ($test) => list([$test]), [list]), + errorOnOddNumbers: EXPORTABLE( + (lambda) => ($payload) => + lambda($payload, (p: any) => { + if (p.index % 2 === 1) { + throw new Error(`ODD! ${p.index}`); + } else { + return p.index; + } + }), + [lambda], + ), + fourtyTwo: EXPORTABLE((constant) => () => constant(42), [constant]), + nonNullableReturningNull: EXPORTABLE( + (constant) => () => constant(null), + [constant], + ), + coercionFailure: EXPORTABLE( + (constant) => () => constant("NOT A NUMBER"), + [constant], + ), + }, + }, + }, + }), + // PrimaryKeyMutationsOnlyPlugin, + PersistedPlugin, + ruruTitle(""), + ExportSchemaPlugin, + NonNullRelationsPlugin, + RuruQueryParamsPlugin, + RuruQueryParamsUpdatePlugin, + ...(Math.random() > 2 ? [LeftArmPlugin] : []), + TestSideEffectCancellingPlugin, + AddToResponseExtensionsPropertyPlugin, + wrapPlans( + () => true, + () => ({ + // autoApplyFieldArgs: false, + plan: EXPORTABLE( + (LOG_RESULTS, sideEffect) => (plan, _) => { + const $result = plan(); + sideEffect( + $result, + (r) => void (LOG_RESULTS ? console.dir(r) : null), + ); + return $result; + }, + [LOG_RESULTS, sideEffect], + ), + }), + ), + ], + extends: [ + PostGraphileAmberPreset, + makeV4Preset({ + simpleCollections: "both", + jwtPgTypeIdentifier: '"b"."jwt_token"', + dynamicJson: true, + graphiql: true, + graphiqlRoute: "/", + ignoreRBAC: false, + simpleSubscriptions: true, + }), + // PgManyToManyPreset, + // PostGraphileConnectionFilterPreset, + PostGraphileRelayPreset, + PgLazyJWTPreset, + ], + ruru: { + htmlParts: { + metaTags: (base) => base + "", + }, + }, + inflection: {}, + gather: { + pgJwtTypes: "b.jwt_token", + }, + schema: { + retryOnInitFail: true, + exportSchemaSDLPath: `${__dirname}/latestSchema.graphql`, + exportSchemaIntrospectionResultPath: `${__dirname}/latestSchema.json`, + sortExport: true, + pgJwtSecret: "FROGS", + }, + grafserv: { + port: 5678, + graphqlPath: "/graphql", + websockets: true, + graphqlOverGET: true, + persistedOperationsDirectory: `${process.cwd()}/.persisted_operations`, + allowUnpersistedOperation: true, + maskError(error) { + const masked = defaultMaskError(error); + const stack = error.originalError?.stack; + if (typeof stack === "string") { + masked.extensions.stack = stack.split(/\n/); + } + return masked; + }, + }, + grafast: { + context(requestContext, args) { + return { + number: -1, + pgSettings: { + // role: "postgres", + ...args.contextValue?.pgSettings, + }, + mol: 42, + }; + }, + explain: true, + }, + pgServices: [ + makePgService({ + // Database connection string: + connectionString: + process.env.DATABASE_URL ?? "postgres:///graphilecrystaltest", + // List of schemas to expose: + schemas: + process.env.DATABASE_SCHEMAS?.split(",") ?? + (process.env.DATABASE_URL ? ["public"] : ["a", "b", "c"]), + // Enable LISTEN/NOTIFY client + pubsub: true, + }), + ], +}; /* satisfies GraphileConfig.Preset */ + +function aEqualsB([a, b]: readonly [a: any, b: any]) { + return a === b; +} +export default preset; diff --git a/deps/swc/crates/swc_ts_fast_strip/benches/assets/hono.types.test.ts b/deps/swc/crates/swc_ts_fast_strip/benches/assets/hono.types.test.ts new file mode 100644 index 000000000..c8c3a44a9 --- /dev/null +++ b/deps/swc/crates/swc_ts_fast_strip/benches/assets/hono.types.test.ts @@ -0,0 +1,3294 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { expectTypeOf } from 'vitest' +import { hc } from './client' +import { Context } from './context' +import { createMiddleware } from './helper/factory' +import { Hono } from './hono' +import { poweredBy } from './middleware/powered-by' +import type { + AddParam, + Env, + ExtractSchema, + Handler, + InputToDataByTarget, + MergePath, + MergeSchemaPath, + MiddlewareHandler, + ParamKeyToRecord, + ParamKeys, + RemoveQuestion, + ResponseFormat, + ToSchema, + TypedResponse, +} from './types' +import type { ContentfulStatusCode, StatusCode } from './utils/http-status' +import type { Equal, Expect } from './utils/types' +import { validator } from './validator' + +describe('Env', () => { + test('Env', () => { + type E = { + Variables: { + foo: string + } + Bindings: { + FLAG: boolean + } + } + const app = new Hono() + app.use('*', poweredBy()) + app.get('/', (c) => { + const foo = c.get('foo') + expectTypeOf(foo).toEqualTypeOf() + const FLAG = c.env.FLAG + expectTypeOf(FLAG).toEqualTypeOf() + return c.text('foo') + }) + }) +}) + +describe('HandlerInterface', () => { + type Env = {} + + type Payload = { foo: string; bar: boolean } + + describe('no path pattern', () => { + const app = new Hono() + const middleware: MiddlewareHandler< + Env, + '/', + { + in: { json: Payload } + out: { json: Payload } + } + > = async (_c, next) => { + await next() + } + test('Context', () => { + const route = app.get(middleware, (c) => { + type Expected = Context< + Env, + '/', + { + in: { json: Payload } + out: { json: Payload } + } + > + expectTypeOf(c).toEqualTypeOf() + return c.json({ + message: 'Hello!', + }) + }) + app.get(middleware, (c) => { + const data = c.req.valid('json') + expectTypeOf(data).toEqualTypeOf() + return c.json({ + message: 'Hello!', + }) + }) + type Actual = ExtractSchema + type Expected = { + '/': { + $get: { + input: { + json: Payload + } + output: { + message: string + } + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + }) + + describe('path pattern', () => { + const app = new Hono() + const middleware: MiddlewareHandler< + Env, + '/foo', + { in: { json: Payload }; out: { json: Payload } }, + never + > = async (_c, next) => { + await next() + } + + test('Context and AppType', () => { + const route = app.get('/foo', middleware, (c) => { + type Expected = Context + expectTypeOf(c).toEqualTypeOf() + return c.json({ + message: 'Hello!', + }) + }) + type Actual = ExtractSchema + type Expected = { + '/foo': { + $get: { + input: { + json: { + foo: string + bar: boolean + } + } + output: { + message: string + } + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + }) + + describe('With path parameters', () => { + const app = new Hono() + const middleware: MiddlewareHandler = async (_c, next) => { + await next() + } + it('Should have the `param` type', () => { + const route = app.get('/post/:id', middleware, (c) => { + return c.text('foo') + }) + type Actual = ExtractSchema + type Expected = { + '/post/:id': { + $get: { + input: { + param: { + id: string + } + } + output: 'foo' + outputFormat: 'text' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + }) + + describe('Without path', () => { + const app = new Hono().basePath('/foo/:foo') + + it('With basePath and path params', () => { + const route = app.get(async (c) => { + const foo = c.req.param('foo') + expect(typeof foo).toBe('string') + return c.text(foo) + }) + type Actual = ExtractSchema + + type Expected = { + '/foo/:foo': { + $get: { + input: { + param: { + foo: string + } + } + output: string + outputFormat: 'text' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + + it('Chained', () => { + const route = app.post('/books/:id').get((c) => { + const id = c.req.param('id') + return c.text(id) + }) + type Actual = ExtractSchema + type Expected = { + '/foo/:foo/books/:id': { + $get: { + input: { + param: { + id: string + } & { + foo: string + } + } + output: string + outputFormat: 'text' + status: ContentfulStatusCode + } + } + } & { + '/foo/:foo/books/:id': { + $post: { + input: { + param: { + id: string + } & { + foo: string + } + } + output: {} + outputFormat: ResponseFormat + status: StatusCode + } + } + } + type verify = Expect> + }) + }) +}) + +describe('OnHandlerInterface', () => { + const app = new Hono() + test('Context', () => { + const middleware: MiddlewareHandler< + Env, + '/purge', + { in: { form: { id: string } }; out: { form: { id: number } } } + > = async (_c, next) => { + await next() + } + const route = app.on('PURGE', '/purge', middleware, (c) => { + const data = c.req.valid('form') + expectTypeOf(data).toEqualTypeOf<{ id: number }>() + return c.json({ + success: true, + }) + }) + type Actual = ExtractSchema + type Expected = { + '/purge': { + $purge: { + input: { + form: { + id: string + } + } + output: { + success: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + + test('app.on(method, path[], middleware, handler) should not throw a type error', () => { + const middleware: MiddlewareHandler<{ Variables: { foo: string } }> = async () => {} + app.on('GET', ['/a', '/b'], middleware, (c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + return c.json({}) + }) + }) +}) + +describe('TypedResponse', () => { + test('unknown', () => { + type Actual = TypedResponse + type Expected = { + _data: unknown + _status: StatusCode + _format: ResponseFormat + } + type verify = Expect> + }) + + test('text auto infer', () => { + type Actual = TypedResponse + type Expected = { + _data: string + _status: StatusCode + _format: 'text' + } + type verify = Expect> + }) + + test('json auto infer', () => { + type Actual = TypedResponse<{ ok: true }> + type Expected = { + _data: { ok: true } + _status: StatusCode + _format: 'json' + } + type verify = Expect> + }) +}) + +describe('Schema', () => { + test('Schema', () => { + type AppType = Hono< + Env, + ToSchema< + 'post', + '/api/posts/:id', + { + in: { + json: { + id: number + title: string + } + } + }, + TypedResponse< + { + message: string + success: boolean + }, + StatusCode, + 'json' + > + > + > + + type Actual = ExtractSchema + type Expected = { + '/api/posts/:id': { + $post: { + input: { + json: { + id: number + title: string + } + } & { + param: { + id: string + } + } + output: { + message: string + success: boolean + } + outputFormat: 'json' + status: StatusCode + } + } + } + type verify = Expect> + }) +}) + +describe('Support c.json(undefined)', () => { + it('Should return a correct type', () => { + const app = new Hono().get('/this/is/a/test', async (c) => { + return c.json(undefined) + }) + type Actual = ExtractSchema + type Expected = { + '/this/is/a/test': { + $get: { + input: {} + output: never + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) +}) + +describe('Test types of Handler', () => { + type E = { + Variables: { + foo: number + } + } + + const url = 'http://localhost/' + + test('Env', async () => { + const app = new Hono() + const handler: Handler = (c) => { + const foo = c.get('foo') + expectTypeOf(foo).toEqualTypeOf() + const id = c.req.param('id') + expectTypeOf(id).toEqualTypeOf() + return c.text('Hi') + } + app.get('/', handler) + const res = await app.request(url) + expect(res.status).toBe(200) + }) + + test('Env, Path', async () => { + const app = new Hono() + const handler: Handler = (c) => { + const foo = c.get('foo') + expectTypeOf(foo).toEqualTypeOf() + return c.text('Hi') + } + app.get('/', handler) + + const res = await app.request(url) + expect(res.status).toBe(200) + }) + + type User = { + name: string + age: number + } + + test('Env, Path, Type', async () => { + const app = new Hono() + const handler: Handler = (c) => { + const foo = c.get('foo') + expectTypeOf(foo).toEqualTypeOf() + const { name } = c.req.valid('json') + expectTypeOf(name).toEqualTypeOf() + return c.text('Hi') + } + }) +}) + +describe('`json()`', () => { + const app = new Hono<{ Variables: { foo: string } }>() + app.get('/post/:id', (c) => { + c.req.param('id') + const id = c.req.param('id') + return c.text('foo') + }) + + test('json', () => { + const route = app.get('/hello', (c) => { + return c.json({ + message: 'Hello!', + }) + }) + type Actual = ExtractSchema + type Expected = { + '/hello': { + $get: { + input: {} + output: { + message: string + } + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + + test('json with specific status code', () => { + const route = app.get('/hello', (c) => { + return c.json( + { + message: 'Hello!', + }, + 200 + ) + }) + type Actual = ExtractSchema + type Expected = { + '/hello': { + $get: { + input: {} + output: { + message: string + } + outputFormat: 'json' + status: 200 + } + } + } + type verify = Expect> + }) +}) + +describe('Path parameters', () => { + test('ParamKeys', () => { + type Actual = ParamKeys<'/posts/:postId/comment/:commentId'> + type Expected = 'postId' | 'commentId' + type verify = Expect> + }) + + describe('ParamKeyToRecord', () => { + test('With ?', () => { + type Actual = ParamKeyToRecord<'/animal/type?'> + type Expected = { [K in '/animal/type']: string | undefined } + type verify = Expect> + }) + test('Without ?', () => { + type Actual = ParamKeyToRecord<'/animal/type'> + type Expected = { [K in '/animal/type']: string } + type verify = Expect> + }) + }) + + describe('Path parameters in app', () => { + test('Optional parameters - /api/:a/:b?', () => { + const app = new Hono() + const routes = app.get('/api/:a/:b?', (c) => { + const a = c.req.param('a') + const b = c.req.param('b') + expectTypeOf(a).toEqualTypeOf() + expectTypeOf(b).toEqualTypeOf() + return c.json({ a, b }) + }) + type T = ExtractSchema + type Output = T['/api/:a/:b?']['$get']['output'] + type Expected = { + a: string + b: string | undefined + } + type verify = Expect> + }) + }) +}) + +describe('For HonoRequest', () => { + type Input = { + json: { + id: number + title: string + } + query: { + page: string + } + } + + test('InputToDataByType with value', () => { + type Actual = InputToDataByTarget + type Expected = { + id: number + title: string + } + type verify = Expect> + }) + + test('InputToDataByType without value', () => { + type Actual = InputToDataByTarget + type verify = Expect> + }) + + test('RemoveQuestion', () => { + type Actual = RemoveQuestion<'/animal/type?'> + type verify = Expect> + }) +}) + +describe('AddParam', () => { + it('Should add params to input correctly', () => { + type Actual = AddParam< + { + param: { + id: string + } + } & { + query: { + page: string + } + }, + '/:id' + > + type Expected = { + query: { + page: string + } + } & { + param: { + id: string + } + } + type verify = Expect> + }) +}) + +describe('ToSchema', () => { + it('Should convert parameters to schema correctly', () => { + type Actual = ToSchema< + 'get', + '/:id', + { in: { param: { id: string }; query: { page: string } } }, + TypedResponse<{}> + > + type Expected = { + '/:id': { + $get: { + input: { + param: { + id: string + } + query: { + page: string + } + } + output: {} + outputFormat: 'json' + status: StatusCode + } + } + } + type verify = Expect> + }) +}) + +describe('MergePath', () => { + it('Should merge paths correctly', () => { + type path1 = MergePath<'/api', '/book'> + type verify1 = Expect> + type path2 = MergePath<'/api/', '/book'> + type verify2 = Expect> + type path3 = MergePath<'/api/', '/'> + type verify3 = Expect> + type path4 = MergePath<'/api', '/'> + type verify4 = Expect> + type path5 = MergePath<'/', ''> + type verify5 = Expect> + type path6 = MergePath<'', '/'> + type verify6 = Expect> + type path7 = MergePath<'/', '/'> + type verify7 = Expect> + type path8 = MergePath<'', ''> + type verify8 = Expect> + }) +}) + +describe('MergeSchemaPath', () => { + it('Should merge schema and sub path correctly', () => { + type Sub = ToSchema< + 'post', + '/posts', + { + in: { + json: { + id: number + title: string + } + } + }, + TypedResponse<{ + message: string + }> + > & + ToSchema< + 'get', + '/posts', + {}, + TypedResponse<{ + ok: boolean + }> + > + + type Actual = MergeSchemaPath + + type Expected = { + '/api/posts': { + $post: { + input: { + json: { + id: number + title: string + } + } + output: { + message: string + } + outputFormat: 'json' + status: StatusCode + } + $get: { + input: {} + output: { + ok: boolean + } + outputFormat: 'json' + status: StatusCode + } + } + } + + type verify = Expect> + }) + + it('Should merge schema which has params and sub path does not have params', () => { + type Actual = MergeSchemaPath< + { + '/': { + $get: { + input: { + param: { + id: string + } + query: { + page: string + } + } + output: {} + outputFormat: 'json' + status: StatusCode + } + } + }, + '/something' + > + type Expected = { + '/something': { + $get: { + input: { + param: { + id: string + } + query: { + page: string + } + } + output: {} + outputFormat: 'json' + status: StatusCode + } + } + } + type verify = Expect> + }) + + type GetKey = T extends Record ? K : never + + it('Should remove a slash - `/` + `/`', () => { + type Sub = ToSchema<'get', '/', {}, TypedResponse<{}>> + type Actual = MergeSchemaPath + type verify = Expect>> + }) + + it('Should remove a slash - `/tags` + `/`', () => { + type Sub = ToSchema<'get', '/tags', {}, TypedResponse<{}>> + type Actual = MergeSchemaPath + type verify = Expect>> + }) + + it('Should remove a slash - `/` + `/tags`', () => { + type Sub = ToSchema<'get', '/', {}, TypedResponse<{}>> + type Actual = MergeSchemaPath + type verify = Expect>> + }) + + test('MergeSchemaPath - SubPath has path params', () => { + type Actual = MergeSchemaPath, '/a/:b'> + type Expected = { + '/a/:b': { + $get: { + input: { + param: { + b: string + } + } + output: {} + outputFormat: ResponseFormat + status: StatusCode + } + } + } + type verify = Expect> + }) + + test('MergeSchemaPath - Path and SubPath have path params', () => { + type Actual = MergeSchemaPath>, '/a/:b'> + type Expected = { + '/a/:b/c/:d': { + $get: { + input: { + param: { + d: string + } & { + b: string + } + } + output: {} + outputFormat: 'json' + status: StatusCode + } + } + } + type verify = Expect> + }) + + test('MergeSchemaPath - Path and SubPath have regexp path params', () => { + type Actual = MergeSchemaPath>, '/a/:b{.+}'> + type Expected = { + '/a/:b{.+}/c/:d{.+}': { + $get: { + input: { + param: { + d: string + } & { + b: string + } + } + output: {} + outputFormat: 'json' + status: StatusCode + } + } + } + type verify = Expect> + }) + + test('MergeSchemaPath - Method has Endpoints as Union', () => { + type Actual = MergeSchemaPath< + { + '/': { + $get: + | { + input: {} + output: { + error: string + } + outputFormat: 'json' + status: 404 + } + | { + input: {} + output: { + success: boolean + } + outputFormat: 'json' + status: 200 + } + } + }, + '/api/hello' + > + type Expected = { + '/api/hello': { + $get: + | { + input: {} + output: { + error: string + } + outputFormat: 'json' + status: 404 + } + | { + input: {} + output: { + success: boolean + } + outputFormat: 'json' + status: 200 + } + } + } + type verify = Expect> + }) +}) + +describe('Different types using json()', () => { + describe('no path pattern', () => { + const app = new Hono() + + test('Three different types', () => { + const route = app.get((c) => { + const flag = false + if (flag) { + return c.json({ + ng: true, + }) + } + if (!flag) { + return c.json({ + ok: true, + }) + } + return c.json({ + default: true, + }) + }) + type Actual = ExtractSchema + type Expected = { + '/': { + $get: + | { + input: {} + output: { + ng: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + | { + input: {} + output: { + ok: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + | { + input: {} + output: { + default: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + + test('Three different types and status codes', () => { + const route = app.get((c) => { + const flag = false + if (flag) { + return c.json( + { + ng: true, + }, + 400 + ) + } + if (!flag) { + return c.json( + { + ok: true, + }, + 200 + ) + } + return c.json({ + default: true, + }) + }) + type Actual = ExtractSchema + type Expected = { + '/': { + $get: + | { + input: {} + output: { + ng: true + } + outputFormat: 'json' + status: 400 + } + | { + input: {} + output: { + ok: true + } + outputFormat: 'json' + status: 200 + } + | { + input: {} + output: { + default: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + }) + + describe('path pattern', () => { + const app = new Hono() + + test('Three different types', () => { + const route = app.get('/foo', (c) => { + const flag = false + if (flag) { + return c.json({ + ng: true, + }) + } + if (!flag) { + return c.json({ + ok: true, + }) + } + return c.json({ + default: true, + }) + }) + type Actual = ExtractSchema + type Expected = { + '/foo': { + $get: + | { + input: {} + output: { + ng: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + | { + input: {} + output: { + ok: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + | { + input: {} + output: { + default: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + + test('Three different types and status codes', () => { + const route = app.get('/foo', (c) => { + const flag = false + if (flag) { + return c.json( + { + ng: true, + }, + 400 + ) + } + if (!flag) { + return c.json( + { + ok: true, + }, + 200 + ) + } + return c.json({ + default: true, + }) + }) + type Actual = ExtractSchema + type Expected = { + '/foo': { + $get: + | { + input: {} + output: { + ng: true + } + outputFormat: 'json' + status: 400 + } + | { + input: {} + output: { + ok: true + } + outputFormat: 'json' + status: 200 + } + | { + input: {} + output: { + default: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + }) +}) + +describe('json() in an async handler', () => { + const app = new Hono() + + test('json', () => { + const route = app.get(async (c) => { + return c.json({ + ok: true, + }) + }) + type Actual = ExtractSchema + type Expected = { + '/': { + $get: { + input: {} + output: { + ok: true + } + outputFormat: 'json' + status: ContentfulStatusCode + } + } + } + type verify = Expect> + }) + + test('json with specific status code', () => { + const route = app.get(async (c) => { + return c.json( + { + ok: true, + }, + 200 + ) + }) + type Actual = ExtractSchema + type Expected = { + '/': { + $get: { + input: {} + output: { + ok: true + } + outputFormat: 'json' + status: 200 + } + } + } + type verify = Expect> + }) +}) + +/** + * Other tests for `c.var` are written in `hono.test.ts`. + * This tests are only for types. + */ +describe('c.var with chaining - test only types', () => { + const mw1 = createMiddleware< + { Variables: { foo1: string } }, + string, + { out: { query: { bar1: number } } } + >(async () => {}) + const mw2 = createMiddleware< + { Variables: { foo2: string } }, + string, + { out: { query: { bar2: number } } } + >(async () => {}) + const mw3 = createMiddleware< + { Variables: { foo3: string } }, + string, + { out: { query: { bar3: number } } } + >(async () => {}) + const mw4 = createMiddleware< + { Variables: { foo4: string } }, + string, + { out: { query: { bar4: number } } } + >(async () => {}) + const mw5 = createMiddleware< + { Variables: { foo5: string } }, + string, + { out: { query: { bar5: number } } } + >(async () => {}) + const mw6 = createMiddleware< + { Variables: { foo6: string } }, + string, + { out: { query: { bar6: number } } } + >(async () => {}) + const mw7 = createMiddleware< + { Variables: { foo7: string } }, + string, + { out: { query: { bar7: number } } } + >(async () => {}) + const mw8 = createMiddleware< + { Variables: { foo8: string } }, + string, + { out: { query: { bar8: number } } } + >(async () => {}) + const mw9 = createMiddleware< + { Variables: { foo9: string } }, + string, + { out: { query: { bar9: number } } } + >(async () => {}) + const mw10 = createMiddleware< + { Variables: { foo10: string } }, + string, + { out: { query: { bar10: number } } } + >(async () => {}) + + it('Should not throw type errors', () => { + // app.get(handler...) + + new Hono().get(mw1).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get(mw1, mw2).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get(mw1, mw2, mw3).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get(mw1, mw2, mw3, mw4).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get(mw1, mw2, mw3, mw4, mw5).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get(mw1, mw2, mw3, mw4, mw5, mw6).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get(mw1, mw2, mw3, mw4, mw5, mw6, mw7).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + expectTypeOf(c.var.foo7).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get(mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + expectTypeOf(c.var.foo7).toEqualTypeOf() + expectTypeOf(c.var.foo8).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get(mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8, mw9).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + expectTypeOf(c.var.foo7).toEqualTypeOf() + expectTypeOf(c.var.foo8).toEqualTypeOf() + expectTypeOf(c.var.foo9).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get(mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8, mw9, mw10).get('/', (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + expectTypeOf(c.var.foo7).toEqualTypeOf() + expectTypeOf(c.var.foo8).toEqualTypeOf() + expectTypeOf(c.var.foo9).toEqualTypeOf() + expectTypeOf(c.var.foo10).toEqualTypeOf() + return c.json(0) + }) + + new Hono().get( + mw1, + mw2, + mw3, + mw4, + mw5, + mw6, + mw7, + mw8, + async (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + expectTypeOf(c.var.foo7).toEqualTypeOf() + expectTypeOf(c.var.foo8).toEqualTypeOf() + }, + (c) => c.json(0) + ) + + new Hono().get(mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8, mw9, (c) => { + expectTypeOf(c.req.valid('query')).toMatchTypeOf<{ + bar1: number + bar2: number + bar3: number + bar4: number + bar5: number + bar6: number + bar7: number + bar8: number + bar9: number + }>() + + return c.json(0) + }) + + new Hono().get( + '/', + mw1, + mw2, + mw3, + mw4, + mw5, + mw6, + mw7, + mw8, + async (c) => { + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + expectTypeOf(c.var.foo7).toEqualTypeOf() + expectTypeOf(c.var.foo8).toEqualTypeOf() + }, + (c) => c.json(0) + ) + + new Hono().get('/', mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8, mw9, (c) => { + expectTypeOf(c.req.valid('query')).toMatchTypeOf<{ + bar1: number + bar2: number + bar3: number + bar4: number + bar5: number + bar6: number + bar7: number + bar8: number + bar9: number + }>() + + return c.json(0) + }) + + type Env = { + Variables: { + init: number + } + } + + new Hono() + .get('/', mw1, (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.var.foo1).toEqualTypeOf() + return c.json(0) + }) + .get('/', (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + // @ts-expect-error foo1 is not typed + c.get('foo1') + // @ts-expect-error foo1 is not typed + c.var.foo1 + return c.json(0) + }) + new Hono() + .get('/', mw1, mw2, (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + return c.json(0) + }) + .get('/', (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + // @ts-expect-error foo1 is not typed + c.get('foo1') + // @ts-expect-error foo1 is not typed + c.var.foo1 + // @ts-expect-error foo2 is not typed + c.get('foo2') + // @ts-expect-error foo2 is not typed + c.var.foo2 + return c.json(0) + }) + new Hono() + .get('/', mw1, mw2, mw3, (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.get('foo3')).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + return c.json(0) + }) + .get('/', (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + // @ts-expect-error foo1 is not typed + c.get('foo1') + // @ts-expect-error foo1 is not typed + c.var.foo1 + // @ts-expect-error foo2 is not typed + c.get('foo2') + // @ts-expect-error foo2 is not typed + c.var.foo2 + // @ts-expect-error foo3 is not typed + c.get('foo3') + // @ts-expect-error foo3 is not typed + c.var.foo3 + return c.json(0) + }) + new Hono() + .get('/', mw1, mw2, mw3, mw4, (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.get('foo3')).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.get('foo4')).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + return c.json(0) + }) + .get('/', (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + // @ts-expect-error foo1 is not typed + c.get('foo1') + // @ts-expect-error foo1 is not typed + c.var.foo1 + // @ts-expect-error foo2 is not typed + c.get('foo2') + // @ts-expect-error foo2 is not typed + c.var.foo2 + // @ts-expect-error foo3 is not typed + c.get('foo3') + // @ts-expect-error foo3 is not typed + c.var.foo3 + // @ts-expect-error foo4 is not typed + c.get('foo4') + // @ts-expect-error foo4 is not typed + c.var.foo4 + return c.json(0) + }) + + new Hono() + .get('/', mw1, mw2, mw3, mw4, mw5, (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.get('foo3')).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.get('foo4')).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.get('foo5')).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + return c.json(0) + }) + .get('/', (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + // @ts-expect-error foo1 is not typed + c.get('foo1') + // @ts-expect-error foo1 is not typed + c.var.foo1 + // @ts-expect-error foo2 is not typed + c.get('foo2') + // @ts-expect-error foo2 is not typed + c.var.foo2 + // @ts-expect-error foo3 is not typed + c.get('foo3') + // @ts-expect-error foo3 is not typed + c.var.foo3 + // @ts-expect-error foo4 is not typed + c.get('foo4') + // @ts-expect-error foo4 is not typed + c.var.foo4 + // @ts-expect-error foo5 is not typed + c.get('foo5') + // @ts-expect-error foo5 is not typed + c.var.foo5 + return c.json(0) + }) + new Hono() + .get('/', mw1, mw2, mw3, mw4, mw5, mw6, (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.get('foo3')).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.get('foo4')).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.get('foo5')).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.get('foo6')).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + return c.json(0) + }) + .get('/', (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + // @ts-expect-error foo1 is not typed + c.get('foo1') + // @ts-expect-error foo1 is not typed + c.var.foo1 + // @ts-expect-error foo2 is not typed + c.get('foo2') + // @ts-expect-error foo2 is not typed + c.var.foo2 + // @ts-expect-error foo3 is not typed + c.get('foo3') + // @ts-expect-error foo3 is not typed + c.var.foo3 + // @ts-expect-error foo4 is not typed + c.get('foo4') + // @ts-expect-error foo4 is not typed + c.var.foo4 + // @ts-expect-error foo5 is not typed + c.get('foo5') + // @ts-expect-error foo5 is not typed + c.var.foo5 + // @ts-expect-error foo6 is not typed + c.get('foo6') + // @ts-expect-error foo6 is not typed + c.var.foo6 + return c.json(0) + }) + new Hono() + .get('/', mw1, mw2, mw3, mw4, mw5, mw6, mw7, (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.get('foo3')).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.get('foo4')).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.get('foo5')).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.get('foo6')).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + expectTypeOf(c.get('foo7')).toEqualTypeOf() + expectTypeOf(c.var.foo7).toEqualTypeOf() + return c.json(0) + }) + .get('/', (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + // @ts-expect-error foo1 is not typed + c.get('foo1') + // @ts-expect-error foo1 is not typed + c.var.foo1 + // @ts-expect-error foo2 is not typed + c.get('foo2') + // @ts-expect-error foo2 is not typed + c.var.foo2 + // @ts-expect-error foo3 is not typed + c.get('foo3') + // @ts-expect-error foo3 is not typed + c.var.foo3 + // @ts-expect-error foo4 is not typed + c.get('foo4') + // @ts-expect-error foo4 is not typed + c.var.foo4 + // @ts-expect-error foo5 is not typed + c.get('foo5') + // @ts-expect-error foo5 is not typed + c.var.foo5 + // @ts-expect-error foo6 is not typed + c.get('foo6') + // @ts-expect-error foo6 is not typed + c.var.foo6 + // @ts-expect-error foo7 is not typed + c.get('foo7') + // @ts-expect-error foo7 is not typed + c.var.foo7 + return c.json(0) + }) + new Hono() + .get('/', mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8, (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.get('foo3')).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.get('foo4')).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.get('foo5')).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.get('foo6')).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + expectTypeOf(c.get('foo7')).toEqualTypeOf() + expectTypeOf(c.var.foo7).toEqualTypeOf() + expectTypeOf(c.get('foo8')).toEqualTypeOf() + expectTypeOf(c.var.foo8).toEqualTypeOf() + return c.json(0) + }) + .get('/', (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + // @ts-expect-error foo1 is not typed + c.get('foo1') + // @ts-expect-error foo1 is not typed + c.var.foo1 + // @ts-expect-error foo2 is not typed + c.get('foo2') + // @ts-expect-error foo2 is not typed + c.var.foo2 + // @ts-expect-error foo3 is not typed + c.get('foo3') + // @ts-expect-error foo3 is not typed + c.var.foo3 + // @ts-expect-error foo4 is not typed + c.get('foo4') + // @ts-expect-error foo4 is not typed + c.var.foo4 + // @ts-expect-error foo5 is not typed + c.get('foo5') + // @ts-expect-error foo5 is not typed + c.var.foo5 + // @ts-expect-error foo6 is not typed + c.get('foo6') + // @ts-expect-error foo6 is not typed + c.var.foo6 + // @ts-expect-error foo7 is not typed + c.get('foo7') + // @ts-expect-error foo7 is not typed + c.var.foo7 + // @ts-expect-error foo8 is not typed + c.get('foo8') + // @ts-expect-error foo8 is not typed + c.var.foo8 + return c.json(0) + }) + + new Hono() + .get('/', mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8, mw9, (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.var.foo1).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + expectTypeOf(c.var.foo2).toEqualTypeOf() + expectTypeOf(c.get('foo3')).toEqualTypeOf() + expectTypeOf(c.var.foo3).toEqualTypeOf() + expectTypeOf(c.get('foo4')).toEqualTypeOf() + expectTypeOf(c.var.foo4).toEqualTypeOf() + expectTypeOf(c.get('foo5')).toEqualTypeOf() + expectTypeOf(c.var.foo5).toEqualTypeOf() + expectTypeOf(c.get('foo6')).toEqualTypeOf() + expectTypeOf(c.var.foo6).toEqualTypeOf() + expectTypeOf(c.get('foo7')).toEqualTypeOf() + expectTypeOf(c.var.foo7).toEqualTypeOf() + expectTypeOf(c.get('foo8')).toEqualTypeOf() + expectTypeOf(c.var.foo8).toEqualTypeOf() + expectTypeOf(c.get('foo9')).toEqualTypeOf() + expectTypeOf(c.var.foo9).toEqualTypeOf() + return c.json(0) + }) + .get('/', (c) => { + expectTypeOf(c.get('init')).toEqualTypeOf() + expectTypeOf(c.var.init).toEqualTypeOf() + // @ts-expect-error foo1 is not typed + c.get('foo1') + // @ts-expect-error foo1 is not typed + c.var.foo1 + // @ts-expect-error foo2 is not typed + c.get('foo2') + // @ts-expect-error foo2 is not typed + c.var.foo2 + // @ts-expect-error foo3 is not typed + c.get('foo3') + // @ts-expect-error foo3 is not typed + c.var.foo3 + // @ts-expect-error foo4 is not typed + c.get('foo4') + // @ts-expect-error foo4 is not typed + c.var.foo4 + // @ts-expect-error foo5 is not typed + c.get('foo5') + // @ts-expect-error foo5 is not typed + c.var.foo5 + // @ts-expect-error foo6 is not typed + c.get('foo6') + // @ts-expect-error foo6 is not typed + c.var.foo6 + // @ts-expect-error foo7 is not typed + c.get('foo7') + // @ts-expect-error foo7 is not typed + c.var.foo7 + // @ts-expect-error foo8 is not typed + c.get('foo8') + // @ts-expect-error foo8 is not typed + c.var.foo8 + // @ts-expect-error foo9 is not typed + c.get('foo9') + // @ts-expect-error foo9 is not typed + c.var.foo9 + return c.json(0) + }) + }) +}) + +/** + * + * Declaring a ContextVariableMap for testing. + */ +declare module './context' { + interface ContextVariableMap { + payload: string + } +} + +describe('ContextVariableMap type tests', () => { + it('Should not throw type errors with c.var', () => { + new Hono().get((c) => { + expectTypeOf(c.get('payload')).toEqualTypeOf() + return c.json(0) + }) + new Hono().get((c) => { + expectTypeOf(c.var.payload).toEqualTypeOf() + return c.json(0) + }) + }) + + it('Should override ContextVariableMap with env variables', () => { + const middleware = createMiddleware<{ + Variables: { + payload: number + } + }>(async (c, next) => { + c.set('payload', 123) + await next() + }) + + new Hono().get(middleware, (c) => { + expectTypeOf(c.get('payload')).toEqualTypeOf() + return c.json(0) + }) + }) + + it('Should use ContextVariableMap when c is Context', () => { + const c = new Context(new Request('http://localhost')) + expectTypeOf(c.get('payload')).toEqualTypeOf() + expectTypeOf(c.var.payload).toEqualTypeOf() + // @ts-expect-error the value of payload should be string + expectTypeOf(c.set('payload', 123)) + }) +}) + +/** + * It's challenge to test all cases. This is a minimal pattern. + */ +describe('Env types with chained routes - test only types', () => { + const app = new Hono<{ Variables: { testVar: string } }>() + it('Should not throw a type error', () => { + app + .post( + '/', + validator('json', (v) => v), + async (c) => { + expectTypeOf(c.get('testVar')).toEqualTypeOf() + return c.json({ success: true }) + } + ) + .patch( + '/', + validator('json', (v) => v), + async (c) => { + expectTypeOf(c.get('testVar')).toEqualTypeOf() + return c.json({ success: true }) + } + ) + }) +}) + +/** + * Ref: https://github.com/honojs/hono/issues/3027 + */ +describe('Env types with validator as first middleware - test only types', () => { + const app = new Hono<{ Variables: { testVar: string } }>() + it('Should not throw a type error', () => { + const testApp = app.get( + validator('json', () => { + return { + cd: 'bar', + } + }), + async (c) => { + const foo = c.req.valid('json') // Error here + return c.json(1) + } + ) + + const dummyMiddleware1 = createMiddleware(async (c, next) => { + await next() + }) + // Multiple levels of middleware + const testApp2 = app.post( + validator('json', () => { + return { + cd: 'bar', + } + }), + dummyMiddleware1, + createMiddleware(async (c, next) => { + await next() + }), + async (c) => { + const foo = c.req.valid('json') // Error here also + return c.json(1) + } + ) + }) +}) + +describe('Env types with `use` middleware - test only types', () => { + const app = new Hono() + + const mw1 = createMiddleware<{ Variables: { foo1: string } }>(async () => {}) + const mw2 = createMiddleware<{ Variables: { foo2: string } }>(async () => {}) + + it('Should not throw a type error', () => { + app + .use(mw1) + .use(mw2) + .get('/', (c) => { + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + return c.json({ success: true }) + }) + app.use(mw1, mw2).get('/', (c) => { + expectTypeOf(c.get('foo1')).toEqualTypeOf() + expectTypeOf(c.get('foo2')).toEqualTypeOf() + return c.json({ success: true }) + }) + }) +}) + +describe('Env types and a path type with `app.use(path, handler...)` - test only types', () => { + it('Should not throw a type error', () => { + type Env = { + Variables: { + foo: string + } + } + + // app.use(path, handler) + new Hono() + .use('/:id', async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + + // app.use(path, handler x2) + new Hono() + .use( + '/:id', + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + } + ) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + + // app.use(path, handler x3) + new Hono() + .use( + '/:id', + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + } + ) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + + // app.use(path, handler x4) + new Hono() + .use( + '/:id', + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + } + ) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + + // app.use(path, handler x5) + new Hono() + .use( + '/:id', + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + } + ) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + + // app.use(path, handler x6) + new Hono() + .use( + '/:id', + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + } + ) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + + // app.use(path, handler x7) + new Hono() + .use( + '/:id', + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + } + ) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + + // app.use(path, handler x8) + new Hono() + .use( + '/:id', + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + } + ) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + + // app.use(path, handler x9) + new Hono() + .use( + '/:id', + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + } + ) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + + // app.use(path, handler x10) + new Hono() + .use( + '/:id', + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + }, + async (c, next) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + await next() + } + ) + .get((c) => { + expectTypeOf(c.var.foo).toEqualTypeOf() + expectTypeOf(c.req.param('id')).toEqualTypeOf() + return c.json(0) + }) + }) +}) + +// https://github.com/honojs/hono/issues/3122 +describe('Returning type from `app.use(path, mw)`', () => { + const mw = createMiddleware(async (c, next) => { + await next() + }) + it('Should not mark `*` as never', () => { + const app = new Hono().use('*', mw) + type Actual = ExtractSchema + type Expected = { + '*': {} + } + type verify = Expect> + }) +}) + +describe('generic typed variables', () => { + const okHelper = (c: Context) => { + return (data: TData) => c.json({ data }) + } + type Variables = { + ok: ReturnType + } + const app = new Hono<{ Variables: Variables }>() + + it('Should set and get variables with correct types', async () => { + const route = app + .use('*', async (c, next) => { + c.set('ok', okHelper(c)) + await next() + }) + .get('/', (c) => { + const ok = c.get('ok') + return ok('Hello') + }) + type Actual = ExtractSchema['/']['$get']['output'] + type Expected = { data: string } + expectTypeOf().toEqualTypeOf() + }) +}) + +describe('status code', () => { + const app = new Hono() + + it('should only allow to return .json() with contentful status codes', async () => { + const route = app.get('/', async (c) => c.json({})) + type Actual = ExtractSchema['/']['$get']['status'] + expectTypeOf().toEqualTypeOf() + }) + + it('should only allow to return .body(null) with all status codes', async () => { + const route = app.get('/', async (c) => c.body(null)) + type Actual = ExtractSchema['/']['$get']['status'] + expectTypeOf().toEqualTypeOf() + }) + + it('should only allow to return .text() with contentful status codes', async () => { + const route = app.get('/', async (c) => c.text('whatever')) + type Actual = ExtractSchema['/']['$get']['status'] + expectTypeOf().toEqualTypeOf() + }) + + it('should throw type error when .json({}) is used with contentless status codes', async () => { + // @ts-expect-error 204 is not contentful status code + app.get('/', async (c) => c.json({}, 204)) + app.get('/', async (c) => + c.json( + {}, + // @ts-expect-error 204 is not contentful status code + { + status: 204, + } + ) + ) + }) + + it('should throw type error when .body(content) is used with contentless status codes', async () => { + // @ts-expect-error 204 is not contentful status code + app.get('/', async (c) => c.body('content', 204)) + // @ts-expect-error 204 is not contentful status code + app.get('/', async (c) => c.body('content', { status: 204 })) + }) + + it('should throw type error when .text(content) is used with contentless status codes', async () => { + // @ts-expect-error 204 is not contentful status code + app.get('/', async (c) => c.text('content', 204)) + // @ts-expect-error 204 is not contentful status code + app.get('/', async (c) => c.text('content', { status: 204 })) + }) + + it('should throw type error when .html(content) is used with contentless status codes', async () => { + // @ts-expect-error 204 is not contentful status code + app.get('/', async (c) => c.html('

title

', 204)) + // @ts-expect-error 204 is not contentful status code + app.get('/', async (c) => c.html('

title

', { status: 204 })) + }) + + it('.body() not override other responses in hono client', async () => { + const router = app.get('/', async (c) => { + if (c.req.header('Content-Type') === 'application/json') { + return c.text('Hello', 200) + } + + if (c.req.header('Content-Type') === 'application/x-www-form-urlencoded') { + return c.body('Hello', 201) + } + + return c.body(null, 204) + }) + + type Actual = ExtractSchema['/']['$get']['status'] + expectTypeOf().toEqualTypeOf<204 | 201 | 200>() + }) +}) + +describe('RPC supports Middleware responses', () => { + describe('Merge responses from multiple handlers, path pattern', () => { + test('merge responses from 1 middleware', async () => { + const middleware = createMiddleware(async (c) => c.json({ '400': true }, 400)) + + const app = new Hono().get('/test', middleware, (c) => c.json({ '200': true }, 200)) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.test.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + }) + + test('merge responses from 2 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + + const app = new Hono().get('/test', middleware1, middleware2, (c) => + c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.test.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + }) + + test('merge responses from 3 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + + const app = new Hono().get('/test', middleware1, middleware2, middleware3, (c) => + c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.test.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + }) + + test('merge responses from 4 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + + const app = new Hono().get('/test', middleware1, middleware2, middleware3, middleware4, (c) => + c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.test.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + }) + + test('merge responses from 5 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + + const app = new Hono().get( + '/test', + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.test.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + }) + + test('merge responses from 6 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + const middleware6 = createMiddleware(async (c) => c.json({ '201': true }, 201)) + + const app = new Hono().get( + '/test', + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + middleware6, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.test.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + if (res.status === 201) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 201: true }>() + } + }) + + test('merge responses from 7 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + const middleware6 = createMiddleware(async (c) => c.json({ '201': true }, 201)) + const middleware7 = createMiddleware(async (c) => c.json({ '202': true }, 202)) + + const app = new Hono().get( + '/test', + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + middleware6, + middleware7, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.test.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + if (res.status === 201) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 201: true }>() + } + if (res.status === 202) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 202: true }>() + } + }) + + test('merge responses from 8 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + const middleware6 = createMiddleware(async (c) => c.json({ '201': true }, 201)) + const middleware7 = createMiddleware(async (c) => c.json({ '202': true }, 202)) + const middleware8 = createMiddleware(async (c) => c.json({ '203': true }, 203)) + + const app = new Hono().get( + '/test', + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + middleware6, + middleware7, + middleware8, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.test.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + if (res.status === 201) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 201: true }>() + } + if (res.status === 202) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 202: true }>() + } + if (res.status === 203) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 203: true }>() + } + }) + + test('merge responses from 9 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + const middleware6 = createMiddleware(async (c) => c.json({ '201': true }, 201)) + const middleware7 = createMiddleware(async (c) => c.json({ '202': true }, 202)) + const middleware8 = createMiddleware(async (c) => c.json({ '203': true }, 203)) + const middleware9 = createMiddleware(async (c) => c.json({ '301': true }, 301)) + + const app = new Hono().get( + '/test', + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + middleware6, + middleware7, + middleware8, + middleware9, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.test.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + if (res.status === 201) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 201: true }>() + } + if (res.status === 202) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 202: true }>() + } + if (res.status === 203) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 203: true }>() + } + if (res.status === 301) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 301: true }>() + } + }) + }) + + describe('Merge responses from multiple handlers, no path pattern', () => { + test('merge responses from 1 middleware', async () => { + const middleware = createMiddleware(async (c) => c.json({ '400': true }, 400)) + + const app = new Hono().get(middleware, (c) => c.json({ '200': true }, 200)) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.index.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + }) + + test('merge responses from 2 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + + const app = new Hono().get(middleware1, middleware2, (c) => c.json({ '200': true }, 200)) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.index.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + }) + + test('merge responses from 3 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + + const app = new Hono().get(middleware1, middleware2, middleware3, (c) => + c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.index.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + }) + + test('merge responses from 4 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + + const app = new Hono().get(middleware1, middleware2, middleware3, middleware4, (c) => + c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.index.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + }) + + test('merge responses from 5 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + + const app = new Hono().get( + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.index.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + }) + + test('merge responses from 6 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + const middleware6 = createMiddleware(async (c) => c.json({ '201': true }, 201)) + + const app = new Hono().get( + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + middleware6, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.index.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + if (res.status === 201) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 201: true }>() + } + }) + + test('merge responses from 7 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + const middleware6 = createMiddleware(async (c) => c.json({ '201': true }, 201)) + const middleware7 = createMiddleware(async (c) => c.json({ '202': true }, 202)) + + const app = new Hono().get( + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + middleware6, + middleware7, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.index.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + if (res.status === 201) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 201: true }>() + } + if (res.status === 202) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 202: true }>() + } + }) + + test('merge responses from 8 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + const middleware6 = createMiddleware(async (c) => c.json({ '201': true }, 201)) + const middleware7 = createMiddleware(async (c) => c.json({ '202': true }, 202)) + const middleware8 = createMiddleware(async (c) => c.json({ '203': true }, 203)) + + const app = new Hono().get( + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + middleware6, + middleware7, + middleware8, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.index.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + if (res.status === 201) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 201: true }>() + } + if (res.status === 202) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 202: true }>() + } + if (res.status === 203) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 203: true }>() + } + }) + + test('merge responses from 9 middlewares', async () => { + const middleware1 = createMiddleware(async (c) => c.json({ '400': true }, 400)) + const middleware2 = createMiddleware(async (c) => c.json({ '401': true }, 401)) + const middleware3 = createMiddleware(async (c) => c.json({ '403': true }, 403)) + const middleware4 = createMiddleware(async (c) => c.json({ '404': true }, 404)) + const middleware5 = createMiddleware(async (c) => c.json({ '300': true }, 300)) + const middleware6 = createMiddleware(async (c) => c.json({ '201': true }, 201)) + const middleware7 = createMiddleware(async (c) => c.json({ '202': true }, 202)) + const middleware8 = createMiddleware(async (c) => c.json({ '203': true }, 203)) + const middleware9 = createMiddleware(async (c) => c.json({ '301': true }, 301)) + + const app = new Hono().get( + middleware1, + middleware2, + middleware3, + middleware4, + middleware5, + middleware6, + middleware7, + middleware8, + middleware9, + (c) => c.json({ '200': true }, 200) + ) + const client = hc('http://localhost', { fetch: app.request }) + const res = await client.index.$get() + + if (res.status === 200) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 200: true }>() + } + if (res.status === 400) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 400: true }>() + } + if (res.status === 401) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 401: true }>() + } + if (res.status === 403) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 403: true }>() + } + if (res.status === 404) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 404: true }>() + } + if (res.status === 300) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 300: true }>() + } + if (res.status === 201) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 201: true }>() + } + if (res.status === 202) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 202: true }>() + } + if (res.status === 203) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 203: true }>() + } + if (res.status === 301) { + expectTypeOf(await res.json()).toEqualTypeOf<{ 301: true }>() + } + }) + }) + + describe('Infers types with multiple middlewares but none returning response', () => { + const middleware = createMiddleware(async () => {}) + const handler = (c: Context) => c.json({ ok: true }, 200) + type Expected = { + '/': { + $get: { + input: {} + output: { + ok: true + } + outputFormat: 'json' + status: 200 + } + } + } + + test('infer the correct response type with 1 middleware and 1 handler', () => { + const routes = new Hono().get('/', middleware, handler) + type Actual = ExtractSchema + type verify = Expect> + }) + + test('infer the correct response type with 1 middleware and 2 handler', () => { + const routes = new Hono().get('/', middleware, handler, handler) + type Actual = ExtractSchema + type verify = Expect> + }) + + test('infer the correct response type with 2 middleware and 1 handler', () => { + const routes = new Hono().get('/', middleware, middleware, handler) + type Actual = ExtractSchema + type verify = Expect> + }) + + test('infer the correct response type with 3 middleware and 1 handler', () => { + const routes = new Hono().get('/', middleware, middleware, middleware, handler) + type Actual = ExtractSchema + type verify = Expect> + }) + + test('infer the correct response type with 4 middleware and 1 handler', () => { + const routes = new Hono().get('/', middleware, middleware, middleware, middleware, handler) + type Actual = ExtractSchema + type verify = Expect> + }) + + test('infer the correct response type with 5 middleware and 1 handler', () => { + const routes = new Hono().get( + '/', + middleware, + middleware, + middleware, + middleware, + middleware, + handler + ) + type Actual = ExtractSchema + type verify = Expect> + }) + + test('infer the correct response type with 6 middleware and 1 handler', () => { + const routes = new Hono().get( + '/', + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + handler + ) + type Actual = ExtractSchema + type verify = Expect> + }) + + test('infer the correct response type with 7 middleware and 1 handler', () => { + const routes = new Hono().get( + '/', + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + handler + ) + type Actual = ExtractSchema + type verify = Expect> + }) + + test('infer the correct response type with 8 middleware and 1 handler', () => { + const routes = new Hono().get( + '/', + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + handler + ) + type Actual = ExtractSchema + type verify = Expect> + }) + + test('infer the correct response type with 9 middleware and 1 handler', () => { + const routes = new Hono().get( + '/', + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + middleware, + handler + ) + type Actual = ExtractSchema + type verify = Expect> + }) + }) + + describe('Infers types with multiple middlewares but only some returning response', () => { + const handler = (c: Context) => c.json({ ok: true }, 200) + + test('infer the correct response type with 2 middleware, only one returning response', () => { + const middleware1 = async (c: Context) => { + if (Math.random() > 0.5) { + return c.json( + { + q: true, + }, + 200 + ) + } + } + const middleware2 = async () => {} + + const routes = new Hono().get('/', middleware1, middleware2, handler) + type Actual = ExtractSchema + type Expected = { + '/': { + $get: + | { + input: {} + output: { + ok: true + } + outputFormat: 'json' + status: 200 + } + | { + input: {} + output: { + q: true + } + outputFormat: 'json' + status: 200 + } + } + } + type verify = Expect> + }) + + test('infer the correct response type with 3 middleware, 2 returning response', () => { + const middleware1 = async (c: Context) => { + if (Math.random() > 0.5) { + return c.json( + { + q1: true, + }, + 200 + ) + } + } + const middleware2 = async (c: Context) => { + if (Math.random() > 0.5) { + return c.json( + { + q2: true, + }, + 200 + ) + } + } + const middleware3 = async () => {} + + const routes = new Hono().get('/', middleware1, middleware2, middleware3, handler) + type Actual = ExtractSchema + type Expected = { + '/': { + $get: + | { + input: {} + output: { + ok: true + } + outputFormat: 'json' + status: 200 + } + | { + input: {} + output: { + q1: true + } + outputFormat: 'json' + status: 200 + } + | { + input: {} + output: { + q2: true + } + outputFormat: 'json' + status: 200 + } + } + } + type verify = Expect> + }) + }) +}) diff --git a/deps/swc/crates/swc_ts_fast_strip/benches/assets/typescript-eslint.generate-configs.mts b/deps/swc/crates/swc_ts_fast_strip/benches/assets/typescript-eslint.generate-configs.mts new file mode 100644 index 000000000..9bd318804 --- /dev/null +++ b/deps/swc/crates/swc_ts_fast_strip/benches/assets/typescript-eslint.generate-configs.mts @@ -0,0 +1,454 @@ +import type { ESLintPluginRuleModule } from '@typescript-eslint/eslint-plugin/use-at-your-own-risk/rules'; +import type { + ClassicConfig, + FlatConfig, + Linter, + RuleRecommendation, +} from '@typescript-eslint/utils/ts-eslint'; + +import eslintPlugin from '@typescript-eslint/eslint-plugin'; +import fs from 'node:fs'; +import path from 'node:path'; +import prettier from 'prettier'; + +import { PACKAGES_ESLINT_PLUGIN, PRETTIER_CONFIG_PATH } from './paths.mts'; + +// no need for us to bring in an entire dependency for a few simple terminal colors +const chalk = { + blueBright: (val: string): string => `\x1B[94m${val}\x1B[39m`, + dim: (val: string): string => `\x1B[2m${val}\x1B[22m`, + gray: (val: string): string => `\x1B[90m${val}\x1B[39m`, + green: (val: string): string => `\x1B[32m${val}\x1B[39m`, + red: (val: string): string => `\x1B[31m${val}\x1B[39m`, +}; + +const AUTO_GENERATED_COMMENT_LINES = [ + '// THIS CODE WAS AUTOMATICALLY GENERATED', + '// DO NOT EDIT THIS CODE BY HAND', + '// SEE https://typescript-eslint.io/users/configs', + '//', + '// For developers working in the typescript-eslint monorepo:', + '// You can regenerate it using `pnpm run generate-configs`', + '', +] as const; + +const EXTENDS_MODULES = [ + { + moduleRelativePath: './base', + name: 'baseConfig', + packageRelativePath: './configs/eslintrc/base', + }, + { + moduleRelativePath: './eslint-recommended', + name: 'eslintRecommendedConfig', + packageRelativePath: './configs/eslintrc/eslint-recommended', + }, +] as const; +const CLASSIC_EXTENDS: readonly string[] = EXTENDS_MODULES.map( + mod => mod.packageRelativePath, +); + +function addAutoGeneratedComment(code?: string): string { + return [...AUTO_GENERATED_COMMENT_LINES, code].join('\n'); +} + +const prettierConfig = await prettier.resolveConfig('file.ts', { + config: PRETTIER_CONFIG_PATH, +}); + +type LinterConfigRules = Record< + string, + [ClassicConfig.RuleLevel, ...unknown[]] | ClassicConfig.RuleLevel +>; + +interface LinterConfig extends ClassicConfig.Config { + extends?: string | string[]; + plugins?: string[]; +} + +const RULE_NAME_PREFIX = '@typescript-eslint/'; +const MAX_RULE_NAME_LENGTH = Math.max( + ...Object.keys(eslintPlugin.rules).map(name => name.length), +); +const BASE_RULES_TO_BE_OVERRIDDEN = new Map( + Object.entries(eslintPlugin.rules) + .filter(([, rule]) => rule.meta.docs.extendsBaseRule) + .map( + ([ruleName, rule]) => + [ + ruleName, + typeof rule.meta.docs.extendsBaseRule === 'string' + ? rule.meta.docs.extendsBaseRule + : ruleName, + ] as const, + ), +); + +// special case - return-await used to be an extension, but no longer is. +// See https://github.com/typescript-eslint/typescript-eslint/issues/9517 +BASE_RULES_TO_BE_OVERRIDDEN.set('return-await', 'no-return-await'); + +type RuleEntry = [string, ESLintPluginRuleModule]; + +const allRuleEntries: RuleEntry[] = Object.entries(eslintPlugin.rules).sort( + (a, b) => a[0].localeCompare(b[0]), +); + +type GetRuleOptions = ( + rule: ESLintPluginRuleModule, +) => readonly unknown[] | true | undefined; + +interface ConfigRuleSettings { + baseRuleForExtensionRule?: 'exclude'; + deprecated?: 'exclude'; + forcedRuleLevel?: Linter.RuleLevel; + getOptions?: GetRuleOptions | undefined; + typeChecked?: 'exclude' | 'include-only'; +} + +/** + * Helper function reduces records to key - value pairs. + */ +function reducer( + config: LinterConfigRules, + [key, value]: RuleEntry, + settings: ConfigRuleSettings = {}, +): LinterConfigRules { + if (value.meta.deprecated) { + if (value.meta.docs.recommended) { + throw new Error(`${key} is both deprecated and recommended.`); + } + if (settings.deprecated) { + return config; + } + } + + // Explicitly exclude rules requiring type-checking + if ( + settings.typeChecked === 'exclude' && + value.meta.docs.requiresTypeChecking === true + ) { + return config; + } + + if ( + settings.typeChecked === 'include-only' && + value.meta.docs.requiresTypeChecking !== true + ) { + return config; + } + + const ruleName = `${RULE_NAME_PREFIX}${key}`; + + if ( + settings.baseRuleForExtensionRule !== 'exclude' && + BASE_RULES_TO_BE_OVERRIDDEN.has(key) + ) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const baseRuleName = BASE_RULES_TO_BE_OVERRIDDEN.get(key)!; + console.log( + baseRuleName + .padStart(RULE_NAME_PREFIX.length + baseRuleName.length) + .padEnd(RULE_NAME_PREFIX.length + MAX_RULE_NAME_LENGTH), + '=', + chalk.green('off'), + ); + config[baseRuleName] = 'off'; + } + console.log( + `${chalk.dim(RULE_NAME_PREFIX)}${key.padEnd(MAX_RULE_NAME_LENGTH)}`, + '=', + chalk.red('error'), + ); + + const ruleLevel = settings.forcedRuleLevel ?? 'error'; + const ruleOptions = settings.getOptions?.(value); + + config[ruleName] = + ruleOptions && ruleOptions !== true + ? [ruleLevel, ...ruleOptions] + : ruleLevel; + + return config; +} + +interface WriteConfigSettings { + description: string; + getConfig: () => LinterConfig; + name: string; +} + +/** + * Helper function that writes configuration. + */ +async function writeConfig({ + description, + getConfig, + name, +}: WriteConfigSettings): Promise { + const hyphens = '-'.repeat(35 - Math.ceil(name.length / 2)); + console.log(chalk.blueBright(`\n${hyphens} ${name}.ts ${hyphens}`)); + + const config = getConfig(); + + // + // 1. Classic Config - written to eslint-plugin/src/configs/eslintrc + // These configs are just JSON blobs that we write as TS files + // + + // note: we use `export =` because ESLint will import these configs via a commonjs import + const classicCode = [ + "import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint';", + '', + `export = ${JSON.stringify(config)} satisfies ClassicConfig.Config;`, + ].join('\n'); + const classicConfigStr = await prettier.format( + addAutoGeneratedComment(classicCode), + { + parser: 'typescript', + ...prettierConfig, + }, + ); + fs.writeFileSync( + path.join( + PACKAGES_ESLINT_PLUGIN, + 'src', + 'configs', + 'eslintrc', + `${name}.ts`, + ), + classicConfigStr, + ); + + // + // 2. Flat Config - written to eslint-plugin/src/configs/flat + // These configs are actual TS modules that import other configs + // + const flatCode: string[] = [ + ...AUTO_GENERATED_COMMENT_LINES, + "import type { FlatConfig } from '@typescript-eslint/utils/ts-eslint';", + '', + ]; + const flatExtends: string[] = []; + const flatConfig: FlatConfig.Config = { + name: `typescript-eslint/${name}`, + rules: config.rules, + }; + if (config.extends) { + for (const extendPath of config.extends) { + const config = EXTENDS_MODULES.find( + mod => mod.packageRelativePath === extendPath, + ); + if (config == null) { + throw new Error("Couldn't find config"); + } + flatCode.push( + `import ${config.name} from '${config.moduleRelativePath}';`, + ); + flatExtends.push(config.name); + } + flatCode.push(''); + } + if (config.parserOptions) { + flatConfig.languageOptions ??= {}; + flatConfig.languageOptions.parserOptions = config.parserOptions; + } + + const docComment = `/** + * ${description} + * @see {@link https://typescript-eslint.io/users/configs#${name}} + */`; + const flatConfigJson = JSON.stringify(flatConfig); + if (flatExtends.length > 0) { + flatCode.push( + docComment, + 'export default (plugin: FlatConfig.Plugin, parser: FlatConfig.Parser): FlatConfig.ConfigArray => [', + ...flatExtends.map(ext => `${ext}(plugin, parser),`), + flatConfigJson, + '];', + ); + } else { + flatCode.push( + docComment, + `export default (_plugin: FlatConfig.Plugin, _parser: FlatConfig.Parser): FlatConfig.Config => (${flatConfigJson});`, + ); + } + const flatConfigStr = await prettier.format(flatCode.join('\n'), { + parser: 'typescript', + ...prettierConfig, + }); + fs.writeFileSync( + path.join(PACKAGES_ESLINT_PLUGIN, 'src', 'configs', 'flat', `${name}.ts`), + flatConfigStr, + ); +} + +interface ExtendedConfigSettings { + description: string; + name: string; + ruleEntries: readonly RuleEntry[]; + settings?: ConfigRuleSettings; +} + +async function writeExtendedConfig({ + description, + name, + ruleEntries, + settings, +}: ExtendedConfigSettings): Promise { + await writeConfig({ + description, + getConfig: () => ({ + extends: [...CLASSIC_EXTENDS], + rules: ruleEntries.reduce( + (config, entry) => reducer(config, entry, settings), + {}, + ), + }), + name, + }); +} + +function filterRuleEntriesTo( + ...recommendations: (RuleRecommendation | undefined)[] +): RuleEntry[] { + return allRuleEntries.filter(([, rule]) => + typeof rule.meta.docs.recommended === 'object' + ? Object.keys(rule.meta.docs.recommended).some(level => + recommendations.includes(level as RuleRecommendation), + ) + : recommendations.includes(rule.meta.docs.recommended), + ); +} + +function createGetOptionsForLevel( + level: 'recommended' | 'strict', +): GetRuleOptions { + return rule => + typeof rule.meta.docs.recommended === 'object' + ? rule.meta.docs.recommended[level] + : undefined; +} + +await writeExtendedConfig({ + description: + 'Enables each the rules provided as a part of typescript-eslint. Note that many rules are not applicable in all codebases, or are meant to be configured.', + name: 'all', + ruleEntries: allRuleEntries, + settings: { + deprecated: 'exclude', + }, +}); + +await writeExtendedConfig({ + description: + 'Recommended rules for code correctness that you can drop in without additional configuration.', + name: 'recommended', + ruleEntries: filterRuleEntriesTo('recommended'), + settings: { + getOptions: createGetOptionsForLevel('recommended'), + typeChecked: 'exclude', + }, +}); + +await writeExtendedConfig({ + description: + 'Contains all of `recommended` along with additional recommended rules that require type information.', + name: 'recommended-type-checked', + ruleEntries: filterRuleEntriesTo('recommended'), + settings: { + getOptions: createGetOptionsForLevel('recommended'), + }, +}); + +await writeExtendedConfig({ + description: + 'A version of `recommended` that only contains type-checked rules and disables of any corresponding core ESLint rules.', + name: 'recommended-type-checked-only', + ruleEntries: filterRuleEntriesTo('recommended'), + settings: { + getOptions: createGetOptionsForLevel('recommended'), + typeChecked: 'include-only', + }, +}); + +await writeExtendedConfig({ + description: + 'Contains all of `recommended`, as well as additional strict rules that can also catch bugs. ', + name: 'strict', + ruleEntries: filterRuleEntriesTo('recommended', 'strict'), + settings: { + getOptions: createGetOptionsForLevel('strict'), + typeChecked: 'exclude', + }, +}); + +await writeExtendedConfig({ + description: + 'Contains all of `recommended`, `recommended-type-checked`, and `strict`, along with additional strict rules that require type information.', + name: 'strict-type-checked', + ruleEntries: filterRuleEntriesTo('recommended', 'strict'), + settings: { + getOptions: createGetOptionsForLevel('strict'), + }, +}); + +await writeExtendedConfig({ + description: + 'A version of `strict` that only contains type-checked rules and disables of any corresponding core ESLint rules.', + name: 'strict-type-checked-only', + ruleEntries: filterRuleEntriesTo('recommended', 'strict'), + settings: { + getOptions: createGetOptionsForLevel('strict'), + typeChecked: 'include-only', + }, +}); + +await writeExtendedConfig({ + description: + 'Rules considered to be best practice for modern TypeScript codebases, but that do not impact program logic.', + name: 'stylistic', + ruleEntries: filterRuleEntriesTo('stylistic'), + settings: { + typeChecked: 'exclude', + }, +}); + +await writeExtendedConfig({ + description: + 'Contains all of `stylistic`, along with additional stylistic rules that require type information.', + name: 'stylistic-type-checked', + ruleEntries: filterRuleEntriesTo('stylistic'), +}); + +await writeExtendedConfig({ + description: + 'A version of `stylistic` that only contains type-checked rules and disables of any corresponding core ESLint rules.', + name: 'stylistic-type-checked-only', + ruleEntries: filterRuleEntriesTo('stylistic'), + settings: { + typeChecked: 'include-only', + }, +}); + +await writeConfig({ + description: + 'A utility ruleset that will disable type-aware linting and all type-aware rules available in our project.', + getConfig: () => ({ + parserOptions: { + program: null, + project: false, + projectService: false, + }, + rules: allRuleEntries.reduce( + (config, entry) => + reducer(config, entry, { + baseRuleForExtensionRule: 'exclude', + forcedRuleLevel: 'off', + typeChecked: 'include-only', + }), + {}, + ), + }), + name: 'disable-type-checked', +}); diff --git a/deps/swc/crates/swc_ts_fast_strip/src/lib.rs b/deps/swc/crates/swc_ts_fast_strip/src/lib.rs index 9f9098ab8..fef3dbfa3 100644 --- a/deps/swc/crates/swc_ts_fast_strip/src/lib.rs +++ b/deps/swc/crates/swc_ts_fast_strip/src/lib.rs @@ -4,7 +4,7 @@ use anyhow::Context; use bytes_str::BytesStr; use serde::{Deserialize, Serialize}; use swc_common::{ - comments::SingleThreadedComments, + comments::{Comments, SingleThreadedComments}, errors::{DiagnosticId, Handler, HANDLER}, source_map::DefaultSourceMapGenConfig, sync::Lrc, @@ -14,12 +14,12 @@ use swc_ecma_ast::{ ArrayPat, ArrowExpr, AutoAccessor, BinaryOp, BindingIdent, Class, ClassDecl, ClassMethod, ClassProp, Constructor, Decl, DefaultDecl, DoWhileStmt, EsVersion, ExportAll, ExportDecl, ExportDefaultDecl, ExportSpecifier, Expr, FnDecl, ForInStmt, ForOfStmt, ForStmt, GetterProp, - IfStmt, ImportDecl, ImportSpecifier, ModuleDecl, ModuleItem, NamedExport, ObjectPat, Param, - Pat, PrivateMethod, PrivateProp, Program, ReturnStmt, SetterProp, Stmt, ThrowStmt, TsAsExpr, - TsConstAssertion, TsEnumDecl, TsExportAssignment, TsImportEqualsDecl, TsIndexSignature, - TsInstantiation, TsModuleDecl, TsModuleName, TsNamespaceBody, TsNonNullExpr, TsParamPropParam, - TsSatisfiesExpr, TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, TsTypeParamDecl, - TsTypeParamInstantiation, VarDeclarator, WhileStmt, YieldExpr, + IfStmt, ImportDecl, ImportSpecifier, ModuleDecl, ModuleItem, NamedExport, ObjectPat, + PrivateMethod, PrivateProp, Program, Stmt, TsAsExpr, TsConstAssertion, TsEnumDecl, + TsExportAssignment, TsImportEqualsDecl, TsIndexSignature, TsInstantiation, TsModuleDecl, + TsModuleName, TsNamespaceBody, TsNonNullExpr, TsParamPropParam, TsSatisfiesExpr, TsThisParam, + TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, TsTypeParamDecl, TsTypeParamInstantiation, + VarDeclarator, WhileStmt, }; use swc_ecma_parser::{ lexer::Lexer, @@ -37,6 +37,10 @@ use swc_ecma_visit::{Visit, VisitWith}; #[cfg(feature = "wasm-bindgen")] use wasm_bindgen::prelude::*; +use crate::strip::StripEditPlan; + +mod strip; + #[derive(Default, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Options { @@ -249,14 +253,15 @@ pub fn operate( let syntax = Syntax::Typescript(options.parser); let target = EsVersion::latest(); - let comments = SingleThreadedComments::default(); + let comments = matches!(&options.mode, Mode::Transform).then(SingleThreadedComments::default); + let lexer_comments = comments.as_ref().map(|comments| comments as &dyn Comments); - let (program, errors, mut tokens) = if should_capture_tokens { + let (program, errors, tokens) = if should_capture_tokens { let lexer = Capturing::new(Lexer::new( syntax, target, StringInput::from(&*fm), - Some(&comments), + lexer_comments, )); let mut parser = Parser::new_from(lexer); @@ -270,7 +275,7 @@ pub fn operate( (program, errors, tokens) } else { - let lexer = Lexer::new(syntax, target, StringInput::from(&*fm), Some(&comments)); + let lexer = Lexer::new(syntax, target, StringInput::from(&*fm), lexer_comments); let mut parser = Parser::new_from(lexer); let program = match options.module { @@ -282,6 +287,12 @@ pub fn operate( (program, errors, Vec::new()) }; + debug_assert!( + tokens + .windows(2) + .all(|tokens| tokens[0].span.lo < tokens[1].span.lo), + "captured tokens must be ordered by source position" + ); let mut program = match program { Ok(program) => program, @@ -318,11 +329,10 @@ pub fn operate( match options.mode { Mode::StripOnly => { - tokens.sort_by_key(|t| t.span); - if deprecated_ts_module_as_error { program.visit_with(&mut ErrorOnTsModule { src: &fm.src, + source_start: fm.start_pos, tokens: &tokens, }); if handler.has_errors() { @@ -334,7 +344,7 @@ pub fn operate( } // Strip typescript types - let mut ts_strip = TsStrip::new(fm.src.clone(), tokens); + let mut ts_strip = TsStrip::new(fm.src.clone(), fm.start_pos, tokens); program.visit_with(&mut ts_strip); if handler.has_errors() { @@ -344,83 +354,16 @@ pub fn operate( }); } - let replacements = ts_strip.replacements; - let overwrites = ts_strip.overwrites; + let edits = ts_strip.edits; - if replacements.is_empty() && overwrites.is_empty() { + if edits.is_empty() { return Ok(TransformOutput { code: fm.src.to_string(), map: Default::default(), }); } - let source = fm.src.clone(); - let mut code = fm.src.to_string().into_bytes(); - - for r in replacements { - let (start, end) = (r.0 .0 as usize - 1, r.1 .0 as usize - 1); - - for (i, c) in source[start..end].char_indices() { - let i = start + i; - match c { - // https://262.ecma-international.org/#sec-white-space - '\u{0009}' | '\u{0000B}' | '\u{000C}' | '\u{FEFF}' => continue, - // Space_Separator - '\u{0020}' | '\u{00A0}' | '\u{1680}' | '\u{2000}' | '\u{2001}' - | '\u{2002}' | '\u{2003}' | '\u{2004}' | '\u{2005}' | '\u{2006}' - | '\u{2007}' | '\u{2008}' | '\u{2009}' | '\u{200A}' | '\u{202F}' - | '\u{205F}' | '\u{3000}' => continue, - // https://262.ecma-international.org/#sec-line-terminators - '\u{000A}' | '\u{000D}' | '\u{2028}' | '\u{2029}' => continue, - _ => match c.len_utf8() { - 1 => { - // Space 0020 - code[i] = 0x20; - } - 2 => { - // No-Break Space 00A0 - code[i] = 0xc2; - code[i + 1] = 0xa0; - } - 3 => { - // En Space 2002 - code[i] = 0xe2; - code[i + 1] = 0x80; - code[i + 2] = 0x82; - } - 4 => { - // We do not have a 4-byte space character in the Unicode standard. - - // Space 0020 - code[i] = 0x20; - // ZWNBSP FEFF - code[i + 1] = 0xef; - code[i + 2] = 0xbb; - code[i + 3] = 0xbf; - } - _ => unreachable!(), - }, - } - } - } - - for (i, v) in overwrites { - code[i.0 as usize - 1] = v; - } - - #[cfg(debug_assertions)] - let code = { - String::from_utf8(code).map_err(|err| TsError { - message: format!("failed to convert to utf-8: {err}"), - code: ErrorCode::Unknown, - })? - }; - #[cfg(not(debug_assertions))] - let code = { - // SAFETY: We've already validated that the source is valid utf-8 - // and our operations are limited to character-level string replacements. - unsafe { String::from_utf8_unchecked(code) } - }; + let code = edits.render(fm.start_pos, &fm.src); Ok(TransformOutput { code, @@ -429,6 +372,7 @@ pub fn operate( } Mode::Transform => { + let comments = comments.expect("transform mode must collect comments"); let unresolved_mark = Mark::new(); let top_level_mark = Mark::new(); @@ -436,10 +380,9 @@ pub fn operate( program.mutate(&mut resolver(unresolved_mark, top_level_mark, true)); if deprecated_ts_module_as_error { - tokens.sort_by_key(|t| t.span); - program.visit_with(&mut ErrorOnTsModule { src: &fm.src, + source_start: fm.start_pos, tokens: &tokens, }); if handler.has_errors() { @@ -541,6 +484,7 @@ pub fn operate( struct ErrorOnTsModule<'a> { src: &'a str, + source_start: BytePos, tokens: &'a [TokenAndSpan], } @@ -591,8 +535,11 @@ impl Visit for ErrorOnTsModule<'_> { } pos = span.lo; - } else if self.src.as_bytes()[pos.0 as usize - 1] != b'm' { - return; + } else { + let offset = (pos.0 - self.source_start.0) as usize; + if self.src.as_bytes()[offset] != b'm' { + return; + } } if HANDLER.is_set() { @@ -611,22 +558,17 @@ impl Visit for ErrorOnTsModule<'_> { struct TsStrip { src: BytesStr, - - /// Replaced with whitespace - replacements: Vec<(BytePos, BytePos)>, - - // should be string, but we use u8 for only `)` usage. - overwrites: Vec<(BytePos, u8)>, - + source_start: BytePos, + edits: StripEditPlan, tokens: std::vec::Vec, } impl TsStrip { - fn new(src: BytesStr, tokens: std::vec::Vec) -> Self { + fn new(src: BytesStr, source_start: BytePos, tokens: std::vec::Vec) -> Self { TsStrip { src, - replacements: Default::default(), - overwrites: Default::default(), + source_start, + edits: Default::default(), tokens, } } @@ -634,15 +576,17 @@ impl TsStrip { impl TsStrip { fn add_replacement(&mut self, span: Span) { - self.replacements.push((span.lo, span.hi)); + self.edits.erase(span); } - fn add_overwrite(&mut self, pos: BytePos, value: u8) { - self.overwrites.push((pos, value)); + fn add_overwrite(&mut self, pos: BytePos, value: char) { + self.edits.overwrite(pos, value); } fn get_src_slice(&self, span: Span) -> &str { - &self.src[(span.lo.0 - 1) as usize..(span.hi.0 - 1) as usize] + let start = (span.lo.0 - self.source_start.0) as usize; + let end = (span.hi.0 - self.source_start.0) as usize; + &self.src[start..end] } fn get_next_token_index(&self, pos: BytePos) -> usize { @@ -708,15 +652,16 @@ impl TsStrip { Token::LParen | Token::LBracket | Token::NoSubstitutionTemplateLiteral + | Token::TemplateHead | Token::Plus | Token::Minus | Token::Regex => { if prev_token == &Token::Semi { - self.add_overwrite(prev_span.lo, b';'); + self.add_overwrite(prev_span.lo, ';'); return; } - self.add_overwrite(span.lo, b';'); + self.add_overwrite(span.lo, ';'); } _ => {} @@ -731,12 +676,16 @@ impl TsStrip { if let TokenAndSpan { // Only `(`, `[` and backtick affect ASI. - token: Token::LParen | Token::LBracket | Token::NoSubstitutionTemplateLiteral, + token: + Token::LParen + | Token::LBracket + | Token::NoSubstitutionTemplateLiteral + | Token::TemplateHead, had_line_break: true, .. } = &self.tokens[index + 1] { - self.add_overwrite(span.lo, b';'); + self.add_overwrite(span.lo, ';'); } } @@ -804,32 +753,51 @@ impl TsStrip { self.add_replacement(*span); } + // Stripping the type parameters can expose a line break that either makes + // JavaScript invalid (`async`, `throw`) or changes its parsing (`return`, + // `yield`): + // // ```TypeScript - // return/yield/throw - // (v: T) => v; + // const f = async + // (value: T) => value; + // + // return + // (value: T) => value; // ``` // - // ```TypeScript - // return/yield/throw ( - // v ) => v; + // Move the existing opening parenthesis into the type parameter slot so + // the output keeps the same byte length and line breaks: + // + // ```JavaScript + // const f = async( + // value ) => value; + // + // return ( + // value ) => value; // ``` - fn fix_asi_in_arrow_expr(&mut self, arrow_expr: &ArrowExpr) { - if let Some(tp) = &arrow_expr.type_params { - let l_paren = self.get_next_token(tp.span.hi); - debug_assert_eq!(l_paren.token, Token::LParen); - - let slice = self.get_src_slice(tp.span.with_hi(l_paren.span.lo)); - - if !slice.chars().any(is_new_line) { - return; - } + fn move_arrow_opening_paren(&mut self, arrow_expr: &ArrowExpr, type_params: Span) { + let type_params_index = self.get_next_token_index(type_params.lo); + let follows_restricted_keyword = type_params_index > 0 + && !self.tokens[type_params_index].had_line_break + && matches!( + self.tokens[type_params_index - 1].token, + Token::Return | Token::Yield | Token::Throw + ); + + if !arrow_expr.is_async && !follows_restricted_keyword { + return; + } - let l_paren_pos = l_paren.span.lo; - let l_lt_pos = tp.span.lo; + let l_paren = self.get_next_token(type_params.hi); + debug_assert_eq!(l_paren.token, Token::LParen); - self.add_overwrite(l_paren_pos, b' '); - self.add_overwrite(l_lt_pos, b'('); + let slice = self.get_src_slice(type_params.with_hi(l_paren.span.lo)); + if !slice.chars().any(is_new_line) { + return; } + + self.add_overwrite(l_paren.span.lo, ' '); + self.add_overwrite(type_params.lo, '('); } fn assertion_chain_would_change_binary_grouping( @@ -951,38 +919,9 @@ impl Visit for TsStrip { } fn visit_arrow_expr(&mut self, n: &ArrowExpr) { - 'type_params: { - // ```TypeScript - // let f = async < - // T - // >(v: T) => v; - // ``` - - // ```TypeScript - // let f = async ( - // - // v ) => v; - // ``` - if let Some(tp) = &n.type_params { - self.add_replacement(tp.span); - - if !n.is_async { - break 'type_params; - } - - let slice = self.get_src_slice(tp.span); - if !slice.chars().any(is_new_line) { - break 'type_params; - } - - let l_paren = self.get_next_token(tp.span.hi); - debug_assert_eq!(l_paren.token, Token::LParen); - let l_paren_pos = l_paren.span.lo; - let l_lt_pos = tp.span.lo; - - self.add_overwrite(l_paren_pos, b' '); - self.add_overwrite(l_lt_pos, b'('); - } + if let Some(type_params) = &n.type_params { + self.add_replacement(type_params.span); + self.move_arrow_opening_paren(n, type_params.span); } if let Some(ret) = &n.return_type { @@ -1015,12 +954,14 @@ impl Visit for TsStrip { // ``` let mut pos = ret.span.hi - BytePos(1); - while !self.src.as_bytes()[pos.0 as usize - 1].is_utf8_char_boundary() { - self.add_overwrite(pos, b' '); + while !self + .src + .is_char_boundary((pos.0 - self.source_start.0) as usize) + { pos = pos - BytePos(1); } - self.add_overwrite(pos, b')'); + self.add_overwrite(pos, ')'); } } @@ -1028,61 +969,6 @@ impl Visit for TsStrip { n.body.visit_with(self); } - fn visit_return_stmt(&mut self, n: &ReturnStmt) { - let Some(arg) = n.arg.as_deref() else { - return; - }; - - arg.visit_with(self); - - let Some(arrow_expr) = arg.as_arrow() else { - return; - }; - - if arrow_expr.is_async { - // We have already handled type parameters in `visit_arrow_expr`. - return; - } - - self.fix_asi_in_arrow_expr(arrow_expr); - } - - fn visit_yield_expr(&mut self, n: &YieldExpr) { - let Some(arg) = &n.arg else { - return; - }; - - arg.visit_with(self); - - let Some(arrow_expr) = arg.as_arrow() else { - return; - }; - - if arrow_expr.is_async { - // We have already handled type parameters in `visit_arrow_expr`. - return; - } - - self.fix_asi_in_arrow_expr(arrow_expr); - } - - fn visit_throw_stmt(&mut self, n: &ThrowStmt) { - let arg = &n.arg; - - arg.visit_with(self); - - let Some(arrow_expr) = arg.as_arrow() else { - return; - }; - - if arrow_expr.is_async { - // We have already handled type parameters in `visit_arrow_expr`. - return; - } - - self.fix_asi_in_arrow_expr(arrow_expr); - } - fn visit_binding_ident(&mut self, n: &BindingIdent) { n.visit_children_with(self); @@ -1180,7 +1066,7 @@ impl Visit for TsStrip { .filter(|k| matches!(k.sym.as_ref(), "in" | "instanceof")) .is_some()) { - self.add_overwrite(start_pos, b';'); + self.add_overwrite(start_pos, ';'); } n.visit_children_with(self); @@ -1215,7 +1101,7 @@ impl Visit for TsStrip { // `get: number` // `get; ` if let Some(type_ann) = &n.type_ann { - self.add_overwrite(type_ann.span.lo, b';'); + self.add_overwrite(type_ann.span.lo, ';'); } } } @@ -1235,7 +1121,7 @@ impl Visit for TsStrip { .filter(|k| matches!(k.sym.as_ref(), "in" | "instanceof")) .is_some()) { - self.add_overwrite(start_pos, b';'); + self.add_overwrite(start_pos, ';'); } n.visit_children_with(self); @@ -1424,29 +1310,15 @@ impl Visit for TsStrip { } } - fn visit_params(&mut self, n: &[Param]) { - if let Some(p) = n.first().filter(|param| { - matches!( - ¶m.pat, - Pat::Ident(id) if id.sym == "this" - ) - }) { - let mut span = p.span; - - let comma = self.get_next_token(span.hi); - if comma.token == Token::Comma { - span = span.with_hi(comma.span.hi); - } else { - debug_assert_eq!(comma.token, Token::RParen); - } - self.add_replacement(span); - - n[1..].visit_children_with(self); - - return; + fn visit_ts_this_param(&mut self, n: &TsThisParam) { + let mut span = n.span; + let next = self.get_next_token(span.hi); + if next.token == Token::Comma { + span = span.with_hi(next.span.hi); + } else { + debug_assert_eq!(next.token, Token::RParen); } - - n.visit_children_with(self); + self.add_replacement(span); } fn visit_ts_as_expr(&mut self, n: &TsAsExpr) { @@ -1633,12 +1505,12 @@ impl Visit for TsStrip { n.visit_children_with(self); if n.cons.is_ts_declare() { - self.add_overwrite(n.cons.span_lo(), b';'); + self.add_overwrite(n.cons.span_lo(), ';'); } if let Some(alt) = &n.alt { if alt.is_ts_declare() { - self.add_overwrite(alt.span_lo(), b';'); + self.add_overwrite(alt.span_lo(), ';'); } } } @@ -1647,7 +1519,7 @@ impl Visit for TsStrip { n.visit_children_with(self); if n.body.is_ts_declare() { - self.add_overwrite(n.body.span_lo(), b';'); + self.add_overwrite(n.body.span_lo(), ';'); } } @@ -1655,7 +1527,7 @@ impl Visit for TsStrip { n.visit_children_with(self); if n.body.is_ts_declare() { - self.add_overwrite(n.body.span_lo(), b';'); + self.add_overwrite(n.body.span_lo(), ';'); } } @@ -1663,7 +1535,7 @@ impl Visit for TsStrip { n.visit_children_with(self); if n.body.is_ts_declare() { - self.add_overwrite(n.body.span_lo(), b';'); + self.add_overwrite(n.body.span_lo(), ';'); } } @@ -1671,7 +1543,7 @@ impl Visit for TsStrip { n.visit_children_with(self); if n.body.is_ts_declare() { - self.add_overwrite(n.body.span_lo(), b';'); + self.add_overwrite(n.body.span_lo(), ';'); } } @@ -1679,7 +1551,7 @@ impl Visit for TsStrip { n.visit_children_with(self); if n.body.is_ts_declare() { - self.add_overwrite(n.body.span_lo(), b';'); + self.add_overwrite(n.body.span_lo(), ';'); } } @@ -1688,27 +1560,22 @@ impl Visit for TsStrip { let l_parern = &self.tokens[l_parern_index]; debug_assert_eq!(l_parern.token, Token::LParen); - let r_parern_pos = n.type_ann.as_ref().map_or(n.body.span_lo(), |t| t.span.lo) - BytePos(1); + let r_parern_pos = n + .function + .return_type + .as_ref() + .map_or(n.function.body.span_lo(), |t| t.span.lo) + - BytePos(1); let r_parern = self.get_prev_token(r_parern_pos); debug_assert_eq!(r_parern.token, Token::RParen); let span = span(l_parern.span.lo + BytePos(1), r_parern.span.hi - BytePos(1)); self.add_replacement(span); - n.visit_children_with(self); - } - - fn visit_setter_prop(&mut self, n: &SetterProp) { - if let Some(this_param) = &n.this_param { - self.add_replacement(this_param.span()); - - let comma = self.get_prev_token(n.param.span_lo() - BytePos(1)); - debug_assert_eq!(comma.token, Token::Comma); - - self.add_replacement(comma.span); - } - - n.visit_children_with(self); + n.key.visit_with(self); + n.function.type_params.visit_with(self); + n.function.return_type.visit_with(self); + n.function.body.visit_with(self); } } @@ -1814,19 +1681,6 @@ impl IsUninstantiated for DefaultDecl { } } -trait U8Helper { - fn is_utf8_char_boundary(&self) -> bool; -} - -impl U8Helper for u8 { - // Copy from std::core::num::u8 - #[inline] - fn is_utf8_char_boundary(&self) -> bool { - // This is bit magic equivalent to: b < 128 || b >= 192 - (*self as i8) >= -0x40 - } -} - fn span(lo: BytePos, hi: BytePos) -> Span { Span::new(lo, hi) } diff --git a/deps/swc/crates/swc_ts_fast_strip/src/strip.rs b/deps/swc/crates/swc_ts_fast_strip/src/strip.rs new file mode 100644 index 000000000..4b6b834a0 --- /dev/null +++ b/deps/swc/crates/swc_ts_fast_strip/src/strip.rs @@ -0,0 +1,271 @@ +use std::ops::Range; + +use swc_common::{BytePos, Span}; + +/// Edits produced while visiting the TypeScript AST. +/// +/// Parser positions remain UTF-8 byte positions. The renderer is solely +/// responsible for translating them to the output coordinate system. +#[derive(Default)] +pub(crate) struct StripEditPlan { + erasures: Vec, + overwrites: Vec, +} + +#[derive(Clone, Copy)] +struct Overwrite { + pos: BytePos, + value: char, +} + +impl StripEditPlan { + pub(crate) fn erase(&mut self, span: Span) { + self.erasures.push(span); + } + + /// Replaces the source scalar at `pos` while preserving its UTF-16 width. + pub(crate) fn overwrite(&mut self, pos: BytePos, value: char) { + assert!(value.is_ascii(), "strip overwrites must be ASCII"); + self.overwrites.push(Overwrite { pos, value }); + } + + pub(crate) fn is_empty(&self) -> bool { + self.erasures.is_empty() && self.overwrites.is_empty() + } + + /// Applies all edits while preserving the source UTF-16 length. + pub(crate) fn render(self, source_start: BytePos, source: &str) -> String { + if self.is_empty() { + return source.to_owned(); + } + + let plan = LocalEditPlan::new(self, source_start, source); + if let Some(output) = plan.render_ascii_edits(source) { + return output; + } + + plan.render_unicode_edits(source) + } +} + +struct LocalEditPlan { + erasures: Vec>, + overwrites: Vec, +} + +#[derive(Clone, Copy)] +struct LocalOverwrite { + byte_offset: usize, + value: char, +} + +impl LocalEditPlan { + fn new(plan: StripEditPlan, source_start: BytePos, source: &str) -> Self { + let source_len = source.len(); + let mut erasures: Vec> = plan + .erasures + .into_iter() + .map(|span| { + let start = local_offset(span.lo, source_start, source_len); + let end = local_offset(span.hi, source_start, source_len); + assert!(start <= end, "invalid strip erasure range"); + start..end + }) + .collect(); + erasures.sort_unstable_by_key(|range| range.start); + let mut merged_erasures: Vec> = Vec::with_capacity(erasures.len()); + for range in erasures { + assert!( + source.is_char_boundary(range.start) && source.is_char_boundary(range.end), + "strip erasure is not on a UTF-8 character boundary" + ); + if let Some(previous) = merged_erasures.last_mut() { + if range.start <= previous.end { + previous.end = previous.end.max(range.end); + continue; + } + } + merged_erasures.push(range); + } + + let mut overwrites: Vec = plan + .overwrites + .into_iter() + .map(|overwrite| LocalOverwrite { + byte_offset: local_offset(overwrite.pos, source_start, source_len), + value: overwrite.value, + }) + .collect(); + // Stable sorting keeps the previous renderer's last-write-wins + // behavior if the planner emits the same position more than once. + overwrites.sort_by_key(|overwrite| overwrite.byte_offset); + let mut deduplicated_overwrites: Vec = Vec::with_capacity(overwrites.len()); + for overwrite in overwrites { + assert!( + overwrite.byte_offset < source_len + && source.is_char_boundary(overwrite.byte_offset), + "strip overwrite is not on a source character" + ); + if let Some(previous) = deduplicated_overwrites.last_mut() { + if previous.byte_offset == overwrite.byte_offset { + *previous = overwrite; + continue; + } + } + deduplicated_overwrites.push(overwrite); + } + + Self { + erasures: merged_erasures, + overwrites: deduplicated_overwrites, + } + } + + /// Uses byte offsets only when every edited source scalar is ASCII. + fn render_ascii_edits(&self, source: &str) -> Option { + let source = source.as_bytes(); + let mut output = source.to_vec(); + + for range in &self.erasures { + for (source, output) in source[range.clone()].iter().zip(&mut output[range.clone()]) { + if !source.is_ascii() { + return None; + } + if !is_preserved_ascii_whitespace(*source) { + *output = b' '; + } + } + } + + for overwrite in &self.overwrites { + if !source[overwrite.byte_offset].is_ascii() { + return None; + } + output[overwrite.byte_offset] = overwrite.value as u8; + } + + // SAFETY: `source` was valid UTF-8. Every modified source byte was + // checked to be ASCII and every replacement is ASCII, so the edits + // cannot change any multi-byte UTF-8 sequence. + Some(unsafe { String::from_utf8_unchecked(output) }) + } + + /// Renders Unicode edits directly to UTF-8 while preserving each source + /// scalar's UTF-16 width. + /// + /// Unedited segments are copied as whole UTF-8 slices. Only erased source + /// segments and overwritten scalars need Unicode decoding. + fn render_unicode_edits(&self, source: &str) -> String { + let mut output = String::with_capacity(source.len()); + let mut source_offset = 0; + let mut overwrite_index = 0; + + for erasure in &self.erasures { + while overwrite_index < self.overwrites.len() + && self.overwrites[overwrite_index].byte_offset < erasure.start + { + let overwrite = self.overwrites[overwrite_index]; + output.push_str(&source[source_offset..overwrite.byte_offset]); + source_offset = render_overwrite(&mut output, source, overwrite); + overwrite_index += 1; + } + + output.push_str(&source[source_offset..erasure.start]); + source_offset = erasure.start; + + while overwrite_index < self.overwrites.len() + && self.overwrites[overwrite_index].byte_offset < erasure.end + { + let overwrite = self.overwrites[overwrite_index]; + render_erasure(&mut output, &source[source_offset..overwrite.byte_offset]); + source_offset = render_overwrite(&mut output, source, overwrite); + overwrite_index += 1; + } + + render_erasure(&mut output, &source[source_offset..erasure.end]); + source_offset = erasure.end; + } + + for &overwrite in &self.overwrites[overwrite_index..] { + output.push_str(&source[source_offset..overwrite.byte_offset]); + source_offset = render_overwrite(&mut output, source, overwrite); + } + output.push_str(&source[source_offset..]); + + output + } +} + +fn local_offset(pos: BytePos, source_start: BytePos, source_len: usize) -> usize { + let offset = pos + .0 + .checked_sub(source_start.0) + .expect("strip edit precedes its source file") as usize; + assert!(offset <= source_len, "strip edit exceeds its source file"); + offset +} + +fn push_spaces(output: &mut String, count: usize) { + for _ in 0..count { + output.push(' '); + } +} + +fn render_erasure(output: &mut String, source: &str) { + for c in source.chars() { + if is_preserved_whitespace(c) { + output.push(c); + } else { + push_spaces(output, c.len_utf16()); + } + } +} + +fn render_overwrite(output: &mut String, source: &str, overwrite: LocalOverwrite) -> usize { + let original = source[overwrite.byte_offset..] + .chars() + .next() + .expect("strip overwrite points to the end of the source"); + + output.push(overwrite.value); + push_spaces(output, original.len_utf16() - 1); + + overwrite.byte_offset + original.len_utf8() +} + +fn is_preserved_whitespace(c: char) -> bool { + matches!( + c, + // ECMAScript whitespace. + '\u{0009}' + | '\u{000B}' + | '\u{000C}' + | '\u{FEFF}' + | '\u{0020}' + | '\u{00A0}' + | '\u{1680}' + | '\u{2000}' + | '\u{2001}' + | '\u{2002}' + | '\u{2003}' + | '\u{2004}' + | '\u{2005}' + | '\u{2006}' + | '\u{2007}' + | '\u{2008}' + | '\u{2009}' + | '\u{200A}' + | '\u{202F}' + | '\u{205F}' + | '\u{3000}' + // ECMAScript line terminators. + | '\u{000A}' + | '\u{000D}' + | '\u{2028}' + | '\u{2029}' + ) +} + +fn is_preserved_ascii_whitespace(byte: u8) -> bool { + matches!(byte, b'\t' | 0x0b | 0x0c | b' ' | b'\n' | b'\r') +} diff --git a/deps/swc/crates/swc_ts_fast_strip_binding/Cargo.toml b/deps/swc/crates/swc_ts_fast_strip_binding/Cargo.toml index 9ba3e78b0..1adc311f2 100644 --- a/deps/swc/crates/swc_ts_fast_strip_binding/Cargo.toml +++ b/deps/swc/crates/swc_ts_fast_strip_binding/Cargo.toml @@ -5,7 +5,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_ts_fast_strip_binding" repository = { workspace = true } -version = "0.18.0" +version = "0.23.0" [lib] bench = false @@ -17,12 +17,17 @@ anyhow = { workspace = true } miette = { workspace = true } owo-colors = { workspace = true } serde = { workspace = true, features = ["derive"] } -swc_common = { version = "23.0.2", path = "../../crates/swc_common" } -swc_error_reporters = { version = "25.0.0", path = "../../crates/swc_error_reporters" } -swc_ts_fast_strip = { version = "53.0.0", path = "../../crates/swc_ts_fast_strip" } +swc_common = { version = "26.0.0", path = "../../crates/swc_common" } +swc_error_reporters = { version = "28.0.0", path = "../../crates/swc_error_reporters" } +swc_ts_fast_strip = { version = "58.0.0", path = "../../crates/swc_ts_fast_strip" } tracing = { workspace = true } unicode-width = { workspace = true } [dev-dependencies] +codspeed-criterion-compat.workspace = true serde_json.workspace = true -swc_ecma_parser = { version = "41.1.2", path = "../../crates/swc_ecma_parser" } +swc_ecma_parser = { version = "45.0.0", path = "../../crates/swc_ecma_parser" } + +[[bench]] +harness = false +name = "assets" diff --git a/deps/swc/crates/swc_ts_fast_strip_binding/benches/assets.rs b/deps/swc/crates/swc_ts_fast_strip_binding/benches/assets.rs new file mode 100644 index 000000000..bd8a16b9e --- /dev/null +++ b/deps/swc/crates/swc_ts_fast_strip_binding/benches/assets.rs @@ -0,0 +1,49 @@ +use codspeed_criterion_compat::{black_box, criterion_group, criterion_main, Bencher, Criterion}; +use swc_ts_fast_strip::Options; +use swc_ts_fast_strip_binding::transform; + +const CASES: &[(&str, &str)] = &[ + ( + "typescript/fast-strip-binding/synthetic", + include_str!("../../swc_ts_fast_strip/benches/assets/test.ts"), + ), + ( + "typescript/fast-strip-binding/docusaurus-config", + include_str!("../../swc_ts_fast_strip/benches/assets/docusaurus.config.ts"), + ), + ( + "typescript/fast-strip-binding/ant-design-config", + include_str!("../../swc_ts_fast_strip/benches/assets/ant-design.vitest.config.ts"), + ), + ( + "typescript/fast-strip-binding/typescript-eslint-generate-configs", + include_str!( + "../../swc_ts_fast_strip/benches/assets/typescript-eslint.generate-configs.mts" + ), + ), + ( + "typescript/fast-strip-binding/graphile-config", + include_str!("../../swc_ts_fast_strip/benches/assets/graphile.config.ts"), + ), + ( + "typescript/fast-strip-binding/hono-types-test", + include_str!("../../swc_ts_fast_strip/benches/assets/hono.types.test.ts"), + ), +]; + +fn assets(c: &mut Criterion) { + for &(name, source) in CASES { + c.bench_function(name, |b| transform_typescript(b, source)); + } +} + +fn transform_typescript(b: &mut Bencher, source: &str) { + b.iter(|| { + let result = transform(black_box(source.to_owned()), Options::default()) + .expect("benchmark source should be valid erasable TypeScript"); + black_box(result); + }); +} + +criterion_group!(benches, assets); +criterion_main!(benches); diff --git a/deps/swc/crates/swc_ts_fast_strip_binding/src/lib.rs b/deps/swc/crates/swc_ts_fast_strip_binding/src/lib.rs index 2d3679066..fe785c6a4 100644 --- a/deps/swc/crates/swc_ts_fast_strip_binding/src/lib.rs +++ b/deps/swc/crates/swc_ts_fast_strip_binding/src/lib.rs @@ -33,7 +33,8 @@ fn operate(input: String, options: Options) -> Result>>, - reporter: SwcReportHandler, + /// Successful transforms never need the graphical diagnostic reporter. + reporter: Option, cm: Lrc, } @@ -43,25 +44,7 @@ where { let wr = JsonErrorWriter { errors: Default::default(), - reporter: SwcReportHandler::default().with_theme(GraphicalTheme { - characters: ThemeCharacters { - hbar: ' ', - vbar: ' ', - xbar: ' ', - vbar_break: ' ', - ltop: ' ', - rtop: ' ', - mtop: ' ', - lbot: ' ', - rbot: ' ', - mbot: ' ', - error: "".into(), - warning: "".into(), - advice: "".into(), - ..ThemeCharacters::ascii() - }, - styles: ThemeStyles::none(), - }), + reporter: None, cm, }; let emitter: Box = Box::new(wr.clone()); @@ -86,7 +69,8 @@ impl Emitter for JsonErrorWriter { let snippet = d.span.primary_span().and_then(|span| { let mut snippet = String::new(); - match self.reporter.render_report( + let reporter = self.reporter.get_or_insert_with(json_reporter); + match reporter.render_report( &mut snippet, &Snippet { source_code: &to_pretty_source_code(&self.cm, true), @@ -142,6 +126,28 @@ impl Emitter for JsonErrorWriter { } } +fn json_reporter() -> SwcReportHandler { + SwcReportHandler::default().with_theme(GraphicalTheme { + characters: ThemeCharacters { + hbar: ' ', + vbar: ' ', + xbar: ' ', + vbar_break: ' ', + ltop: ' ', + rtop: ' ', + mtop: ' ', + lbot: ' ', + rbot: ' ', + mbot: ' ', + error: "".into(), + warning: "".into(), + advice: "".into(), + ..ThemeCharacters::ascii() + }, + styles: ThemeStyles::none(), + }) +} + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct JsonDiagnostic { diff --git a/deps/swc/crates/swc_typescript/Cargo.toml b/deps/swc/crates/swc_typescript/Cargo.toml index 2f5374e9e..af1b6551b 100644 --- a/deps/swc/crates/swc_typescript/Cargo.toml +++ b/deps/swc/crates/swc_typescript/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "swc_typescript" repository = { workspace = true } -version = "30.0.1" +version = "34.0.0" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] } @@ -16,15 +16,15 @@ bitflags = { workspace = true } petgraph = { workspace = true } rustc-hash = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_ecma_ast = { version = "25.0.0", path = "../swc_ecma_ast" } -swc_ecma_utils = { version = "31.0.1", path = "../swc_ecma_utils" } -swc_ecma_visit = { version = "25.0.0", path = "../swc_ecma_visit" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_ecma_ast = { version = "29.0.0", path = "../swc_ecma_ast" } +swc_ecma_utils = { version = "35.0.0", path = "../swc_ecma_utils" } +swc_ecma_visit = { version = "29.0.0", path = "../swc_ecma_visit" } [dev-dependencies] -swc_ecma_codegen = { version = "28.0.2", path = "../swc_ecma_codegen" } -swc_ecma_parser = { version = "41.1.2", path = "../swc_ecma_parser" } -swc_ecma_transforms_base = { version = "44.0.3", path = "../swc_ecma_transforms_base" } -testing = { version = "24.0.1", path = "../testing" } +swc_ecma_codegen = { version = "32.0.0", path = "../swc_ecma_codegen" } +swc_ecma_parser = { version = "45.0.0", path = "../swc_ecma_parser" } +swc_ecma_transforms_base = { version = "49.0.0", path = "../swc_ecma_transforms_base" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_typescript/src/fast_dts/class.rs b/deps/swc/crates/swc_typescript/src/fast_dts/class.rs index 7a5070d75..039209585 100644 --- a/deps/swc/crates/swc_typescript/src/fast_dts/class.rs +++ b/deps/swc/crates/swc_typescript/src/fast_dts/class.rs @@ -102,12 +102,13 @@ impl FastDts { })); continue; } - self.transform_fn_params(&mut method.function.params); + self.transform_function_params(&mut method.function); } MethodKind::Getter => { if method.accessibility.is_some_and(|accessibility| { accessibility == Accessibility::Private }) { + method.function.this_param = None; method.function.params.clear(); method.function.return_type = None; method.function.decorators.clear(); @@ -119,12 +120,13 @@ impl FastDts { class.body.push(member); continue; } - self.transform_fn_params(&mut method.function.params); + self.transform_function_params(&mut method.function); } MethodKind::Setter => { if method.accessibility.is_some_and(|accessibility| { accessibility == Accessibility::Private }) { + method.function.this_param = None; method.function.params = vec![Param { span: DUMMY_SP, decorators: Vec::new(), @@ -144,6 +146,7 @@ impl FastDts { continue; } + self.check_this_param(method.function.this_param.as_deref()); if method.function.params.is_empty() { method.function.params.push(Param { span: DUMMY_SP, diff --git a/deps/swc/crates/swc_typescript/src/fast_dts/enum.rs b/deps/swc/crates/swc_typescript/src/fast_dts/enum.rs index f43b385ac..30a2a3399 100644 --- a/deps/swc/crates/swc_typescript/src/fast_dts/enum.rs +++ b/deps/swc/crates/swc_typescript/src/fast_dts/enum.rs @@ -1,25 +1,53 @@ use core::f64; +use std::borrow::Borrow; use rustc_hash::FxHashMap; -use swc_atoms::{atom, Atom}; -use swc_common::{Spanned, SyntaxContext, DUMMY_SP}; +use swc_atoms::{wtf8::Wtf8Buf, Atom, Wtf8Atom}; +use swc_common::{Spanned, DUMMY_SP}; use swc_ecma_ast::{ - BinExpr, BinaryOp, Expr, Ident, Lit, Number, Str, TsEnumDecl, TsEnumMemberId, UnaryExpr, - UnaryOp, + BinExpr, BinaryOp, Expr, Lit, Number, Str, TsEnumDecl, TsEnumMemberId, UnaryExpr, UnaryOp, }; -use swc_ecma_utils::number::JsNumber; +use swc_ecma_utils::number::{JsNumber, ToJsString}; use super::{util::ast_ext::MemberPropExt, FastDts}; #[derive(Debug, Clone)] enum ConstantValue { - Number(f64), - String(String), + Number(Number), + String(Wtf8Atom), +} + +impl ConstantValue { + /// Creates a computed number. Computations intentionally discard source + /// spelling so code generation can choose the canonical representation. + fn number(value: f64) -> Self { + Self::Number(Number { + span: DUMMY_SP, + value, + raw: None, + }) + } + + /// Creates a number converted directly from an AST value. + fn converted_number(value: f64, raw: Option) -> Self { + Self::Number(Number { + span: DUMMY_SP, + value, + raw, + }) + } + + fn push_to(self, output: &mut Wtf8Buf) { + match self { + Self::Number(number) => output.push_str(&number.value.to_js_string()), + Self::String(string) => output.push_wtf8(&string), + } + } } impl FastDts { pub(crate) fn transform_enum(&mut self, decl: &mut TsEnumDecl) { - let mut prev_init_value = Some(ConstantValue::Number(-1.0)); + let mut prev_init_value = Some(ConstantValue::number(-1.0)); let mut prev_members = FxHashMap::default(); for member in &mut decl.members { let value = if let Some(init_expr) = &member.init { @@ -29,58 +57,22 @@ impl FastDts { } computed_value } else if let Some(ConstantValue::Number(v)) = prev_init_value { - Some(ConstantValue::Number(v + 1.0)) + Some(ConstantValue::number(v.value + 1.0)) } else { None }; prev_init_value = value.clone(); if let Some(value) = &value { - let member_name = match &member.id { - TsEnumMemberId::Ident(ident) => ident.sym.clone(), - TsEnumMemberId::Str(s) => s - .value - .clone() - .try_into_atom() - .unwrap_or_else(|wtf8| Atom::from(&*wtf8.to_string_lossy())), - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }; - prev_members.insert(member_name.clone(), value.clone()); + prev_members.insert(enum_member_name(&member.id), value.clone()); } member.init = value.map(|value| { Box::new(match value { - ConstantValue::Number(v) => { - let is_neg = v < 0.0; - let expr = if v.is_infinite() { - Expr::Ident(Ident { - span: DUMMY_SP, - sym: atom!("Infinity"), - ctxt: SyntaxContext::empty(), - optional: false, - }) - } else { - Expr::Lit(Lit::Num(Number { - span: DUMMY_SP, - value: v, - raw: Some(v.to_string().into()), - })) - }; - - if is_neg { - Expr::Unary(UnaryExpr { - span: DUMMY_SP, - arg: Box::new(expr), - op: UnaryOp::Minus, - }) - } else { - expr - } - } - ConstantValue::String(s) => Expr::Lit(Lit::Str(Str { + ConstantValue::Number(number) => Expr::Lit(Lit::Num(number)), + ConstantValue::String(value) => Expr::Lit(Lit::Str(Str { span: DUMMY_SP, - value: s.clone().into(), + value, raw: None, })), }) @@ -92,24 +84,30 @@ impl FastDts { &self, expr: &Expr, enum_name: &Atom, - prev_members: &FxHashMap, + prev_members: &FxHashMap, ) -> Option { match expr { Expr::Lit(lit) => match lit { - Lit::Str(s) => Some(ConstantValue::String(s.value.to_string_lossy().to_string())), - Lit::Num(number) => Some(ConstantValue::Number(number.value)), + Lit::Str(string) => Some(ConstantValue::String(string.value.clone())), + Lit::Num(number) => Some(ConstantValue::Number(number.clone())), Lit::Null(_) | Lit::BigInt(_) | Lit::Bool(_) | Lit::Regex(_) | Lit::JSXText(_) => { None } #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), }, - Expr::Tpl(tpl) => { - let mut value = String::new(); - for part in &tpl.quasis { - value.push_str(&part.raw); + Expr::Tpl(template) => { + let mut quasis = template.quasis.iter(); + let first = quasis.next()?.cooked.as_ref()?; + let mut value = Wtf8Buf::from(first); + + for (expr, quasi) in template.exprs.iter().zip(quasis) { + self.evaluate(expr, enum_name, prev_members)? + .push_to(&mut value); + value.push_wtf8(quasi.cooked.as_ref()?); } - Some(ConstantValue::String(value)) + + Some(ConstantValue::String(Wtf8Atom::from(&*value))) } Expr::Paren(expr) => self.evaluate(&expr.expr, enum_name, prev_members), Expr::Bin(bin_expr) => self.evaluate_binary_expr(bin_expr, enum_name, prev_members), @@ -118,11 +116,17 @@ impl FastDts { } Expr::Ident(ident) => { if ident.sym == "Infinity" { - Some(ConstantValue::Number(f64::INFINITY)) + Some(ConstantValue::converted_number( + f64::INFINITY, + Some(ident.sym.clone()), + )) } else if ident.sym == "NaN" { - Some(ConstantValue::Number(f64::NAN)) + Some(ConstantValue::converted_number( + f64::NAN, + Some(ident.sym.clone()), + )) } else { - prev_members.get(&ident.sym).cloned() + prev_members.get(ident.sym.borrow()).cloned() } } Expr::Member(member) => { @@ -152,16 +156,16 @@ impl FastDts { &self, expr: &UnaryExpr, enum_name: &Atom, - prev_members: &FxHashMap, + prev_members: &FxHashMap, ) -> Option { let value = self.evaluate(&expr.arg, enum_name, prev_members)?; let value = match value { - ConstantValue::Number(n) => n, + ConstantValue::Number(number) => number.value, ConstantValue::String(_) => { let value = if expr.op == UnaryOp::Minus { - ConstantValue::Number(f64::NAN) + ConstantValue::number(f64::NAN) } else if expr.op == UnaryOp::Tilde { - ConstantValue::Number(-1.0) + ConstantValue::number(-1.0) } else { value }; @@ -170,9 +174,9 @@ impl FastDts { }; match expr.op { - UnaryOp::Minus => Some(ConstantValue::Number(-value)), - UnaryOp::Plus => Some(ConstantValue::Number(value)), - UnaryOp::Tilde => Some(ConstantValue::Number((!JsNumber::from(value)).into())), + UnaryOp::Minus => Some(ConstantValue::number(-value)), + UnaryOp::Plus => Some(ConstantValue::number(value)), + UnaryOp::Tilde => Some(ConstantValue::number((!JsNumber::from(value)).into())), _ => None, } } @@ -181,7 +185,7 @@ impl FastDts { &self, expr: &BinExpr, enum_name: &Atom, - prev_members: &FxHashMap, + prev_members: &FxHashMap, ) -> Option { let left = self.evaluate(&expr.left, enum_name, prev_members)?; let right = self.evaluate(&expr.right, enum_name, prev_members)?; @@ -190,28 +194,19 @@ impl FastDts { && (matches!(left, ConstantValue::String(_)) || matches!(right, ConstantValue::String(_))) { - let left_string = match left { - ConstantValue::Number(number) => number.to_string(), - ConstantValue::String(s) => s, - }; - - let right_string = match right { - ConstantValue::Number(number) => number.to_string(), - ConstantValue::String(s) => s, - }; - - return Some(ConstantValue::String(format!( - "{left_string}{right_string}" - ))); + let mut value = Wtf8Buf::new(); + left.push_to(&mut value); + right.push_to(&mut value); + return Some(ConstantValue::String(Wtf8Atom::from(&*value))); } let left = JsNumber::from(match left { - ConstantValue::Number(n) => n, + ConstantValue::Number(number) => number.value, ConstantValue::String(_) => return None, }); let right = JsNumber::from(match right { - ConstantValue::Number(n) => n, + ConstantValue::Number(number) => number.value, ConstantValue::String(_) => return None, }); @@ -223,13 +218,22 @@ impl FastDts { BinaryOp::Sub => Some(left - right), BinaryOp::Mul => Some(left * right), BinaryOp::Div => Some(left / right), - BinaryOp::Mod => Some(left & right), + BinaryOp::Mod => Some(left % right), BinaryOp::BitOr => Some(left | right), BinaryOp::BitXor => Some(left ^ right), BinaryOp::BitAnd => Some(left & right), BinaryOp::Exp => Some(left.pow(right)), _ => None, } - .map(|number| ConstantValue::Number(number.into())) + .map(|number| ConstantValue::number(number.into())) + } +} + +fn enum_member_name(member: &TsEnumMemberId) -> Wtf8Atom { + match member { + TsEnumMemberId::Ident(ident) => ident.sym.clone().into(), + TsEnumMemberId::Str(string) => string.value.clone(), + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), } } diff --git a/deps/swc/crates/swc_typescript/src/fast_dts/function.rs b/deps/swc/crates/swc_typescript/src/fast_dts/function.rs index b8453fdee..1d516a9f1 100644 --- a/deps/swc/crates/swc_typescript/src/fast_dts/function.rs +++ b/deps/swc/crates/swc_typescript/src/fast_dts/function.rs @@ -4,7 +4,7 @@ use swc_atoms::Atom; use swc_common::{Span, Spanned, DUMMY_SP}; use swc_ecma_ast::{ AssignPat, Decl, ExportDecl, Function, ModuleDecl, ModuleItem, ObjectPatProp, Param, Pat, - Script, Stmt, TsKeywordTypeKind, TsParenthesizedType, TsType, TsTypeAnn, + Script, Stmt, TsKeywordTypeKind, TsParenthesizedType, TsThisParam, TsType, TsTypeAnn, TsUnionOrIntersectionType, TsUnionType, }; @@ -22,7 +22,7 @@ impl FastDts { ident_span.unwrap_or_else(|| Span::new(func.span_lo(), func.body.span_lo())), ); } - self.transform_fn_params(&mut func.params); + self.transform_function_params(func); func.is_async = false; func.is_generator = false; func.body = None @@ -50,6 +50,20 @@ impl FastDts { } } + pub(crate) fn transform_function_params(&mut self, function: &mut Function) { + self.check_this_param(function.this_param.as_deref()); + self.transform_fn_params(&mut function.params); + } + + pub(crate) fn check_this_param(&mut self, this_param: Option<&TsThisParam>) { + let Some(this_param) = this_param else { + return; + }; + if this_param.type_ann.is_none() { + self.parameter_must_have_explicit_type(this_param.span); + } + } + pub(crate) fn transform_fn_param(&mut self, param: &mut Param, is_required: bool) { // 1. Check assign pat type if let Pat::Assign(assign_pat) = &mut param.pat { diff --git a/deps/swc/crates/swc_typescript/src/fast_dts/inferrer.rs b/deps/swc/crates/swc_typescript/src/fast_dts/inferrer.rs index 8f1f3e5da..c10cd509d 100644 --- a/deps/swc/crates/swc_typescript/src/fast_dts/inferrer.rs +++ b/deps/swc/crates/swc_typescript/src/fast_dts/inferrer.rs @@ -1,7 +1,7 @@ use swc_common::{Spanned, DUMMY_SP}; use swc_ecma_ast::{ - ArrowExpr, BindingIdent, BlockStmtOrExpr, Class, Expr, Function, Ident, Lit, ReturnStmt, Stmt, - TsKeywordTypeKind, TsParenthesizedType, TsType, TsTypeAliasDecl, TsTypeAnn, + ArrowExpr, ArrowFunctionBody, BindingIdent, Class, Expr, Function, Ident, Lit, ReturnStmt, + Stmt, TsKeywordTypeKind, TsParenthesizedType, TsType, TsTypeAliasDecl, TsTypeAnn, TsUnionOrIntersectionType, TsUnionType, UnaryExpr, UnaryOp, }; use swc_ecma_visit::{Visit, VisitWith}; @@ -84,10 +84,10 @@ impl FastDts { } match arrow.body.as_ref() { - BlockStmtOrExpr::BlockStmt(block_stmt) => { + ArrowFunctionBody::FunctionBody(block_stmt) => { ReturnTypeInferrer::infer(self, &block_stmt.stmts) } - BlockStmtOrExpr::Expr(expr) => self.infer_type_from_expr(expr), + ArrowFunctionBody::Expr(expr) => self.infer_type_from_expr(expr), #[cfg(swc_ast_unknown)] _ => panic!("unable to access unknown nodes"), } diff --git a/deps/swc/crates/swc_typescript/src/fast_dts/types.rs b/deps/swc/crates/swc_typescript/src/fast_dts/types.rs index 8fe0d6dd9..1f9fe8e5e 100644 --- a/deps/swc/crates/swc_typescript/src/fast_dts/types.rs +++ b/deps/swc/crates/swc_typescript/src/fast_dts/types.rs @@ -1,10 +1,11 @@ use rustc_hash::{FxHashMap, FxHashSet}; use swc_common::{BytePos, Span, Spanned, SyntaxContext, DUMMY_SP}; use swc_ecma_ast::{ - ArrayLit, ArrowExpr, Expr, Function, GetterProp, Lit, MemberExpr, ObjectLit, Param, Pat, Prop, - PropName, PropOrSpread, Str, Tpl, TsFnOrConstructorType, TsFnParam, TsFnType, - TsKeywordTypeKind, TsLit, TsMethodSignature, TsPropertySignature, TsTupleElement, TsTupleType, - TsType, TsTypeAnn, TsTypeElement, TsTypeLit, TsTypeOperator, TsTypeOperatorOp, UnaryOp, + ArrayLit, ArrowExpr, BindingIdent, Expr, Function, Ident, Lit, MemberExpr, ObjectLit, Param, + Pat, Prop, PropName, PropOrSpread, Str, Tpl, TsFnOrConstructorType, TsFnParam, TsFnType, + TsKeywordTypeKind, TsLit, TsMethodSignature, TsPropertySignature, TsThisParam, TsTupleElement, + TsTupleType, TsType, TsTypeAnn, TsTypeElement, TsTypeLit, TsTypeOperator, TsTypeOperatorOp, + UnaryOp, }; use swc_ecma_utils::quote_ident; @@ -85,7 +86,7 @@ impl FastDts { Box::new(TsType::TsFnOrConstructorType( TsFnOrConstructorType::TsFnType(TsFnType { span: DUMMY_SP, - params: self.transform_fn_params_to_ts_type(&function.params), + params: self.transform_function_params_to_ts_type(function), type_params: function.type_params.clone(), type_ann: return_type, }), @@ -128,20 +129,45 @@ impl FastDts { } pub(crate) fn transform_fn_params_to_ts_type(&mut self, params: &[Param]) -> Vec { - let mut params = params.to_owned().clone(); + self.transform_params_to_ts_type(None, params) + } + + fn transform_params_to_ts_type( + &mut self, + this_param: Option<&TsThisParam>, + params: &[Param], + ) -> Vec { + self.check_this_param(this_param); + let mut params = params.to_owned(); self.transform_fn_params(&mut params); - params - .into_iter() - .filter_map(|param| match param.pat { - Pat::Ident(binding_ident) => Some(TsFnParam::Ident(binding_ident)), - Pat::Array(array_pat) => Some(TsFnParam::Array(array_pat)), - Pat::Rest(rest_pat) => Some(TsFnParam::Rest(rest_pat)), - Pat::Object(object_pat) => Some(TsFnParam::Object(object_pat)), - Pat::Assign(_) | Pat::Invalid(_) | Pat::Expr(_) => None, - #[cfg(swc_ast_unknown)] - _ => panic!("unable to access unknown nodes"), - }) - .collect() + let mut output = Vec::with_capacity(params.len() + usize::from(this_param.is_some())); + if let Some(this_param) = this_param { + output.push(Self::transform_this_param_to_ts_type(this_param)); + } + output.extend(params.into_iter().filter_map(|param| match param.pat { + Pat::Ident(binding_ident) => Some(TsFnParam::Ident(binding_ident)), + Pat::Array(array_pat) => Some(TsFnParam::Array(array_pat)), + Pat::Rest(rest_pat) => Some(TsFnParam::Rest(rest_pat)), + Pat::Object(object_pat) => Some(TsFnParam::Object(object_pat)), + Pat::Assign(_) | Pat::Invalid(_) | Pat::Expr(_) => None, + #[cfg(swc_ast_unknown)] + _ => panic!("unable to access unknown nodes"), + })); + output + } + + pub(crate) fn transform_function_params_to_ts_type( + &mut self, + function: &Function, + ) -> Vec { + self.transform_params_to_ts_type(function.this_param.as_deref(), &function.params) + } + + fn transform_this_param_to_ts_type(this_param: &TsThisParam) -> TsFnParam { + TsFnParam::Ident(BindingIdent { + id: Ident::new_no_ctxt("this".into(), this_param.this_span), + type_ann: this_param.type_ann.clone(), + }) } pub(crate) fn transform_object_to_ts_type( @@ -243,7 +269,11 @@ impl FastDts { } if setter_type_ann.is_none() { - setter_type_ann = setter.param.get_type_ann().clone(); + setter_type_ann = setter + .function + .params + .first() + .and_then(|param| param.pat.get_type_ann().clone()); } if setter_type_ann.is_none() { @@ -290,8 +320,7 @@ impl FastDts { key: Box::new(key), computed: method.key.is_computed(), optional: false, - params: self - .transform_fn_params_to_ts_type(&method.function.params), + params: self.transform_function_params_to_ts_type(&method.function), type_ann: return_type, type_params: method.function.type_params.clone(), })); @@ -488,20 +517,22 @@ impl FastDts { }; match &**prop { - Prop::Getter(GetterProp { - type_ann: ty, - body: Some(body), - .. - }) => { - if let Some(type_ann) = ty - .clone() - .or_else(|| ReturnTypeInferrer::infer(self, &body.stmts).map(type_ann)) - { + Prop::Getter(getter) => { + if let Some(type_ann) = getter.function.return_type.clone().or_else(|| { + getter.function.body.as_ref().and_then(|body| { + ReturnTypeInferrer::infer(self, &body.stmts).map(type_ann) + }) + }) { annotations.insert(static_prop, type_ann); } } Prop::Setter(setter) => { - if let Some(type_ann) = setter.param.get_type_ann().clone() { + if let Some(type_ann) = setter + .function + .params + .first() + .and_then(|param| param.pat.get_type_ann().clone()) + { annotations.insert(static_prop.clone(), type_ann); } seen_setter.insert(static_prop); diff --git a/deps/swc/crates/swc_typescript/src/fast_dts/util/ast_ext.rs b/deps/swc/crates/swc_typescript/src/fast_dts/util/ast_ext.rs index c109f582e..6de072074 100644 --- a/deps/swc/crates/swc_typescript/src/fast_dts/util/ast_ext.rs +++ b/deps/swc/crates/swc_typescript/src/fast_dts/util/ast_ext.rs @@ -1,11 +1,12 @@ -use std::borrow::Cow; +use std::borrow::{Borrow, Cow}; -use swc_atoms::Atom; +use swc_atoms::{Atom, Wtf8Atom}; use swc_common::Mark; use swc_ecma_ast::{ BindingIdent, ComputedPropName, Expr, Ident, Lit, MemberProp, ObjectPatProp, Pat, Prop, PropName, TsTypeAnn, }; +use swc_ecma_utils::number::ToJsString; pub trait ExprExit { fn get_root_ident(&self) -> Option<&Ident>; @@ -144,7 +145,7 @@ impl PropNameExit for PropName { match self { PropName::Ident(ident_name) => Some(Cow::Borrowed(ident_name.sym.as_str())), PropName::Str(string) => Some(Cow::Borrowed(string.value.as_str()?)), - PropName::Num(number) => Some(Cow::Owned(number.value.to_string())), + PropName::Num(number) => Some(Cow::Owned(number.value.to_js_string())), PropName::BigInt(big_int) => Some(Cow::Owned(big_int.value.to_string())), PropName::Computed(computed_prop_name) => computed_prop_name.static_name(), #[cfg(swc_ast_unknown)] @@ -167,7 +168,7 @@ impl PropNameExit for ComputedPropName { Lit::Str(string) => Some(Cow::Borrowed(string.value.as_str()?)), Lit::Bool(b) => Some(Cow::Owned(b.value.to_string())), Lit::Null(_) => Some(Cow::Borrowed("null")), - Lit::Num(number) => Some(Cow::Owned(number.value.to_string())), + Lit::Num(number) => Some(Cow::Owned(number.value.to_js_string())), Lit::BigInt(big_int) => Some(Cow::Owned(big_int.value.to_string())), Lit::Regex(regex) => Some(Cow::Owned(regex.exp.to_string())), Lit::JSXText(_) => None, @@ -233,17 +234,17 @@ impl PropNameExit for Prop { } pub trait MemberPropExt { - fn static_name(&self) -> Option<&Atom>; + fn static_name(&self) -> Option<&Wtf8Atom>; } impl MemberPropExt for MemberProp { - fn static_name(&self) -> Option<&Atom> { + fn static_name(&self) -> Option<&Wtf8Atom> { match self { - MemberProp::Ident(ident_name) => Some(&ident_name.sym), + MemberProp::Ident(ident_name) => Some(ident_name.sym.borrow()), MemberProp::Computed(computed_prop_name) => match computed_prop_name.expr.as_ref() { - Expr::Lit(Lit::Str(s)) => s.value.as_atom(), + Expr::Lit(Lit::Str(s)) => Some(&s.value), Expr::Tpl(tpl) if tpl.quasis.len() == 1 && tpl.exprs.is_empty() => { - Some(&tpl.quasis[0].raw) + tpl.quasis[0].cooked.as_ref() } _ => None, }, diff --git a/deps/swc/crates/swc_typescript/src/fast_dts/visitors/type_usage.rs b/deps/swc/crates/swc_typescript/src/fast_dts/visitors/type_usage.rs index 89102c1e1..95a75978e 100644 --- a/deps/swc/crates/swc_typescript/src/fast_dts/visitors/type_usage.rs +++ b/deps/swc/crates/swc_typescript/src/fast_dts/visitors/type_usage.rs @@ -391,6 +391,7 @@ impl Visit for TypeUsageAnalyzer<'_> { fn visit_function(&mut self, node: &Function) { // Skip body + node.this_param.visit_with(self); node.params.visit_with(self); node.decorators.visit_with(self); node.type_params.visit_with(self); diff --git a/deps/swc/crates/swc_xml/Cargo.toml b/deps/swc/crates/swc_xml/Cargo.toml index 433a42426..693d5c4ed 100644 --- a/deps/swc/crates/swc_xml/Cargo.toml +++ b/deps/swc/crates/swc_xml/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" license = { workspace = true } name = "swc_xml" repository = "https://github.com/swc-project/swc.git" -version = "23.0.0" +version = "26.0.0" [package.metadata.docs.rs] all-features = true @@ -19,7 +19,7 @@ rustdoc-args = ["--cfg", "docsrs"] bench = false [dependencies] -swc_xml_ast = { version = "23.0.0", path = "../swc_xml_ast" } -swc_xml_codegen = { version = "23.0.0", path = "../swc_xml_codegen" } -swc_xml_parser = { version = "23.0.0", path = "../swc_xml_parser" } -swc_xml_visit = { version = "23.0.0", path = "../swc_xml_visit" } +swc_xml_ast = { version = "26.0.0", path = "../swc_xml_ast" } +swc_xml_codegen = { version = "26.0.0", path = "../swc_xml_codegen" } +swc_xml_parser = { version = "26.0.0", path = "../swc_xml_parser" } +swc_xml_visit = { version = "26.0.0", path = "../swc_xml_visit" } diff --git a/deps/swc/crates/swc_xml_ast/Cargo.toml b/deps/swc/crates/swc_xml_ast/Cargo.toml index bc5a6ade8..356194ae4 100644 --- a/deps/swc/crates/swc_xml_ast/Cargo.toml +++ b/deps/swc/crates/swc_xml_ast/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" license = { workspace = true } name = "swc_xml_ast" repository = "https://github.com/swc-project/swc.git" -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -28,5 +28,5 @@ is-macro = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } string_enum = { version = "1.0.2", path = "../string_enum/" } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } diff --git a/deps/swc/crates/swc_xml_codegen/Cargo.toml b/deps/swc/crates/swc_xml_codegen/Cargo.toml index 675fcdd5a..bfc0d60e6 100644 --- a/deps/swc/crates/swc_xml_codegen/Cargo.toml +++ b/deps/swc/crates/swc_xml_codegen/Cargo.toml @@ -10,7 +10,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = { workspace = true } name = "swc_xml_codegen" repository = "https://github.com/swc-project/swc.git" -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -19,14 +19,14 @@ bench = false auto_impl = { workspace = true } bitflags = { workspace = true } rustc-hash = { workspace = true } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_xml_ast = { version = "23.0.0", path = "../swc_xml_ast" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_xml_ast = { version = "26.0.0", path = "../swc_xml_ast" } swc_xml_codegen_macros = { version = "1.0.1", path = "../swc_xml_codegen_macros" } [dev-dependencies] -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "sourcemap", ] } -swc_xml_parser = { version = "23.0.0", path = "../swc_xml_parser" } -swc_xml_visit = { version = "23.0.0", path = "../swc_xml_visit" } -testing = { version = "24.0.1", path = "../testing" } +swc_xml_parser = { version = "26.0.0", path = "../swc_xml_parser" } +swc_xml_visit = { version = "26.0.0", path = "../swc_xml_visit" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_xml_parser/Cargo.toml b/deps/swc/crates/swc_xml_parser/Cargo.toml index 828d11249..837cd6531 100644 --- a/deps/swc/crates/swc_xml_parser/Cargo.toml +++ b/deps/swc/crates/swc_xml_parser/Cargo.toml @@ -10,7 +10,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/**/*.json"] license = { workspace = true } name = "swc_xml_parser" repository = "https://github.com/swc-project/swc.git" -version = "23.0.0" +version = "26.0.0" [lib] bench = false @@ -21,16 +21,16 @@ debug = [] [dependencies] rustc-hash = { workspace = true } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } -swc_xml_ast = { version = "23.0.0", path = "../swc_xml_ast" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } +swc_xml_ast = { version = "26.0.0", path = "../swc_xml_ast" } [dev-dependencies] serde = { workspace = true } serde_json = { workspace = true } -swc_xml_ast = { version = "23.0.0", path = "../swc_xml_ast", features = [ +swc_xml_ast = { version = "26.0.0", path = "../swc_xml_ast", features = [ "serde-impl", ] } -swc_xml_visit = { version = "23.0.0", path = "../swc_xml_visit" } -testing = { version = "24.0.1", path = "../testing" } +swc_xml_visit = { version = "26.0.0", path = "../swc_xml_visit" } +testing = { version = "27.0.0", path = "../testing" } diff --git a/deps/swc/crates/swc_xml_visit/Cargo.toml b/deps/swc/crates/swc_xml_visit/Cargo.toml index bde76ef35..ab5d2e620 100644 --- a/deps/swc/crates/swc_xml_visit/Cargo.toml +++ b/deps/swc/crates/swc_xml_visit/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" license = { workspace = true } name = "swc_xml_visit" repository = "https://github.com/swc-project/swc.git" -version = "23.0.0" +version = "26.0.0" [package.metadata.docs.rs] all-features = true @@ -26,7 +26,7 @@ serde-impl = ["serde"] [dependencies] serde = { workspace = true, optional = true, features = ["derive"] } -swc_atoms = { version = "9.0.3", path = "../swc_atoms" } -swc_common = { version = "23.0.2", path = "../swc_common" } +swc_atoms = { version = "10.0.0", path = "../swc_atoms" } +swc_common = { version = "26.0.0", path = "../swc_common" } swc_visit = { version = "2.0.1", path = "../swc_visit" } -swc_xml_ast = { version = "23.0.0", path = "../swc_xml_ast" } +swc_xml_ast = { version = "26.0.0", path = "../swc_xml_ast" } diff --git a/deps/swc/crates/testing/Cargo.toml b/deps/swc/crates/testing/Cargo.toml index 803f3f31d..848e85403 100644 --- a/deps/swc/crates/testing/Cargo.toml +++ b/deps/swc/crates/testing/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "testing" repository = { workspace = true } -version = "24.0.1" +version = "27.0.0" [lib] bench = false @@ -23,8 +23,8 @@ serde_json = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } -swc_common = { version = "23.0.2", path = "../swc_common", features = [ +swc_common = { version = "26.0.0", path = "../swc_common", features = [ "tty-emitter", ] } -swc_error_reporters = { version = "25.0.0", path = "../swc_error_reporters" } -testing_macros = { version = "1.0.1", path = "../testing_macros" } +swc_error_reporters = { version = "28.0.0", path = "../swc_error_reporters" } +testing_macros = { version = "1.0.2", path = "../testing_macros" } diff --git a/deps/swc/crates/testing_macros/Cargo.toml b/deps/swc/crates/testing_macros/Cargo.toml index d241562e3..4198b842b 100644 --- a/deps/swc/crates/testing_macros/Cargo.toml +++ b/deps/swc/crates/testing_macros/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } name = "testing_macros" repository = { workspace = true } -version = "1.0.1" +version = "1.0.2" [features] # Skip generating fixtures so the editor becomes faster again @@ -28,3 +28,6 @@ relative-path = { workspace = true } [dependencies.syn] features = ["fold", "parsing", "full", "extra-traits"] workspace = true + +[dev-dependencies] +tempfile = { workspace = true } diff --git a/deps/swc/crates/testing_macros/src/fixture.rs b/deps/swc/crates/testing_macros/src/fixture.rs index 39c980174..81a5735e0 100644 --- a/deps/swc/crates/testing_macros/src/fixture.rs +++ b/deps/swc/crates/testing_macros/src/fixture.rs @@ -1,6 +1,6 @@ use std::{ env, - path::{Component, PathBuf}, + path::{Component, Path, PathBuf}, }; use anyhow::{Context, Error}; @@ -96,7 +96,12 @@ pub fn expand(callee: &Ident, attr: Config) -> Result, Error> { let base_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect( "#[fixture] requires CARGO_MANIFEST_DIR because it's relative to cargo manifest directory", )); - let resolved_path = RelativePath::new(&attr.pattern).to_path(&base_dir); + + expand_from(callee, attr, &base_dir) +} + +fn expand_from(callee: &Ident, attr: Config, base_dir: &Path) -> Result, Error> { + let resolved_path = RelativePath::new(&attr.pattern).to_path(base_dir); let pattern = resolved_path.to_string_lossy(); let paths = @@ -111,7 +116,7 @@ pub fn expand(callee: &Ident, attr: Config) -> Result, Error> { .canonicalize() .with_context(|| format!("failed to canonicalize {}", path.display()))?; - let path_for_name = path.strip_prefix(&base_dir).with_context(|| { + let path_for_name = path.strip_prefix(base_dir).with_context(|| { format!( "Failed to strip prefix `{}` from `{}`", base_dir.display(), @@ -130,10 +135,7 @@ pub fn expand(callee: &Ident, attr: Config) -> Result, Error> { } } - let ignored = path.components().any(|c| match c { - Component::Normal(s) => s.to_string_lossy().starts_with('.'), - _ => false, - }); + let ignored = is_ignored_fixture(path_for_name); let test_name = format!( "{}_{}", callee, @@ -174,6 +176,15 @@ pub fn expand(callee: &Ident, attr: Config) -> Result, Error> { Ok(test_fns) } +/// Returns whether a manifest-relative fixture path contains a hidden +/// component. +fn is_ignored_fixture(path: &Path) -> bool { + path.components().any(|component| match component { + Component::Normal(name) => name.to_string_lossy().starts_with('.'), + _ => false, + }) +} + struct InputParen { input: Punctuated, } @@ -185,3 +196,61 @@ impl Parse for InputParen { }) } } + +#[cfg(test)] +mod tests { + use std::fs::{create_dir_all, write}; + + use proc_macro2::Span; + use tempfile::tempdir; + + use super::*; + + #[test] + fn ignores_only_hidden_fixture_path_components() { + let temp_dir = tempdir().unwrap(); + let manifest_dir = temp_dir + .path() + .join(".codex") + .join("worktrees") + .join("swc") + .join("crates") + .join("testing_macros"); + let fixture_dir = manifest_dir.join("tests").join("fixture"); + let ignored_fixture_dir = fixture_dir.join(".ignored"); + + create_dir_all(&ignored_fixture_dir).unwrap(); + write(fixture_dir.join("normal.ts"), "").unwrap(); + write(ignored_fixture_dir.join("ignored.ts"), "").unwrap(); + + let cases = expand_from( + &Ident::new("fixture", Span::call_site()), + Config { + pattern: "tests/fixture/**/*.ts".into(), + exclude_patterns: Vec::new(), + }, + &manifest_dir, + ) + .unwrap(); + + let case_count = cases.len(); + let ignored_count = cases + .into_iter() + .map(|case| syn::parse2::(case).unwrap()) + .filter(|case| case.attrs.iter().any(|attr| attr.path().is_ident("ignore"))) + .count(); + + assert_eq!(case_count, 2); + assert_eq!(ignored_count, 1); + } + + #[test] + fn ignores_hidden_components_in_cross_crate_fixture_paths() { + assert!(!is_ignored_fixture(Path::new( + "../other-crate/tests/fixture/input.js" + ))); + assert!(is_ignored_fixture(Path::new( + "../other-crate/tests/fixture/.case/input.js" + ))); + } +} diff --git a/deps/swc/crates/testing_macros/src/lib.rs b/deps/swc/crates/testing_macros/src/lib.rs index 0e9c2a3bb..e6841642d 100644 --- a/deps/swc/crates/testing_macros/src/lib.rs +++ b/deps/swc/crates/testing_macros/src/lib.rs @@ -38,10 +38,11 @@ mod fixture; /// /// ## Ignoring a test /// -/// If the path to the file contains a component starts with `.` (dot), it will -/// be ignore. This convention is widely used in many projects (including other -/// languages), as a file or a directory starting with `.` means hidden file in -/// unix system. +/// If the fixture path relative to the crate's `Cargo.toml` contains a +/// component that starts with `.` (dot), it will be ignored. Ancestors of the +/// crate are not considered. This convention is widely used in many projects +/// (including other languages), as a file or a directory starting with `.` +/// means a hidden file in unix systems. /// /// Note that they are added as a test `#[ignore]`, so you can use /// `cargo test -- --ignored` or `cargo test -- --include-ignored` to run those diff --git a/deps/swc/tools/generate-code/Cargo.toml b/deps/swc/tools/generate-code/Cargo.toml index c1e0c7bf5..48b1b8d71 100644 --- a/deps/swc/tools/generate-code/Cargo.toml +++ b/deps/swc/tools/generate-code/Cargo.toml @@ -15,6 +15,6 @@ quote = { workspace = true } syn = { workspace = true, features = ["full", "visit-mut", "extra-traits"] } walkdir = { workspace = true } -swc_config = { version = "5.0.0", path = "../../crates/swc_config", features = [ +swc_config = { version = "6.0.0", path = "../../crates/swc_config", features = [ "regex", ] } diff --git a/deps/swc/tools/generate-code/src/generators/helpers.rs b/deps/swc/tools/generate-code/src/generators/helpers.rs new file mode 100644 index 000000000..97c0a022f --- /dev/null +++ b/deps/swc/tools/generate-code/src/generators/helpers.rs @@ -0,0 +1,571 @@ +use std::{ + collections::{BTreeMap, BTreeSet}, + fs, + path::{Path, PathBuf}, +}; + +use anyhow::{bail, Context, Result}; + +const GENERATED_HEADER: &str = + "// This file is generated by `cargo codegen helpers`. DO NOT MODIFY.\n"; +const HELPER_BITMAP_BITS: usize = 128; + +#[derive(Debug)] +pub struct Config { + pub input_dir: PathBuf, + pub output_dir: PathBuf, +} + +#[derive(Debug)] +struct Helper { + module_name: String, + ident: String, + source: String, + deps: Vec, +} + +pub fn generate(config: Config) -> Result> { + let input_dir = config + .input_dir + .canonicalize() + .context("failed to canonicalize helper input directory")?; + + let ordered_modules = read_index_order(&input_dir)?; + let available_modules = read_available_modules(&input_dir)?; + + let ordered_set = ordered_modules.iter().collect::>(); + for module_name in &available_modules { + if !ordered_set.contains(module_name) { + bail!( + "helper `{module_name}` exists in packages/helpers/esm but is missing from \ + index.js" + ); + } + } + + let mut helpers = Vec::with_capacity(ordered_modules.len()); + for module_name in &ordered_modules { + if !available_modules.contains(module_name) { + bail!("helper `{module_name}` is exported from index.js but the file is missing"); + } + + let path = input_dir.join(format!("{module_name}.js")); + helpers.push(parse_helper(module_name, &path)?); + } + + validate_deps(&helpers)?; + let inline_deps = compute_inline_deps(&helpers)?; + + fs::create_dir_all(&config.output_dir) + .with_context(|| format!("failed to create output directory: {:?}", config.output_dir))?; + + let expected_files = helpers + .iter() + .map(|helper| format!("{}.rs", helper.module_name)) + .chain(std::iter::once("mod.rs".into())) + .collect::>(); + + for entry in fs::read_dir(&config.output_dir) + .with_context(|| format!("failed to read output directory: {:?}", config.output_dir))? + { + let entry = entry?; + let path = entry.path(); + if path.extension().and_then(|ext| ext.to_str()) != Some("rs") { + continue; + } + + let file_name = path + .file_name() + .and_then(|file_name| file_name.to_str()) + .context("generated helper path is not utf-8")?; + + if !expected_files.contains(file_name) { + fs::remove_file(&path) + .with_context(|| format!("failed to remove stale generated helper: {path:?}"))?; + } + } + + let mut written = Vec::with_capacity(helpers.len() + 1); + let mod_rs = config.output_dir.join("mod.rs"); + fs::write(&mod_rs, generate_mod_rs(&helpers)) + .with_context(|| format!("failed to write generated helper module: {mod_rs:?}"))?; + written.push(mod_rs); + + for (helper, inline_deps) in helpers.iter().zip(inline_deps) { + let output = config.output_dir.join(format!("{}.rs", helper.module_name)); + fs::write(&output, generate_helper_rs(helper, inline_deps)) + .with_context(|| format!("failed to write generated helper file: {output:?}"))?; + written.push(output); + } + + Ok(written) +} + +fn read_index_order(input_dir: &Path) -> Result> { + let index_path = input_dir.join("index.js"); + let index = fs::read_to_string(&index_path) + .with_context(|| format!("failed to read helper index: {index_path:?}"))?; + let mut modules = Vec::new(); + + for line in index.lines() { + let line = line.trim(); + let Some(rest) = line.strip_prefix("export { _ as ") else { + continue; + }; + + let Some((exported, rest)) = rest.split_once(" } from \"./") else { + bail!("unsupported helper index export line: `{line}`"); + }; + let Some(source) = rest.strip_suffix(".js\";") else { + bail!("unsupported helper index export source: `{line}`"); + }; + + if exported != source { + bail!("helper index exports `{exported}` from `{source}`, but they must match"); + } + + modules.push(exported.to_string()); + } + + if modules.is_empty() { + bail!("helper index did not contain any helper exports"); + } + + Ok(modules) +} + +fn read_available_modules(input_dir: &Path) -> Result> { + let mut modules = BTreeSet::new(); + + for entry in fs::read_dir(input_dir) + .with_context(|| format!("failed to read helper input directory: {input_dir:?}"))? + { + let entry = entry?; + let path = entry.path(); + if path.extension().and_then(|ext| ext.to_str()) != Some("js") { + continue; + } + + let Some(stem) = path.file_stem().and_then(|stem| stem.to_str()) else { + bail!("helper path is not utf-8: {path:?}"); + }; + + if stem == "index" { + continue; + } + + if !stem.starts_with('_') { + bail!("helper file name must start with `_`: {path:?}"); + } + + modules.insert(stem.to_string()); + } + + Ok(modules) +} + +fn parse_helper(module_name: &str, path: &Path) -> Result { + let code = fs::read_to_string(path) + .with_context(|| format!("failed to read helper source: {path:?}"))?; + + let mut deps = Vec::new(); + let mut stripped = Vec::new(); + let mut export_count = 0usize; + + for line in code.lines() { + let trimmed = line.trim(); + + if trimmed.starts_with("import ") { + deps.push(parse_import(module_name, trimmed)?); + continue; + } + + if trimmed.starts_with("export ") { + let expected = format!("export {{ {module_name} as _ }};"); + if trimmed != expected { + bail!("helper `{module_name}` must export exactly `{expected}`, found `{trimmed}`"); + } + + export_count += 1; + continue; + } + + stripped.push(line); + } + + if export_count != 1 { + bail!("helper `{module_name}` must have exactly one export, found {export_count}"); + } + + let mut source = stripped.join("\n"); + source = source.trim_matches('\n').to_string(); + source.push('\n'); + + let function_head = format!("function {module_name}("); + if !source.contains(&function_head) { + bail!("helper `{module_name}` must define `{function_head}`"); + } + + if source.lines().any(|line| { + line.trim_start().starts_with("import ") || line.trim_start().starts_with("export ") + }) { + bail!("helper `{module_name}` still contains module syntax after stripping"); + } + + let first_function = source + .find("function ") + .context("helper source must contain a function declaration")?; + let prelude = &source[..first_function]; + for dep in &deps { + if prelude.contains(dep) { + bail!( + "helper `{module_name}` references dependency `{dep}` before the first function \ + declaration; helper order would become significant" + ); + } + } + + let ident = module_name + .strip_prefix('_') + .context("helper module name must start with `_`")? + .to_string(); + if !is_valid_helper_ident(&ident) { + bail!("invalid helper module name: {module_name}"); + } + + Ok(Helper { + module_name: module_name.to_string(), + ident, + source, + deps, + }) +} + +fn is_valid_helper_ident(ident: &str) -> bool { + if ident.is_empty() || ident.split('_').any(|part| part.is_empty()) || is_rust_keyword(ident) { + return false; + } + + ident + .bytes() + .all(|byte| byte == b'_' || byte.is_ascii_lowercase() || byte.is_ascii_digit()) +} + +fn is_rust_keyword(ident: &str) -> bool { + matches!( + ident, + "Self" + | "abstract" + | "as" + | "async" + | "await" + | "become" + | "box" + | "break" + | "const" + | "continue" + | "crate" + | "do" + | "dyn" + | "else" + | "enum" + | "extern" + | "false" + | "final" + | "fn" + | "for" + | "gen" + | "if" + | "impl" + | "in" + | "let" + | "loop" + | "macro" + | "match" + | "mod" + | "move" + | "mut" + | "override" + | "priv" + | "pub" + | "ref" + | "return" + | "self" + | "static" + | "struct" + | "super" + | "trait" + | "true" + | "try" + | "type" + | "typeof" + | "unsafe" + | "unsized" + | "use" + | "virtual" + | "where" + | "while" + | "yield" + ) +} + +fn parse_import(module_name: &str, line: &str) -> Result { + let Some(rest) = line.strip_prefix("import { _ as ") else { + bail!("unsupported import in helper `{module_name}`: `{line}`"); + }; + + let Some((binding, rest)) = rest.split_once(" } from \"./") else { + bail!("unsupported import in helper `{module_name}`: `{line}`"); + }; + + let Some(source) = rest.strip_suffix(".js\";") else { + bail!("unsupported import source in helper `{module_name}`: `{line}`"); + }; + + if binding != source { + bail!( + "helper `{module_name}` imports `{binding}` from `{source}`, but the binding must \ + match the source" + ); + } + + Ok(binding.to_string()) +} + +fn validate_deps(helpers: &[Helper]) -> Result<()> { + let helper_map = helpers + .iter() + .map(|helper| (helper.module_name.as_str(), helper)) + .collect::>(); + + for helper in helpers { + for dep in &helper.deps { + if !helper_map.contains_key(dep.as_str()) { + bail!( + "helper `{}` imports missing helper `{dep}`", + helper.module_name + ); + } + } + } + + Ok(()) +} + +fn compute_inline_deps(helpers: &[Helper]) -> Result> { + if helpers.len() > HELPER_BITMAP_BITS { + bail!( + "helper count {} exceeds {HELPER_BITMAP_BITS}; migrate helper dependency bitmaps to \ + multiple words", + helpers.len() + ); + } + + let helper_indices = helpers + .iter() + .enumerate() + .map(|(index, helper)| (helper.module_name.as_str(), index)) + .collect::>(); + + let mut inline_deps = Vec::with_capacity(helpers.len()); + for index in 0..helpers.len() { + let mut bits = 0u128; + collect_inline_deps(index, helpers, &helper_indices, &mut bits)?; + inline_deps.push(bits); + } + + Ok(inline_deps) +} + +fn collect_inline_deps( + index: usize, + helpers: &[Helper], + helper_indices: &BTreeMap<&str, usize>, + bits: &mut u128, +) -> Result<()> { + let bit = 1u128 << index; + if *bits & bit != 0 { + return Ok(()); + } + + *bits |= bit; + + for dep in &helpers[index].deps { + let dep_index = helper_indices + .get(dep.as_str()) + .copied() + .with_context(|| format!("missing helper `{dep}` during dependency flattening"))?; + collect_inline_deps(dep_index, helpers, helper_indices, bits)?; + } + + Ok(()) +} + +fn generate_mod_rs(helpers: &[Helper]) -> String { + let mut output = String::new(); + + output.push_str(GENERATED_HEADER); + output.push_str("#![allow(clippy::all)]\n\n"); + + for helper in helpers { + output.push_str("mod "); + output.push_str(&helper.module_name); + output.push_str(";\n"); + } + + output.push_str("\n#[allow(non_camel_case_types)]\n"); + output.push_str("#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]\n"); + output.push_str("#[repr(usize)]\n"); + output.push_str("pub enum HelperName {\n"); + for helper in helpers { + output.push_str(" "); + output.push_str(&helper.ident); + output.push_str(",\n"); + } + output.push_str("}\n\n"); + + output.push_str("pub const HELPER_COUNT: usize = "); + output.push_str(&helpers.len().to_string()); + output.push_str(";\n\n"); + + output.push_str("#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]\n"); + output.push_str("pub struct HelperBitmap(u128);\n\n"); + output.push_str("impl HelperBitmap {\n"); + output.push_str(" pub const EMPTY: Self = Self(0);\n\n"); + output.push_str(" pub const fn single(name: HelperName) -> Self {\n"); + output.push_str(" Self(1u128 << (name as usize))\n"); + output.push_str(" }\n\n"); + output.push_str(" pub const fn from_bits(bits: u128) -> Self {\n"); + output.push_str(" Self(bits)\n"); + output.push_str(" }\n\n"); + output.push_str(" pub fn contains(self, name: HelperName) -> bool {\n"); + output.push_str(" self.0 & Self::single(name).0 != 0\n"); + output.push_str(" }\n\n"); + output.push_str(" pub fn insert(&mut self, name: HelperName) {\n"); + output.push_str(" self.0 |= Self::single(name).0;\n"); + output.push_str(" }\n\n"); + output.push_str(" pub fn is_empty(self) -> bool {\n"); + output.push_str(" self.0 == 0\n"); + output.push_str(" }\n"); + output.push_str("}\n\n"); + output.push_str("impl core::ops::BitOr for HelperBitmap {\n"); + output.push_str(" type Output = Self;\n\n"); + output.push_str(" fn bitor(self, rhs: Self) -> Self {\n"); + output.push_str(" Self(self.0 | rhs.0)\n"); + output.push_str(" }\n"); + output.push_str("}\n\n"); + output.push_str("impl core::ops::BitOrAssign for HelperBitmap {\n"); + output.push_str(" fn bitor_assign(&mut self, rhs: Self) {\n"); + output.push_str(" self.0 |= rhs.0;\n"); + output.push_str(" }\n"); + output.push_str("}\n\n"); + + output.push_str("#[derive(Clone, Copy, Debug)]\n"); + output.push_str("pub struct HelperDef {\n"); + output.push_str(" pub name: HelperName,\n"); + output.push_str(" pub local: &'static str,\n"); + output.push_str(" pub import_path: &'static str,\n"); + output.push_str(" #[cfg(feature = \"inline-helpers\")]\n"); + output.push_str(" pub source: &'static str,\n"); + output.push_str(" #[cfg(feature = \"inline-helpers\")]\n"); + output.push_str(" pub deps: HelperBitmap,\n"); + output.push_str("}\n\n"); + + output.push_str("pub const ALL: &[HelperDef; HELPER_COUNT] = &[\n"); + for helper in helpers { + output.push_str(" "); + output.push_str(&helper.module_name); + output.push_str("::DEF,\n"); + } + output.push_str("];\n\n"); + + output.push_str("pub fn helper(name: HelperName) -> &'static HelperDef {\n"); + output.push_str(" &ALL[name as usize]\n"); + output.push_str("}\n\n"); + + output.push_str("pub fn helper_name(name: &str) -> Option {\n"); + output.push_str(" match name {\n"); + for helper in helpers { + output.push_str(" \""); + output.push_str(&helper.ident); + output.push_str("\" => Some(HelperName::"); + output.push_str(&helper.ident); + output.push_str("),\n"); + } + output.push_str(" _ => None,\n"); + output.push_str(" }\n"); + output.push_str("}\n\n"); + + output.push_str("impl super::Helpers {\n"); + for helper in helpers { + output.push_str(" pub fn "); + output.push_str(&helper.ident); + output.push_str("(&self) {\n"); + output.push_str(" self.enable(HelperName::"); + output.push_str(&helper.ident); + output.push_str(");\n"); + output.push_str(" }\n\n"); + } + output.push_str("}\n\n"); + + output.push_str("#[cfg(feature = \"inline-helpers\")]\n"); + output.push_str("pub fn stmts(name: HelperName) -> &'static [swc_ecma_ast::Stmt] {\n"); + output.push_str(" match name {\n"); + for helper in helpers { + output.push_str(" HelperName::"); + output.push_str(&helper.ident); + output.push_str(" => "); + output.push_str(&helper.module_name); + output.push_str("::stmts(),\n"); + } + output.push_str(" }\n"); + output.push_str("}\n"); + + output +} + +fn generate_helper_rs(helper: &Helper, inline_deps: u128) -> String { + let mut output = String::new(); + + output.push_str(GENERATED_HEADER); + output.push_str("\nuse super::{HelperDef, HelperName};\n\n"); + output.push_str("pub const DEF: HelperDef = HelperDef {\n"); + output.push_str(" name: HelperName::"); + output.push_str(&helper.ident); + output.push_str(",\n"); + output.push_str(" local: \""); + output.push_str(&helper.module_name); + output.push_str("\",\n"); + output.push_str(" import_path: \"@swc/helpers/_/"); + output.push_str(&helper.module_name); + output.push_str("\",\n"); + output.push_str(" #[cfg(feature = \"inline-helpers\")]\n"); + output.push_str(" source: "); + output.push_str(&raw_string_literal(&helper.source)); + output.push_str(",\n"); + output.push_str(" #[cfg(feature = \"inline-helpers\")]\n"); + output.push_str(" deps: super::HelperBitmap::from_bits("); + output.push_str(&format!("0x{inline_deps:032x}")); + output.push_str("),\n"); + output.push_str("};\n\n"); + output.push_str("#[cfg(feature = \"inline-helpers\")]\n"); + output.push_str("pub fn stmts() -> &'static [swc_ecma_ast::Stmt] {\n"); + output.push_str(" static STMTS: once_cell::sync::Lazy> =\n"); + output.push_str(" once_cell::sync::Lazy::new(|| "); + output.push_str("super::super::parse(DEF.source, DEF.import_path));\n"); + output.push_str(" &STMTS\n"); + output.push_str("}\n"); + + output +} + +fn raw_string_literal(value: &str) -> String { + for hashes in 1.. { + let delimiter = "#".repeat(hashes); + if !value.contains(&format!("\"{delimiter}")) { + return format!("r{delimiter}\"{value}\"{delimiter}"); + } + } + + unreachable!("raw string delimiter search should always terminate") +} diff --git a/deps/swc/tools/generate-code/src/generators/mod.rs b/deps/swc/tools/generate-code/src/generators/mod.rs index 1a49dced3..8e6e8a0b7 100644 --- a/deps/swc/tools/generate-code/src/generators/mod.rs +++ b/deps/swc/tools/generate-code/src/generators/mod.rs @@ -1 +1,2 @@ +pub mod helpers; pub mod visitor; diff --git a/deps/swc/tools/generate-code/src/main.rs b/deps/swc/tools/generate-code/src/main.rs index 3d2fa7bf6..64d7ce146 100644 --- a/deps/swc/tools/generate-code/src/main.rs +++ b/deps/swc/tools/generate-code/src/main.rs @@ -1,9 +1,14 @@ #![allow(clippy::only_used_in_recursion)] -use std::path::{Path, PathBuf}; - -use anyhow::{bail, Context, Result}; -use clap::Parser; +use std::{ + collections::BTreeMap, + fs, + path::{Path, PathBuf}, + time::{SystemTime, UNIX_EPOCH}, +}; + +use anyhow::{anyhow, bail, Context, Result}; +use clap::{Parser, Subcommand}; use swc_config::regex::CachedRegex; use syn::Item; @@ -14,27 +19,198 @@ mod types; #[derive(Debug, Parser)] struct CliArgs { + #[clap(subcommand)] + command: Option, + /// The directory containing the crate to generate the visitor for. #[clap(short = 'i', long)] - input_dir: PathBuf, + input_dir: Option, /// The file for the generated visitor code. #[clap(short = 'o', long)] - output: PathBuf, + output: Option, /// The list of types to exclude from the generated visitor. #[clap(long)] exclude: Vec, } +#[derive(Debug, Subcommand)] +enum Command { + /// Generate Rust artifacts for ECMAScript helpers. + Helpers { + /// Check that generated helper artifacts are up to date without + /// changing the workspace. + #[clap(long)] + check: bool, + }, +} + fn main() -> Result<()> { let CliArgs { + command, input_dir, output, exclude, } = CliArgs::parse(); - run_visitor_codegen(&input_dir, &output, &exclude)?; + match command { + Some(Command::Helpers { check }) => run_helpers_codegen(check)?, + None => { + let input_dir = input_dir.context("`--input-dir` is required for visitor codegen")?; + let output = output.context("`--output` is required for visitor codegen")?; + + run_visitor_codegen(&input_dir, &output, &exclude)?; + } + } + + Ok(()) +} + +fn run_helpers_codegen(check: bool) -> Result<()> { + let root = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../..") + .canonicalize() + .context("failed to canonicalize repository root")?; + + let input_dir = root.join("packages/helpers/esm"); + let output_dir = root.join("crates/swc_ecma_transforms_base/src/helpers/generated"); + + if check { + return check_helpers_codegen(&input_dir, &output_dir); + } + + let written = generators::helpers::generate(generators::helpers::Config { + input_dir, + output_dir, + })?; + + eprintln!("Generated {} helper artifact files", written.len()); + + run_cargo_fmt_many(&written)?; + + Ok(()) +} + +fn check_helpers_codegen(input_dir: &Path, output_dir: &Path) -> Result<()> { + let temp_dir = create_temp_dir("swc-helper-codegen-check")?; + let generated_dir = temp_dir.join("generated"); + + let result = (|| { + let written = generators::helpers::generate(generators::helpers::Config { + input_dir: input_dir.to_path_buf(), + output_dir: generated_dir.clone(), + })?; + + run_cargo_fmt_many(&written)?; + compare_generated_dirs(output_dir, &generated_dir) + })(); + + let cleanup_result = fs::remove_dir_all(&temp_dir) + .with_context(|| format!("failed to remove temporary directory: {temp_dir:?}")); + + result?; + cleanup_result?; + + eprintln!("Helper artifacts are up to date"); + + Ok(()) +} + +fn create_temp_dir(prefix: &str) -> Result { + let nanos = SystemTime::now() + .duration_since(UNIX_EPOCH) + .context("system clock is before unix epoch")? + .as_nanos(); + let path = std::env::temp_dir().join(format!("{prefix}-{}-{nanos}", std::process::id())); + + fs::create_dir_all(&path) + .with_context(|| format!("failed to create temporary directory: {path:?}"))?; + + Ok(path) +} + +fn compare_generated_dirs(committed_dir: &Path, generated_dir: &Path) -> Result<()> { + let committed_files = collect_files(committed_dir)?; + let generated_files = collect_files(generated_dir)?; + + for path in generated_files.keys() { + if !committed_files.contains_key(path) { + return Err(stale_helper_artifacts(format_args!( + "generated helper artifact `{}` is missing", + path.display() + ))); + } + } + + for path in committed_files.keys() { + if !generated_files.contains_key(path) { + return Err(stale_helper_artifacts(format_args!( + "generated helper artifact `{}` is stale", + path.display() + ))); + } + } + + for (path, generated_path) in generated_files { + let committed_path = &committed_files[&path]; + let committed = fs::read(committed_path) + .with_context(|| format!("failed to read generated artifact: {committed_path:?}"))?; + let generated = fs::read(&generated_path) + .with_context(|| format!("failed to read generated artifact: {generated_path:?}"))?; + + if committed != generated { + return Err(stale_helper_artifacts(format_args!( + "generated helper artifact `{}` is stale", + path.display() + ))); + } + } + + Ok(()) +} + +fn stale_helper_artifacts(message: std::fmt::Arguments<'_>) -> anyhow::Error { + anyhow!("{message}; run `cargo codegen helpers` and commit the generated helper artifacts") +} + +fn collect_files(root: &Path) -> Result> { + let mut files = BTreeMap::new(); + collect_files_inner(root, root, &mut files)?; + Ok(files) +} + +fn collect_files_inner( + root: &Path, + dir: &Path, + files: &mut BTreeMap, +) -> Result<()> { + for entry in fs::read_dir(dir) + .with_context(|| format!("failed to read generated artifact directory: {dir:?}"))? + { + let entry = entry?; + let path = entry.path(); + let file_type = entry.file_type().with_context(|| { + format!("failed to read file type for generated artifact: {path:?}") + })?; + + if file_type.is_dir() { + collect_files_inner(root, &path, files)?; + continue; + } + + if file_type.is_file() { + let relative = path + .strip_prefix(root) + .with_context(|| { + format!( + "generated artifact path is not under root: path={path:?}, root={root:?}" + ) + })? + .to_path_buf(); + files.insert(relative, path); + } + } Ok(()) } @@ -257,6 +433,12 @@ fn test_xml() { .unwrap(); } +#[test] +fn test_helpers() { + run_helpers_codegen(false).unwrap(); + run_helpers_codegen(true).unwrap(); +} + fn get_type_defs(file: &syn::File) -> Vec<&Item> { let mut type_defs = Vec::new(); for item in &file.items { @@ -301,3 +483,26 @@ fn run_cargo_fmt(file: &Path) -> Result<()> { Ok(()) } + +fn run_cargo_fmt_many(files: &[PathBuf]) -> Result<()> { + if files.is_empty() { + return Ok(()); + } + + let files = files + .iter() + .map(|file| file.canonicalize().context("failed to canonicalize file")) + .collect::>>()?; + + let mut cmd = std::process::Command::new("cargo"); + cmd.arg("fmt").arg("--").args(&files); + + eprintln!("Running cargo fmt for {} files", files.len()); + let status = cmd.status().context("failed to run cargo fmt")?; + + if !status.success() { + bail!("cargo fmt failed with status: {status:?}"); + } + + Ok(()) +}