From 8010ff5a23c1b3d2da7d7a4d0bb26e13497d49e6 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Tue, 16 May 2023 14:05:01 +0200 Subject: [PATCH 01/19] Node.js production runtime POC --- .github/workflows/test.yml | 38 + Cargo.lock | 42 + Cargo.toml | 2 + crates/turbopack-binding/Cargo.toml | 8 + crates/turbopack-binding/src/lib.rs | 4 + crates/turbopack-build/Cargo.toml | 34 + crates/turbopack-build/build.rs | 5 + .../turbopack-build/src/chunking_context.rs | 374 ++++ crates/turbopack-build/src/ecmascript/mod.rs | 1 + .../src/ecmascript/node/chunk.rs | 143 ++ .../src/ecmascript/node/content.rs | 101 + .../src/ecmascript/node/evaluate/chunk.rs | 245 +++ .../src/ecmascript/node/evaluate/mod.rs | 2 + .../src/ecmascript/node/evaluate/runtime.rs | 175 ++ .../src/ecmascript/node/mod.rs | 3 + crates/turbopack-build/src/lib.rs | 18 + crates/turbopack-cli/Cargo.toml | 1 + crates/turbopack-cli/js/package.json | 2 +- crates/turbopack-cli/js/src/entry/client.ts | 4 +- crates/turbopack-cli/js/tsconfig.json | 2 +- .../turbopack-cli/src/dev/web_entry_source.rs | 4 +- .../src/chunk/chunking_context.rs | 3 + .../src/chunk/data.rs} | 44 +- crates/turbopack-core/src/chunk/mod.rs | 2 + crates/turbopack-core/src/code_builder.rs | 6 + crates/turbopack-core/src/ident.rs | 138 +- crates/turbopack-core/src/lib.rs | 1 + crates/turbopack-core/src/virtual_fs.rs | 67 + crates/turbopack-dev/Cargo.toml | 5 + crates/turbopack-dev/js/package.json | 20 - crates/turbopack-dev/js/tsconfig.json | 32 - crates/turbopack-dev/js/types/backend.d.ts | 20 - crates/turbopack-dev/js/types/index.d.ts | 216 -- crates/turbopack-dev/js/types/runtime.d.ts | 22 - .../turbopack-dev/js/types/runtime.dom.d.ts | 6 - .../turbopack-dev/js/types/runtime.none.d.ts | 7 - crates/turbopack-dev/src/chunking_context.rs | 186 +- .../src/ecmascript/content_entry.rs | 9 +- .../src/ecmascript/evaluate/chunk.rs | 65 +- crates/turbopack-dev/src/ecmascript/mod.rs | 3 - .../src/ecmascript/module_factory.rs | 48 - .../turbopack-dev/src/ecmascript/runtime.rs | 214 ++ crates/turbopack-dev/src/lib.rs | 3 +- .../turbopack-ecmascript-runtime/Cargo.toml | 32 + crates/turbopack-ecmascript-runtime/README.md | 34 + crates/turbopack-ecmascript-runtime/build.rs | 5 + .../js/package.json | 26 + .../js/src/build/runtime.ts | 252 +++ .../js/src/build/tsconfig.json | 9 + .../js/src/dev}/client/hmr-client.ts | 23 +- .../js/src/dev/client/tsconfig.json | 9 + .../js/src/dev}/client/websocket.ts | 0 .../js/src/dev/runtime/base/dummy.ts | 9 + .../js/src/dev/runtime/base/extensions.d.ts} | 29 +- .../js/src/dev/runtime/base/globals.d.ts | 30 + .../js/src/dev/runtime/base}/protocol.d.ts | 37 +- .../js/src/dev/runtime/base/runtime-base.ts} | 890 ++++----- .../js/src/dev/runtime/base/tsconfig.json | 9 + .../dev/runtime/dom/runtime-backend-dom.ts} | 66 +- .../js/src/dev/runtime/dom/tsconfig.json | 8 + .../runtime/nodejs/runtime-backend-nodejs.ts} | 32 +- .../js/src/dev/runtime/nodejs/tsconfig.json | 9 + .../dev/runtime/none/runtime-backend-none.ts} | 56 +- .../js/src/dev/runtime/none/tsconfig.json | 8 + .../js/src/shared/dummy.ts | 9 + .../js/src/shared/runtime-types.d.ts | 37 + .../js/src/shared/runtime-utils.ts | 199 ++ .../js/src/shared/tsconfig.json | 8 + .../js/src/tsconfig.base.json | 20 + .../src/asset_context.rs | 30 + .../src/build_runtime.rs | 27 + .../src/dev_runtime.rs | 73 + .../src/dummy_runtime.rs | 10 + .../src/embed_js.rs | 6 +- .../turbopack-ecmascript-runtime/src/lib.rs | 23 + .../src/runtime_type.rs | 25 + .../turbopack-ecmascript/src/chunk/context.rs | 18 +- crates/turbopack-ecmascript/src/chunk/data.rs | 39 + crates/turbopack-ecmascript/src/chunk/item.rs | 149 +- crates/turbopack-ecmascript/src/chunk/mod.rs | 2 + crates/turbopack-ecmascript/src/lib.rs | 208 +- .../src}/manifest/chunk_asset.rs | 47 +- .../src}/manifest/chunk_item.rs | 38 +- .../src}/manifest/loader_item.rs | 86 +- .../src}/manifest/mod.rs | 0 .../turbopack-ecmascript/src/static_code.rs | 54 + .../src/tree_shake/chunk_item.rs | 15 +- crates/turbopack-tests/Cargo.toml | 4 +- crates/turbopack-tests/tests/snapshot.rs | 58 +- .../output/20803_bar_index_c8a3ce.js | 2 +- .../output/20803_foo_index_5f9e1e.js | 2 +- ...t_basic_async_chunk_input_import_571bb9.js | 2 +- ...t_basic_async_chunk_input_import_a29514.js | 2 +- ...t_basic_async_chunk_input_import_e0f91a.js | 11 + ...ot_basic_async_chunk_input_index_0d348e.js | 1734 +--------------- ...ot_basic_async_chunk_input_index_b53fce.js | 10 +- .../chunked/output/39e84_foo_index_4427e1.js | 2 +- ...apshot_basic_chunked_input_index_b53fce.js | 2 +- ...apshot_basic_chunked_input_index_e77e9f.js | 1734 +--------------- ...apshot_basic_shebang_input_index_b1f0c2.js | 1734 +--------------- ...apshot_basic_shebang_input_index_b53fce.js | 2 +- .../shebang/output/d1787_foo_index_dd389c.js | 2 +- ...shot_comptime_define_input_index_6b0d2b.js | 1734 +--------------- ...shot_comptime_define_input_index_b53fce.js | 2 +- ..._absolute-uri-import_input_index_b53fce.js | 2 +- ..._absolute-uri-import_input_index_fa9a30.js | 1734 +--------------- ....css => 8697f_foo_style_module_b5a149.css} | 4 +- ... => 8697f_foo_style_module_b5a149.css.map} | 0 ...=> 8697f_foo_style_module_css_7740ee._.js} | 6 +- ...697f_foo_style_module_css_7740ee._.js.map} | 0 ....css => 8697f_foo_style_module_fb38f0.css} | 2 +- ... => 8697f_foo_style_module_fb38f0.css.map} | 0 ...sts_snapshot_css_css_input_index_011705.js | 6 + ...napshot_css_css_input_index_011705.js.map} | 0 ...sts_snapshot_css_css_input_index_37a138.js | 1738 ----------------- ...ts_snapshot_css_css_input_index_41af4f.js} | 10 +- ...sts_snapshot_css_css_input_index_b53fce.js | 4 +- ...hot_css_css_input_style_module_b5a149.css} | 4 +- ...css_css_input_style_module_b5a149.css.map} | 0 ...hot_css_css_input_style_module_fb38f0.css} | 2 +- ...css_css_input_style_module_fb38f0.css.map} | 0 .../63a02_@emotion_react_index_a1c0c3.js | 2 +- ...2_@emotion_react_jsx-dev-runtime_73b602.js | 2 +- .../63a02_@emotion_styled_index_fd4de2.js | 2 +- ...shot_emotion_emotion_input_index_b080c4.js | 1734 +--------------- ...shot_emotion_emotion_input_index_b53fce.js | 2 +- ...napshot_env_env_input__env__env_b53fce.js} | 6 +- ...hot_env_env_input__env__env_b53fce.js.map} | 0 ...sts_snapshot_env_env_input_index_29a23f.js | 1738 ----------------- ...ts_snapshot_env_env_input_index_84512e.js} | 6 +- ...sts_snapshot_env_env_input_index_8a0be0.js | 6 + ...napshot_env_env_input_index_8a0be0.js.map} | 0 ...sts_snapshot_env_env_input_index_b53fce.js | 2 +- ...entrry_runtime_entry_input_index_b53fce.js | 2 +- ...entrry_runtime_entry_input_index_f59cc7.js | 1734 +--------------- ...shot_example_example_input_index_78b6bf.js | 1734 +--------------- ...shot_example_example_input_index_b53fce.js | 2 +- ...ot_export-alls_cjs-2_input_index_289ae7.js | 1734 +--------------- ...ot_export-alls_cjs-2_input_index_b53fce.js | 8 +- ...port-alls_cjs-script_input_index_3e96b7.js | 1734 +--------------- ...port-alls_cjs-script_input_index_b53fce.js | 6 +- ...shot_import-meta_cjs_input_index_537553.js | 1734 +--------------- ...shot_import-meta_cjs_input_index_b53fce.js | 4 +- ...rt-meta_esm-multiple_input_index_b53fce.js | 4 +- ...rt-meta_esm-multiple_input_index_c00392.js | 1734 +--------------- ...ort-meta_esm-mutable_input_index_6c9201.js | 1734 +--------------- ...ort-meta_esm-mutable_input_index_b53fce.js | 4 +- ...port-meta_esm-object_input_index_6fcf7d.js | 1734 +--------------- ...port-meta_esm-object_input_index_b53fce.js | 4 +- ...shot_import-meta_esm_input_index_b53fce.js | 4 +- ...shot_import-meta_esm_input_index_c4c88a.js | 1734 +--------------- ...shot_import-meta_url_input_index_988b57.js | 1734 +--------------- ...shot_import-meta_url_input_index_b53fce.js | 6 +- ...shot_imports_dynamic_input_index_45c162.js | 1734 +--------------- ...shot_imports_dynamic_input_index_b53fce.js | 8 +- ...orts_dynamic_input_vercel_mjs_36739f._.js} | 6 +- ...orts_dynamic_input_vercel_mjs_4e74d3._.js} | 8 +- ..._dynamic_input_vercel_mjs_4e74d3._.js.map} | 0 ...orts_dynamic_input_vercel_mjs_536504._.js} | 6 +- ..._dynamic_input_vercel_mjs_536504._.js.map} | 0 ...ports_dynamic_input_vercel_mjs_d4d527._.js | 11 + ...eration for chunk item errored-b5c990.txt} | 2 +- ...napshot_imports_json_input_index_961ae2.js | 1734 +--------------- ...napshot_imports_json_input_index_b53fce.js | 6 +- ...apshot_imports_order_input_index_9cd22f.js | 1734 +--------------- ...ot_imports_order_input_index_9cd22f.js.map | 2 +- ...apshot_imports_order_input_index_b53fce.js | 8 +- ...ts_resolve_error_cjs_input_index_b53fce.js | 2 +- ...ts_resolve_error_cjs_input_index_f8412b.js | 1734 +--------------- ...ts_resolve_error_esm_input_index_0b3e45.js | 1734 +--------------- ...ts_resolve_error_esm_input_index_b53fce.js | 2 +- ...s_static-and-dynamic_input_index_b53fce.js | 10 +- ...s_static-and-dynamic_input_index_ec8693.js | 1734 +--------------- ...-and-dynamic_input_vercel_mjs_10fe7a._.js} | 8 +- ...-dynamic_input_vercel_mjs_10fe7a._.js.map} | 0 ...-and-dynamic_input_vercel_mjs_26aaf6._.js} | 6 +- ...-dynamic_input_vercel_mjs_26aaf6._.js.map} | 0 ...-and-dynamic_input_vercel_mjs_84c275._.js} | 6 +- ...c-and-dynamic_input_vercel_mjs_ab3761._.js | 11 + ...pshot_imports_static_input_index_885269.js | 1734 +--------------- ...pshot_imports_static_input_index_b53fce.js | 4 +- ...orts_subpath-imports_input_index_31b659.js | 1734 +--------------- ...orts_subpath-imports_input_index_b53fce.js | 12 +- ...de_protocol_external_input_index_667edf.js | 1734 +--------------- ...de_protocol_external_input_index_b53fce.js | 2 +- .../default_build_runtime/input/index.js | 1 + .../default_build_runtime/options.json | 4 + ...efault_build_runtime_input_index_7c123c.js | 4 + ...t_build_runtime_input_index_7c123c.js.map} | 0 ...efault_build_runtime_input_index_e254c5.js | 11 + ...lt_build_runtime_input_index_e254c5.js.map | 6 + .../output/[turbopack]_runtime.js | 256 +++ .../output/[turbopack]_runtime.js.map | 6 + .../default_dev_runtime/input/index.js | 1 + .../runtime/default_dev_runtime/options.json | 3 + ..._default_dev_runtime_input_index_7fa8ff.js | 11 + ..._default_dev_runtime_input_index_b53fce.js | 10 + ...ault_dev_runtime_input_index_b53fce.js.map | 6 + ..._default_dev_runtime_input_index_e60ecd.js | 1033 ++++++++++ ...ault_dev_runtime_input_index_e60ecd.js.map | 8 + .../63a02_styled-components_index_a35c8c.js | 2 +- ...ts_styled_components_input_index_afc482.js | 1734 +--------------- ...ts_styled_components_input_index_b53fce.js | 2 +- .../63a02_react_jsx-dev-runtime_7d1be7.js | 2 +- ...b7bf_third_party_component_index_8e9ad8.js | 2 +- ...s_input_packages_component_index_b0e6f8.js | 2 +- ...nsforms_input_packages_app_index_4a3d65.js | 1734 +--------------- ...nsforms_input_packages_app_index_b53fce.js | 2 +- ...@swc_helpers____class_call_check_f08d44.js | 2 +- ...ransforms_preset_env_input_index_9dcfd0.js | 1734 +--------------- ...ransforms_preset_env_input_index_b53fce.js | 2 +- ...ipt_jsconfig-baseurl_input_index_8f1e58.js | 1734 +--------------- ...ipt_jsconfig-baseurl_input_index_b53fce.js | 4 +- ...sconfig-baseurl_input_index.ts_0aa04e._.js | 1738 ----------------- ...config-baseurl_input_index_ts_8fad73._.js} | 6 +- ...sconfig-baseurl_input_index_ts_99f69d._.js | 6 + ...ig-baseurl_input_index_ts_99f69d._.js.map} | 0 ...config-baseurl_input_index_ts_b53fce._.js} | 8 +- ...ig-baseurl_input_index_ts_b53fce._.js.map} | 0 .../63a02_tsconfig-mod_prop_ts_2aa573._.js} | 6 +- ...3a02_tsconfig-mod_prop_ts_2aa573._.js.map} | 0 ...odule-full-path_input_index.ts_a751eb._.js | 1738 ----------------- ...odule-full-path_input_index_ts_1f521f._.js | 6 + ...-full-path_input_index_ts_1f521f._.js.map} | 0 ...dule-full-path_input_index_ts_62d7aa._.js} | 8 +- ...dule-full-path_input_index_ts_b53fce._.js} | 6 +- ...-full-path_input_index_ts_b53fce._.js.map} | 0 .../63a02_tsconfig-mod_prop_ts_ae3f0e._.js} | 6 +- ...3a02_tsconfig-mod_prop_ts_ae3f0e._.js.map} | 0 ...-extends-module_input_index.ts_a662d4._.js | 1738 ----------------- ...extends-module_input_index_ts_93ee43._.js} | 8 +- ...extends-module_input_index_ts_b53fce._.js} | 6 +- ...nds-module_input_index_ts_b53fce._.js.map} | 0 ...-extends-module_input_index_ts_ca2f6f._.js | 6 + ...nds-module_input_index_ts_ca2f6f._.js.map} | 0 ...ds-relative-dir_input_index.ts_be3d7b._.js | 1738 ----------------- ...ds-relative-dir_input_index_ts_5381a8._.js | 6 + ...lative-dir_input_index_ts_5381a8._.js.map} | 0 ...s-relative-dir_input_index_ts_64225d._.js} | 6 +- ...s-relative-dir_input_index_ts_b53fce._.js} | 8 +- ...lative-dir_input_index_ts_b53fce._.js.map} | 0 ...nds-without-ext_input_index.ts_38aae8._.js | 1738 ----------------- ...nds-without-ext_input_index_ts_385208._.js | 6 + ...ithout-ext_input_index_ts_385208._.js.map} | 0 ...ds-without-ext_input_index_ts_4121b1._.js} | 6 +- ...ds-without-ext_input_index_ts_b53fce._.js} | 8 +- ...ithout-ext_input_index_ts_b53fce._.js.map} | 0 ...sconfig-extends_input_index.ts_18c083._.js | 1738 ----------------- ...sconfig-extends_input_index_ts_3e6d5a._.js | 6 + ...fig-extends_input_index_ts_3e6d5a._.js.map | 4 + ...config-extends_input_index_ts_b53fce._.js} | 8 +- ...ig-extends_input_index_ts_b53fce._.js.map} | 0 ...config-extends_input_index_ts_db43e7._.js} | 6 +- pnpm-lock.yaml | 12 +- 254 files changed, 5272 insertions(+), 65800 deletions(-) create mode 100644 crates/turbopack-build/Cargo.toml create mode 100644 crates/turbopack-build/build.rs create mode 100644 crates/turbopack-build/src/chunking_context.rs create mode 100644 crates/turbopack-build/src/ecmascript/mod.rs create mode 100644 crates/turbopack-build/src/ecmascript/node/chunk.rs create mode 100644 crates/turbopack-build/src/ecmascript/node/content.rs create mode 100644 crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs create mode 100644 crates/turbopack-build/src/ecmascript/node/evaluate/mod.rs create mode 100644 crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs create mode 100644 crates/turbopack-build/src/ecmascript/node/mod.rs create mode 100644 crates/turbopack-build/src/lib.rs rename crates/{turbopack-dev/src/ecmascript/chunk_data.rs => turbopack-core/src/chunk/data.rs} (80%) create mode 100644 crates/turbopack-core/src/virtual_fs.rs delete mode 100644 crates/turbopack-dev/js/package.json delete mode 100644 crates/turbopack-dev/js/tsconfig.json delete mode 100644 crates/turbopack-dev/js/types/backend.d.ts delete mode 100644 crates/turbopack-dev/js/types/index.d.ts delete mode 100644 crates/turbopack-dev/js/types/runtime.d.ts delete mode 100644 crates/turbopack-dev/js/types/runtime.dom.d.ts delete mode 100644 crates/turbopack-dev/js/types/runtime.none.d.ts delete mode 100644 crates/turbopack-dev/src/ecmascript/module_factory.rs create mode 100644 crates/turbopack-dev/src/ecmascript/runtime.rs create mode 100644 crates/turbopack-ecmascript-runtime/Cargo.toml create mode 100644 crates/turbopack-ecmascript-runtime/README.md create mode 100644 crates/turbopack-ecmascript-runtime/build.rs create mode 100644 crates/turbopack-ecmascript-runtime/js/package.json create mode 100644 crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts create mode 100644 crates/turbopack-ecmascript-runtime/js/src/build/tsconfig.json rename crates/{turbopack-dev/js/src => turbopack-ecmascript-runtime/js/src/dev}/client/hmr-client.ts (97%) create mode 100644 crates/turbopack-ecmascript-runtime/js/src/dev/client/tsconfig.json rename crates/{turbopack-dev/js/src => turbopack-ecmascript-runtime/js/src/dev}/client/websocket.ts (100%) create mode 100644 crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts rename crates/{turbopack-dev/js/types/hot.d.ts => turbopack-ecmascript-runtime/js/src/dev/runtime/base/extensions.d.ts} (67%) create mode 100644 crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/globals.d.ts rename crates/{turbopack-dev/js/types => turbopack-ecmascript-runtime/js/src/dev/runtime/base}/protocol.d.ts (75%) rename crates/{turbopack-dev/js/src/runtime.js => turbopack-ecmascript-runtime/js/src/dev/runtime/base/runtime-base.ts} (63%) create mode 100644 crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/tsconfig.json rename crates/{turbopack-dev/js/src/runtime.dom.js => turbopack-ecmascript-runtime/js/src/dev/runtime/dom/runtime-backend-dom.ts} (79%) create mode 100644 crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/tsconfig.json rename crates/{turbopack-dev/js/src/runtime.nodejs.js => turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/runtime-backend-nodejs.ts} (70%) create mode 100644 crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/tsconfig.json rename crates/{turbopack-dev/js/src/runtime.none.js => turbopack-ecmascript-runtime/js/src/dev/runtime/none/runtime-backend-none.ts} (74%) create mode 100644 crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/tsconfig.json create mode 100644 crates/turbopack-ecmascript-runtime/js/src/shared/dummy.ts create mode 100644 crates/turbopack-ecmascript-runtime/js/src/shared/runtime-types.d.ts create mode 100644 crates/turbopack-ecmascript-runtime/js/src/shared/runtime-utils.ts create mode 100644 crates/turbopack-ecmascript-runtime/js/src/shared/tsconfig.json create mode 100644 crates/turbopack-ecmascript-runtime/js/src/tsconfig.base.json create mode 100644 crates/turbopack-ecmascript-runtime/src/asset_context.rs create mode 100644 crates/turbopack-ecmascript-runtime/src/build_runtime.rs create mode 100644 crates/turbopack-ecmascript-runtime/src/dev_runtime.rs create mode 100644 crates/turbopack-ecmascript-runtime/src/dummy_runtime.rs rename crates/{turbopack-dev => turbopack-ecmascript-runtime}/src/embed_js.rs (60%) create mode 100644 crates/turbopack-ecmascript-runtime/src/lib.rs create mode 100644 crates/turbopack-ecmascript-runtime/src/runtime_type.rs create mode 100644 crates/turbopack-ecmascript/src/chunk/data.rs rename crates/{turbopack-dev/src/ecmascript => turbopack-ecmascript/src}/manifest/chunk_asset.rs (75%) rename crates/{turbopack-dev/src/ecmascript => turbopack-ecmascript/src}/manifest/chunk_item.rs (65%) rename crates/{turbopack-dev/src/ecmascript => turbopack-ecmascript/src}/manifest/loader_item.rs (66%) rename crates/{turbopack-dev/src/ecmascript => turbopack-ecmascript/src}/manifest/mod.rs (100%) create mode 100644 crates/turbopack-ecmascript/src/static_code.rs create mode 100644 crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_e0f91a.js rename crates/turbopack-tests/tests/snapshot/css/css/output/{8697f_foo_style.module_b5a149.css => 8697f_foo_style_module_b5a149.css} (69%) rename crates/turbopack-tests/tests/snapshot/css/css/output/{8697f_foo_style.module_b5a149.css.map => 8697f_foo_style_module_b5a149.css.map} (100%) rename crates/turbopack-tests/tests/snapshot/css/css/output/{8697f_foo_style.module.css_7740ee._.js => 8697f_foo_style_module_css_7740ee._.js} (75%) rename crates/turbopack-tests/tests/snapshot/css/css/output/{8697f_foo_style.module.css_7740ee._.js.map => 8697f_foo_style_module_css_7740ee._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/css/css/output/{8697f_foo_style.module_fb38f0.css => 8697f_foo_style_module_fb38f0.css} (74%) rename crates/turbopack-tests/tests/snapshot/css/css/output/{8697f_foo_style.module_fb38f0.css.map => 8697f_foo_style_module_fb38f0.css.map} (100%) create mode 100644 crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_011705.js rename crates/turbopack-tests/tests/snapshot/css/css/output/{crates_turbopack-tests_tests_snapshot_css_css_input_index_37a138.js.map => crates_turbopack-tests_tests_snapshot_css_css_input_index_011705.js.map} (100%) delete mode 100644 crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_37a138.js rename crates/turbopack-tests/tests/snapshot/css/css/output/{crates_turbopack-tests_tests_snapshot_css_css_input_index_469b46.js => crates_turbopack-tests_tests_snapshot_css_css_input_index_41af4f.js} (77%) rename crates/turbopack-tests/tests/snapshot/css/css/output/{crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css => crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css} (90%) rename crates/turbopack-tests/tests/snapshot/css/css/output/{crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css.map => crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css.map} (100%) rename crates/turbopack-tests/tests/snapshot/css/css/output/{crates_turbopack-tests_tests_snapshot_css_css_input_style.module_fb38f0.css => crates_turbopack-tests_tests_snapshot_css_css_input_style_module_fb38f0.css} (92%) rename crates/turbopack-tests/tests/snapshot/css/css/output/{crates_turbopack-tests_tests_snapshot_css_css_input_style.module_fb38f0.css.map => crates_turbopack-tests_tests_snapshot_css_css_input_style_module_fb38f0.css.map} (100%) rename crates/turbopack-tests/tests/snapshot/env/env/output/{crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js => crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js} (72%) rename crates/turbopack-tests/tests/snapshot/env/env/output/{crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js.map => crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js.map} (100%) delete mode 100644 crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_29a23f.js rename crates/turbopack-tests/tests/snapshot/env/env/output/{crates_turbopack-tests_tests_snapshot_env_env_input_index_936aa9.js => crates_turbopack-tests_tests_snapshot_env_env_input_index_84512e.js} (88%) create mode 100644 crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_8a0be0.js rename crates/turbopack-tests/tests/snapshot/env/env/output/{crates_turbopack-tests_tests_snapshot_env_env_input_index_29a23f.js.map => crates_turbopack-tests_tests_snapshot_env_env_input_index_8a0be0.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/imports/dynamic/output/{crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_1e2f57._.js => crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_36739f._.js} (78%) rename crates/turbopack-tests/tests/snapshot/imports/dynamic/output/{crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_4e74d3._.js => crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js} (83%) rename crates/turbopack-tests/tests/snapshot/imports/dynamic/output/{crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_4e74d3._.js.map => crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/imports/dynamic/output/{crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js => crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js} (77%) rename crates/turbopack-tests/tests/snapshot/imports/dynamic/output/{crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js.map => crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js.map} (100%) create mode 100644 crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_d4d527._.js rename crates/turbopack-tests/tests/snapshot/imports/json/issues/{Code generation for chunk item errored-5f72a6.txt => Code generation for chunk item errored-b5c990.txt} (59%) rename crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/{a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_10fe7a._.js => a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js} (79%) rename crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/{a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_10fe7a._.js.map => a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/{a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js => a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js} (80%) rename crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/{a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js.map => a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/{a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_b21398._.js => a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_84c275._.js} (81%) create mode 100644 crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_ab3761._.js create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/options.json create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js rename crates/turbopack-tests/tests/snapshot/{typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_0aa04e._.js.map => runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js.map} (100%) create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js.map create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/options.json create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_7fa8ff.js create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js.map create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js create mode 100644 crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js.map delete mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_0aa04e._.js rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/{a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_9122ac._.js => a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_8fad73._.js} (82%) create mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_99f69d._.js rename crates/turbopack-tests/tests/snapshot/typescript/{tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_a751eb._.js.map => tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_99f69d._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/{a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js => a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js} (91%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/{a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js.map => a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/typescript/{tsconfig-extends-module/output/63a02_tsconfig-mod_prop.ts_ae3f0e._.js => tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js} (67%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/{63a02_tsconfig-mod_prop.ts_2aa573._.js.map => 63a02_tsconfig-mod_prop_ts_2aa573._.js.map} (100%) delete mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_a751eb._.js create mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_1f521f._.js rename crates/turbopack-tests/tests/snapshot/typescript/{tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_a662d4._.js.map => tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_1f521f._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/{8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_bfc829._.js => 8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_62d7aa._.js} (69%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/{8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js => 8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js} (92%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/{8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js.map => 8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/typescript/{tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop.ts_2aa573._.js => tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js} (67%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/{63a02_tsconfig-mod_prop.ts_ae3f0e._.js.map => 63a02_tsconfig-mod_prop_ts_ae3f0e._.js.map} (100%) delete mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_a662d4._.js rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/{a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_31d3a0._.js => a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_93ee43._.js} (71%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/{a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js => a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js} (93%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/{a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js.map => a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js.map} (100%) create mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_ca2f6f._.js rename crates/turbopack-tests/tests/snapshot/typescript/{tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_be3d7b._.js.map => tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_ca2f6f._.js.map} (100%) delete mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_be3d7b._.js create mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_5381a8._.js rename crates/turbopack-tests/tests/snapshot/typescript/{tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_38aae8._.js.map => tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_5381a8._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/{a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_ced665._.js => a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_64225d._.js} (76%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/{a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js => a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js} (93%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/{a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js.map => a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js.map} (100%) delete mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_38aae8._.js create mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_385208._.js rename crates/turbopack-tests/tests/snapshot/typescript/{tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_18c083._.js.map => tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_385208._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/{a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_53300f._.js => a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_4121b1._.js} (76%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/{a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js => a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js} (93%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/{a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js.map => a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js.map} (100%) delete mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_18c083._.js create mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_3e6d5a._.js create mode 100644 crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_3e6d5a._.js.map rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/{a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js => a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js} (91%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/{a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js.map => a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js.map} (100%) rename crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/{a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_997596._.js => a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_db43e7._.js} (82%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 107e9bf4e928d..29d67348886d5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -107,6 +107,13 @@ jobs: crates/turbopack-bench/** !*.md + - name: Turbopack TypeScript related changes + id: turbopack_typescript + uses: technote-space/get-diff-action@v6 + with: + PATTERNS: | + crates/turbpack*/js/** + - name: Turborepo Rust related changes id: turborepo_rust uses: technote-space/get-diff-action@v6 @@ -172,6 +179,7 @@ jobs: # We only test workspace dependency changes on main, not on PRs to speed up CI cargo_on_main: ${{ steps.ci.outputs.diff != '' || (steps.cargo.outputs.diff != '' && github.event_name == 'push' && github.ref == 'refs/heads/main') }} turbopack: ${{ steps.ci.outputs.diff != '' || steps.turbopack.outputs.diff != '' }} + turbopack_typescript: ${{ steps.ci.outputs.diff != '' || steps.turbopack_typescript.outputs.diff != '' }} turborepo_rust: ${{ steps.ci.outputs.diff != '' || steps.turborepo_rust.outputs.diff != '' }} turbopack_bench: ${{ steps.ci.outputs.diff != '' || steps.turbopack_bench.outputs.diff != '' }} go: ${{ steps.ci.outputs.diff != '' || steps.turborepo_go.outputs.diff != '' }} @@ -446,6 +454,36 @@ jobs: run: | turbo run check-types test --filter=...[${{ github.event.pull_request.base.sha || 'HEAD^1' }}] --filter="./packages/*" --color + turbopack_typescript: + name: Turbopack TypeScript files + runs-on: ubuntu-latest + needs: determine_jobs + if: needs.determine_jobs.outputs.turbopack_typescript == 'true' + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: pnpm + + - name: Install dependencies + run: pnpm install -r --side-effects-cache false + + - name: Check turbopack-node types + working-directory: crates/turbopack-node/js + run: pnpm run check + + - name: Check turbopack-cli types + working-directory: crates/turbopack-cli/js + run: pnpm run check + + - name: Check turbopack-ecmascript-runtime types + working-directory: crates/turbopack-ecmascript-runtime/js + run: pnpm run check + rust_prepare: name: Check rust crates runs-on: ubuntu-latest-16-core-oss diff --git a/Cargo.lock b/Cargo.lock index e990f5e12b5eb..8cd58ec6ed284 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8815,6 +8815,7 @@ dependencies = [ "turbo-updater", "turbopack", "turbopack-bench", + "turbopack-build", "turbopack-cli-utils", "turbopack-core", "turbopack-create-test-app", @@ -8823,6 +8824,7 @@ dependencies = [ "turbopack-dev-server", "turbopack-ecmascript", "turbopack-ecmascript-plugins", + "turbopack-ecmascript-runtime", "turbopack-env", "turbopack-image", "turbopack-json", @@ -8834,6 +8836,25 @@ dependencies = [ "turbopack-tests", ] +[[package]] +name = "turbopack-build" +version = "0.1.0" +dependencies = [ + "anyhow", + "indexmap", + "indoc", + "serde", + "serde_json", + "serde_qs", + "turbo-tasks", + "turbo-tasks-build", + "turbo-tasks-fs", + "turbopack-core", + "turbopack-css", + "turbopack-ecmascript", + "turbopack-ecmascript-runtime", +] + [[package]] name = "turbopack-cli" version = "0.1.0" @@ -8868,6 +8889,7 @@ dependencies = [ "turbopack-dev", "turbopack-dev-server", "turbopack-ecmascript-plugins", + "turbopack-ecmascript-runtime", "turbopack-env", "turbopack-node", "webbrowser", @@ -8984,6 +9006,7 @@ dependencies = [ "serde", "serde_json", "serde_qs", + "swc_core", "tracing", "turbo-tasks", "turbo-tasks-build", @@ -8993,6 +9016,7 @@ dependencies = [ "turbopack-core", "turbopack-css", "turbopack-ecmascript", + "turbopack-ecmascript-runtime", ] [[package]] @@ -9085,6 +9109,22 @@ dependencies = [ "turbopack-ecmascript", ] +[[package]] +name = "turbopack-ecmascript-runtime" +version = "0.1.0" +dependencies = [ + "anyhow", + "indoc", + "serde", + "swc_core", + "turbo-tasks", + "turbo-tasks-build", + "turbo-tasks-fs", + "turbopack", + "turbopack-core", + "turbopack-ecmascript", +] + [[package]] name = "turbopack-env" version = "0.1.0" @@ -9237,9 +9277,11 @@ dependencies = [ "turbo-tasks-fs", "turbo-tasks-memory", "turbopack", + "turbopack-build", "turbopack-core", "turbopack-dev", "turbopack-ecmascript-plugins", + "turbopack-ecmascript-runtime", "turbopack-env", "turbopack-test-utils", ] diff --git a/Cargo.toml b/Cargo.toml index 8cac343d20cc2..fb4d8b3438cb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,6 +92,7 @@ turbo-tasks-testing = { path = "crates/turbo-tasks-testing" } turbo-updater = { path = "crates/turborepo-updater" } turbopack = { path = "crates/turbopack" } turbopack-bench = { path = "crates/turbopack-bench" } +turbopack-build = { path = "crates/turbopack-build" } turbopack-cli = { path = "crates/turbopack-cli" } turbopack-cli-utils = { path = "crates/turbopack-cli-utils" } turbopack-core = { path = "crates/turbopack-core" } @@ -101,6 +102,7 @@ turbopack-dev = { path = "crates/turbopack-dev" } turbopack-dev-server = { path = "crates/turbopack-dev-server" } turbopack-ecmascript = { path = "crates/turbopack-ecmascript" } turbopack-ecmascript-plugins = { path = "crates/turbopack-ecmascript-plugins" } +turbopack-ecmascript-runtime = { path = "crates/turbopack-ecmascript-runtime" } turbopack-env = { path = "crates/turbopack-env" } turbopack-image = { path = "crates/turbopack-image" } turbopack-json = { path = "crates/turbopack-json" } diff --git a/crates/turbopack-binding/Cargo.toml b/crates/turbopack-binding/Cargo.toml index ad6a6d0446324..4d234365875a7 100644 --- a/crates/turbopack-binding/Cargo.toml +++ b/crates/turbopack-binding/Cargo.toml @@ -97,6 +97,10 @@ __turbo_updater = ["__turbo", "turbo-updater"] __turbopack = ["turbopack"] __turbopack_bench = ["__turbopack", "turbopack-bench"] +__turbopack_build = ["__turbopack", "turbopack-build"] +__turbopack_build_dynamic_embed_contents = [ + "turbopack-build/dynamic_embed_contents", +] __turbopack_cli_utils = ["__turbopack", "turbopack-cli-utils"] __turbopack_core = ["__turbopack", "turbopack-core"] __turbopack_core_issue_path = ["turbopack-core/issue_path"] @@ -114,6 +118,8 @@ __turbopack_ecmascript_plugin = [ "turbopack-ecmascript-plugins", "turbopack-ecmascript-plugins/transform_emotion", ] +__turbopack_ecmascript_runtime = ["__turbopack", "turbopack-ecmascript-runtime"] + __turbopack_env = ["__turbopack", "turbopack-env"] __turbopack_image = ["__turbopack", "turbopack-image"] __turbopack_image_avif = ["turbopack-image/avif"] @@ -186,6 +192,7 @@ turbo-tasks-testing = { optional = true, workspace = true } turbo-updater = { optional = true, workspace = true } turbopack = { optional = true, workspace = true } turbopack-bench = { optional = true, workspace = true } +turbopack-build = { optional = true, workspace = true } turbopack-cli-utils = { optional = true, workspace = true } turbopack-core = { optional = true, workspace = true } turbopack-create-test-app = { optional = true, workspace = true } @@ -194,6 +201,7 @@ turbopack-dev = { optional = true, workspace = true } turbopack-dev-server = { optional = true, workspace = true } turbopack-ecmascript = { optional = true, workspace = true } turbopack-ecmascript-plugins = { optional = true, workspace = true } +turbopack-ecmascript-runtime = { optional = true, workspace = true } turbopack-env = { optional = true, workspace = true } turbopack-image = { optional = true, workspace = true } turbopack-json = { optional = true, workspace = true } diff --git a/crates/turbopack-binding/src/lib.rs b/crates/turbopack-binding/src/lib.rs index 92156d1b9d7ba..af2ed45149c5e 100644 --- a/crates/turbopack-binding/src/lib.rs +++ b/crates/turbopack-binding/src/lib.rs @@ -56,6 +56,8 @@ pub mod turbopack { pub use turbopack; #[cfg(feature = "__turbopack_bench")] pub use turbopack_bench as bench; + #[cfg(feature = "__turbopack_build")] + pub use turbopack_build as build; #[cfg(feature = "__turbopack_cli_utils")] pub use turbopack_cli_utils as cli_utils; #[cfg(feature = "__turbopack_core")] @@ -72,6 +74,8 @@ pub mod turbopack { pub use turbopack_ecmascript as ecmascript; #[cfg(feature = "__turbopack_ecmascript_plugin")] pub use turbopack_ecmascript_plugins as ecmascript_plugin; + #[cfg(feature = "__turbopack_ecmascript_runtime")] + pub use turbopack_ecmascript_runtime as ecmascript_runtime; #[cfg(feature = "__turbopack_env")] pub use turbopack_env as env; #[cfg(feature = "__turbopack_image")] diff --git a/crates/turbopack-build/Cargo.toml b/crates/turbopack-build/Cargo.toml new file mode 100644 index 0000000000000..21b971f575ef2 --- /dev/null +++ b/crates/turbopack-build/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "turbopack-build" +version = "0.1.0" +description = "TBD" +license = "MPL-2.0" +edition = "2021" +autobenches = false + +[lib] +bench = false + +[features] +# enable "HMR" for embedded assets +dynamic_embed_contents = ["turbo-tasks-fs/dynamic_embed_contents"] +# enable test utilities such as `RuntimeType::Dummy` +test = ["turbopack-ecmascript-runtime/test"] + +[dependencies] +anyhow = { workspace = true } +indexmap = { workspace = true } +indoc = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +serde_qs = { workspace = true } + +turbo-tasks = { workspace = true } +turbo-tasks-fs = { workspace = true } +turbopack-core = { workspace = true } +turbopack-css = { workspace = true } +turbopack-ecmascript = { workspace = true } +turbopack-ecmascript-runtime = { workspace = true } + +[build-dependencies] +turbo-tasks-build = { workspace = true } diff --git a/crates/turbopack-build/build.rs b/crates/turbopack-build/build.rs new file mode 100644 index 0000000000000..1673efed59cce --- /dev/null +++ b/crates/turbopack-build/build.rs @@ -0,0 +1,5 @@ +use turbo_tasks_build::generate_register; + +fn main() { + generate_register(); +} diff --git a/crates/turbopack-build/src/chunking_context.rs b/crates/turbopack-build/src/chunking_context.rs new file mode 100644 index 0000000000000..3e3a92e036fd1 --- /dev/null +++ b/crates/turbopack-build/src/chunking_context.rs @@ -0,0 +1,374 @@ +use anyhow::Result; +use indexmap::IndexSet; +use turbo_tasks::{ + graph::{GraphTraversal, ReverseTopological}, + primitives::{BoolVc, StringVc}, + TryJoinIterExt, Value, +}; +use turbo_tasks_fs::FileSystemPathVc; +use turbopack_core::{ + asset::{Asset, AssetVc, AssetsVc}, + chunk::{ + Chunk, ChunkVc, ChunkableAsset, ChunkingContext, ChunkingContextVc, ChunksVc, + EvaluatableAssetsVc, + }, + environment::EnvironmentVc, + ident::AssetIdentVc, +}; +use turbopack_css::chunk::CssChunkVc; +use turbopack_ecmascript::{ + chunk::{EcmascriptChunkVc, EcmascriptChunkingContext, EcmascriptChunkingContextVc}, + EcmascriptModuleAssetVc, +}; +use turbopack_ecmascript_runtime::RuntimeType; + +use crate::ecmascript::node::{ + chunk::EcmascriptBuildNodeChunkVc, evaluate::chunk::EcmascriptBuildNodeEvaluateChunkVc, +}; + +/// A builder for [`BuildChunkingContextVc`]. +pub struct BuildChunkingContextBuilder { + context: BuildChunkingContext, +} + +impl BuildChunkingContextBuilder { + pub fn runtime_type(mut self, runtime_type: RuntimeType) -> Self { + self.context.runtime_type = runtime_type; + self + } + + /// Builds the chunking context. + pub fn build(self) -> BuildChunkingContextVc { + BuildChunkingContextVc::new(Value::new(self.context)) + } +} + +/// A chunking context for build mode. +#[turbo_tasks::value(serialization = "auto_for_input")] +#[derive(Debug, Clone, Hash, PartialOrd, Ord)] +pub struct BuildChunkingContext { + /// This path get stripped off of chunk paths before generating output asset + /// paths. + context_path: FileSystemPathVc, + /// This path is used to compute the url to request chunks or assets from + output_root: FileSystemPathVc, + /// Chunks are placed at this path + chunk_root_path: FileSystemPathVc, + /// Static assets are placed at this path + asset_root_path: FileSystemPathVc, + /// Layer name within this context + layer: Option, + /// The environment chunks will be evaluated in. + environment: EnvironmentVc, + /// The kind of runtime to include in the output. + runtime_type: RuntimeType, +} + +impl BuildChunkingContextVc { + /// Creates a new chunking context builder. + pub fn builder( + context_path: FileSystemPathVc, + output_root: FileSystemPathVc, + chunk_root_path: FileSystemPathVc, + asset_root_path: FileSystemPathVc, + environment: EnvironmentVc, + ) -> BuildChunkingContextBuilder { + BuildChunkingContextBuilder { + context: BuildChunkingContext { + context_path, + output_root, + chunk_root_path, + asset_root_path, + layer: None, + environment, + runtime_type: Default::default(), + }, + } + } +} + +impl BuildChunkingContext { + /// Returns the kind of runtime to include in output chunks. + /// + /// This is defined directly on `BuildChunkingContext` so it is zero-cost + /// when `RuntimeType` has a single variant. + pub fn runtime_type(&self) -> RuntimeType { + self.runtime_type + } +} + +#[turbo_tasks::value_impl] +impl BuildChunkingContextVc { + #[turbo_tasks::function] + fn new(this: Value) -> Self { + this.into_value().cell() + } + + #[turbo_tasks::function] + fn generate_evaluate_chunk( + self_vc: BuildChunkingContextVc, + entry_chunk: ChunkVc, + other_chunks: AssetsVc, + evaluatable_assets: EvaluatableAssetsVc, + exported_module: Option, + ) -> AssetVc { + EcmascriptBuildNodeEvaluateChunkVc::new( + self_vc, + entry_chunk, + other_chunks, + evaluatable_assets, + exported_module, + ) + .into() + } + + /// Generates an output chunk that: + /// * evaluates the given assets; and + /// * exports the result of evaluating the given module as a CommonJS + /// default export. + #[turbo_tasks::function] + pub async fn generate_exported_chunk( + self_vc: BuildChunkingContextVc, + module: EcmascriptModuleAssetVc, + evaluatable_assets: EvaluatableAssetsVc, + ) -> Result { + let entry_chunk = module.as_root_chunk(self_vc.into()); + + let assets = self_vc + .get_evaluate_chunk_assets(entry_chunk, evaluatable_assets) + .await?; + + let asset = self_vc.generate_evaluate_chunk( + entry_chunk, + AssetsVc::cell(assets.clone()), + evaluatable_assets, + Some(module), + ); + + Ok(asset) + } +} + +impl BuildChunkingContextVc { + async fn get_evaluate_chunk_assets( + self, + entry_chunk: ChunkVc, + evaluatable_assets: EvaluatableAssetsVc, + ) -> Result> { + let evaluatable_assets_ref = evaluatable_assets.await?; + + let mut chunks: IndexSet<_> = evaluatable_assets_ref + .iter() + .map({ + move |evaluatable_asset| async move { + Ok(evaluatable_asset + .as_root_chunk(self.into()) + .resolve() + .await?) + } + }) + .try_join() + .await? + .into_iter() + .collect(); + + chunks.insert(entry_chunk.resolve().await?); + + let chunks = get_parallel_chunks(chunks); + + let chunks = get_optimized_chunks(chunks.await?).await?; + + Ok(chunks + .await? + .iter() + .map(|chunk| self.generate_chunk(*chunk)) + .collect()) + } +} + +#[turbo_tasks::value_impl] +impl ChunkingContext for BuildChunkingContext { + #[turbo_tasks::function] + fn context_path(&self) -> FileSystemPathVc { + self.context_path + } + + #[turbo_tasks::function] + fn output_root(&self) -> FileSystemPathVc { + self.output_root + } + + #[turbo_tasks::function] + fn environment(&self) -> EnvironmentVc { + self.environment + } + + #[turbo_tasks::function] + async fn chunk_path(&self, ident: AssetIdentVc, extension: &str) -> Result { + let root_path = self.chunk_root_path; + let root_path = if let Some(layer) = self.layer.as_deref() { + root_path.join(layer) + } else { + root_path + }; + let name = ident.output_name(self.context_path, extension).await?; + Ok(root_path.join(&name)) + } + + #[turbo_tasks::function] + fn reference_chunk_source_maps(&self, _chunk: AssetVc) -> BoolVc { + BoolVc::cell(true) + } + + #[turbo_tasks::function] + async fn can_be_in_same_chunk(&self, asset_a: AssetVc, asset_b: AssetVc) -> Result { + let parent_dir = asset_a.ident().path().parent().await?; + + let path = asset_b.ident().path().await?; + if let Some(rel_path) = parent_dir.get_path_to(&path) { + if !rel_path.starts_with("node_modules/") && !rel_path.contains("/node_modules/") { + return Ok(BoolVc::cell(true)); + } + } + + Ok(BoolVc::cell(false)) + } + + #[turbo_tasks::function] + async fn asset_path( + &self, + content_hash: &str, + original_asset_ident: AssetIdentVc, + ) -> Result { + let source_path = original_asset_ident.path().await?; + let basename = source_path.file_name(); + let asset_path = match source_path.extension() { + Some(ext) => format!( + "{basename}.{content_hash}.{ext}", + basename = &basename[..basename.len() - ext.len() - 1], + content_hash = &content_hash[..8] + ), + None => format!( + "{basename}.{content_hash}", + content_hash = &content_hash[..8] + ), + }; + Ok(self.asset_root_path.join(&asset_path)) + } + + #[turbo_tasks::function] + fn layer(&self) -> StringVc { + StringVc::cell(self.layer.clone().unwrap_or_default()) + } + + #[turbo_tasks::function] + async fn with_layer(self_vc: BuildChunkingContextVc, layer: &str) -> Result { + let mut context = self_vc.await?.clone_value(); + context.layer = (!layer.is_empty()).then(|| layer.to_string()); + Ok(BuildChunkingContextVc::new(Value::new(context)).into()) + } + + #[turbo_tasks::function] + async fn chunk_group( + self_vc: BuildChunkingContextVc, + entry_chunk: ChunkVc, + ) -> Result { + let parallel_chunks = get_parallel_chunks([entry_chunk]).await?; + + let optimized_chunks = get_optimized_chunks(parallel_chunks).await?; + + let assets: Vec = optimized_chunks + .await? + .iter() + .map(|chunk| self_vc.generate_chunk(*chunk)) + .collect(); + + Ok(AssetsVc::cell(assets)) + } + + #[turbo_tasks::function] + async fn evaluated_chunk_group( + self_vc: BuildChunkingContextVc, + entry_chunk: ChunkVc, + evaluatable_assets: EvaluatableAssetsVc, + ) -> Result { + let mut assets = self_vc + .get_evaluate_chunk_assets(entry_chunk, evaluatable_assets) + .await?; + + assets.push(self_vc.generate_evaluate_chunk( + entry_chunk, + AssetsVc::cell(assets.clone()), + evaluatable_assets, + None, + )); + + Ok(AssetsVc::cell(assets)) + } + + #[turbo_tasks::function] + async fn generate_chunk(self_vc: BuildChunkingContextVc, chunk: ChunkVc) -> Result { + Ok( + if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(chunk).await? { + EcmascriptBuildNodeChunkVc::new(self_vc, ecmascript_chunk).into() + } else { + chunk.into() + }, + ) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkingContext for BuildChunkingContext {} + +async fn get_parallel_chunks(entries: I) -> Result> +where + I: IntoIterator, +{ + Ok(ReverseTopological::new() + .skip_duplicates() + .visit(entries, |chunk: ChunkVc| async move { + Ok(chunk + .parallel_chunks() + .await? + .iter() + .copied() + .collect::>() + .into_iter()) + }) + .await + .completed()? + .into_inner() + .into_iter()) +} + +async fn get_optimized_chunks(chunks: I) -> Result +where + I: IntoIterator, +{ + let mut ecmascript_chunks = vec![]; + let mut css_chunks = vec![]; + let mut other_chunks = vec![]; + + for chunk in chunks.into_iter() { + if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(&chunk).await? { + ecmascript_chunks.push(ecmascript_chunk); + } else if let Some(css_chunk) = CssChunkVc::resolve_from(&chunk).await? { + css_chunks.push(css_chunk); + } else { + other_chunks.push(chunk); + } + } + + // TODO(WEB-403) Optimize pass here. + + let chunks = ecmascript_chunks + .iter() + .copied() + .map(|chunk| chunk.as_chunk()) + .chain(css_chunks.iter().copied().map(|chunk| chunk.as_chunk())) + .chain(other_chunks.into_iter()) + .collect(); + + Ok(ChunksVc::cell(chunks)) +} diff --git a/crates/turbopack-build/src/ecmascript/mod.rs b/crates/turbopack-build/src/ecmascript/mod.rs new file mode 100644 index 0000000000000..6b3c8edd4cf78 --- /dev/null +++ b/crates/turbopack-build/src/ecmascript/mod.rs @@ -0,0 +1 @@ +pub(crate) mod node; diff --git a/crates/turbopack-build/src/ecmascript/node/chunk.rs b/crates/turbopack-build/src/ecmascript/node/chunk.rs new file mode 100644 index 0000000000000..e677cdb465e48 --- /dev/null +++ b/crates/turbopack-build/src/ecmascript/node/chunk.rs @@ -0,0 +1,143 @@ +use anyhow::Result; +use indexmap::IndexSet; +use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbopack_core::{ + asset::{Asset, AssetContentVc, AssetVc}, + chunk::ChunkingContext, + ident::AssetIdentVc, + introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}, + reference::AssetReferencesVc, + source_map::{ + GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc, SourceMapAssetReferenceVc, + }, +}; +use turbopack_ecmascript::chunk::EcmascriptChunkVc; + +use super::content::EcmascriptBuildNodeChunkContentVc; +use crate::BuildChunkingContextVc; + +/// Production Ecmascript chunk targeting Node.js. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptBuildNodeChunk { + chunking_context: BuildChunkingContextVc, + chunk: EcmascriptChunkVc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeChunkVc { + /// Creates a new [`EcmascriptBuildNodeChunkVc`]. + #[turbo_tasks::function] + pub fn new(chunking_context: BuildChunkingContextVc, chunk: EcmascriptChunkVc) -> Self { + EcmascriptBuildNodeChunk { + chunking_context, + chunk, + } + .cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + async fn to_string(&self) -> Result { + Ok(StringVc::cell("Ecmascript Build Node Chunk".to_string())) + } +} + +#[turbo_tasks::function] +fn modifier() -> StringVc { + StringVc::cell("ecmascript build node chunk".to_string()) +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeChunkVc { + #[turbo_tasks::function] + async fn own_content(self) -> Result { + let this = self.await?; + Ok(EcmascriptBuildNodeChunkContentVc::new( + this.chunking_context, + self, + this.chunk.chunk_content(), + )) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + fn ident(&self) -> AssetIdentVc { + let ident = self.chunk.ident().with_modifier(modifier()); + AssetIdentVc::from_path(self.chunking_context.chunk_path(ident, ".js")) + } + + #[turbo_tasks::function] + async fn references(self_vc: EcmascriptBuildNodeChunkVc) -> Result { + let this = self_vc.await?; + let chunk_references = this.chunk.references().await?; + let mut references = Vec::with_capacity(chunk_references.len() + 1); + + for reference in &*chunk_references { + references.push(*reference); + } + + if *this + .chunking_context + .reference_chunk_source_maps(self_vc.into()) + .await? + { + references.push(SourceMapAssetReferenceVc::new(self_vc.into()).into()); + } + + Ok(AssetReferencesVc::cell(references)) + } + + #[turbo_tasks::function] + fn content(self_vc: EcmascriptBuildNodeChunkVc) -> AssetContentVc { + self_vc.own_content().content() + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + fn generate_source_map(self_vc: EcmascriptBuildNodeChunkVc) -> OptionSourceMapVc { + self_vc.own_content().generate_source_map() + } +} + +#[turbo_tasks::function] +fn introspectable_type() -> StringVc { + StringVc::cell("ecmascript build node chunk".to_string()) +} + +#[turbo_tasks::function] +fn introspectable_details() -> StringVc { + StringVc::cell("generates a production EcmaScript chunk targeting Node.js".to_string()) +} + +#[turbo_tasks::value_impl] +impl Introspectable for EcmascriptBuildNodeChunk { + #[turbo_tasks::function] + fn ty(&self) -> StringVc { + introspectable_type() + } + + #[turbo_tasks::function] + fn title(self_vc: EcmascriptBuildNodeChunkVc) -> StringVc { + self_vc.ident().to_string() + } + + #[turbo_tasks::function] + fn details(&self) -> StringVc { + introspectable_details() + } + + #[turbo_tasks::function] + async fn children(&self) -> Result { + let mut children = IndexSet::new(); + if let Some(chunk) = IntrospectableVc::resolve_from(self.chunk).await? { + children.insert((StringVc::cell("chunk".to_string()), chunk)); + } + Ok(IntrospectableChildrenVc::cell(children)) + } +} diff --git a/crates/turbopack-build/src/ecmascript/node/content.rs b/crates/turbopack-build/src/ecmascript/node/content.rs new file mode 100644 index 0000000000000..4ecc05901879c --- /dev/null +++ b/crates/turbopack-build/src/ecmascript/node/content.rs @@ -0,0 +1,101 @@ +use std::io::Write; + +use anyhow::Result; +use indoc::writedoc; +use turbo_tasks::{TryJoinIterExt, Value}; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::{Asset, AssetContentVc}, + code_builder::{CodeBuilder, CodeVc}, + source_map::{GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc}, +}; +use turbopack_ecmascript::{chunk::EcmascriptChunkContentVc, utils::StringifyJs}; + +use super::chunk::EcmascriptBuildNodeChunkVc; +use crate::BuildChunkingContextVc; + +#[turbo_tasks::value(serialization = "none")] +pub(super) struct EcmascriptBuildNodeChunkContent { + pub(super) content: EcmascriptChunkContentVc, + pub(super) chunking_context: BuildChunkingContextVc, + pub(super) chunk: EcmascriptBuildNodeChunkVc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeChunkContentVc { + #[turbo_tasks::function] + pub(crate) async fn new( + chunking_context: BuildChunkingContextVc, + chunk: EcmascriptBuildNodeChunkVc, + content: EcmascriptChunkContentVc, + ) -> Result { + Ok(EcmascriptBuildNodeChunkContent { + content, + chunking_context, + chunk, + } + .cell()) + } +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeChunkContentVc { + #[turbo_tasks::function] + async fn code(self) -> Result { + let this = self.await?; + let chunk_path = this.chunk.ident().path().await?; + + let mut code = CodeBuilder::default(); + + writedoc!( + code, + r#" + module.exports = {{ + + "#, + )?; + + let content = this.content.await?; + let availability_info = Value::new(content.availability_info); + for (id, item_code) in content + .chunk_items + .iter() + .map(|chunk_item| async move { + Ok(( + chunk_item.id().await?, + chunk_item.code(availability_info).await?, + )) + }) + .try_join() + .await? + { + write!(code, "{}: ", StringifyJs(&id))?; + code.push_code(&*item_code); + write!(code, ",\n")?; + } + + write!(code, "\n}};")?; + + if code.has_source_map() { + let filename = chunk_path.file_name(); + write!(code, "\n\n//# sourceMappingURL={}.map", filename)?; + } + + let code = code.build(); + Ok(code.cell()) + } + + #[turbo_tasks::function] + pub async fn content(self_vc: EcmascriptBuildNodeChunkContentVc) -> Result { + let code = self_vc.code().await?; + Ok(File::from(code.source_code().clone()).into()) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptBuildNodeChunkContent { + #[turbo_tasks::function] + fn generate_source_map(self_vc: EcmascriptBuildNodeChunkContentVc) -> OptionSourceMapVc { + self_vc.code().generate_source_map() + } +} diff --git a/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs b/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs new file mode 100644 index 0000000000000..5c87c2d8f3a27 --- /dev/null +++ b/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs @@ -0,0 +1,245 @@ +use std::io::Write; + +use anyhow::{bail, Result}; +use indoc::writedoc; +use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks_fs::File; +use turbopack_core::{ + asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, + chunk::{ChunkVc, ChunkingContext, EvaluatableAssetsVc}, + code_builder::{CodeBuilder, CodeVc}, + ident::AssetIdentVc, + reference::{AssetReferencesVc, SingleAssetReferenceVc}, + source_map::{ + GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc, SourceMapAssetReferenceVc, + }, +}; +use turbopack_ecmascript::{ + chunk::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc}, + utils::StringifyJs, + EcmascriptModuleAssetVc, +}; + +use super::runtime::EcmascriptBuildNodeRuntimeReferenceVc; +use crate::BuildChunkingContextVc; + +/// An Ecmascript chunk that loads a list of parallel chunks, then instantiates +/// runtime entries. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptBuildNodeEvaluateChunk { + chunking_context: BuildChunkingContextVc, + entry_chunk: ChunkVc, + other_chunks: AssetsVc, + evaluatable_assets: EvaluatableAssetsVc, + exported_module: Option, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeEvaluateChunkVc { + /// Creates a new [`EcmascriptBuildNodeEvaluateChunkVc`]. + #[turbo_tasks::function] + pub fn new( + chunking_context: BuildChunkingContextVc, + entry_chunk: ChunkVc, + other_chunks: AssetsVc, + evaluatable_assets: EvaluatableAssetsVc, + exported_module: Option, + ) -> Self { + EcmascriptBuildNodeEvaluateChunk { + chunking_context, + entry_chunk, + other_chunks, + evaluatable_assets, + exported_module, + } + .cell() + } + + #[turbo_tasks::function] + async fn code(self) -> Result { + let this = self.await?; + + let output_root = this.chunking_context.output_root().await?; + let chunk_path = self.ident().path().await?; + let chunk_directory = self.ident().path().parent().await?; + let runtime_path = self + .runtime_reference() + .runtime_chunk() + .ident() + .path() + .await?; + let runtime_relative_path = + if let Some(path) = chunk_directory.get_relative_path_to(&runtime_path) { + path + } else { + bail!( + "cannot find a relative path from the chunk ({}) to the runtime chunk ({})", + chunk_path.to_string(), + runtime_path.to_string(), + ); + }; + let chunk_public_path = if let Some(path) = output_root.get_path_to(&chunk_path) { + path + } else { + bail!( + "chunk path ({}) is not in output root ({})", + chunk_path.to_string(), + output_root.to_string() + ); + }; + + let mut code = CodeBuilder::default(); + + writedoc!( + code, + r#" + const CHUNK_PUBLIC_PATH = {}; + const runtime = require({}); + "#, + StringifyJs(&*chunk_public_path), + StringifyJs(&*runtime_relative_path) + )?; + + let other_chunks = this.other_chunks.await?; + for other_chunk in &*other_chunks { + let other_chunk_path = &*other_chunk.ident().path().await?; + if let Some(other_chunk_public_path) = output_root.get_path_to(other_chunk_path) { + writedoc!( + code, + r#" + runtime.loadChunk({}); + "#, + StringifyJs(&other_chunk_public_path) + )?; + } + } + + let evaluatable_assets = this.evaluatable_assets.await?; + for evaluatable_asset in &*evaluatable_assets { + if let Some(placeable) = + EcmascriptChunkPlaceableVc::resolve_from(evaluatable_asset).await? + { + let runtime_module_id = placeable + .as_chunk_item(this.chunking_context.into()) + .id() + .await?; + + writedoc!( + code, + r#" + runtime.getOrInstantiateRuntimeModule({}, CHUNK_PUBLIC_PATH); + "#, + StringifyJs(&*runtime_module_id), + )?; + } + } + + if let Some(exported_module) = this.exported_module { + let runtime_module_id = exported_module + .as_chunk_item(this.chunking_context.into()) + .id() + .await?; + + writedoc!( + code, + r#" + module.exports = runtime.getOrInstantiateRuntimeModule({}, CHUNK_PUBLIC_PATH).exports; + "#, + StringifyJs(&*runtime_module_id), + )?; + } + + Ok(CodeVc::cell(code.build())) + } + + #[turbo_tasks::function] + async fn runtime_reference(self) -> Result { + let this = self.await?; + Ok(EcmascriptBuildNodeRuntimeReferenceVc::new( + this.chunking_context, + )) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptBuildNodeEvaluateChunk { + #[turbo_tasks::function] + async fn to_string(&self) -> Result { + Ok(StringVc::cell( + "Ecmascript Build Node Evaluate Chunk".to_string(), + )) + } +} + +#[turbo_tasks::function] +fn modifier() -> StringVc { + StringVc::cell("ecmascript build node evaluate chunk".to_string()) +} + +#[turbo_tasks::function] +fn chunk_reference_description() -> StringVc { + StringVc::cell("chunk".to_string()) +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptBuildNodeEvaluateChunk { + #[turbo_tasks::function] + async fn ident(&self) -> Result { + let mut ident = self.entry_chunk.ident().await?.clone_value(); + + ident.add_modifier(modifier()); + + ident.modifiers.extend( + self.evaluatable_assets + .await? + .iter() + .map(|entry| entry.ident().to_string()), + ); + + for chunk in &*self.other_chunks.await? { + ident.add_modifier(chunk.ident().to_string()); + } + + let ident = AssetIdentVc::new(Value::new(ident)); + Ok(AssetIdentVc::from_path( + self.chunking_context.chunk_path(ident, ".js"), + )) + } + + #[turbo_tasks::function] + async fn references(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> Result { + let this = self_vc.await?; + let mut references = vec![self_vc.runtime_reference().into()]; + + if *this + .chunking_context + .reference_chunk_source_maps(self_vc.into()) + .await? + { + references.push(SourceMapAssetReferenceVc::new(self_vc.into()).into()) + } + + let other_chunks = this.other_chunks.await?; + for other_chunk in &*other_chunks { + references.push( + SingleAssetReferenceVc::new(*other_chunk, chunk_reference_description()).into(), + ); + } + + Ok(AssetReferencesVc::cell(references)) + } + + #[turbo_tasks::function] + async fn content(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> Result { + let code = self_vc.code().await?; + Ok(File::from(code.source_code().clone()).into()) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptBuildNodeEvaluateChunk { + #[turbo_tasks::function] + fn generate_source_map(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> OptionSourceMapVc { + self_vc.code().generate_source_map() + } +} diff --git a/crates/turbopack-build/src/ecmascript/node/evaluate/mod.rs b/crates/turbopack-build/src/ecmascript/node/evaluate/mod.rs new file mode 100644 index 0000000000000..cd4d9271d1b59 --- /dev/null +++ b/crates/turbopack-build/src/ecmascript/node/evaluate/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod chunk; +pub(crate) mod runtime; diff --git a/crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs b/crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs new file mode 100644 index 0000000000000..9c4fcf4e66b85 --- /dev/null +++ b/crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs @@ -0,0 +1,175 @@ +use std::io::Write; + +use anyhow::{bail, Result}; +use indoc::writedoc; +use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks_fs::{File, FileSystem}; +use turbopack_core::{ + asset::{Asset, AssetContentVc, AssetVc}, + chunk::ChunkingContext, + code_builder::{CodeBuilder, CodeVc}, + ident::AssetIdentVc, + reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, + resolve::{ResolveResult, ResolveResultVc}, + source_map::{ + GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc, SourceMapAssetReferenceVc, + }, +}; +use turbopack_ecmascript::utils::StringifyJs; +use turbopack_ecmascript_runtime::RuntimeType; + +use crate::BuildChunkingContextVc; + +/// An Ecmascript chunk that contains the Node.js runtime code. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptBuildNodeRuntimeChunk { + chunking_context: BuildChunkingContextVc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeRuntimeChunkVc { + /// Creates a new [`EcmascriptBuildNodeRuntimeChunkVc`]. + #[turbo_tasks::function] + pub fn new(chunking_context: BuildChunkingContextVc) -> Self { + EcmascriptBuildNodeRuntimeChunk { chunking_context }.cell() + } + + #[turbo_tasks::function] + async fn code(self) -> Result { + let this = self.await?; + + let output_root = this.chunking_context.output_root().await?; + let runtime_path = self.ident().path().await?; + let runtime_public_path = if let Some(path) = output_root.get_path_to(&runtime_path) { + path + } else { + bail!( + "runtime path {} is not in output root {}", + runtime_path.to_string(), + output_root.to_string() + ); + }; + + let mut code = CodeBuilder::default(); + + writedoc!( + code, + r#" + const RUNTIME_PUBLIC_PATH = {}; + "#, + StringifyJs(&*runtime_public_path) + )?; + + match this.chunking_context.await?.runtime_type() { + RuntimeType::Default => { + let runtime_code = turbopack_ecmascript_runtime::get_build_runtime_code( + this.chunking_context.environment(), + ); + code.push_code(&*runtime_code.await?); + } + #[cfg(feature = "test")] + RuntimeType::Dummy => { + let runtime_code = turbopack_ecmascript_runtime::get_dummy_runtime_code(); + code.push_code(&runtime_code); + } + } + + Ok(CodeVc::cell(code.build())) + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptBuildNodeRuntimeChunk { + #[turbo_tasks::function] + async fn to_string(&self) -> Result { + Ok(StringVc::cell( + "Ecmascript Build Node Runtime Chunk".to_string(), + )) + } +} + +#[turbo_tasks::value_impl] +impl Asset for EcmascriptBuildNodeRuntimeChunk { + #[turbo_tasks::function] + fn ident(&self) -> AssetIdentVc { + let ident = AssetIdentVc::from_path( + turbopack_ecmascript_runtime::embed_fs() + .root() + .join("runtime.js"), + ); + + AssetIdentVc::from_path(self.chunking_context.chunk_path(ident, ".js")) + } + + #[turbo_tasks::function] + async fn references(self_vc: EcmascriptBuildNodeRuntimeChunkVc) -> Result { + let this = self_vc.await?; + let mut references = vec![]; + + if *this + .chunking_context + .reference_chunk_source_maps(self_vc.into()) + .await? + { + references.push(SourceMapAssetReferenceVc::new(self_vc.into()).into()) + } + + Ok(AssetReferencesVc::cell(references)) + } + + #[turbo_tasks::function] + async fn content(self_vc: EcmascriptBuildNodeRuntimeChunkVc) -> Result { + let code = self_vc.code().await?; + Ok(File::from(code.source_code().clone()).into()) + } +} + +#[turbo_tasks::value_impl] +impl GenerateSourceMap for EcmascriptBuildNodeRuntimeChunk { + #[turbo_tasks::function] + fn generate_source_map(self_vc: EcmascriptBuildNodeRuntimeChunkVc) -> OptionSourceMapVc { + self_vc.code().generate_source_map() + } +} + +/// A reference to the runtime chunk. +#[turbo_tasks::value] +pub(crate) struct EcmascriptBuildNodeRuntimeReference { + chunking_context: BuildChunkingContextVc, +} + +#[turbo_tasks::value_impl] +impl EcmascriptBuildNodeRuntimeReferenceVc { + #[turbo_tasks::function] + pub fn new(chunking_context: BuildChunkingContextVc) -> Self { + Self::cell(EcmascriptBuildNodeRuntimeReference { chunking_context }) + } + + #[turbo_tasks::function] + pub async fn runtime_chunk( + self_vc: EcmascriptBuildNodeRuntimeReferenceVc, + ) -> Result { + Ok(EcmascriptBuildNodeRuntimeChunkVc::new( + self_vc.await?.chunking_context, + )) + } +} + +#[turbo_tasks::value_impl] +impl AssetReference for EcmascriptBuildNodeRuntimeReference { + #[turbo_tasks::function] + fn resolve_reference(self_vc: EcmascriptBuildNodeRuntimeReferenceVc) -> ResolveResultVc { + ResolveResult::asset(self_vc.runtime_chunk().into()).into() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptBuildNodeRuntimeReference { + #[turbo_tasks::function] + async fn to_string(self_vc: EcmascriptBuildNodeRuntimeReferenceVc) -> Result { + Ok(StringVc::cell(format!( + "runtime chunk {}", + self_vc.runtime_chunk().ident().to_string().await? + ))) + } +} diff --git a/crates/turbopack-build/src/ecmascript/node/mod.rs b/crates/turbopack-build/src/ecmascript/node/mod.rs new file mode 100644 index 0000000000000..5b9b729122ed5 --- /dev/null +++ b/crates/turbopack-build/src/ecmascript/node/mod.rs @@ -0,0 +1,3 @@ +pub(crate) mod chunk; +pub(crate) mod content; +pub(crate) mod evaluate; diff --git a/crates/turbopack-build/src/lib.rs b/crates/turbopack-build/src/lib.rs new file mode 100644 index 0000000000000..9edc258a2881f --- /dev/null +++ b/crates/turbopack-build/src/lib.rs @@ -0,0 +1,18 @@ +#![feature(lint_reasons)] +#![feature(iter_intersperse)] + +pub(crate) mod chunking_context; +pub(crate) mod ecmascript; + +pub use chunking_context::{ + BuildChunkingContext, BuildChunkingContextBuilder, BuildChunkingContextVc, +}; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + turbopack_ecmascript_runtime::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-cli/Cargo.toml b/crates/turbopack-cli/Cargo.toml index 20ebf6ab5ab8a..1ac25fa4ed7d8 100644 --- a/crates/turbopack-cli/Cargo.toml +++ b/crates/turbopack-cli/Cargo.toml @@ -64,6 +64,7 @@ turbopack-dev-server = { workspace = true } turbopack-ecmascript-plugins = { workspace = true, features = [ "transform_emotion", ] } +turbopack-ecmascript-runtime = { workspace = true } turbopack-env = { workspace = true } turbopack-node = { workspace = true } webbrowser = { workspace = true } diff --git a/crates/turbopack-cli/js/package.json b/crates/turbopack-cli/js/package.json index bad41e16efb4e..c9b944b6aca6c 100644 --- a/crates/turbopack-cli/js/package.json +++ b/crates/turbopack-cli/js/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@next/react-refresh-utils": "^13.0.6", - "@vercel/turbopack-dev": "*" + "@vercel/turbopack-ecmascript-runtime": "*" }, "devDependencies": { "@types/node": "^18.11.11" diff --git a/crates/turbopack-cli/js/src/entry/client.ts b/crates/turbopack-cli/js/src/entry/client.ts index 976595169b49f..d2d5ab7a2670f 100644 --- a/crates/turbopack-cli/js/src/entry/client.ts +++ b/crates/turbopack-cli/js/src/entry/client.ts @@ -1,5 +1,5 @@ -import { connect } from "@vercel/turbopack-dev/client/hmr-client"; -import { connectHMR } from "@vercel/turbopack-dev/client/websocket"; +import { connect } from "@vercel/turbopack-ecmascript-runtime/dev/client/hmr-client"; +import { connectHMR } from "@vercel/turbopack-ecmascript-runtime/dev/client/websocket"; export function initializeHMR(options: { assetPrefix: string }) { connect({ diff --git a/crates/turbopack-cli/js/tsconfig.json b/crates/turbopack-cli/js/tsconfig.json index 30d83824c2b25..bdc9e4dba9791 100644 --- a/crates/turbopack-cli/js/tsconfig.json +++ b/crates/turbopack-cli/js/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // type checking - "strict": false, + "strict": true, "noFallthroughCasesInSwitch": true, "skipLibCheck": true, diff --git a/crates/turbopack-cli/src/dev/web_entry_source.rs b/crates/turbopack-cli/src/dev/web_entry_source.rs index 14345a8378dce..e030fe141f0ca 100644 --- a/crates/turbopack-cli/src/dev/web_entry_source.rs +++ b/crates/turbopack-cli/src/dev/web_entry_source.rs @@ -58,10 +58,10 @@ pub async fn get_client_import_map(project_path: FileSystemPathVc) -> Result AssetsVc; + + /// Generate an output chunk asset for the given chunk. + fn generate_chunk(&self, chunk: ChunkVc) -> AssetVc; } diff --git a/crates/turbopack-dev/src/ecmascript/chunk_data.rs b/crates/turbopack-core/src/chunk/data.rs similarity index 80% rename from crates/turbopack-dev/src/ecmascript/chunk_data.rs rename to crates/turbopack-core/src/chunk/data.rs index c4ecaed36c4cd..845b519abe0e4 100644 --- a/crates/turbopack-dev/src/ecmascript/chunk_data.rs +++ b/crates/turbopack-core/src/chunk/data.rs @@ -1,10 +1,8 @@ -use std::hash::Hash; - use anyhow::Result; -use serde::Serialize; use turbo_tasks::{primitives::StringVc, TryJoinIterExt}; use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::{ + +use crate::{ asset::{Asset, AssetVc, AssetsVc}, chunk::{ModuleIdReadRef, OutputChunk, OutputChunkRuntimeInfo, OutputChunkVc}, reference::{AssetReferencesVc, SingleAssetReferenceVc}, @@ -19,44 +17,6 @@ pub struct ChunkData { pub references: AssetReferencesVc, } -impl ChunkData { - /// Returns a serializable version of this chunk data. - pub fn runtime_chunk_data(&self) -> RuntimeChunkData { - let ChunkData { - path, - included, - excluded, - module_chunks, - references: _, - } = self; - if included.is_empty() && excluded.is_empty() && module_chunks.is_empty() { - return RuntimeChunkData::Simple(&path); - } - RuntimeChunkData::WithRuntimeInfo { - path, - included: &included, - excluded: &excluded, - module_chunks: &module_chunks, - } - } -} - -#[derive(Serialize, Hash, PartialEq, Eq)] -#[serde(untagged)] -pub enum RuntimeChunkData<'a> { - Simple(&'a str), - #[serde(rename_all = "camelCase")] - WithRuntimeInfo { - path: &'a str, - #[serde(skip_serializing_if = "<[_]>::is_empty", default)] - included: &'a [ModuleIdReadRef], - #[serde(skip_serializing_if = "<[_]>::is_empty", default)] - excluded: &'a [ModuleIdReadRef], - #[serde(skip_serializing_if = "<[_]>::is_empty", default)] - module_chunks: &'a [String], - }, -} - #[turbo_tasks::value(transparent)] pub struct ChunkDataOption(Option); diff --git a/crates/turbopack-core/src/chunk/mod.rs b/crates/turbopack-core/src/chunk/mod.rs index b23f30d79c8fb..4b1fd67df36c3 100644 --- a/crates/turbopack-core/src/chunk/mod.rs +++ b/crates/turbopack-core/src/chunk/mod.rs @@ -2,6 +2,7 @@ pub mod availability_info; pub mod available_assets; pub(crate) mod chunking_context; pub(crate) mod containment_tree; +pub(crate) mod data; pub(crate) mod evaluate; pub mod optimize; @@ -29,6 +30,7 @@ use turbo_tasks_hash::DeterministicHash; use self::availability_info::AvailabilityInfo; pub use self::{ chunking_context::{ChunkingContext, ChunkingContextVc}, + data::{ChunkData, ChunkDataOption, ChunkDataOptionVc, ChunkDataVc, ChunksData, ChunksDataVc}, evaluate::{EvaluatableAsset, EvaluatableAssetVc, EvaluatableAssets, EvaluatableAssetsVc}, }; use crate::{ diff --git a/crates/turbopack-core/src/code_builder.rs b/crates/turbopack-core/src/code_builder.rs index b148071997570..39062c30abb1e 100644 --- a/crates/turbopack-core/src/code_builder.rs +++ b/crates/turbopack-core/src/code_builder.rs @@ -126,6 +126,12 @@ impl ops::AddAssign<&'static str> for CodeBuilder { } } +impl ops::AddAssign<&'static str> for &mut CodeBuilder { + fn add_assign(&mut self, rhs: &'static str) { + self.push_static_bytes(rhs.as_bytes()); + } +} + impl Write for CodeBuilder { fn write(&mut self, bytes: &[u8]) -> IoResult { self.push_map(None); diff --git a/crates/turbopack-core/src/ident.rs b/crates/turbopack-core/src/ident.rs index 19a054ba3ab58..f53c32b54b5f6 100644 --- a/crates/turbopack-core/src/ident.rs +++ b/crates/turbopack-core/src/ident.rs @@ -3,8 +3,9 @@ use std::fmt::Write; use anyhow::Result; use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks_hash::{encode_hex, hash_xxh3_hash64, DeterministicHash, Xxh3Hash64Hasher}; -use crate::resolve::ModulePartVc; +use crate::resolve::{ModulePart, ModulePartVc}; #[turbo_tasks::value(serialization = "auto_for_input")] #[derive(Clone, Debug, PartialOrd, Ord, Hash)] @@ -116,4 +117,139 @@ impl AssetIdentVc { pub async fn path(self) -> Result { Ok(self.await?.path) } + + /// Computes a unique output asset name for the given asset identifier. + /// TODO(alexkirsz) This is `turbopack-dev` specific, as `turbopack-build` + /// would use a content hash instead. But for now both are using the same + /// name generation logic. + #[turbo_tasks::function] + pub async fn output_name( + self, + context_path: FileSystemPathVc, + expected_extension: &str, + ) -> Result { + let this = &*self.await?; + + // For clippy -- This explicit deref is necessary + let path = &*this.path.await?; + let mut name = if let Some(inner) = context_path.await?.get_path_to(path) { + clean_separators(inner) + } else { + clean_separators(&this.path.to_string().await?) + }; + let removed_extension = name.ends_with(expected_extension); + if removed_extension { + name.truncate(name.len() - expected_extension.len()); + } + // This step ensures that leading dots are not preserved in file names. This is + // important as some file servers do not serve files with leading dots (e.g. + // Next.js). + let mut name = clean_additional_extensions(&name); + + let default_modifier = match expected_extension { + ".js" => Some("ecmascript"), + ".css" => Some("css"), + _ => None, + }; + + let mut hasher = Xxh3Hash64Hasher::new(); + let mut has_hash = false; + let AssetIdent { + path: _, + query, + fragment, + assets, + modifiers, + part, + } = this; + if let Some(query) = query { + 0_u8.deterministic_hash(&mut hasher); + query.await?.deterministic_hash(&mut hasher); + has_hash = true; + } + if let Some(fragment) = fragment { + 1_u8.deterministic_hash(&mut hasher); + fragment.await?.deterministic_hash(&mut hasher); + has_hash = true; + } + for (key, ident) in assets.iter() { + 2_u8.deterministic_hash(&mut hasher); + key.await?.deterministic_hash(&mut hasher); + ident.to_string().await?.deterministic_hash(&mut hasher); + has_hash = true; + } + for modifier in modifiers.iter() { + let modifier = modifier.await?; + if let Some(default_modifier) = default_modifier { + if *modifier == default_modifier { + continue; + } + } + 3_u8.deterministic_hash(&mut hasher); + modifier.deterministic_hash(&mut hasher); + has_hash = true; + } + if let Some(part) = part { + 4_u8.deterministic_hash(&mut hasher); + match &*part.await? { + ModulePart::ModuleEvaluation => { + 1_u8.deterministic_hash(&mut hasher); + } + ModulePart::Export(export) => { + 2_u8.deterministic_hash(&mut hasher); + export.await?.deterministic_hash(&mut hasher); + } + ModulePart::Internal(id) => { + 3_u8.deterministic_hash(&mut hasher); + id.deterministic_hash(&mut hasher); + } + } + + has_hash = true; + } + + if has_hash { + let hash = encode_hex(hasher.finish()); + let truncated_hash = &hash[..6]; + write!(name, "_{}", truncated_hash)?; + } + + // Location in "path" where hashed and named parts are split. + // Everything before i is hashed and after i named. + let mut i = 0; + static NODE_MODULES: &str = "_node_modules_"; + if let Some(j) = name.rfind(NODE_MODULES) { + i = j + NODE_MODULES.len(); + } + const MAX_FILENAME: usize = 80; + if name.len() - i > MAX_FILENAME { + i = name.len() - MAX_FILENAME; + if let Some(j) = name[i..].find('_') { + if j < 20 { + i += j + 1; + } + } + } + if i > 0 { + let hash = encode_hex(hash_xxh3_hash64(name[..i].as_bytes())); + let truncated_hash = &hash[..5]; + name = format!("{}_{}", truncated_hash, &name[i..]); + } + // We need to make sure that `.json` and `.json.js` doesn't end up with the same + // name. So when we add an extra extension when want to mark that with a "._" + // suffix. + if !removed_extension { + name += "._"; + } + name += expected_extension; + Ok(StringVc::cell(name)) + } +} + +fn clean_separators(s: &str) -> String { + s.replace('/', "_") +} + +fn clean_additional_extensions(s: &str) -> String { + s.replace('.', "_") } diff --git a/crates/turbopack-core/src/lib.rs b/crates/turbopack-core/src/lib.rs index 6fa94581689ad..8bdf03d26ae0a 100644 --- a/crates/turbopack-core/src/lib.rs +++ b/crates/turbopack-core/src/lib.rs @@ -31,6 +31,7 @@ pub mod target; mod utils; pub mod version; pub mod virtual_asset; +pub mod virtual_fs; pub const PROJECT_FILESYSTEM_NAME: &str = "project"; pub const SOURCE_MAP_ROOT_NAME: &str = "turbopack"; diff --git a/crates/turbopack-core/src/virtual_fs.rs b/crates/turbopack-core/src/virtual_fs.rs new file mode 100644 index 0000000000000..f1f33fe01d450 --- /dev/null +++ b/crates/turbopack-core/src/virtual_fs.rs @@ -0,0 +1,67 @@ +use anyhow::{bail, Result}; +use turbo_tasks::{primitives::StringVc, CompletionVc, ValueToString, ValueToStringVc}; +use turbo_tasks_fs::{ + DirectoryContentVc, FileContentVc, FileMetaVc, FileSystem, FileSystemPathVc, FileSystemVc, + LinkContentVc, +}; + +#[turbo_tasks::value] +pub struct VirtualFileSystem; + +#[turbo_tasks::value_impl] +impl VirtualFileSystemVc { + #[turbo_tasks::function] + pub fn new() -> Self { + Self::cell(VirtualFileSystem) + } +} + +#[turbo_tasks::value_impl] +impl FileSystem for VirtualFileSystem { + #[turbo_tasks::function] + fn read(&self, _fs_path: FileSystemPathVc) -> Result { + bail!("Reading is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn read_link(&self, _fs_path: FileSystemPathVc) -> Result { + bail!("Reading is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn read_dir(&self, _fs_path: FileSystemPathVc) -> Result { + bail!("Reading is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn track(&self, _fs_path: FileSystemPathVc) -> Result { + bail!("Tracking is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn write(&self, _fs_path: FileSystemPathVc, _content: FileContentVc) -> Result { + bail!("Writing is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn write_link( + &self, + _fs_path: FileSystemPathVc, + _target: LinkContentVc, + ) -> Result { + bail!("Writing is not possible on the virtual file system") + } + + #[turbo_tasks::function] + fn metadata(&self, _fs_path: FileSystemPathVc) -> Result { + bail!("Reading is not possible on the virtual file system") + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for VirtualFileSystem { + #[turbo_tasks::function] + fn to_string(&self) -> StringVc { + StringVc::cell("virtual file system".to_string()) + } +} diff --git a/crates/turbopack-dev/Cargo.toml b/crates/turbopack-dev/Cargo.toml index 3da1398a90b1a..4c8fa46ccee88 100644 --- a/crates/turbopack-dev/Cargo.toml +++ b/crates/turbopack-dev/Cargo.toml @@ -12,6 +12,8 @@ bench = false [features] # enable "HMR" for embedded assets dynamic_embed_contents = ["turbo-tasks-fs/dynamic_embed_contents"] +# enable test utilities such as `RuntimeType::Dummy` +test = ["turbopack-ecmascript-runtime/test"] [dependencies] anyhow = { workspace = true } @@ -28,6 +30,9 @@ turbopack = { workspace = true } turbopack-core = { workspace = true } turbopack-css = { workspace = true } turbopack-ecmascript = { workspace = true } +turbopack-ecmascript-runtime = { workspace = true } + +swc_core = { workspace = true } [build-dependencies] turbo-tasks-build = { workspace = true } diff --git a/crates/turbopack-dev/js/package.json b/crates/turbopack-dev/js/package.json deleted file mode 100644 index 3966e012ddd58..0000000000000 --- a/crates/turbopack-dev/js/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "@vercel/turbopack-dev", - "version": "0.0.0", - "description": "Turbopack development runtime", - "license": "UNLICENSED", - "private": true, - "scripts": { - "check": "tsc --noEmit" - }, - "dependencies": { - "@next/react-refresh-utils": "^13.0.6" - }, - "devDependencies": { - "@types/node": "^18.11.11" - }, - "exports": { - "./types/*": "./types/*.d.ts", - "./*": "./src/*.ts" - } -} diff --git a/crates/turbopack-dev/js/tsconfig.json b/crates/turbopack-dev/js/tsconfig.json deleted file mode 100644 index 30d83824c2b25..0000000000000 --- a/crates/turbopack-dev/js/tsconfig.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "compilerOptions": { - // type checking - "strict": false, - "noFallthroughCasesInSwitch": true, - "skipLibCheck": true, - - // interop constraints - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - - // js support - "allowJs": true, - "checkJs": true, - - // environment - "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], - "target": "esnext", - - // modules - "baseUrl": ".", - "module": "esnext", - "moduleResolution": "node", - "types": [], - - // emit - "noEmit": true, - "stripInternal": true - }, - "include": ["src"] -} diff --git a/crates/turbopack-dev/js/types/backend.d.ts b/crates/turbopack-dev/js/types/backend.d.ts deleted file mode 100644 index 01dde590586c6..0000000000000 --- a/crates/turbopack-dev/js/types/backend.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - GetFirstModuleChunk, - GetOrInstantiateRuntimeModule, - LoadChunk, - SourceType, -} from "."; -import { DevRuntimeParams } from "./runtime"; - -export { RuntimeBackend } from "types"; - -declare global { - declare const RUNTIME_PARAMS: DevRuntimeParams; - declare const getFirstModuleChunk: GetFirstModuleChunk; - declare const getOrInstantiateRuntimeModule: GetOrInstantiateRuntimeModule; - declare const getChunkPath: GetChunkPath; - declare const loadChunk: InternalLoadChunk; - declare const SourceTypeRuntime: SourceType.Runtime; - declare const SourceTypeParent: SourceType.Parent; - declare const SourceTypeUpdate: SourceType.Update; -} diff --git a/crates/turbopack-dev/js/types/index.d.ts b/crates/turbopack-dev/js/types/index.d.ts deleted file mode 100644 index ff3b12c33b24f..0000000000000 --- a/crates/turbopack-dev/js/types/index.d.ts +++ /dev/null @@ -1,216 +0,0 @@ -import { RefreshRuntimeGlobals } from "@next/react-refresh-utils/dist/runtime"; -import { ServerMessage } from "./protocol"; -import { Hot } from "./hot"; -import { DevRuntimeParams } from "./runtime"; - -export type RefreshHelpers = RefreshRuntimeGlobals["$RefreshHelpers$"]; - -export type RefreshContext = { - register: RefreshRuntimeGlobals["$RefreshReg$"]; - signature: RefreshRuntimeGlobals["$RefreshSig$"]; -}; - -type ChunkPath = string; -type ModuleId = string; - -interface Chunk {} - -interface Exports { - __esModule?: boolean; - - [key: string]: any; -} - -export type ChunkModule = () => void; -export type ChunkRegistration = [ - chunkPath: ChunkPath, - chunkModules: ChunkModule[], - DevRuntimeParams | undefined -]; -export type ChunkData = - | ChunkPath - | { - path: ChunkPath; - included: ModuleId[]; - excluded: ModuleId[]; - moduleChunks: ChunkPath[]; - }; -export type ChunkList = { - path: ChunkPath; - chunks: ChunkData[]; - source: "entry" | "dynamic"; -}; - -interface Module { - exports: Exports; - error: Error | undefined; - loaded: boolean; - id: ModuleId; - hot?: Hot; - children: ModuleId[]; - parents: ModuleId[]; - namespaceObject?: EsmNamespaceObject; -} - -enum SourceType { - /** - * The module was instantiated because it was included in an evaluated chunk's - * runtime. - */ - Runtime = 0, - /** - * The module was instantiated because a parent module imported it. - */ - Parent = 1, - /** - * The module was instantiated because it was included in a chunk's hot module - * update. - */ - Update = 2, -} - -type SourceInfo = - | { - type: SourceType.Runtime; - chunkPath: ChunkPath; - } - | { - type: SourceType.Parent; - parentId: ModuleId; - } - | { - type: SourceType.Update; - parents?: ModuleId[]; - }; - -type ModuleCache = Record; - -type CommonJsRequire = (moduleId: ModuleId) => Exports; -type CommonJsExport = (exports: Record) => void; - -type RequireContextFactory = ( - dir: string, - useSubdirectories = true -) => RequireContext; - -type RequireContextMap = Record< - ModuleId, - { internal: boolean; id: () => ModuleId } ->; - -interface RequireContext { - (moduleId: ModuleId): Exports | EsmNamespaceObject; - keys(): ModuleId[]; - resolve(moduleId: ModuleId): ModuleId; -} - -export type EsmNamespaceObject = Record; -type EsmImport = ( - moduleId: ModuleId, - allowExportDefault: boolean -) => EsmNamespaceObject; -type EsmExport = (exportGetters: Record any>) => void; -type ExportValue = (value: any) => void; - -type LoadChunk = (chunkPath: ChunkPath) => Promise | undefined; - -interface TurbopackContext { - e: Module["exports"]; - r: CommonJsRequire; - x: NodeJS.Require; - f: RequireContextFactory; - i: EsmImport; - s: EsmExport; - j: CommonJsExport; - v: ExportValue; - m: Module; - c: ModuleCache; - l: LoadChunk; - g: globalThis; - k: RefreshContext; - __dirname: string; -} - -type ModuleFactory = ( - this: Module["exports"], - context: TurbopackContext -) => undefined; - -// string encoding of a module factory (used in hmr updates) -type ModuleFactoryString = string; - -interface RuntimeBackend { - registerChunk: (chunkPath: ChunkPath, params?: DevRuntimeParams) => void; - loadChunk: (chunkPath: ChunkPath, source: SourceInfo) => Promise; - reloadChunk?: (chunkPath: ChunkPath) => Promise; - unloadChunk?: (chunkPath: ChunkPath) => void; - - restart: () => void; -} - -export type UpdateCallback = (update: ServerMessage) => void; -export type ChunkUpdateProvider = { - push: (registration: [ChunkPath, UpdateCallback]) => void; -}; - -export interface TurbopackGlobals { - // This is used by the Next.js integration test suite to notify it when HMR - // updates have been completed. - __NEXT_HMR_CB?: null | (() => void); - TURBOPACK?: ChunkRegistration[]; - TURBOPACK_CHUNK_UPDATE_LISTENERS?: - | ChunkUpdateProvider - | [ChunkPath, UpdateCallback][]; - TURBOPACK_CHUNK_LISTS?: ChunkList[]; -} - -export type GetChunkPath = (chunkData: ChunkData) => ChunkPath; - -export type GetFirstModuleChunk = (moduleId: ModuleId) => ChunkPath | null; -export type GetOrInstantiateRuntimeModule = ( - moduleId: ModuleId, - chunkPath: ChunkPath -) => Module; -export type InternalLoadChunk = ( - source: SourceInfo, - chunkData: ChunkData -) => Promise; - -export interface Loader { - promise: Promise; - onLoad: () => void; -} - -export type ModuleEffect = - | { - type: "unaccepted"; - dependencyChain: ModuleId[]; - } - | { - type: "self-declined"; - dependencyChain: ModuleId[]; - moduleId: ModuleId; - } - | { - type: "accepted"; - moduleId: ModuleId; - outdatedModules: Set; - }; - -declare global { - var TURBOPACK: ChunkRegistration[]; - var TURBOPACK_CHUNK_UPDATE_LISTENERS: - | ChunkUpdateProvider - | [ChunkPath, UpdateCallback][] - | undefined; - var TURBOPACK_CHUNK_LISTS: ChunkList[]; - - var $RefreshHelpers$: RefreshRuntimeGlobals["$RefreshHelpers$"]; - var $RefreshReg$: RefreshRuntimeGlobals["$RefreshReg$"]; - var $RefreshSig$: RefreshRuntimeGlobals["$RefreshSig$"]; - var $RefreshInterceptModuleExecution$: RefreshRuntimeGlobals["$RefreshInterceptModuleExecution$"]; - - interface NodeModule { - hot: Hot; - } -} diff --git a/crates/turbopack-dev/js/types/runtime.d.ts b/crates/turbopack-dev/js/types/runtime.d.ts deleted file mode 100644 index 14529980105bb..0000000000000 --- a/crates/turbopack-dev/js/types/runtime.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ModuleId, ChunkPath } from "./index"; - -export type ModuleEffect = - | { - type: "unaccepted"; - dependencyChain: ModuleId[]; - } - | { - type: "self-declined"; - dependencyChain: ModuleId[]; - moduleId: ModuleId; - } - | { - type: "accepted"; - moduleId: ModuleId; - outdatedModules: Set; - }; - -export type DevRuntimeParams = { - otherChunks: ChunkData[]; - runtimeModuleIds: ModuleId[]; -}; diff --git a/crates/turbopack-dev/js/types/runtime.dom.d.ts b/crates/turbopack-dev/js/types/runtime.dom.d.ts deleted file mode 100644 index d137c34255cd0..0000000000000 --- a/crates/turbopack-dev/js/types/runtime.dom.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type ChunkResolver = { - resolved: boolean; - resolve: () => void; - reject: (error?: Error) => void; - promise: Promise; -}; diff --git a/crates/turbopack-dev/js/types/runtime.none.d.ts b/crates/turbopack-dev/js/types/runtime.none.d.ts deleted file mode 100644 index d75f013457408..0000000000000 --- a/crates/turbopack-dev/js/types/runtime.none.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ChunkPath, ModuleId } from "./index"; - -export type ChunkRunner = { - requiredChunks: Set; - chunkPath: ChunkPath; - runtimeModuleIds: ModuleId[]; -}; diff --git a/crates/turbopack-dev/src/chunking_context.rs b/crates/turbopack-dev/src/chunking_context.rs index 5c165d86f2c25..5b980174929c0 100644 --- a/crates/turbopack-dev/src/chunking_context.rs +++ b/crates/turbopack-dev/src/chunking_context.rs @@ -1,29 +1,25 @@ -use std::fmt::Write; - use anyhow::Result; use indexmap::IndexSet; use turbo_tasks::{ graph::{GraphTraversal, ReverseTopological}, primitives::{BoolVc, StringVc}, - TryJoinIterExt, Value, ValueToString, + TryJoinIterExt, Value, }; use turbo_tasks_fs::FileSystemPathVc; -use turbo_tasks_hash::{encode_hex, hash_xxh3_hash64, DeterministicHash, Xxh3Hash64Hasher}; use turbopack_core::{ asset::{Asset, AssetVc, AssetsVc}, chunk::{ - availability_info::AvailabilityInfo, Chunk, ChunkVc, ChunkableAsset, ChunkableAssetVc, - ChunkingContext, ChunkingContextVc, ChunksVc, EvaluatableAssetsVc, + Chunk, ChunkVc, ChunkableAsset, ChunkingContext, ChunkingContextVc, ChunksVc, + EvaluatableAssetsVc, }, environment::EnvironmentVc, - ident::{AssetIdent, AssetIdentVc}, - resolve::ModulePart, + ident::AssetIdentVc, }; use turbopack_css::chunk::{CssChunkVc, CssChunksVc}; use turbopack_ecmascript::chunk::{ - EcmascriptChunkItemVc, EcmascriptChunkVc, EcmascriptChunkingContext, - EcmascriptChunkingContextVc, EcmascriptChunksVc, + EcmascriptChunkVc, EcmascriptChunkingContext, EcmascriptChunkingContextVc, EcmascriptChunksVc, }; +use turbopack_ecmascript_runtime::RuntimeType; use crate::{ css::optimize::optimize_css_chunks, @@ -31,7 +27,6 @@ use crate::{ chunk::EcmascriptDevChunkVc, evaluate::chunk::EcmascriptDevEvaluateChunkVc, list::asset::{EcmascriptDevChunkListSource, EcmascriptDevChunkListVc}, - manifest::{chunk_asset::DevManifestChunkAssetVc, loader_item::DevManifestLoaderItemVc}, optimize::optimize_ecmascript_chunks, }, }; @@ -61,6 +56,11 @@ impl DevChunkingContextBuilder { self } + pub fn runtime_type(mut self, runtime_type: RuntimeType) -> Self { + self.context.runtime_type = runtime_type; + self + } + pub fn build(self) -> ChunkingContextVc { DevChunkingContextVc::new(Value::new(self.context)).into() } @@ -74,7 +74,8 @@ impl DevChunkingContextBuilder { #[turbo_tasks::value(serialization = "auto_for_input")] #[derive(Debug, Clone, Hash, PartialOrd, Ord)] pub struct DevChunkingContext { - /// This path get striped off of path before creating a name out of it + /// This path get stripped off of chunk paths before generating output asset + /// paths. context_path: FileSystemPathVc, /// This path is used to compute the url to request chunks or assets from output_root: FileSystemPathVc, @@ -92,6 +93,8 @@ pub struct DevChunkingContext { enable_hot_module_replacement: bool, /// The environment chunks will be evaluated in. environment: EnvironmentVc, + /// The kind of runtime to include in the output. + runtime_type: RuntimeType, } impl DevChunkingContextVc { @@ -113,11 +116,22 @@ impl DevChunkingContextVc { layer: None, enable_hot_module_replacement: false, environment, + runtime_type: Default::default(), }, } } } +impl DevChunkingContext { + /// Returns the kind of runtime to include in output chunks. + /// + /// This is defined directly on `DevChunkingContext` so it is zero-cost when + /// `RuntimeType` has a single variant. + pub fn runtime_type(&self) -> RuntimeType { + self.runtime_type + } +} + #[turbo_tasks::value_impl] impl DevChunkingContextVc { #[turbo_tasks::function] @@ -125,20 +139,6 @@ impl DevChunkingContextVc { this.into_value().cell() } - #[turbo_tasks::function] - pub(crate) async fn generate_chunk( - self_vc: DevChunkingContextVc, - chunk: ChunkVc, - ) -> Result { - Ok( - if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(chunk).await? { - EcmascriptDevChunkVc::new(self_vc, ecmascript_chunk).into() - } else { - chunk.into() - }, - ) - } - #[turbo_tasks::function] fn generate_evaluate_chunk( self_vc: DevChunkingContextVc, @@ -180,125 +180,13 @@ impl ChunkingContext for DevChunkingContext { #[turbo_tasks::function] async fn chunk_path(&self, ident: AssetIdentVc, extension: &str) -> Result { - fn clean(s: &str) -> String { - s.replace('/', "_") - } - let ident = &*ident.await?; - - // For clippy -- This explicit deref is necessary - let path = &*ident.path.await?; - let mut name = if let Some(inner) = self.context_path.await?.get_path_to(path) { - clean(inner) - } else { - clean(&ident.path.to_string().await?) - }; - let removed_extension = name.ends_with(extension); - if removed_extension { - name.truncate(name.len() - extension.len()); - } - - let default_modifier = match extension { - ".js" => Some("ecmascript"), - ".css" => Some("css"), - _ => None, - }; - - let mut hasher = Xxh3Hash64Hasher::new(); - let mut has_hash = false; - let AssetIdent { - path: _, - query, - fragment, - assets, - modifiers, - part, - } = ident; - if let Some(query) = query { - 0_u8.deterministic_hash(&mut hasher); - query.await?.deterministic_hash(&mut hasher); - has_hash = true; - } - if let Some(fragment) = fragment { - 1_u8.deterministic_hash(&mut hasher); - fragment.await?.deterministic_hash(&mut hasher); - has_hash = true; - } - for (key, ident) in assets.iter() { - 2_u8.deterministic_hash(&mut hasher); - key.await?.deterministic_hash(&mut hasher); - ident.to_string().await?.deterministic_hash(&mut hasher); - has_hash = true; - } - for modifier in modifiers.iter() { - let modifier = modifier.await?; - if let Some(default_modifier) = default_modifier { - if *modifier == default_modifier { - continue; - } - } - 3_u8.deterministic_hash(&mut hasher); - modifier.deterministic_hash(&mut hasher); - has_hash = true; - } - if let Some(part) = part { - 4_u8.deterministic_hash(&mut hasher); - match &*part.await? { - ModulePart::ModuleEvaluation => { - 1_u8.deterministic_hash(&mut hasher); - } - ModulePart::Export(export) => { - 2_u8.deterministic_hash(&mut hasher); - export.await?.deterministic_hash(&mut hasher); - } - ModulePart::Internal(id) => { - 3_u8.deterministic_hash(&mut hasher); - id.deterministic_hash(&mut hasher); - } - } - - has_hash = true; - } - - if has_hash { - let hash = encode_hex(hasher.finish()); - let truncated_hash = &hash[..6]; - write!(name, "_{}", truncated_hash)?; - } - - // Location in "path" where hashed and named parts are split. - // Everything before i is hashed and after i named. - let mut i = 0; - static NODE_MODULES: &str = "_node_modules_"; - if let Some(j) = name.rfind(NODE_MODULES) { - i = j + NODE_MODULES.len(); - } - const MAX_FILENAME: usize = 80; - if name.len() - i > MAX_FILENAME { - i = name.len() - MAX_FILENAME; - if let Some(j) = name[i..].find('_') { - if j < 20 { - i += j + 1; - } - } - } - if i > 0 { - let hash = encode_hex(hash_xxh3_hash64(name[..i].as_bytes())); - let truncated_hash = &hash[..5]; - name = format!("{}_{}", truncated_hash, &name[i..]); - } - // We need to make sure that `.json` and `.json.js` doesn't end up with the same - // name. So when we add an extra extension when want to mark that with a "._" - // suffix. - if !removed_extension { - name += "._"; - } - name += extension; let root_path = self.chunk_root_path; let root_path = if let Some(layer) = self.layer.as_deref() { root_path.join(layer) } else { root_path }; + let name = ident.output_name(self.context_path, extension).await?; Ok(root_path.join(&name)) } @@ -438,18 +326,24 @@ impl ChunkingContext for DevChunkingContext { Ok(AssetsVc::cell(assets)) } + + #[turbo_tasks::function] + async fn generate_chunk(self_vc: DevChunkingContextVc, chunk: ChunkVc) -> Result { + Ok( + if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(chunk).await? { + EcmascriptDevChunkVc::new(self_vc, ecmascript_chunk).into() + } else { + chunk.into() + }, + ) + } } #[turbo_tasks::value_impl] impl EcmascriptChunkingContext for DevChunkingContext { #[turbo_tasks::function] - fn manifest_loader_item( - self_vc: DevChunkingContextVc, - asset: ChunkableAssetVc, - availability_info: Value, - ) -> EcmascriptChunkItemVc { - let manifest_asset = DevManifestChunkAssetVc::new(asset, self_vc, availability_info); - DevManifestLoaderItemVc::new(manifest_asset).into() + fn has_react_refresh(&self) -> BoolVc { + BoolVc::cell(true) } } diff --git a/crates/turbopack-dev/src/ecmascript/content_entry.rs b/crates/turbopack-dev/src/ecmascript/content_entry.rs index 265f7cbd9c4f6..51b6bd6652b38 100644 --- a/crates/turbopack-dev/src/ecmascript/content_entry.rs +++ b/crates/turbopack-dev/src/ecmascript/content_entry.rs @@ -17,8 +17,6 @@ use turbopack_ecmascript::chunk::{ EcmascriptChunkContentVc, EcmascriptChunkItem, EcmascriptChunkItemVc, }; -use crate::ecmascript::module_factory::module_factory; - /// A chunk item's content entry. /// /// Instead of storing the [`EcmascriptChunkItemVc`] itself from which `code` @@ -37,7 +35,8 @@ impl EcmascriptDevChunkContentEntry { chunk_item: EcmascriptChunkItemVc, availability_info: AvailabilityInfo, ) -> Result { - let code = item_code(chunk_item, Value::new(availability_info)) + let code = chunk_item + .code(Value::new(availability_info)) .resolve() .await?; Ok(EcmascriptDevChunkContentEntry { @@ -92,7 +91,9 @@ async fn item_code( availability_info: Value, ) -> Result { Ok( - match module_factory(item.content_with_availability_info(availability_info)) + match item + .content_with_availability_info(availability_info) + .module_factory() .resolve() .await { diff --git a/crates/turbopack-dev/src/ecmascript/evaluate/chunk.rs b/crates/turbopack-dev/src/ecmascript/evaluate/chunk.rs index d6bbfd3d14404..3dd90e16f9ddc 100644 --- a/crates/turbopack-dev/src/ecmascript/evaluate/chunk.rs +++ b/crates/turbopack-dev/src/ecmascript/evaluate/chunk.rs @@ -4,12 +4,13 @@ use anyhow::{bail, Result}; use indoc::writedoc; use serde::Serialize; use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString, ValueToStringVc}; -use turbo_tasks_fs::{embed_file, File, FileContent}; +use turbo_tasks_fs::File; use turbopack_core::{ asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, - chunk::{ChunkVc, ChunkingContext, EvaluatableAssetsVc, ModuleIdReadRef}, + chunk::{ + ChunkDataVc, ChunkVc, ChunkingContext, ChunksDataVc, EvaluatableAssetsVc, ModuleIdReadRef, + }, code_builder::{CodeBuilder, CodeVc}, - environment::ChunkLoading, ident::AssetIdentVc, reference::AssetReferencesVc, source_map::{ @@ -17,14 +18,12 @@ use turbopack_core::{ }, }; use turbopack_ecmascript::{ - chunk::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc}, + chunk::{EcmascriptChunkData, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc}, utils::StringifyJs, }; +use turbopack_ecmascript_runtime::RuntimeType; -use crate::{ - ecmascript::chunk_data::{ChunkDataVc, ChunksDataVc}, - DevChunkingContextVc, -}; +use crate::DevChunkingContextVc; /// An Ecmascript chunk that: /// * Contains the Turbopack dev runtime code; and @@ -68,6 +67,7 @@ impl EcmascriptDevEvaluateChunkVc { #[turbo_tasks::function] async fn code(self) -> Result { let this = self.await?; + let environment = this.chunking_context.environment(); let output_root = this.chunking_context.output_root().await?; let chunk_path = self.ident().path().await?; @@ -85,7 +85,7 @@ impl EcmascriptDevEvaluateChunkVc { let other_chunks_data = other_chunks_data.iter().try_join().await?; let other_chunks_data: Vec<_> = other_chunks_data .iter() - .map(|chunk_data| chunk_data.runtime_chunk_data()) + .map(|chunk_data| EcmascriptChunkData::new(chunk_data)) .collect(); let runtime_module_ids = this @@ -132,47 +132,22 @@ impl EcmascriptDevEvaluateChunkVc { {{}}, {} ]); - (() => {{ - if (!Array.isArray(globalThis.TURBOPACK)) {{ - return; - }} "#, StringifyJs(&chunk_public_path), StringifyJs(¶ms), )?; - let shared_runtime_code = embed_file!("js/src/runtime.js").await?; - - match &*shared_runtime_code { - FileContent::NotFound => bail!("shared runtime code is not found"), - FileContent::Content(file) => code.push_source(file.content(), None), - }; - - // The specific runtime code depends on declarations in the shared runtime code, - // hence it must be appended after it. - let specific_runtime_code = - match &*this.chunking_context.environment().chunk_loading().await? { - ChunkLoading::None => embed_file!("js/src/runtime.none.js").await?, - ChunkLoading::NodeJs => embed_file!("js/src/runtime.nodejs.js").await?, - ChunkLoading::Dom => embed_file!("js/src/runtime.dom.js").await?, - }; - - match &*specific_runtime_code { - FileContent::NotFound => bail!("specific runtime code is not found"), - FileContent::Content(file) => code.push_source(file.content(), None), - }; - - // Registering chunks depends on the BACKEND variable, which is set by the - // specific runtime code, hence it must be appended after it. - writedoc!( - code, - r#" - const chunksToRegister = globalThis.TURBOPACK; - globalThis.TURBOPACK = {{ push: registerChunk }}; - chunksToRegister.forEach(registerChunk); - }})(); - "# - )?; + match this.chunking_context.await?.runtime_type() { + RuntimeType::Default => { + let runtime_code = turbopack_ecmascript_runtime::get_dev_runtime_code(environment); + code.push_code(&*runtime_code.await?); + } + #[cfg(feature = "test")] + RuntimeType::Dummy => { + let runtime_code = turbopack_ecmascript_runtime::get_dummy_runtime_code(); + code.push_code(&runtime_code); + } + } if code.has_source_map() { let filename = chunk_path.file_name(); diff --git a/crates/turbopack-dev/src/ecmascript/mod.rs b/crates/turbopack-dev/src/ecmascript/mod.rs index 6aa1c482f763a..76c536359a8e3 100644 --- a/crates/turbopack-dev/src/ecmascript/mod.rs +++ b/crates/turbopack-dev/src/ecmascript/mod.rs @@ -1,12 +1,9 @@ pub(crate) mod chunk; -pub(crate) mod chunk_data; pub(crate) mod content; pub(crate) mod content_entry; pub(crate) mod evaluate; pub(crate) mod list; -pub(crate) mod manifest; pub(crate) mod merged; -pub(crate) mod module_factory; pub(crate) mod optimize; pub(crate) mod update; pub(crate) mod version; diff --git a/crates/turbopack-dev/src/ecmascript/module_factory.rs b/crates/turbopack-dev/src/ecmascript/module_factory.rs deleted file mode 100644 index 3f3405c2a23f6..0000000000000 --- a/crates/turbopack-dev/src/ecmascript/module_factory.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::io::Write; - -use anyhow::Result; -use turbopack_core::code_builder::{CodeBuilder, CodeVc}; -use turbopack_ecmascript::{chunk::EcmascriptChunkItemContentVc, utils::FormatIter}; - -#[turbo_tasks::function] -pub(super) async fn module_factory(content: EcmascriptChunkItemContentVc) -> Result { - let content = content.await?; - let mut args = vec![ - "r: __turbopack_require__", - "x: __turbopack_external_require__", - "f: __turbopack_require_context__", - "i: __turbopack_import__", - "s: __turbopack_esm__", - "v: __turbopack_export_value__", - "n: __turbopack_export_namespace__", - "c: __turbopack_cache__", - "l: __turbopack_load__", - "j: __turbopack_cjs__", - "k: __turbopack_refresh__", - "g: global", - // HACK - "__dirname", - ]; - if content.options.module { - args.push("m: module"); - } - if content.options.exports { - args.push("e: exports"); - } - let mut code = CodeBuilder::default(); - let args = FormatIter(|| args.iter().copied().intersperse(", ")); - if content.options.this { - write!(code, "(function({{ {} }}) {{ !function() {{\n\n", args,)?; - } else { - write!(code, "(({{ {} }}) => (() => {{\n\n", args,)?; - } - - let source_map = content.source_map.map(|sm| sm.as_generate_source_map()); - code.push_source(&content.inner_code, source_map); - if content.options.this { - code += "\n}.call(this) })"; - } else { - code += "\n})())"; - } - Ok(code.build().cell()) -} diff --git a/crates/turbopack-dev/src/ecmascript/runtime.rs b/crates/turbopack-dev/src/ecmascript/runtime.rs new file mode 100644 index 0000000000000..5e1845029b39f --- /dev/null +++ b/crates/turbopack-dev/src/ecmascript/runtime.rs @@ -0,0 +1,214 @@ +use anyhow::{bail, Result}; +use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbopack_core::{ + asset::Asset, + chunk::{ChunkGroupVc, ChunkListReferenceVc, ChunkingContext}, + ident::AssetIdentVc, + reference::AssetReferencesVc, +}; +use turbopack_ecmascript::chunk::{ + EcmascriptChunkPlaceablesVc, EcmascriptChunkRuntime, EcmascriptChunkRuntimeContentVc, + EcmascriptChunkRuntimeVc, EcmascriptChunkVc, EcmascriptChunkingContextVc, +}; + +use crate::ecmascript::content::EcmascriptDevChunkContentVc; + +/// Development runtime for Ecmascript chunks. +#[turbo_tasks::value(shared)] +pub(crate) struct EcmascriptDevChunkRuntime { + /// The chunking context that created this runtime. + chunking_context: EcmascriptChunkingContextVc, + /// All chunks of this chunk group need to be ready for execution to start. + /// When None, it will use a chunk group created from the current chunk. + chunk_group: Option, + /// If any evaluated entries are set, the main runtime code will be included + /// in the chunk and the provided entries will be evaluated as soon as the + /// chunk executes. + evaluated_entries: Option, +} + +#[turbo_tasks::value_impl] +impl EcmascriptDevChunkRuntimeVc { + /// Creates a new [`EcmascriptDevChunkRuntimeVc`]. + #[turbo_tasks::function] + pub fn new( + chunking_context: EcmascriptChunkingContextVc, + evaluated_entries: Option, + ) -> Self { + EcmascriptDevChunkRuntime { + chunking_context, + chunk_group: None, + evaluated_entries, + } + .cell() + } +} + +#[turbo_tasks::value_impl] +impl ValueToString for EcmascriptDevChunkRuntime { + #[turbo_tasks::function] + async fn to_string(&self) -> Result { + Ok(StringVc::cell("Ecmascript Dev Runtime".to_string())) + } +} + +#[turbo_tasks::function] +fn modifier() -> StringVc { + StringVc::cell("ecmascript dev chunk".to_string()) +} + +#[turbo_tasks::value_impl] +impl EcmascriptChunkRuntime for EcmascriptDevChunkRuntime { + #[turbo_tasks::function] + async fn decorate_asset_ident( + &self, + origin_chunk: EcmascriptChunkVc, + ident: AssetIdentVc, + ) -> Result { + let Self { + chunking_context: _, + chunk_group, + evaluated_entries, + } = self; + + let mut ident = ident.await?.clone_value(); + + // Add a constant modifier to qualify this runtime. + ident.add_modifier(modifier()); + + // Only add other modifiers when the chunk is evaluated. Otherwise, it will + // not receive any params and as such won't differ from another chunk in a + // different chunk group. + if let Some(evaluated_entries) = evaluated_entries { + ident.modifiers.extend( + evaluated_entries + .await? + .iter() + .map(|entry| entry.ident().to_string()), + ); + + // When the chunk group has changed, e.g. due to optimization, we want to + // include the information too. Since the optimization is + // deterministic, it's enough to include the entry chunk which is the only + // factor that influences the chunk group chunks. + // We want to avoid a cycle when this chunk is the entry chunk. + if let Some(chunk_group) = chunk_group { + let entry = chunk_group.entry().resolve().await?; + if entry != origin_chunk.into() { + ident.add_modifier(entry.ident().to_string()); + } + } + } + + Ok(AssetIdentVc::new(Value::new(ident))) + } + + #[turbo_tasks::function] + fn with_chunk_group(&self, chunk_group: ChunkGroupVc) -> EcmascriptDevChunkRuntimeVc { + EcmascriptDevChunkRuntimeVc::cell(EcmascriptDevChunkRuntime { + chunking_context: self.chunking_context, + chunk_group: Some(chunk_group), + evaluated_entries: self.evaluated_entries, + }) + } + + #[turbo_tasks::function] + fn references(&self, origin_chunk: EcmascriptChunkVc) -> AssetReferencesVc { + let Self { + chunk_group, + chunking_context, + evaluated_entries, + } = self; + + let mut references = vec![]; + if evaluated_entries.is_some() { + let chunk_group = + chunk_group.unwrap_or_else(|| ChunkGroupVc::from_chunk(origin_chunk.into())); + references.push( + ChunkListReferenceVc::new(chunking_context.output_root(), chunk_group).into(), + ); + } + AssetReferencesVc::cell(references) + } + + #[turbo_tasks::function] + fn content(&self, origin_chunk: EcmascriptChunkVc) -> EcmascriptChunkRuntimeContentVc { + EcmascriptDevChunkContentVc::new( + origin_chunk, + self.chunking_context, + self.chunk_group, + self.evaluated_entries, + ) + .into() + } + + #[turbo_tasks::function] + async fn merge( + &self, + runtimes: Vec, + ) -> Result { + let Self { + chunking_context, + chunk_group, + evaluated_entries, + } = self; + + let chunking_context = chunking_context.resolve().await?; + let chunk_group = if let Some(chunk_group) = chunk_group { + Some(chunk_group.resolve().await?) + } else { + None + }; + + let mut evaluated_entries = if let Some(evaluated_entries) = evaluated_entries { + Some(evaluated_entries.await?.clone_value()) + } else { + None + }; + + for runtime in runtimes { + let Some(runtime) = EcmascriptDevChunkRuntimeVc::resolve_from(runtime).await? else { + bail!("cannot merge EcmascriptDevChunkRuntime with non-EcmascriptDevChunkRuntime"); + }; + + let Self { + chunking_context: other_chunking_context, + chunk_group: other_chunk_group, + evaluated_entries: other_evaluated_entries, + } = &*runtime.await?; + + let other_chunking_context = other_chunking_context.resolve().await?; + let other_chunk_group = if let Some(other_chunk_group) = other_chunk_group { + Some(other_chunk_group.resolve().await?) + } else { + None + }; + + if chunking_context != other_chunking_context { + bail!("cannot merge EcmascriptDevChunkRuntime with different chunking contexts",); + } + + if chunk_group != other_chunk_group { + bail!("cannot merge EcmascriptDevChunkRuntime with different chunk groups",); + } + + match (&mut evaluated_entries, other_evaluated_entries) { + (Some(evaluated_entries), Some(other_evaluated_entries)) => { + evaluated_entries.extend(other_evaluated_entries.await?.iter().copied()); + } + (None, Some(other_evaluated_entries)) => { + evaluated_entries = Some(other_evaluated_entries.await?.clone_value()); + } + _ => {} + } + } + + Ok(EcmascriptDevChunkRuntime { + chunking_context, + chunk_group, + evaluated_entries: evaluated_entries.map(EcmascriptChunkPlaceablesVc::cell), + } + .cell() + .into()) + } +} diff --git a/crates/turbopack-dev/src/lib.rs b/crates/turbopack-dev/src/lib.rs index 7e40a164e1830..f18625f7a387d 100644 --- a/crates/turbopack-dev/src/lib.rs +++ b/crates/turbopack-dev/src/lib.rs @@ -5,16 +5,15 @@ pub(crate) mod chunking_context; pub(crate) mod css; pub(crate) mod ecmascript; -pub mod embed_js; pub mod react_refresh; pub use chunking_context::{DevChunkingContext, DevChunkingContextBuilder, DevChunkingContextVc}; -pub use ecmascript::chunk_data::{ChunkDataOptionVc, ChunkDataVc, ChunksDataVc}; pub fn register() { turbo_tasks::register(); turbo_tasks_fs::register(); turbopack_core::register(); turbopack_ecmascript::register(); + turbopack_ecmascript_runtime::register(); include!(concat!(env!("OUT_DIR"), "/register.rs")); } diff --git a/crates/turbopack-ecmascript-runtime/Cargo.toml b/crates/turbopack-ecmascript-runtime/Cargo.toml new file mode 100644 index 0000000000000..f8146c4d95660 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "turbopack-ecmascript-runtime" +version = "0.1.0" +description = "TBD" +license = "MPL-2.0" +edition = "2021" +autobenches = false + +[lib] +bench = false + +[features] +# enable "HMR" for embedded assets +dynamic_embed_contents = ["turbo-tasks-fs/dynamic_embed_contents"] +# enable test utilities such as `RuntimeType::Dummy` +test = [] + +[dependencies] +anyhow = { workspace = true } +indoc = { workspace = true } +serde = { workspace = true } + +turbo-tasks = { workspace = true } +turbo-tasks-fs = { workspace = true } +turbopack = { workspace = true } +turbopack-core = { workspace = true } +turbopack-ecmascript = { workspace = true } + +swc_core = { workspace = true } + +[build-dependencies] +turbo-tasks-build = { workspace = true } diff --git a/crates/turbopack-ecmascript-runtime/README.md b/crates/turbopack-ecmascript-runtime/README.md new file mode 100644 index 0000000000000..736d12f36368a --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/README.md @@ -0,0 +1,34 @@ +# turbopack-ecmascript-runtime + +This crate contains Turbopack's ECMAScript runtimes. These include: + +- Development runtimes for the browser, Node.js, and Edge-like runtimes; +- Production runtimes for the browser, Node.js, and Edge-like runtimes (only Node.js is implemented for now). + +## `` + +The TypeScript files corresponding to the runtime itself all use `` instead of `import`/`export` +to import dependencies. This is because the runtime doesn't use a module system. Instead, the files are concatenated +together in a specific order. + +As such, the `` statements more closely map to the way the runtime is actually built. They also +allow us to refer to top-level declarations in another file without having to `import`/`export` them, which makes no +sense in the context of a runtime. + +## Why is everything in one crate? + +The runtime-agnostic code (`js/src/shared`) was originally placed in `turbopack-ecmascript`, and the runtime-specific +code (`js/src/{build,dev}`) in `turbopack-{build,dev}`. + +However, `` statements only support relative paths. You can't refer to a file in a dependency. For +the typings to work properly, and for them to be usable from outside of this repo (e.g. in the Next.js repo), it's much +easier to have everything in one package. + +## Why so many `tsconfig.json`? + +Since different runtimes are meant to run in different environments, they use different `tsconfig.json` files to +customize what APIs are available to them. For example, the browser runtime can use `window` and `document`, but the +Node.js runtime can't. + +All of these `tsconfig.json` files extend `tsconfig.base.json`, which contains the common configuration for all +runtimes. diff --git a/crates/turbopack-ecmascript-runtime/build.rs b/crates/turbopack-ecmascript-runtime/build.rs new file mode 100644 index 0000000000000..1673efed59cce --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/build.rs @@ -0,0 +1,5 @@ +use turbo_tasks_build::generate_register; + +fn main() { + generate_register(); +} diff --git a/crates/turbopack-ecmascript-runtime/js/package.json b/crates/turbopack-ecmascript-runtime/js/package.json new file mode 100644 index 0000000000000..ec6d9a91e5b88 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/package.json @@ -0,0 +1,26 @@ +{ + "name": "@vercel/turbopack-ecmascript-runtime", + "version": "0.0.0", + "description": "Turbopack EcmaScript runtime code and utilities", + "license": "UNLICENSED", + "private": true, + "scripts": { + "check": "run-p check:*", + "check:build": "tsc -p src/build", + "check:dev-client": "tsc -p src/dev/client", + "check:dev-runtime-base": "tsc -p src/dev/runtime/base", + "check:dev-runtime-dom": "tsc -p src/dev/runtime/dom", + "check:dev-runtime-nodejs": "tsc -p src/dev/runtime/nodejs", + "check:dev-runtime-none": "tsc -p src/dev/runtime/none" + }, + "exports": { + "./*": "./src/*.ts" + }, + "dependencies": { + "@next/react-refresh-utils": "^13.0.6", + "@types/node": "^18.11.11" + }, + "devDependencies": { + "npm-run-all": "^4.1.5" + } +} diff --git a/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts b/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts new file mode 100644 index 0000000000000..37f87ce9ae31c --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts @@ -0,0 +1,252 @@ +/// + +declare var RUNTIME_PUBLIC_PATH: string; + +enum SourceType { + /** + * The module was instantiated because it was included in an evaluated chunk's + * runtime. + */ + Runtime = 0, + /** + * The module was instantiated because a parent module imported it. + */ + Parent = 1, +} + +type SourceInfo = + | { + type: SourceType.Runtime; + chunkPath: ChunkPath; + } + | { + type: SourceType.Parent; + parentId: ModuleId; + }; + +interface TurbopackNodeBuildContext { + e: Module["exports"]; + r: CommonJsRequire; + x: ExternalRequire; + f: RequireContextFactory; + i: EsmImport; + s: EsmExport; + j: typeof cjsExport; + v: ExportValue; + n: typeof exportNamespace; + m: Module; + c: ModuleCache; + l: LoadChunk; + g: typeof globalThis; + __dirname: string; +} + +type ModuleFactory = ( + this: Module["exports"], + context: TurbopackNodeBuildContext +) => undefined; + +const path = require("path"); +const relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, "."); +const RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot); + +const moduleFactories: ModuleFactories = Object.create(null); +const moduleCache: ModuleCache = Object.create(null); + +function externalRequire( + id: ModuleId, + esm: boolean = false +): Exports | EsmNamespaceObject { + let raw; + try { + raw = require(id); + } catch (err) { + // TODO(alexkirsz) This can happen when a client-side module tries to load + // an external module we don't provide a shim for (e.g. querystring, url). + // For now, we fail semi-silently, but in the future this should be a + // compilation error. + throw new Error(`Failed to load external module ${id}: ${err}`); + } + if (!esm || raw.__esModule) { + return raw; + } + const ns = {}; + interopEsm(raw, ns, true); + return ns; +} +externalRequire.resolve = ( + id: string, + options?: + | { + paths?: string[] | undefined; + } + | undefined +) => { + return require.resolve(id, options); +}; + +function loadChunk(chunkPath: ChunkPath) { + if (!chunkPath.endsWith(".js")) { + // We only support loading JS chunks in Node.js. + // This branch can be hit when trying to load a CSS chunk. + return; + } + + const path = require("path"); + const resolved = require.resolve(path.resolve(RUNTIME_ROOT, chunkPath)); + delete require.cache[resolved]; + const chunkModules: ModuleFactories = require(resolved); + + for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { + if (!moduleFactories[moduleId]) { + moduleFactories[moduleId] = moduleFactory; + } + } +} + +function loadChunkAsync(source: SourceInfo, chunkPath: string): Promise { + return new Promise((resolve, reject) => { + try { + loadChunk(chunkPath); + } catch (err) { + reject(err); + return; + } + resolve(); + }); +} + +function instantiateModule(id: ModuleId, source: SourceInfo): Module { + const moduleFactory = moduleFactories[id]; + if (typeof moduleFactory !== "function") { + // This can happen if modules incorrectly handle HMR disposes/updates, + // e.g. when they keep a `setTimeout` around which still executes old code + // and contains e.g. a `require("something")` call. + let instantiationReason; + switch (source.type) { + case SourceType.Runtime: + instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; + break; + case SourceType.Parent: + instantiationReason = `because it was required from module ${source.parentId}`; + break; + } + throw new Error( + `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` + ); + } + + let parents: ModuleId[]; + switch (source.type) { + case SourceType.Runtime: + parents = []; + break; + case SourceType.Parent: + // No need to add this module as a child of the parent module here, this + // has already been taken care of in `getOrInstantiateModuleFromParent`. + parents = [source.parentId]; + break; + } + + const module: Module = { + exports: {}, + error: undefined, + loaded: false, + id, + parents, + children: [], + namespaceObject: undefined, + }; + moduleCache[id] = module; + + // NOTE(alexkirsz) This can fail when the module encounters a runtime error. + try { + moduleFactory.call(module.exports, { + e: module.exports, + r: commonJsRequire.bind(null, module), + x: externalRequire, + f: requireContext.bind(null, module), + i: esmImport.bind(null, module), + s: esm.bind(null, module.exports), + j: cjsExport.bind(null, module.exports), + v: exportValue.bind(null, module), + n: exportNamespace.bind(null, module), + m: module, + c: moduleCache, + l: loadChunkAsync.bind(null, { type: SourceType.Parent, parentId: id }), + g: globalThis, + __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), + }); + } catch (error) { + module.error = error as any; + throw error; + } + + module.loaded = true; + if (module.namespaceObject) { + // in case of a circular dependency: cjs1 -> esm2 -> cjs1 + interopEsm(module.exports, module.namespaceObject); + } + + return module; +} + +/** + * Retrieves a module from the cache, or instantiate it if it is not cached. + */ +function getOrInstantiateModuleFromParent( + id: ModuleId, + sourceModule: Module +): Module { + const module = moduleCache[id]; + + if (sourceModule.children.indexOf(id) === -1) { + sourceModule.children.push(id); + } + + if (module) { + if (module.parents.indexOf(sourceModule.id) === -1) { + module.parents.push(sourceModule.id); + } + + return module; + } + + return instantiateModule(id, { + type: SourceType.Parent, + parentId: sourceModule.id, + }); +} + +/** + * Instantiates a runtime module. + */ +function instantiateRuntimeModule( + moduleId: ModuleId, + chunkPath: ChunkPath +): Module { + return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath }); +} + +/** + * Retrieves a module from the cache, or instantiate it as a runtime module if it is not cached. + */ +function getOrInstantiateRuntimeModule( + moduleId: ModuleId, + chunkPath: ChunkPath +): Module { + const module = moduleCache[moduleId]; + if (module) { + if (module.error) { + throw module.error; + } + return module; + } + + return instantiateRuntimeModule(moduleId, chunkPath); +} + +module.exports = { + getOrInstantiateRuntimeModule, + loadChunk, +}; diff --git a/crates/turbopack-ecmascript-runtime/js/src/build/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/src/build/tsconfig.json new file mode 100644 index 0000000000000..7334dd71e4928 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/build/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + // environment + "lib": ["ESNext"], + "types": ["node"] + }, + "include": ["*.ts"] +} \ No newline at end of file diff --git a/crates/turbopack-dev/js/src/client/hmr-client.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/client/hmr-client.ts similarity index 97% rename from crates/turbopack-dev/js/src/client/hmr-client.ts rename to crates/turbopack-ecmascript-runtime/js/src/dev/client/hmr-client.ts index 1d08fc42dc38f..27539f5669ecf 100644 --- a/crates/turbopack-dev/js/src/client/hmr-client.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/client/hmr-client.ts @@ -1,25 +1,10 @@ -import type { - ChunkListUpdate, - ChunkUpdate, - ClientMessage, - EcmascriptMergedChunkUpdate, - EcmascriptMergedUpdate, - EcmascriptModuleEntry, - Issue, - ResourceIdentifier, - ServerMessage, -} from "../../types/protocol"; -import type { - ChunkPath, - ModuleId, - UpdateCallback, - TurbopackGlobals, -} from "../../types"; +/// +/// +/// +/// import { addEventListener, sendMessage } from "./websocket"; -declare var globalThis: TurbopackGlobals; - export type ClientOptions = { assetPrefix: string; }; diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/client/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/src/dev/client/tsconfig.json new file mode 100644 index 0000000000000..7d9bdb5f2acf6 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/client/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + // environment + "lib": ["ESNext", "DOM"], + "target": "esnext" + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-dev/js/src/client/websocket.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/client/websocket.ts similarity index 100% rename from crates/turbopack-dev/js/src/client/websocket.ts rename to crates/turbopack-ecmascript-runtime/js/src/dev/client/websocket.ts diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts new file mode 100644 index 0000000000000..942a535df01bb --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts @@ -0,0 +1,9 @@ +/** + * This file acts as a dummy implementor for the interface that + * `runtime-base.ts` expects to be available in the global scope. + * + * This interface will be implemented by runtime backends. + */ + +declare var BACKEND: RuntimeBackend; +declare var _eval: (code: EcmascriptModuleEntry) => any; diff --git a/crates/turbopack-dev/js/types/hot.d.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/extensions.d.ts similarity index 67% rename from crates/turbopack-dev/js/types/hot.d.ts rename to crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/extensions.d.ts index cefa70406da6b..a4eb01fa5d7fa 100644 --- a/crates/turbopack-dev/js/types/hot.d.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/extensions.d.ts @@ -1,29 +1,36 @@ -import { Exports, ModuleId } from "./index"; +/** + * Extensions to the shared runtime types that are specific to the development + * runtime (e.g. `module.hot`). + */ -export const enum HotUpdateStatus { +interface RequireContextEntry { + internal: boolean; +} + +declare const enum HotUpdateStatus { idle = "idle", } -export type HotUpdateStatusHandler = (status: HotUpdateStatus) => void; +type HotUpdateStatusHandler = (status: HotUpdateStatus) => void; -export interface HotData { +interface HotData { prevExports?: Exports; } -export interface HotState { +interface HotState { selfAccepted: boolean | Function; selfDeclined: boolean; selfInvalidated: boolean; disposeHandlers: ((data: object) => void)[]; } -export type AcceptErrorHandler = ( +type AcceptErrorHandler = ( err: Error, context: { moduleId: ModuleId; dependencyId: string | number } ) => void; -export type AcceptCallback = (outdatedDependencies: string[]) => void; +type AcceptCallback = (outdatedDependencies: string[]) => void; -export interface AcceptFunction { +interface AcceptFunction { // accept updates for self (errorHandler?: AcceptErrorHandler): void; @@ -35,7 +42,7 @@ export interface AcceptFunction { ): void; } -export interface Hot { +interface Hot { active: boolean; data: HotData; @@ -55,3 +62,7 @@ export interface Hot { addStatusHandler: (handler: HotUpdateStatusHandler) => void; removeStatusHandler: (handler: HotUpdateStatusHandler) => void; } + +interface Module { + hot: Hot; +} diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/globals.d.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/globals.d.ts new file mode 100644 index 0000000000000..eae4e2323ee6c --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/globals.d.ts @@ -0,0 +1,30 @@ +/** + * Definitions for globals that are injected by the Turbopack runtime. + * + * These are available from every module, but should only be used by Turbopack + * code, not by user code. + */ + +type UpdateCallback = (update: ServerMessage) => void; + +type ChunkRegistry = { + push: (registration: ChunkRegistration) => void; +}; + +type ChunkListProvider = { + push: (registration: ChunkList) => void; +}; + +type ChunkUpdateProvider = { + push: (registration: [ChunkPath, UpdateCallback]) => void; +}; + +declare var TURBOPACK: ChunkRegistry | ChunkRegistration[] | undefined; +declare var TURBOPACK_CHUNK_LISTS: ChunkListProvider | ChunkList[] | undefined; +declare var TURBOPACK_CHUNK_UPDATE_LISTENERS: + | ChunkUpdateProvider + | [ChunkPath, UpdateCallback][] + | undefined; +// This is used by the Next.js integration test suite to notify it when HMR +// updates have been completed. +declare var __NEXT_HMR_CB: undefined | null | (() => void); diff --git a/crates/turbopack-dev/js/types/protocol.d.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/protocol.d.ts similarity index 75% rename from crates/turbopack-dev/js/types/protocol.d.ts rename to crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/protocol.d.ts index b269a2341833f..7e3103ca37063 100644 --- a/crates/turbopack-dev/js/types/protocol.d.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/protocol.d.ts @@ -1,6 +1,9 @@ -import { ChunkPath, ModuleFactoryString, ModuleId } from "./index"; +/** + * Definitions for the protocol that is used to communicate between the + * Turbopack runtime and the Turbopack server for issue reporting and HMR. + */ -export type ServerMessage = { +type ServerMessage = { resource: ResourceIdentifier; issues: Issue[]; } & ( @@ -24,19 +27,19 @@ type UnknownType = { type: "future-type-marker-do-not-use-or-you-will-be-fired"; }; -export type PartialUpdate = +type PartialUpdate = | ChunkListUpdate | { type: never; }; -export type ChunkListUpdate = { +type ChunkListUpdate = { type: "ChunkListUpdate"; chunks?: Record; merged?: MergedChunkUpdate[]; }; -export type ChunkUpdate = +type ChunkUpdate = | { type: "added"; } @@ -46,19 +49,19 @@ export type ChunkUpdate = // be merged either. So these updates would go into `MergedChunkUpdate` instead. | { type: "partial"; instruction: never }; -export type MergedChunkUpdate = +type MergedChunkUpdate = | EcmascriptMergedUpdate | { type: never; }; -export type EcmascriptMergedUpdate = { +type EcmascriptMergedUpdate = { type: "EcmascriptMergedUpdate"; entries?: Record; chunks?: Record; }; -export type EcmascriptMergedChunkUpdate = +type EcmascriptMergedChunkUpdate = | { type: "added"; modules?: ModuleId[]; @@ -76,7 +79,7 @@ export type EcmascriptMergedChunkUpdate = type: never; }; -export type EcmascriptModuleEntry = { +type EcmascriptModuleEntry = { code: ModuleFactoryString; url: string; map?: string; @@ -87,17 +90,17 @@ type ResourceIdentifier = { headers?: { [string]: string }; }; -export type ClientMessageSubscribe = { +type ClientMessageSubscribe = { type: "subscribe"; } & ResourceIdentifier; -export type ClientMessageUnsubscribe = { +type ClientMessageUnsubscribe = { type: "unsubscribe"; } & ResourceIdentifier; -export type ClientMessage = ClientMessageSubscribe | ClientMessageUnsubscribe; +type ClientMessage = ClientMessageSubscribe | ClientMessageUnsubscribe; -export type IssueSeverity = +type IssueSeverity = | "bug" | "fatal" | "error" @@ -107,22 +110,22 @@ export type IssueSeverity = | "suggestion" | "info"; -export type IssueAsset = { +type IssueAsset = { path: string; }; -export type SourcePos = { +type SourcePos = { line: number; column: number; }; -export type IssueSource = { +type IssueSource = { asset: IssueAsset; start: SourcePos; end: SourcePos; }; -export type Issue = { +type Issue = { severity: IssueSeverity; context: string; category: string; diff --git a/crates/turbopack-dev/js/src/runtime.js b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/runtime-base.ts similarity index 63% rename from crates/turbopack-dev/js/src/runtime.js rename to crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/runtime-base.ts index e322c55b3db85..76dfc8575dabc 100644 --- a/crates/turbopack-dev/js/src/runtime.js +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/runtime-base.ts @@ -1,286 +1,187 @@ +/** + * This file contains runtime types and functions that are shared between all + * Turbopack *development* ECMAScript runtimes. + * + * It will be appended to the runtime code of each runtime right after the + * shared runtime utils. + */ + /* eslint-disable @next/next/no-assign-module-variable */ -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; +/// +/// +/// +/// + +// This file must not use `import` and `export` statements. Otherwise, it +// becomes impossible to augment interfaces declared in ``d files +// (e.g. `Module`). Hence the need for `import()` here. +type RefreshRuntimeGlobals = + import("@next/react-refresh-utils/dist/runtime").RefreshRuntimeGlobals; + +declare var $RefreshHelpers$: RefreshRuntimeGlobals["$RefreshHelpers$"]; +declare var $RefreshReg$: RefreshRuntimeGlobals["$RefreshReg$"]; +declare var $RefreshSig$: RefreshRuntimeGlobals["$RefreshSig$"]; +declare var $RefreshInterceptModuleExecution$: + | RefreshRuntimeGlobals["$RefreshInterceptModuleExecution$"]; + +type RefreshContext = { + register: RefreshRuntimeGlobals["$RefreshReg$"]; + signature: RefreshRuntimeGlobals["$RefreshSig$"]; +}; + +// @next/react-refresh-utils/internal/helpers +type RefreshHelpers = { + registerExportsForReactRefresh( + moduleExports: unknown, + moduleID: string + ): void; + getRefreshBoundarySignature(moduleExports: unknown): Array; + isReactRefreshBoundary(moduleExports: unknown): boolean; + shouldInvalidateReactRefreshBoundary( + prevExports: unknown, + nextExports: unknown + ): boolean; + scheduleUpdate(): void; +}; + +interface TurbopackDevContext { + e: Module["exports"]; + r: CommonJsRequire; + x: ExternalRequire; + f: RequireContextFactory; + i: EsmImport; + s: EsmExport; + j: typeof cjsExport; + v: ExportValue; + n: typeof exportNamespace; + m: Module; + c: ModuleCache; + l: LoadChunk; + g: typeof globalThis; + k: RefreshContext; + __dirname: string; +} + +// string encoding of a module factory (used in hmr updates) +type ModuleFactoryString = string; + +type ModuleFactory = ( + this: Module["exports"], + context: TurbopackDevContext +) => undefined; + +type DevRuntimeParams = { + otherChunks: ChunkData[]; + runtimeModuleIds: ModuleId[]; +}; + +type ChunkRegistration = [ + chunkPath: ChunkPath, + chunkModules: ModuleFactories, + params: DevRuntimeParams | undefined +]; +type ChunkList = { + path: ChunkPath; + chunks: ChunkData[]; + source: "entry" | "dynamic"; +}; + +enum SourceType { + /** + * The module was instantiated because it was included in an evaluated chunk's + * runtime. + */ + Runtime = 0, + /** + * The module was instantiated because a parent module imported it. + */ + Parent = 1, + /** + * The module was instantiated because it was included in a chunk's hot module + * update. + */ + Update = 2, +} + +type SourceInfo = + | { + type: SourceType.Runtime; + chunkPath: ChunkPath; + } + | { + type: SourceType.Parent; + parentId: ModuleId; + } + | { + type: SourceType.Update; + parents?: ModuleId[]; + }; + +interface RuntimeBackend { + registerChunk: (chunkPath: ChunkPath, params?: DevRuntimeParams) => void; + loadChunk: (chunkPath: ChunkPath, source: SourceInfo) => Promise; + reloadChunk?: (chunkPath: ChunkPath) => Promise; + unloadChunk?: (chunkPath: ChunkPath) => void; + + restart: () => void; +} + +const moduleFactories: ModuleFactories = Object.create(null); +const moduleCache: ModuleCache = Object.create(null); /** * Maps module IDs to persisted data between executions of their hot module * implementation (`hot.data`). - * - * @type {Map} */ -const moduleHotData = new Map(); +const moduleHotData: Map = new Map(); /** * Maps module instances to their hot module state. - * - * @type {Map} */ -const moduleHotState = new Map(); +const moduleHotState: Map = new Map(); /** * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} */ -const runtimeModules = new Set(); +const runtimeModules: Set = new Set(); /** * Map from module ID to the chunks that contain this module. * * In HMR, we need to keep track of which modules are contained in which so * chunks. This is so we don't eagerly dispose of a module when it is removed * from chunk A, but still exists in chunk B. - * - * @type {Map>} */ -const moduleChunksMap = new Map(); +const moduleChunksMap: Map> = new Map(); /** * Map from chunk path to all modules it contains. - * @type {Map>} */ -const chunkModulesMap = new Map(); +const chunkModulesMap: Map> = new Map(); /** * Chunk lists that contain a runtime. When these chunk lists receive an update * that can't be reconciled with the current state of the page, we need to * reload the runtime entirely. - * @type {Set} */ -const runtimeChunkLists = new Set(); +const runtimeChunkLists: Set = new Set(); /** * Map from chunk list to the chunk paths it contains. - * @type {Map>} */ -const chunkListChunksMap = new Map(); +const chunkListChunksMap: Map> = new Map(); /** * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} +const chunkChunkListsMap: Map> = new Map(); + +const commonJsRequireContext: CommonJsRequireContext = ( + entry, + sourceModule +) => { + return entry.internal + ? commonJsRequire(sourceModule, entry.id()) + : externalRequire(entry.id(), false); +}; -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { +function externalRequire( + id: ModuleId, + esm: boolean = false +): Exports | EsmNamespaceObject { let raw; try { raw = require(id); @@ -298,22 +199,25 @@ function externalRequire(id, esm) { interopEsm(raw, ns, raw.__esModule); return ns; } -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); +externalRequire.resolve = ( + id: string, + options?: + | { + paths?: string[] | undefined; + } + | undefined +) => { + return require.resolve(id, options); }; -/** @type {Map | true>} */ -const availableModules = new Map(); +const availableModules: Map | true> = new Map(); -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); +const availableModuleChunks: Map | true> = new Map(); -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { +async function loadChunk( + source: SourceInfo, + chunkData: ChunkData +): Promise { if (typeof chunkData === "string") { return loadChunkPath(source, chunkData); } @@ -346,7 +250,7 @@ async function loadChunk(source, chunkData) { return Promise.all(moduleChunksPromises); } - const moduleChunksToLoad = new Set(); + const moduleChunksToLoad: Set = new Set(); for (const moduleChunk of includedModuleChunksList) { if (!availableModuleChunks.has(moduleChunk)) { moduleChunksToLoad.add(moduleChunk); @@ -384,24 +288,22 @@ async function loadChunk(source, chunkData) { return promise; } -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { +async function loadChunkPath( + source: SourceInfo, + chunkPath: ChunkPath +): Promise { try { await BACKEND.loadChunk(chunkPath, source); } catch (error) { let loadReason; switch (source.type) { - case SourceTypeRuntime: + case SourceType.Runtime: loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; break; - case SourceTypeParent: + case SourceType.Parent: loadReason = `from module ${source.parentId}`; break; - case SourceTypeUpdate: + case SourceType.Update: loadReason = "from an HMR update"; break; } @@ -413,21 +315,7 @@ async function loadChunkPath(source, chunkPath) { } } -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ +function instantiateModule(id: ModuleId, source: SourceInfo): Module { const moduleFactory = moduleFactories[id]; if (typeof moduleFactory !== "function") { // This can happen if modules incorrectly handle HMR disposes/updates, @@ -435,13 +323,13 @@ function instantiateModule(id, source) { // and contains e.g. a `require("something")` call. let instantiationReason; switch (source.type) { - case SourceTypeRuntime: + case SourceType.Runtime: instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; break; - case SourceTypeParent: + case SourceType.Parent: instantiationReason = `because it was required from module ${source.parentId}`; break; - case SourceTypeUpdate: + case SourceType.Update: instantiationReason = "because of an HMR update"; break; } @@ -450,38 +338,38 @@ function instantiateModule(id, source) { ); } - const hotData = moduleHotData.get(id); + const hotData = moduleHotData.get(id)!; const { hot, hotState } = createModuleHot(hotData); - /** @type {Module} */ - const module = { + let parents: ModuleId[]; + switch (source.type) { + case SourceType.Runtime: + runtimeModules.add(id); + parents = []; + break; + case SourceType.Parent: + // No need to add this module as a child of the parent module here, this + // has already been taken care of in `getOrInstantiateModuleFromParent`. + parents = [source.parentId]; + break; + case SourceType.Update: + parents = source.parents || []; + break; + } + const module: Module = { exports: {}, error: undefined, loaded: false, id, - parents: undefined, + parents, children: [], namespaceObject: undefined, hot, }; + moduleCache[id] = module; moduleHotState.set(module, hotState); - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. try { runModuleExecutionHooks(module, (refresh) => { @@ -491,20 +379,20 @@ function instantiateModule(id, source) { x: externalRequire, f: requireContext.bind(null, module), i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), + s: esmExport.bind(null, module), + j: cjsExport.bind(null, module.exports), v: exportValue.bind(null, module), n: exportNamespace.bind(null, module), m: module, c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), + l: loadChunk.bind(null, { type: SourceType.Parent, parentId: id }), g: globalThis, k: refresh, __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), }); }); } catch (error) { - module.error = error; + module.error = error as any; throw error; } @@ -521,11 +409,11 @@ function instantiateModule(id, source) { * NOTE(alexkirsz) Webpack has an "module execution" interception hook that * Next.js' React Refresh runtime hooks into to add module context to the * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule */ -function runModuleExecutionHooks(module, executeModule) { +function runModuleExecutionHooks( + module: Module, + executeModule: (ctx: RefreshContext) => void +) { const cleanupReactRefreshIntercept = typeof globalThis.$RefreshInterceptModuleExecution$ === "function" ? globalThis.$RefreshInterceptModuleExecution$(module.id) @@ -555,12 +443,11 @@ function runModuleExecutionHooks(module, executeModule) { /** * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} */ -function getOrInstantiateModuleFromParent(id, sourceModule) { +const getOrInstantiateModuleFromParent: GetOrInstantiateModuleFromParent = ( + id, + sourceModule +) => { if (!sourceModule.hot.active) { console.warn( `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` @@ -582,18 +469,18 @@ function getOrInstantiateModuleFromParent(id, sourceModule) { } return instantiateModule(id, { - type: SourceTypeParent, + type: SourceType.Parent, parentId: sourceModule.id, }); -} +}; /** * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { +function registerExportsAndSetupBoundaryForReactRefresh( + module: Module, + helpers: RefreshHelpers +) { const currentExports = module.exports; const prevExports = module.hot.data.prevExports ?? null; @@ -645,31 +532,14 @@ function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { } } -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { +function formatDependencyChain(dependencyChain: ModuleId[]): string { return `Dependency chain: ${dependencyChain.join(" -> ")}`; } -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { +function computeOutdatedModules( + added: Map, + modified: Map +): { outdatedModules: Set; newModuleFactories: Map } { const outdatedModules = new Set(); const newModuleFactories = new Map(); @@ -708,15 +578,13 @@ function computeOutdatedModules(added, modified) { return { outdatedModules, newModuleFactories }; } -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { +function computeOutdatedSelfAcceptedModules( + outdatedModules: Iterable +): { moduleId: ModuleId; errorHandler: true | Function }[] { const outdatedSelfAcceptedModules = []; for (const moduleId of outdatedModules) { const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); + const hotState = moduleHotState.get(module)!; if (module && hotState.selfAccepted && !hotState.selfInvalidated) { outdatedSelfAcceptedModules.push({ moduleId, @@ -731,19 +599,18 @@ function computeOutdatedSelfAcceptedModules(outdatedModules) { * Adds, deletes, and moves modules between chunks. This must happen before the * dispose phase as it needs to know which modules were removed from all chunks, * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { +function updateChunksPhase( + chunksAddedModules: Map>, + chunksDeletedModules: Map> +): { disposedModules: Set } { for (const [chunkPath, addedModuleIds] of chunksAddedModules) { for (const moduleId of addedModuleIds) { addModuleToChunk(moduleId, chunkPath); } } - const disposedModules = new Set(); + const disposedModules: Set = new Set(); for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { for (const moduleId of addedModuleIds) { if (removeModuleFromChunk(moduleId, chunkPath)) { @@ -755,12 +622,10 @@ function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { return { disposedModules }; } -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { +function disposePhase( + outdatedModules: Iterable, + disposedModules: Set +): { outdatedModuleParents: Map> } { for (const moduleId of outdatedModules) { disposeModule(moduleId, "replace"); } @@ -796,17 +661,14 @@ function disposePhase(outdatedModules, disposedModules) { * parent/child relationships before they are actually removed from the moduleCache. * If this would be done in this method, following disposeModulecalls won't find * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode */ -function disposeModule(moduleId, mode) { +function disposeModule(moduleId: ModuleId, mode: "clear" | "replace") { const module = moduleCache[moduleId]; if (!module) { return; } - const hotState = moduleHotState.get(module); + const hotState = moduleHotState.get(module)!; const data = {}; // Run the `hot.dispose` handler, if any, passing in the persistent @@ -851,16 +713,13 @@ function disposeModule(moduleId, mode) { } } -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents + outdatedSelfAcceptedModules: { + moduleId: ModuleId; + errorHandler: true | Function; + }[], + newModuleFactories: Map, + outdatedModuleParents: Map> ) { // Update module factories. for (const [moduleId, factory] of newModuleFactories.entries()) { @@ -875,7 +734,7 @@ function applyPhase( for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { try { instantiateModule(moduleId, { - type: SourceTypeUpdate, + type: SourceType.Update, parents: outdatedModuleParents.get(moduleId), }); } catch (err) { @@ -892,20 +751,12 @@ function applyPhase( /** * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} */ -function invariant(never, computeMessage) { +function invariant(never: never, computeMessage: (arg: any) => string): never { throw new Error(`Invariant: ${computeMessage(never)}`); } -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { +function applyUpdate(chunkListPath: ChunkPath, update: PartialUpdate) { switch (update.type) { case "ChunkListUpdate": applyChunkListUpdate(chunkListPath, update); @@ -915,12 +766,10 @@ function applyUpdate(chunkListPath, update) { } } -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { +function applyChunkListUpdate( + chunkListPath: ChunkPath, + update: ChunkListUpdate +) { if (update.merged != null) { for (const merged of update.merged) { switch (merged.type) { @@ -937,7 +786,7 @@ function applyChunkListUpdate(chunkListPath, update) { for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { switch (chunkUpdate.type) { case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); + BACKEND.loadChunk(chunkPath, { type: SourceType.Update }); break; case "total": BACKEND.reloadChunk?.(chunkPath); @@ -961,11 +810,10 @@ function applyChunkListUpdate(chunkListPath, update) { } } -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { +function applyEcmascriptMergedUpdate( + chunkPath: ChunkPath, + update: EcmascriptMergedUpdate +) { const { entries = {}, chunks = {} } = update; const { added, modified, deleted, chunksAdded, chunksDeleted } = computeChangedModules(entries, chunks); @@ -987,23 +835,21 @@ function applyEcmascriptMergedUpdate(chunkPath, update) { ); } -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { +function computeChangedModules( + entries: Record, + updates: Record +): { + added: Map; + modified: Map; + deleted: Set; + chunksAdded: Map>; + chunksDeleted: Map>; +} { const chunksAdded = new Map(); const chunksDeleted = new Map(); - const added = new Map(); + const added: Map = new Map(); const modified = new Map(); - const deleted = new Set(); + const deleted: Set = new Set(); for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { switch (mergedChunkUpdate.type) { @@ -1031,7 +877,7 @@ function computeChangedModules(entries, updates) { added.set(moduleId, entries[moduleId]); } for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); + deleted.add(moduleId); } chunksAdded.set(chunkPath, updateAdded); chunksDeleted.set(chunkPath, updateDeleted); @@ -1069,28 +915,41 @@ function computeChangedModules(entries, updates) { return { added, deleted, modified, chunksAdded, chunksDeleted }; } -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); +type ModuleEffect = + | { + type: "unaccepted"; + dependencyChain: ModuleId[]; + } + | { + type: "self-declined"; + dependencyChain: ModuleId[]; + moduleId: ModuleId; + } + | { + type: "accepted"; + moduleId: ModuleId; + outdatedModules: Set; + }; - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ +function getAffectedModuleEffects(moduleId: ModuleId): ModuleEffect { + const outdatedModules: Set = new Set(); - /** @type {QueueItem[]} */ - const queue = [ + type QueueItem = { moduleId?: ModuleId; dependencyChain: ModuleId[] }; + + const queue: QueueItem[] = [ { moduleId, dependencyChain: [], }, ]; - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); + let nextItem; + while ((nextItem = queue.shift())) { + const { moduleId, dependencyChain } = nextItem; + + if (moduleId != null) { + outdatedModules.add(moduleId); + } // We've arrived at the runtime of the chunk, which means that nothing // else above can accept this update. @@ -1102,7 +961,7 @@ function getAffectedModuleEffects(moduleId) { } const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); + const hotState = moduleHotState.get(module)!; if ( // The module is not in the cache. Since this is a "modified" update, @@ -1155,11 +1014,7 @@ function getAffectedModuleEffects(moduleId) { }; } -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { +function handleApply(chunkListPath: ChunkPath, update: ServerMessage) { switch (update.type) { case "partial": { // This indicates that the update is can be applied to the current state of the application. @@ -1190,38 +1045,15 @@ function handleApply(chunkListPath, update) { } } -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { +function createModuleHot(hotData: HotData): { hot: Hot; hotState: HotState } { + const hotState: HotState = { selfAccepted: false, selfDeclined: false, selfInvalidated: false, disposeHandlers: [], }; - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { + const hot: Hot = { // TODO(alexkirsz) This is not defined in the HMR API. It was used to // decide whether to warn whenever an HMR-disposed module required other // modules. We might want to remove it. @@ -1229,7 +1061,20 @@ function createModuleHot(hotData) { data: hotData ?? {}, - accept: accept, + // TODO(alexkirsz) Support full (dep, callback, errorHandler) form. + accept: ( + modules?: string | string[] | AcceptErrorHandler, + _callback?: AcceptCallback, + _errorHandler?: AcceptErrorHandler + ) => { + if (modules === undefined) { + hotState.selfAccepted = true; + } else if (typeof modules === "function") { + hotState.selfAccepted = modules; + } else { + throw new Error("unsupported `accept` signature"); + } + }, decline: (dep) => { if (dep === undefined) { @@ -1275,11 +1120,8 @@ function createModuleHot(hotData) { /** * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath */ -function addModuleToChunk(moduleId, chunkPath) { +function addModuleToChunk(moduleId: ModuleId, chunkPath: ChunkPath) { let moduleChunks = moduleChunksMap.get(moduleId); if (!moduleChunks) { moduleChunks = new Set([chunkPath]); @@ -1301,10 +1143,8 @@ function addModuleToChunk(moduleId, chunkPath) { * Returns the first chunk that included a module. * This is used by the Node.js backend, hence why it's marked as unused in this * file. - * - * @type {GetFirstModuleChunk} */ -function getFirstModuleChunk(moduleId) { +function getFirstModuleChunk(moduleId: ModuleId) { const moduleChunkPaths = moduleChunksMap.get(moduleId); if (moduleChunkPaths == null) { return null; @@ -1316,16 +1156,15 @@ function getFirstModuleChunk(moduleId) { /** * Removes a module from a chunk. Returns true there are no remaining chunks * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); +function removeModuleFromChunk( + moduleId: ModuleId, + chunkPath: ChunkPath +): boolean { + const moduleChunks = moduleChunksMap.get(moduleId)!; moduleChunks.delete(chunkPath); - const chunkModules = chunkModulesMap.get(chunkPath); + const chunkModules = chunkModulesMap.get(chunkPath)!; chunkModules.delete(moduleId); const noRemainingModules = chunkModules.size === 0; @@ -1343,11 +1182,8 @@ function removeModuleFromChunk(moduleId, chunkPath) { /** * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. */ -function disposeChunkList(chunkListPath) { +function disposeChunkList(chunkListPath: ChunkPath): boolean { const chunkPaths = chunkListChunksMap.get(chunkListPath); if (chunkPaths == null) { return false; @@ -1355,7 +1191,7 @@ function disposeChunkList(chunkListPath) { chunkListChunksMap.delete(chunkListPath); for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); + const chunkChunkLists = chunkChunkListsMap.get(chunkPath)!; chunkChunkLists.delete(chunkListPath); if (chunkChunkLists.size === 0) { @@ -1366,7 +1202,7 @@ function disposeChunkList(chunkListPath) { // We must also dispose of the chunk list's chunk itself to ensure it may // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); + BACKEND.unloadChunk?.(chunkListPath); return true; } @@ -1374,13 +1210,12 @@ function disposeChunkList(chunkListPath) { /** * Disposes of a chunk and its corresponding exclusive modules. * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. + * @returns Whether the chunk was disposed of. */ -function disposeChunk(chunkPath) { +function disposeChunk(chunkPath: ChunkPath): boolean { // This should happen whether or not the chunk has any modules in it. For instance, // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); + BACKEND.unloadChunk?.(chunkPath); const chunkModules = chunkModulesMap.get(chunkPath); if (chunkModules == null) { @@ -1389,7 +1224,7 @@ function disposeChunk(chunkPath) { chunkModules.delete(chunkPath); for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); + const moduleChunks = moduleChunksMap.get(moduleId)!; moduleChunks.delete(chunkPath); const noRemainingChunks = moduleChunks.size === 0; @@ -1405,23 +1240,21 @@ function disposeChunk(chunkPath) { /** * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); +function instantiateRuntimeModule( + moduleId: ModuleId, + chunkPath: ChunkPath +): Module { + return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath }); } /** * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { +function getOrInstantiateRuntimeModule( + moduleId: ModuleId, + chunkPath: ChunkPath +): Module { const module = moduleCache[moduleId]; if (module) { if (module.error) { @@ -1430,26 +1263,17 @@ function getOrInstantiateRuntimeModule(moduleId, chunkPath) { return module; } - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; + return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath }); } /** * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ +function registerChunkList( + chunkUpdateProvider: ChunkUpdateProvider, + chunkList: ChunkList +) { + chunkUpdateProvider.push([ chunkList.path, handleApply.bind(null, chunkList.path), ]); @@ -1476,17 +1300,16 @@ function registerChunkList(chunkList) { * Marks a chunk list as a runtime chunk list. There can be more than one * runtime chunk list. For instance, integration tests can have multiple chunk * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath */ -function markChunkListAsRuntime(chunkListPath) { +function markChunkListAsRuntime(chunkListPath: ChunkPath) { runtimeChunkLists.add(chunkListPath); } -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { +function registerChunk([ + chunkPath, + chunkModules, + runtimeParams, +]: ChunkRegistration) { for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { if (!moduleFactories[moduleId]) { moduleFactories[moduleId] = moduleFactory; @@ -1497,18 +1320,17 @@ function registerChunk([chunkPath, chunkModules, runtimeParams]) { return BACKEND.registerChunk(chunkPath, runtimeParams); } -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; +globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS ??= []; -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); +const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS; +if (Array.isArray(chunkListsToRegister)) { + for (const chunkList of chunkListsToRegister) { + registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS, chunkList); + } } + globalThis.TURBOPACK_CHUNK_LISTS = { push: (chunkList) => { - registerChunkList(chunkList); + registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS!, chunkList); }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; +} satisfies ChunkListProvider; diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/tsconfig.json new file mode 100644 index 0000000000000..df2abe0a4dfab --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + // environment + "lib": ["ESNext"], + "target": "ESNext" + }, + "include": ["runtime-base.ts", "dummy.ts"] +} diff --git a/crates/turbopack-dev/js/src/runtime.dom.js b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/runtime-backend-dom.ts similarity index 79% rename from crates/turbopack-dev/js/src/runtime.dom.js rename to crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/runtime-backend-dom.ts index 12e8f5a286ae0..2fba6341a31c4 100644 --- a/crates/turbopack-dev/js/src/runtime.dom.js +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/runtime-backend-dom.ts @@ -1,10 +1,20 @@ -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ +/** + * This file contains the runtime code specific to the Turbopack development + * ECMAScript DOM runtime. + * + * It will be appended to the base development runtime code. + */ -/** @type {RuntimeBackend} */ -let BACKEND; +/// + +type ChunkResolver = { + resolved: boolean; + resolve: () => void; + reject: (error?: Error) => void; + promise: Promise; +}; + +let BACKEND: RuntimeBackend; (() => { BACKEND = { @@ -25,7 +35,7 @@ let BACKEND; // This waits for chunks to be loaded, but also marks included items as available. await Promise.all( params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) + loadChunk({ type: SourceType.Runtime, chunkPath }, otherChunkData) ) ); @@ -65,7 +75,7 @@ let BACKEND; }, reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { if (!chunkPath.endsWith(".css")) { reject(new Error("The DOM backend can only reload CSS chunks")); return; @@ -104,7 +114,10 @@ let BACKEND; // Make sure to insert the new CSS right after the previous one, so that // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); + previousLink.parentElement!.insertBefore( + link, + previousLink.nextSibling + ); }); }, @@ -113,21 +126,15 @@ let BACKEND; /** * Maps chunk paths to the corresponding resolver. - * - * @type {Map} */ - const chunkResolvers = new Map(); + const chunkResolvers: Map = new Map(); - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { + function getOrCreateResolver(chunkPath: ChunkPath): ChunkResolver { let resolver = chunkResolvers.get(chunkPath); if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { + let resolve: () => void; + let reject: (error?: Error) => void; + const promise = new Promise((innerResolve, innerReject) => { resolve = innerResolve; reject = innerReject; }); @@ -135,34 +142,31 @@ let BACKEND; resolved: false, promise, resolve: () => { - resolver.resolved = true; + resolver!.resolved = true; resolve(); }, - reject, + reject: reject!, }; chunkResolvers.set(chunkPath, resolver); } return resolver; } - function deleteResolver(chunkPath) { + function deleteResolver(chunkPath: ChunkPath) { chunkResolvers.delete(chunkPath); } /** * Loads the given chunk, and returns a promise that resolves once the chunk * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source */ - async function doLoadChunk(chunkPath, source) { + async function doLoadChunk(chunkPath: ChunkPath, source: SourceInfo) { const resolver = getOrCreateResolver(chunkPath); if (resolver.resolved) { return resolver.promise; } - if (source.type === SourceTypeRuntime) { + if (source.type === SourceType.Runtime) { // We don't need to load chunks references from runtime code, as they're already // present in the DOM. @@ -209,3 +213,9 @@ let BACKEND; return resolver.promise; } })(); + +function _eval({ code, url, map }: EcmascriptModuleEntry): ModuleFactory { + code += `\n\n//# sourceURL=${location.origin}${url}`; + if (map) code += `\n//# sourceMappingURL=${map}`; + return eval(code); +} diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/tsconfig.json new file mode 100644 index 0000000000000..0cb03c3d26a4e --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + // environment + "lib": ["ESNext", "DOM"] + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-dev/js/src/runtime.nodejs.js b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/runtime-backend-nodejs.ts similarity index 70% rename from crates/turbopack-dev/js/src/runtime.nodejs.js rename to crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/runtime-backend-nodejs.ts index a53e866db9429..654f6a577939e 100644 --- a/crates/turbopack-dev/js/src/runtime.nodejs.js +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/runtime-backend-nodejs.ts @@ -1,9 +1,13 @@ -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ +/** + * This file contains the runtime code specific to the Turbopack development + * ECMAScript Node.js runtime. + * + * It will be appended to the base development runtime code. + */ -/** @type {RuntimeBackend} */ -let BACKEND; +/// + +let BACKEND: RuntimeBackend; (() => { BACKEND = { @@ -15,7 +19,7 @@ let BACKEND; if (params.runtimeModuleIds.length > 0) { for (const otherChunkData of params.otherChunks) { loadChunk(getChunkPath(otherChunkData), { - type: SourceTypeRuntime, + type: SourceType.Runtime, chunkPath, }); } @@ -35,11 +39,7 @@ let BACKEND; }, }; - /** - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - function loadChunk(chunkPath, source) { + function loadChunk(chunkPath: ChunkPath, source: SourceInfo) { if (!chunkPath.endsWith(".js")) { // We only support loading JS chunks in Node.js. // This branch can be hit when trying to load a CSS chunk. @@ -48,13 +48,13 @@ let BACKEND; let fromChunkPath = undefined; switch (source.type) { - case SourceTypeRuntime: + case SourceType.Runtime: fromChunkPath = source.chunkPath; break; - case SourceTypeParent: + case SourceType.Parent: fromChunkPath = getFirstModuleChunk(source.parentId); break; - case SourceTypeUpdate: + case SourceType.Update: break; } @@ -68,3 +68,7 @@ let BACKEND; require(resolved); } })(); + +function _eval({ code, url, map }: EcmascriptModuleEntry): ModuleFactory { + throw new Error("HMR evaluation is not implemented on this backend"); +} diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/tsconfig.json new file mode 100644 index 0000000000000..3d43ec6e2b61d --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + // environment + "lib": ["ESNext"], + "types": ["node"] + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-dev/js/src/runtime.none.js b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/runtime-backend-none.ts similarity index 74% rename from crates/turbopack-dev/js/src/runtime.none.js rename to crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/runtime-backend-none.ts index cb84502bf4b0d..5f0443bcc235f 100644 --- a/crates/turbopack-dev/js/src/runtime.none.js +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/runtime-backend-none.ts @@ -1,11 +1,19 @@ -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.none').ChunkRunner} ChunkRunner */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ChunkData} ChunkData */ +/** + * This file contains the runtime code specific to the Turbopack development + * ECMAScript "None" runtime (e.g. for Edge). + * + * It will be appended to the base development runtime code. + */ -/** @type {RuntimeBackend} */ -let BACKEND; +/// + +type ChunkRunner = { + requiredChunks: Set; + chunkPath: ChunkPath; + runtimeModuleIds: ModuleId[]; +}; + +let BACKEND: RuntimeBackend; (() => { BACKEND = { @@ -46,21 +54,19 @@ let BACKEND; }, }; - /** @type {Set} */ - const registeredChunks = new Set(); - /** @type {Map>} */ - const runners = new Map(); + const registeredChunks: Set = new Set(); + const runners: Map> = new Map(); /** * Registers a chunk runner that will be instantiated once all of the * dependencies of the chunk have been registered. - * - * @param {ChunkPath} chunkPath - * @param {ChunkData[]} otherChunks - * @param {ModuleId[]} runtimeModuleIds */ - function registerChunkRunner(chunkPath, otherChunks, runtimeModuleIds) { - const requiredChunks = new Set(); + function registerChunkRunner( + chunkPath: ChunkPath, + otherChunks: ChunkData[], + runtimeModuleIds: ModuleId[] + ) { + const requiredChunks: Set = new Set(); const runner = { runtimeModuleIds, chunkPath, @@ -90,10 +96,8 @@ let BACKEND; /** * Instantiates any chunk runners that were waiting for the given chunk to be * registered. - * - * @param {ChunkPath} chunkPath */ - function instantiateDependentChunks(chunkPath) { + function instantiateDependentChunks(chunkPath: ChunkPath) { // Run any chunk runners that were waiting for this chunk to be // registered. const runnersForChunk = runners.get(chunkPath); @@ -111,13 +115,17 @@ let BACKEND; /** * Instantiates the runtime modules for the given chunk. - * - * @param {ModuleId[]} runtimeModuleIds - * @param {ChunkPath} chunkPath */ - function instantiateRuntimeModules(runtimeModuleIds, chunkPath) { + function instantiateRuntimeModules( + runtimeModuleIds: ModuleId[], + chunkPath: ChunkPath + ) { for (const moduleId of runtimeModuleIds) { getOrInstantiateRuntimeModule(moduleId, chunkPath); } } })(); + +function _eval({ code, url, map }: EcmascriptModuleEntry): ModuleFactory { + throw new Error("HMR evaluation is not implemented on this backend"); +} diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/tsconfig.json new file mode 100644 index 0000000000000..147dd31d23965 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + // environment + "lib": ["ESNext"] + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-ecmascript-runtime/js/src/shared/dummy.ts b/crates/turbopack-ecmascript-runtime/js/src/shared/dummy.ts new file mode 100644 index 0000000000000..0174cb2893523 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/shared/dummy.ts @@ -0,0 +1,9 @@ +/** + * This file acts as a dummy implementor for the interface that + * `runtime-utils.ts` expects to be available in the global scope. + * + * This interface will be implemented by runtimes. + */ + +declare var commonJsRequireContext: CommonJsRequireContext; +declare var getOrInstantiateModuleFromParent: GetOrInstantiateModuleFromParent; diff --git a/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-types.d.ts b/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-types.d.ts new file mode 100644 index 0000000000000..84581ac8f665d --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-types.d.ts @@ -0,0 +1,37 @@ +/** + * This file contains runtime types that are shared between all TurboPack + * ECMAScript runtimes. + * + * It is separate from `runtime-utils.ts` because it can be used outside of + * runtime code, hence it should not contain any function declarations that are + * specific to the runtime context. + */ + +type ChunkPath = string; +type ModuleId = string; + +type ChunkData = + | ChunkPath + | { + path: ChunkPath; + included: ModuleId[]; + excluded: ModuleId[]; + moduleChunks: ChunkPath[]; + }; + +type CommonJsRequire = (moduleId: ModuleId) => Exports; +type CommonJsExport = (exports: Record) => void; + +type EsmImport = ( + moduleId: ModuleId, + allowExportDefault: boolean +) => EsmNamespaceObject; +type EsmExport = (exportGetters: Record any>) => void; +type ExportValue = (value: any) => void; + +type ExternalRequire = (id: ModuleId) => Exports | EsmNamespaceObject; + +type LoadChunk = (chunkPath: ChunkPath) => Promise | undefined; + +type ModuleCache = Record; +type ModuleFactories = Record; diff --git a/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-utils.ts b/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-utils.ts new file mode 100644 index 0000000000000..869af0d5af649 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-utils.ts @@ -0,0 +1,199 @@ +/** + * This file contains runtime types and functions that are shared between all + * TurboPack ECMAScript runtimes. + * + * It will be prepended to the runtime code of each runtime. + */ + +/* eslint-disable @next/next/no-assign-module-variable */ + +/// + +interface Exports { + __esModule?: boolean; + + [key: string]: any; +} +type EsmNamespaceObject = Record; + +interface BaseModule { + exports: Exports; + error: Error | undefined; + loaded: boolean; + id: ModuleId; + children: ModuleId[]; + parents: ModuleId[]; + namespaceObject?: EsmNamespaceObject; +} + +interface Module extends BaseModule {} + +type RequireContextMap = Record; + +interface RequireContextEntry { + id: () => ModuleId; +} + +interface RequireContext { + (moduleId: ModuleId): Exports | EsmNamespaceObject; + keys(): ModuleId[]; + resolve(moduleId: ModuleId): ModuleId; +} + +type GetOrInstantiateModuleFromParent = ( + moduleId: ModuleId, + parentModule: Module +) => Module; + +type CommonJsRequireContext = ( + entry: RequireContextEntry, + parentModule: Module +) => Exports; + +const hasOwnProperty = Object.prototype.hasOwnProperty; +const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; + +function defineProp( + obj: any, + name: PropertyKey, + options: PropertyDescriptor & ThisType +) { + if (!hasOwnProperty.call(obj, name)) + Object.defineProperty(obj, name, options); +} + +/** + * Adds the getters to the exports object. + */ +function esm(exports: Exports, getters: Record any>) { + defineProp(exports, "__esModule", { value: true }); + if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); + for (const key in getters) { + defineProp(exports, key, { get: getters[key], enumerable: true }); + } +} + +/** + * Makes the module an ESM with exports + */ +function esmExport(module: Module, getters: Record any>) { + esm((module.namespaceObject = module.exports), getters); +} + +/** + * Adds the props to the exports object + */ +function cjsExport(exports: Exports, props: Record) { + for (const key in props) { + defineProp(exports, key, { get: () => props[key], enumerable: true }); + } +} + +function exportValue(module: Module, value: any) { + module.exports = value; +} + +function exportNamespace(module: Module, namespace: any) { + module.exports = module.namespaceObject = namespace; +} + +function createGetter(obj: Record, key: string) { + return () => obj[key]; +} + +/** + * @returns prototype of the object + */ +const getProto: (obj: any) => any = Object.getPrototypeOf + ? (obj) => Object.getPrototypeOf(obj) + : (obj) => obj.__proto__; + +/** Prototypes that are not expanded for exports */ +const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; + +/** + * @param allowExportDefault + * * `false`: will have the raw module as default export + * * `true`: will have the default property as default export + */ +function interopEsm( + raw: Exports, + ns: EsmNamespaceObject, + allowExportDefault?: boolean +) { + const getters: { [s: string]: () => any } = Object.create(null); + for ( + let current = raw; + (typeof current === "object" || typeof current === "function") && + !LEAF_PROTOTYPES.includes(current); + current = getProto(current) + ) { + for (const key of Object.getOwnPropertyNames(current)) { + getters[key] = createGetter(raw, key); + } + } + if (!(allowExportDefault && "default" in getters)) { + getters["default"] = () => raw; + } + esm(ns, getters); +} + +function esmImport(sourceModule: Module, id: ModuleId): EsmNamespaceObject { + const module = getOrInstantiateModuleFromParent(id, sourceModule); + if (module.error) throw module.error; + if (module.namespaceObject) return module.namespaceObject; + const raw = module.exports; + const ns = (module.namespaceObject = {}); + interopEsm(raw, ns, raw.__esModule); + return ns; +} + +function commonJsRequire(sourceModule: Module, id: ModuleId): Exports { + const module = getOrInstantiateModuleFromParent(id, sourceModule); + if (module.error) throw module.error; + return module.exports; +} + +type RequireContextFactory = (map: RequireContextMap) => RequireContext; + +function requireContext( + sourceModule: Module, + map: RequireContextMap +): RequireContext { + function requireContext(id: ModuleId): Exports { + const entry = map[id]; + + if (!entry) { + throw new Error( + `module ${id} is required from a require.context, but is not in the context` + ); + } + + return commonJsRequireContext(entry, sourceModule); + } + + requireContext.keys = (): ModuleId[] => { + return Object.keys(map); + }; + + requireContext.resolve = (id: ModuleId): ModuleId => { + const entry = map[id]; + + if (!entry) { + throw new Error( + `module ${id} is resolved from a require.context, but is not in the context` + ); + } + + return entry.id(); + }; + + return requireContext; +} + +/** + * Returns the path of a chunk defined by its data. + */ +function getChunkPath(chunkData: ChunkData): ChunkPath { + return typeof chunkData === "string" ? chunkData : chunkData.path; +} diff --git a/crates/turbopack-ecmascript-runtime/js/src/shared/tsconfig.json b/crates/turbopack-ecmascript-runtime/js/src/shared/tsconfig.json new file mode 100644 index 0000000000000..f8b2080f48e96 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/shared/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + // environment + "lib": ["ESNext"] + }, + "include": ["*.ts"] +} diff --git a/crates/turbopack-ecmascript-runtime/js/src/tsconfig.base.json b/crates/turbopack-ecmascript-runtime/js/src/tsconfig.base.json new file mode 100644 index 0000000000000..081030a0fd84e --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/js/src/tsconfig.base.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + // type checking + "strict": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + + // environment + "target": "ESNext", + + // modules + "baseUrl": ".", + "module": "CommonJS", + "moduleResolution": "nodenext", + + // emit + "noEmit": true, + "stripInternal": true + } +} diff --git a/crates/turbopack-ecmascript-runtime/src/asset_context.rs b/crates/turbopack-ecmascript-runtime/src/asset_context.rs new file mode 100644 index 0000000000000..62c26a6fb2ed3 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/src/asset_context.rs @@ -0,0 +1,30 @@ +use turbopack::{ + module_options::{ModuleOptionsContext, TypescriptTransformOptions}, + resolve_options_context::ResolveOptionsContextVc, + transition::TransitionsByNameVc, + ModuleAssetContextVc, +}; +use turbopack_core::{ + compile_time_info::CompileTimeInfo, context::AssetContextVc, environment::EnvironmentVc, +}; + +/// Returns the runtime asset context to use to process runtime code assets. +pub fn get_runtime_asset_context(environment: EnvironmentVc) -> AssetContextVc { + let resolve_options_context = ResolveOptionsContextVc::default(); + let module_options_context = ModuleOptionsContext { + enable_typescript_transform: Some(TypescriptTransformOptions::default().cell()), + ..Default::default() + } + .cell(); + let compile_time_info = CompileTimeInfo::builder(environment).cell(); + + let context: AssetContextVc = ModuleAssetContextVc::new( + TransitionsByNameVc::cell(Default::default()), + compile_time_info, + module_options_context, + resolve_options_context, + ) + .into(); + + context +} diff --git a/crates/turbopack-ecmascript-runtime/src/build_runtime.rs b/crates/turbopack-ecmascript-runtime/src/build_runtime.rs new file mode 100644 index 0000000000000..75bffaee9d9bf --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/src/build_runtime.rs @@ -0,0 +1,27 @@ +use anyhow::Result; +use turbopack_core::{ + code_builder::{CodeBuilder, CodeVc}, + environment::EnvironmentVc, +}; +use turbopack_ecmascript::StaticEcmascriptCodeVc; + +use crate::{asset_context::get_runtime_asset_context, embed_file_path}; + +/// Returns the code for the Node.js production ECMAScript runtime. +#[turbo_tasks::function] +pub async fn get_build_runtime_code(environment: EnvironmentVc) -> Result { + let asset_context = get_runtime_asset_context(environment); + + let shared_runtime_utils_code = + StaticEcmascriptCodeVc::new(asset_context, embed_file_path("shared/runtime-utils.ts")) + .code(); + + let runtime_code = + StaticEcmascriptCodeVc::new(asset_context, embed_file_path("build/runtime.ts")).code(); + + let mut code = CodeBuilder::default(); + code.push_code(&*shared_runtime_utils_code.await?); + code.push_code(&*runtime_code.await?); + + Ok(CodeVc::cell(code.build())) +} diff --git a/crates/turbopack-ecmascript-runtime/src/dev_runtime.rs b/crates/turbopack-ecmascript-runtime/src/dev_runtime.rs new file mode 100644 index 0000000000000..a5aa64746c796 --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/src/dev_runtime.rs @@ -0,0 +1,73 @@ +use std::io::Write; + +use anyhow::Result; +use indoc::writedoc; +use turbopack_core::{ + code_builder::{CodeBuilder, CodeVc}, + context::AssetContext, + environment::{ChunkLoading, EnvironmentVc}, +}; +use turbopack_ecmascript::StaticEcmascriptCodeVc; + +use crate::{asset_context::get_runtime_asset_context, embed_file_path}; + +/// Returns the code for the development ECMAScript runtime. +#[turbo_tasks::function] +pub async fn get_dev_runtime_code(environment: EnvironmentVc) -> Result { + let asset_context = get_runtime_asset_context(environment); + + let shared_runtime_utils_code = + StaticEcmascriptCodeVc::new(asset_context, embed_file_path("shared/runtime-utils.ts")) + .code(); + + let runtime_base_code = StaticEcmascriptCodeVc::new( + asset_context, + embed_file_path("dev/runtime/base/runtime-base.ts"), + ) + .code(); + + let runtime_backend_code = StaticEcmascriptCodeVc::new( + asset_context, + match &*asset_context + .compile_time_info() + .environment() + .chunk_loading() + .await? + { + ChunkLoading::None => embed_file_path("dev/runtime/none/runtime-backend-none.ts"), + ChunkLoading::NodeJs => embed_file_path("dev/runtime/nodejs/runtime-backend-nodejs.ts"), + ChunkLoading::Dom => embed_file_path("dev/runtime/dom/runtime-backend-dom.ts"), + }, + ) + .code(); + + let mut code: CodeBuilder = CodeBuilder::default(); + + writedoc!( + code, + r#" + (() => {{ + if (!Array.isArray(globalThis.TURBOPACK)) {{ + return; + }} + "# + )?; + + code.push_code(&*shared_runtime_utils_code.await?); + code.push_code(&*runtime_base_code.await?); + code.push_code(&*runtime_backend_code.await?); + + // Registering chunks depends on the BACKEND variable, which is set by the + // specific runtime code, hence it must be appended after it. + writedoc!( + code, + r#" + const chunksToRegister = globalThis.TURBOPACK; + globalThis.TURBOPACK = {{ push: registerChunk }}; + chunksToRegister.forEach(registerChunk); + }})(); + "# + )?; + + Ok(CodeVc::cell(code.build())) +} diff --git a/crates/turbopack-ecmascript-runtime/src/dummy_runtime.rs b/crates/turbopack-ecmascript-runtime/src/dummy_runtime.rs new file mode 100644 index 0000000000000..e9662b67f304f --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/src/dummy_runtime.rs @@ -0,0 +1,10 @@ +use turbopack_core::code_builder::{Code, CodeBuilder}; + +/// Returns the code for the dummy runtime, which is used for snapshots. +pub fn get_dummy_runtime_code() -> Code { + let mut code = CodeBuilder::default(); + + code += "// Dummy runtime\n"; + + code.build() +} diff --git a/crates/turbopack-dev/src/embed_js.rs b/crates/turbopack-ecmascript-runtime/src/embed_js.rs similarity index 60% rename from crates/turbopack-dev/src/embed_js.rs rename to crates/turbopack-ecmascript-runtime/src/embed_js.rs index 4e9ca39e8c2df..ff3e36f6f916b 100644 --- a/crates/turbopack-dev/src/embed_js.rs +++ b/crates/turbopack-ecmascript-runtime/src/embed_js.rs @@ -2,15 +2,15 @@ use turbo_tasks_fs::{embed_directory, FileContentVc, FileSystem, FileSystemPathV #[turbo_tasks::function] pub fn embed_fs() -> FileSystemVc { - embed_directory!("turbopack-dev", "$CARGO_MANIFEST_DIR/js/src") + embed_directory!("turbopack", "$CARGO_MANIFEST_DIR/js/src") } #[turbo_tasks::function] -pub(crate) fn embed_file(path: &str) -> FileContentVc { +pub fn embed_file(path: &str) -> FileContentVc { embed_fs().root().join(path).read() } #[turbo_tasks::function] -pub(crate) fn embed_file_path(path: &str) -> FileSystemPathVc { +pub fn embed_file_path(path: &str) -> FileSystemPathVc { embed_fs().root().join(path) } diff --git a/crates/turbopack-ecmascript-runtime/src/lib.rs b/crates/turbopack-ecmascript-runtime/src/lib.rs new file mode 100644 index 0000000000000..32d2a56b8c1ae --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/src/lib.rs @@ -0,0 +1,23 @@ +pub(crate) mod asset_context; +pub(crate) mod build_runtime; +pub(crate) mod dev_runtime; +#[cfg(feature = "test")] +pub(crate) mod dummy_runtime; +pub(crate) mod embed_js; +pub(crate) mod runtime_type; + +pub use build_runtime::get_build_runtime_code; +pub use dev_runtime::get_dev_runtime_code; +#[cfg(feature = "test")] +pub use dummy_runtime::get_dummy_runtime_code; +pub use embed_js::{embed_file, embed_file_path, embed_fs}; +pub use runtime_type::RuntimeType; + +pub fn register() { + turbo_tasks::register(); + turbo_tasks_fs::register(); + turbopack::register(); + turbopack_core::register(); + turbopack_ecmascript::register(); + include!(concat!(env!("OUT_DIR"), "/register.rs")); +} diff --git a/crates/turbopack-ecmascript-runtime/src/runtime_type.rs b/crates/turbopack-ecmascript-runtime/src/runtime_type.rs new file mode 100644 index 0000000000000..63b316d3b27dd --- /dev/null +++ b/crates/turbopack-ecmascript-runtime/src/runtime_type.rs @@ -0,0 +1,25 @@ +use serde::{Deserialize, Serialize}; +use turbo_tasks::trace::TraceRawVcs; + +#[derive( + Serialize, + Deserialize, + Debug, + Clone, + Copy, + Hash, + PartialEq, + Eq, + PartialOrd, + Ord, + TraceRawVcs, + Default, +)] +pub enum RuntimeType { + #[default] + /// Default, full-featured runtime. + Default, + #[cfg(feature = "test")] + /// Dummy runtime for snapshot tests. + Dummy, +} diff --git a/crates/turbopack-ecmascript/src/chunk/context.rs b/crates/turbopack-ecmascript/src/chunk/context.rs index 98f79875a99af..6a2243c5e77bf 100644 --- a/crates/turbopack-ecmascript/src/chunk/context.rs +++ b/crates/turbopack-ecmascript/src/chunk/context.rs @@ -1,9 +1,6 @@ use anyhow::Result; -use turbo_tasks::{Value, ValueToString}; -use turbopack_core::chunk::{ - availability_info::AvailabilityInfo, ChunkItem, ChunkableAssetVc, ChunkingContext, - ChunkingContextVc, ModuleId, ModuleIdVc, -}; +use turbo_tasks::{primitives::BoolVc, ValueToString}; +use turbopack_core::chunk::{ChunkItem, ChunkingContext, ChunkingContextVc, ModuleId, ModuleIdVc}; use super::item::EcmascriptChunkItemVc; @@ -11,12 +8,11 @@ use super::item::EcmascriptChunkItemVc; /// implementors that want to operate on [`EcmascriptChunk`]s. #[turbo_tasks::value_trait] pub trait EcmascriptChunkingContext: ChunkingContext { - /// Returns the loader item that is used to load the given manifest asset. - fn manifest_loader_item( - &self, - asset: ChunkableAssetVc, - availability_info: Value, - ) -> EcmascriptChunkItemVc; + /// Whether chunk items generated by this chunking context should include + /// the `__turbopack_refresh__` argument. + fn has_react_refresh(&self) -> BoolVc { + BoolVc::cell(false) + } async fn chunk_item_id(&self, chunk_item: EcmascriptChunkItemVc) -> Result { let layer = self.layer(); diff --git a/crates/turbopack-ecmascript/src/chunk/data.rs b/crates/turbopack-ecmascript/src/chunk/data.rs new file mode 100644 index 0000000000000..d5fdab9c88a04 --- /dev/null +++ b/crates/turbopack-ecmascript/src/chunk/data.rs @@ -0,0 +1,39 @@ +use serde::Serialize; +use turbopack_core::chunk::{ChunkData, ModuleIdReadRef}; + +#[derive(Serialize, Hash, PartialEq, Eq)] +#[serde(untagged)] +pub enum EcmascriptChunkData<'a> { + Simple(&'a str), + #[serde(rename_all = "camelCase")] + WithRuntimeInfo { + path: &'a str, + #[serde(skip_serializing_if = "<[_]>::is_empty", default)] + included: &'a [ModuleIdReadRef], + #[serde(skip_serializing_if = "<[_]>::is_empty", default)] + excluded: &'a [ModuleIdReadRef], + #[serde(skip_serializing_if = "<[_]>::is_empty", default)] + module_chunks: &'a [String], + }, +} + +impl<'a> EcmascriptChunkData<'a> { + pub fn new(chunk_data: &ChunkData) -> EcmascriptChunkData { + let ChunkData { + path, + included, + excluded, + module_chunks, + references: _, + } = chunk_data; + if included.is_empty() && excluded.is_empty() && module_chunks.is_empty() { + return EcmascriptChunkData::Simple(&path); + } + EcmascriptChunkData::WithRuntimeInfo { + path, + included: &included, + excluded: &excluded, + module_chunks: &module_chunks, + } + } +} diff --git a/crates/turbopack-ecmascript/src/chunk/item.rs b/crates/turbopack-ecmascript/src/chunk/item.rs index 10f5c28b3e29a..650e40d521087 100644 --- a/crates/turbopack-ecmascript/src/chunk/item.rs +++ b/crates/turbopack-ecmascript/src/chunk/item.rs @@ -1,6 +1,12 @@ +use std::io::Write; + use anyhow::Result; use serde::{Deserialize, Serialize}; -use turbo_tasks::{trace::TraceRawVcs, Value}; +use turbo_tasks::{ + primitives::{BoolVc, StringVc}, + trace::TraceRawVcs, + Value, ValueToString, +}; use turbo_tasks_fs::rope::Rope; use turbopack_core::{ asset::AssetVc, @@ -8,13 +14,20 @@ use turbopack_core::{ availability_info::AvailabilityInfo, available_assets::AvailableAssetsVc, ChunkItem, ChunkItemVc, ChunkableAssetVc, ChunkingContextVc, FromChunkableAsset, ModuleIdVc, }, + code_builder::{CodeBuilder, CodeVc}, + error::PrettyPrintError, + issue::{code_gen::CodeGenerationIssue, IssueSeverity}, }; use super::{ context::EcmascriptChunkingContextVc, placeable::EcmascriptChunkPlaceableVc, EcmascriptChunkPlaceable, EcmascriptChunkingContext, }; -use crate::ParseResultSourceMapVc; +use crate::{ + manifest::{chunk_asset::ManifestChunkAssetVc, loader_item::ManifestLoaderItemVc}, + utils::FormatIter, + EcmascriptModuleContentVc, ParseResultSourceMapVc, +}; #[turbo_tasks::value(shared)] #[derive(Default)] @@ -25,9 +38,95 @@ pub struct EcmascriptChunkItemContent { pub placeholder_for_future_extensions: (), } +#[turbo_tasks::value_impl] +impl EcmascriptChunkItemContentVc { + #[turbo_tasks::function] + pub async fn new( + content: EcmascriptModuleContentVc, + has_react_refresh: BoolVc, + ) -> Result { + let refresh = *has_react_refresh.await?; + + let content = content.await?; + Ok(EcmascriptChunkItemContent { + inner_code: content.inner_code.clone(), + source_map: content.source_map, + options: if content.is_esm { + EcmascriptChunkItemOptions { + refresh, + ..Default::default() + } + } else { + EcmascriptChunkItemOptions { + refresh, + // These things are not available in ESM + module: true, + exports: true, + this: true, + ..Default::default() + } + }, + ..Default::default() + } + .into()) + } + + #[turbo_tasks::function] + pub async fn module_factory(self) -> Result { + let this = self.await?; + let mut args = vec![ + "r: __turbopack_require__", + "x: __turbopack_external_require__", + "f: __turbopack_require_context__", + "i: __turbopack_import__", + "s: __turbopack_esm__", + "v: __turbopack_export_value__", + "n: __turbopack_export_namespace__", + "c: __turbopack_cache__", + "l: __turbopack_load__", + "j: __turbopack_cjs__", + "g: global", + // HACK + "__dirname", + ]; + if this.options.refresh { + args.push("k: __turbopack_refresh__"); + } + if this.options.module { + args.push("m: module"); + } + if this.options.exports { + args.push("e: exports"); + } + let mut code = CodeBuilder::default(); + let args = FormatIter(|| args.iter().copied().intersperse(", ")); + if this.options.this { + write!(code, "(function({{ {} }}) {{ !function() {{\n\n", args,)?; + } else { + write!(code, "(({{ {} }}) => (() => {{\n\n", args,)?; + } + + let source_map = this.source_map.map(|sm| sm.as_generate_source_map()); + code.push_source(&this.inner_code, source_map); + if this.options.this { + code += "\n}.call(this) })"; + } else { + code += "\n})())"; + } + Ok(code.build().cell()) + } +} + #[derive(PartialEq, Eq, Default, Debug, Clone, Serialize, Deserialize, TraceRawVcs)] pub struct EcmascriptChunkItemOptions { + /// Whether this chunk item's module factory should include a + /// `__turbopack_refresh__` argument. + pub refresh: bool, + /// Whether this chunk item's module factory should include a `module` + /// argument. pub module: bool, + /// Whether this chunk item's module factory should include an `exports` + /// argument. pub exports: bool, pub this: bool, pub placeholder_for_future_extensions: (), @@ -52,6 +151,44 @@ impl EcmascriptChunkItemVc { pub fn id(self) -> ModuleIdVc { self.chunking_context().chunk_item_id(self) } + + /// Generates the module factory for this chunk item. + #[turbo_tasks::function] + pub async fn code(self, availability_info: Value) -> Result { + Ok( + match self + .content_with_availability_info(availability_info) + .module_factory() + .resolve() + .await + { + Ok(factory) => factory, + Err(error) => { + let id = self.id().to_string().await; + let id = id.as_ref().map_or_else(|_| "unknown", |id| &**id); + let error = error.context(format!( + "An error occurred while generating the chunk item {}", + id + )); + let error_message = format!("{}", PrettyPrintError(&error)); + let js_error_message = serde_json::to_string(&error_message)?; + let issue = CodeGenerationIssue { + severity: IssueSeverity::Error.cell(), + path: self.asset_ident().path(), + title: StringVc::cell("Code generation for chunk item errored".to_string()), + message: StringVc::cell(error_message), + } + .cell(); + issue.as_issue().emit(); + let mut code = CodeBuilder::default(); + code += "(() => {{\n\n"; + writeln!(code, "throw new Error({error});", error = &js_error_message)?; + code += "\n}})"; + code.build().cell() + } + }, + ) + } } #[async_trait::async_trait] @@ -93,10 +230,10 @@ impl FromChunkableAsset for EcmascriptChunkItemVc { current_availability_root: asset.as_asset(), }, }; - Ok(Some(context.manifest_loader_item( - asset, - Value::new(next_availability_info), - ))) + + let manifest_asset = + ManifestChunkAssetVc::new(asset, context, Value::new(next_availability_info)); + Ok(Some(ManifestLoaderItemVc::new(manifest_asset).into())) } } diff --git a/crates/turbopack-ecmascript/src/chunk/mod.rs b/crates/turbopack-ecmascript/src/chunk/mod.rs index ee14257bb887f..d35a650934e88 100644 --- a/crates/turbopack-ecmascript/src/chunk/mod.rs +++ b/crates/turbopack-ecmascript/src/chunk/mod.rs @@ -1,5 +1,6 @@ pub(crate) mod content; pub(crate) mod context; +pub(crate) mod data; pub(crate) mod item; pub(crate) mod placeable; @@ -30,6 +31,7 @@ use self::content::ecmascript_chunk_content; pub use self::{ content::{EcmascriptChunkContent, EcmascriptChunkContentVc}, context::{EcmascriptChunkingContext, EcmascriptChunkingContextVc}, + data::EcmascriptChunkData, item::{ EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, EcmascriptChunkItemOptions, EcmascriptChunkItemVc, diff --git a/crates/turbopack-ecmascript/src/lib.rs b/crates/turbopack-ecmascript/src/lib.rs index 177cfed555818..f026ec6fc9419 100644 --- a/crates/turbopack-ecmascript/src/lib.rs +++ b/crates/turbopack-ecmascript/src/lib.rs @@ -11,17 +11,20 @@ pub mod chunk_group_files_asset; pub mod code_gen; mod errors; pub mod magic_identifier; +pub(crate) mod manifest; pub mod parse; mod path_visitor; pub(crate) mod references; pub mod resolve; pub(crate) mod special_cases; +pub(crate) mod static_code; pub mod text; pub(crate) mod transform; pub mod tree_shake; pub mod typescript; pub mod utils; pub mod webpack; + use anyhow::Result; use chunk::{ EcmascriptChunkItem, EcmascriptChunkItemVc, EcmascriptChunkPlaceablesVc, EcmascriptChunkVc, @@ -34,6 +37,7 @@ pub use parse::{ParseResultSourceMap, ParseResultSourceMapVc}; use path_visitor::ApplyVisitors; use references::AnalyzeEcmascriptModuleResult; pub use references::TURBOPACK_HELPER; +pub use static_code::{StaticEcmascriptCode, StaticEcmascriptCodeVc}; use swc_core::{ common::GLOBALS, ecma::{ @@ -49,7 +53,7 @@ pub use transform::{ use turbo_tasks::{ primitives::StringVc, trace::TraceRawVcs, RawVc, ReadRef, TryJoinIterExt, Value, ValueToString, }; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks_fs::{rope::Rope, FileSystemPathVc}; use turbopack_core::{ asset::{Asset, AssetContentVc, AssetOptionVc, AssetVc}, chunk::{ @@ -69,11 +73,12 @@ use turbopack_core::{ pub use self::references::AnalyzeEcmascriptModuleResultVc; use self::{ chunk::{ - placeable::EcmascriptExportsReadRef, EcmascriptChunkItemContent, - EcmascriptChunkItemContentVc, EcmascriptChunkItemOptions, EcmascriptExportsVc, + placeable::EcmascriptExportsReadRef, EcmascriptChunkItemContentVc, + EcmascriptChunkingContext, EcmascriptExportsVc, }, code_gen::{ CodeGen, CodeGenerateableWithAvailabilityInfo, CodeGenerateableWithAvailabilityInfoVc, + VisitorFactory, }, parse::ParseResultVc, }; @@ -258,6 +263,44 @@ impl EcmascriptModuleAssetVc { let this = self.await?; Ok(parse(this.source, Value::new(this.ty), this.transforms)) } + + /// Generates module contents without an analysis pass. This is useful for + /// transforming code that is not a module, e.g. runtime code. + #[turbo_tasks::function] + pub async fn module_content_without_analysis(self) -> Result { + let this = self.await?; + + let parsed = parse(this.source, Value::new(this.ty), this.transforms); + + Ok(EcmascriptModuleContentVc::new_without_analysis( + parsed, + self.ident(), + )) + } + + #[turbo_tasks::function] + pub async fn module_content( + self, + chunking_context: EcmascriptChunkingContextVc, + availability_info: Value, + ) -> Result { + let this = self.await?; + if *self.analyze().needs_availability_info().await? { + availability_info + } else { + Value::new(AvailabilityInfo::Untracked) + }; + + let parsed = parse(this.source, Value::new(this.ty), this.transforms); + + Ok(EcmascriptModuleContentVc::new( + parsed, + self.ident(), + chunking_context, + self.analyze(), + availability_info, + )) + } } #[turbo_tasks::value_impl] @@ -392,74 +435,93 @@ impl EcmascriptChunkItem for ModuleChunkItem { availability_info: Value, ) -> Result { let this = self_vc.await?; - if *this.module.analyze().needs_availability_info().await? { - availability_info - } else { - Value::new(AvailabilityInfo::Untracked) - }; - - let module = this.module.await?; - let parsed = parse(module.source, Value::new(module.ty), module.transforms); - - Ok(gen_content( - this.context.into(), - this.module.analyze(), - parsed, - this.module.ident(), - availability_info, + let content = this.module.module_content(this.context, availability_info); + Ok(EcmascriptChunkItemContentVc::new( + content, + this.context.has_react_refresh(), )) } } -#[turbo_tasks::function] -async fn gen_content( - context: EcmascriptChunkingContextVc, - analyzed: AnalyzeEcmascriptModuleResultVc, - parsed: ParseResultVc, - ident: AssetIdentVc, - availability_info: Value, -) -> Result { - let AnalyzeEcmascriptModuleResult { - references, - code_generation, - .. - } = &*analyzed.await?; - - let mut code_gens = Vec::new(); - for r in references.await?.iter() { - let r = r.resolve().await?; - if let Some(code_gen) = CodeGenerateableWithAvailabilityInfoVc::resolve_from(r).await? { - code_gens.push(code_gen.code_generation(context, availability_info)); - } else if let Some(code_gen) = CodeGenerateableVc::resolve_from(r).await? { - code_gens.push(code_gen.code_generation(context)); - } - } - for c in code_generation.await?.iter() { - match c { - CodeGen::CodeGenerateable(c) => { - code_gens.push(c.code_generation(context)); +/// The transformed contents of an Ecmascript module. +#[turbo_tasks::value] +pub struct EcmascriptModuleContent { + pub inner_code: Rope, + pub source_map: Option, + pub is_esm: bool, +} + +#[turbo_tasks::value_impl] +impl EcmascriptModuleContentVc { + /// Creates a new [`EcmascriptModuleContentVc`]. + #[turbo_tasks::function] + pub async fn new( + parsed: ParseResultVc, + ident: AssetIdentVc, + context: EcmascriptChunkingContextVc, + analyzed: AnalyzeEcmascriptModuleResultVc, + availability_info: Value, + ) -> Result { + let AnalyzeEcmascriptModuleResult { + references, + code_generation, + .. + } = &*analyzed.await?; + + let mut code_gens = Vec::new(); + for r in references.await?.iter() { + let r = r.resolve().await?; + if let Some(code_gen) = CodeGenerateableWithAvailabilityInfoVc::resolve_from(r).await? { + code_gens.push(code_gen.code_generation(context, availability_info)); + } else if let Some(code_gen) = CodeGenerateableVc::resolve_from(r).await? { + code_gens.push(code_gen.code_generation(context)); } - CodeGen::CodeGenerateableWithAvailabilityInfo(c) => { - code_gens.push(c.code_generation(context, availability_info)); + } + for c in code_generation.await?.iter() { + match c { + CodeGen::CodeGenerateable(c) => { + code_gens.push(c.code_generation(context)); + } + CodeGen::CodeGenerateableWithAvailabilityInfo(c) => { + code_gens.push(c.code_generation(context, availability_info)); + } } } - } - // need to keep that around to allow references into that - let code_gens = code_gens.into_iter().try_join().await?; - let code_gens = code_gens.iter().map(|cg| &**cg).collect::>(); - // TOOD use interval tree with references into "code_gens" - let mut visitors = Vec::new(); - let mut root_visitors = Vec::new(); - for code_gen in code_gens { - for (path, visitor) in code_gen.visitors.iter() { - if path.is_empty() { - root_visitors.push(&**visitor); - } else { - visitors.push((path, &**visitor)); + // need to keep that around to allow references into that + let code_gens = code_gens.into_iter().try_join().await?; + let code_gens = code_gens.iter().map(|cg| &**cg).collect::>(); + // TOOD use interval tree with references into "code_gens" + let mut visitors = Vec::new(); + let mut root_visitors = Vec::new(); + for code_gen in code_gens { + for (path, visitor) in code_gen.visitors.iter() { + if path.is_empty() { + root_visitors.push(&**visitor); + } else { + visitors.push((path, &**visitor)); + } } } + + gen_content_with_visitors(parsed, ident, visitors, root_visitors).await + } + + /// Creates a new [`EcmascriptModuleContentVc`] without an analysis pass. + #[turbo_tasks::function] + pub async fn new_without_analysis(parsed: ParseResultVc, ident: AssetIdentVc) -> Result { + gen_content_with_visitors(parsed, ident, Vec::new(), Vec::new()).await } +} +async fn gen_content_with_visitors( + parsed: ParseResultVc, + ident: AssetIdentVc, + visitors: Vec<( + &Vec, + &dyn VisitorFactory, + )>, + root_visitors: Vec<&dyn VisitorFactory>, +) -> Result { let parsed = parsed.await?; if let ParseResult::Ok { @@ -509,36 +571,24 @@ async fn gen_content( let srcmap = ParseResultSourceMap::new(source_map.clone(), srcmap).cell(); - Ok(EcmascriptChunkItemContent { + Ok(EcmascriptModuleContent { inner_code: bytes.into(), source_map: Some(srcmap), - options: if eval_context.is_esm() { - EcmascriptChunkItemOptions { - ..Default::default() - } - } else { - EcmascriptChunkItemOptions { - // These things are not available in ESM - module: true, - exports: true, - this: true, - ..Default::default() - } - }, - ..Default::default() + is_esm: eval_context.is_esm(), } - .into()) + .cell()) } else { - Ok(EcmascriptChunkItemContent { + Ok(EcmascriptModuleContent { inner_code: format!( "const e = new Error(\"Could not parse module '{path}'\");\ne.code = \ 'MODULE_UNPARSEABLE';\nthrow e;", path = ident.path().to_string().await? ) .into(), - ..Default::default() + source_map: None, + is_esm: false, } - .into()) + .cell()) } } diff --git a/crates/turbopack-dev/src/ecmascript/manifest/chunk_asset.rs b/crates/turbopack-ecmascript/src/manifest/chunk_asset.rs similarity index 75% rename from crates/turbopack-dev/src/ecmascript/manifest/chunk_asset.rs rename to crates/turbopack-ecmascript/src/manifest/chunk_asset.rs index 207aa14ebc83d..8dfe461fffb4a 100644 --- a/crates/turbopack-dev/src/ecmascript/manifest/chunk_asset.rs +++ b/crates/turbopack-ecmascript/src/manifest/chunk_asset.rs @@ -1,4 +1,4 @@ -use anyhow::{bail, Result}; +use anyhow::Result; use turbo_tasks::{primitives::StringVc, Value}; use turbopack_core::{ asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, @@ -9,14 +9,13 @@ use turbopack_core::{ ident::AssetIdentVc, reference::{AssetReferencesVc, SingleAssetReferenceVc}, }; -use turbopack_ecmascript::chunk::{ + +use super::chunk_item::ManifestChunkItem; +use crate::chunk::{ EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, }; -use super::chunk_item::DevManifestChunkItem; -use crate::DevChunkingContextVc; - #[turbo_tasks::function] fn modifier() -> StringVc { StringVc::cell("manifest chunk".to_string()) @@ -33,21 +32,21 @@ fn modifier() -> StringVc { /// actually reached, instead of eagerly as part of the chunk that the dynamic /// import appears in. #[turbo_tasks::value(shared)] -pub struct DevManifestChunkAsset { +pub struct ManifestChunkAsset { pub asset: ChunkableAssetVc, - pub chunking_context: DevChunkingContextVc, + pub chunking_context: EcmascriptChunkingContextVc, pub availability_info: AvailabilityInfo, } #[turbo_tasks::value_impl] -impl DevManifestChunkAssetVc { +impl ManifestChunkAssetVc { #[turbo_tasks::function] pub fn new( asset: ChunkableAssetVc, - chunking_context: DevChunkingContextVc, + chunking_context: EcmascriptChunkingContextVc, availability_info: Value, ) -> Self { - Self::cell(DevManifestChunkAsset { + Self::cell(ManifestChunkAsset { asset, chunking_context, availability_info: availability_info.into_value(), @@ -70,9 +69,9 @@ impl DevManifestChunkAssetVc { } #[turbo_tasks::function] - pub async fn manifest_chunk(self) -> Result { + pub async fn manifest_chunks(self) -> Result { let this = self.await?; - Ok(this.chunking_context.generate_chunk(self.as_chunk( + Ok(this.chunking_context.chunk_group(self.as_chunk( this.chunking_context.into(), Value::new(this.availability_info), ))) @@ -80,12 +79,12 @@ impl DevManifestChunkAssetVc { } #[turbo_tasks::function] -fn dev_manifest_chunk_reference_description() -> StringVc { - StringVc::cell("dev manifest chunk".to_string()) +fn manifest_chunk_reference_description() -> StringVc { + StringVc::cell("manifest chunk".to_string()) } #[turbo_tasks::value_impl] -impl Asset for DevManifestChunkAsset { +impl Asset for ManifestChunkAsset { #[turbo_tasks::function] fn ident(&self) -> AssetIdentVc { self.asset.ident().with_modifier(modifier()) @@ -97,7 +96,7 @@ impl Asset for DevManifestChunkAsset { } #[turbo_tasks::function] - async fn references(self_vc: DevManifestChunkAssetVc) -> Result { + async fn references(self_vc: ManifestChunkAssetVc) -> Result { let chunks = self_vc.chunks(); Ok(AssetReferencesVc::cell( @@ -106,7 +105,7 @@ impl Asset for DevManifestChunkAsset { .iter() .copied() .map(|chunk| { - SingleAssetReferenceVc::new(chunk, dev_manifest_chunk_reference_description()) + SingleAssetReferenceVc::new(chunk, manifest_chunk_reference_description()) .into() }) .collect(), @@ -115,10 +114,10 @@ impl Asset for DevManifestChunkAsset { } #[turbo_tasks::value_impl] -impl ChunkableAsset for DevManifestChunkAsset { +impl ChunkableAsset for ManifestChunkAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: DevManifestChunkAssetVc, + self_vc: ManifestChunkAssetVc, context: ChunkingContextVc, availability_info: Value, ) -> ChunkVc { @@ -127,17 +126,13 @@ impl ChunkableAsset for DevManifestChunkAsset { } #[turbo_tasks::value_impl] -impl EcmascriptChunkPlaceable for DevManifestChunkAsset { +impl EcmascriptChunkPlaceable for ManifestChunkAsset { #[turbo_tasks::function] async fn as_chunk_item( - self_vc: DevManifestChunkAssetVc, + self_vc: ManifestChunkAssetVc, context: EcmascriptChunkingContextVc, ) -> Result { - let Some(context) = DevChunkingContextVc::resolve_from(context).await? else { - bail!("invalid chunking context"); - }; - - Ok(DevManifestChunkItem { + Ok(ManifestChunkItem { context, manifest: self_vc, } diff --git a/crates/turbopack-dev/src/ecmascript/manifest/chunk_item.rs b/crates/turbopack-ecmascript/src/manifest/chunk_item.rs similarity index 65% rename from crates/turbopack-dev/src/ecmascript/manifest/chunk_item.rs rename to crates/turbopack-ecmascript/src/manifest/chunk_item.rs index c2f421339fa6d..5c9ab98796a47 100644 --- a/crates/turbopack-dev/src/ecmascript/manifest/chunk_item.rs +++ b/crates/turbopack-ecmascript/src/manifest/chunk_item.rs @@ -3,35 +3,31 @@ use indoc::formatdoc; use turbo_tasks::TryJoinIterExt; use turbopack_core::{ asset::Asset, - chunk::{ChunkItem, ChunkItemVc, ChunkingContext}, + chunk::{ChunkDataVc, ChunkItem, ChunkItemVc, ChunkingContext, ChunksDataVc}, ident::AssetIdentVc, reference::AssetReferencesVc, }; -use turbopack_ecmascript::{ + +use super::chunk_asset::ManifestChunkAssetVc; +use crate::{ chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, - EcmascriptChunkItemVc, EcmascriptChunkingContextVc, + data::EcmascriptChunkData, EcmascriptChunkItem, EcmascriptChunkItemContent, + EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, EcmascriptChunkingContextVc, }, utils::StringifyJs, }; -use super::chunk_asset::DevManifestChunkAssetVc; -use crate::{ - ecmascript::chunk_data::{ChunkDataVc, ChunksDataVc}, - DevChunkingContextVc, -}; - -/// The DevManifestChunkItem generates a __turbopack_load__ call for every chunk +/// The ManifestChunkItem generates a __turbopack_load__ call for every chunk /// necessary to load the real asset. Once all the loads resolve, it is safe to /// __turbopack_import__ the actual module that was dynamically imported. #[turbo_tasks::value(shared)] -pub(super) struct DevManifestChunkItem { - pub context: DevChunkingContextVc, - pub manifest: DevManifestChunkAssetVc, +pub(super) struct ManifestChunkItem { + pub context: EcmascriptChunkingContextVc, + pub manifest: ManifestChunkAssetVc, } #[turbo_tasks::value_impl] -impl DevManifestChunkItemVc { +impl ManifestChunkItemVc { #[turbo_tasks::function] async fn chunks_data(self) -> Result { let this = self.await?; @@ -43,19 +39,19 @@ impl DevManifestChunkItemVc { } #[turbo_tasks::value_impl] -impl EcmascriptChunkItem for DevManifestChunkItem { +impl EcmascriptChunkItem for ManifestChunkItem { #[turbo_tasks::function] fn chunking_context(&self) -> EcmascriptChunkingContextVc { - self.context.into() + self.context } #[turbo_tasks::function] - async fn content(self_vc: DevManifestChunkItemVc) -> Result { + async fn content(self_vc: ManifestChunkItemVc) -> Result { let chunks_data = self_vc.chunks_data().await?; let chunks_data = chunks_data.iter().try_join().await?; let chunks_data: Vec<_> = chunks_data .iter() - .map(|chunk_data| chunk_data.runtime_chunk_data()) + .map(|chunk_data| EcmascriptChunkData::new(chunk_data)) .collect(); let code = formatdoc! { @@ -74,14 +70,14 @@ impl EcmascriptChunkItem for DevManifestChunkItem { } #[turbo_tasks::value_impl] -impl ChunkItem for DevManifestChunkItem { +impl ChunkItem for ManifestChunkItem { #[turbo_tasks::function] fn asset_ident(&self) -> AssetIdentVc { self.manifest.ident() } #[turbo_tasks::function] - async fn references(self_vc: DevManifestChunkItemVc) -> Result { + async fn references(self_vc: ManifestChunkItemVc) -> Result { let this = self_vc.await?; let mut references = this.manifest.references().await?.clone_value(); diff --git a/crates/turbopack-dev/src/ecmascript/manifest/loader_item.rs b/crates/turbopack-ecmascript/src/manifest/loader_item.rs similarity index 66% rename from crates/turbopack-dev/src/ecmascript/manifest/loader_item.rs rename to crates/turbopack-ecmascript/src/manifest/loader_item.rs index 2837601f193ca..5244eadab917c 100644 --- a/crates/turbopack-dev/src/ecmascript/manifest/loader_item.rs +++ b/crates/turbopack-ecmascript/src/manifest/loader_item.rs @@ -1,26 +1,25 @@ use std::io::Write as _; -use anyhow::{anyhow, bail, Result}; +use anyhow::{anyhow, Result}; use indoc::writedoc; -use turbo_tasks::{primitives::StringVc, ValueToString}; +use turbo_tasks::{primitives::StringVc, TryJoinIterExt}; use turbopack_core::{ asset::Asset, - chunk::{ChunkItem, ChunkItemVc, ChunkingContext}, + chunk::{ChunkDataVc, ChunkItem, ChunkItemVc, ChunkingContext, ChunksDataVc}, ident::AssetIdentVc, reference::{AssetReferencesVc, SingleAssetReferenceVc}, }; -use turbopack_ecmascript::{ + +use super::chunk_asset::ManifestChunkAssetVc; +use crate::{ chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, - EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, - EcmascriptChunkingContextVc, + data::EcmascriptChunkData, EcmascriptChunkItem, EcmascriptChunkItemContent, + EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, EcmascriptChunkPlaceable, + EcmascriptChunkPlaceableVc, EcmascriptChunkingContextVc, }, utils::StringifyJs, }; -use super::chunk_asset::DevManifestChunkAssetVc; -use crate::{ChunkDataOptionVc, ChunkDataVc}; - #[turbo_tasks::function] fn modifier() -> StringVc { StringVc::cell("loader".to_string()) @@ -39,52 +38,57 @@ fn modifier() -> StringVc { /// actually reached, instead of eagerly as part of the chunk that the dynamic /// import appears in. #[turbo_tasks::value] -pub struct DevManifestLoaderItem { - manifest: DevManifestChunkAssetVc, +pub struct ManifestLoaderItem { + manifest: ManifestChunkAssetVc, } #[turbo_tasks::value_impl] -impl DevManifestLoaderItemVc { +impl ManifestLoaderItemVc { #[turbo_tasks::function] - pub fn new(manifest: DevManifestChunkAssetVc) -> Self { - Self::cell(DevManifestLoaderItem { manifest }) + pub fn new(manifest: ManifestChunkAssetVc) -> Self { + Self::cell(ManifestLoaderItem { manifest }) } #[turbo_tasks::function] - pub async fn chunk_data(self) -> Result { + pub async fn chunks_data(self) -> Result { let this = self.await?; - let chunk = this.manifest.manifest_chunk(); + let chunks = this.manifest.manifest_chunks(); let manifest = this.manifest.await?; - Ok(ChunkDataVc::from_asset( + Ok(ChunkDataVc::from_assets( manifest.chunking_context.output_root(), - chunk, + chunks, )) } } #[turbo_tasks::function] -fn dev_manifest_loader_chunk_reference_description() -> StringVc { - StringVc::cell("dev manifest loader chunk".to_string()) +fn manifest_loader_chunk_reference_description() -> StringVc { + StringVc::cell("manifest loader chunk".to_string()) } #[turbo_tasks::value_impl] -impl ChunkItem for DevManifestLoaderItem { +impl ChunkItem for ManifestLoaderItem { #[turbo_tasks::function] fn asset_ident(&self) -> AssetIdentVc { self.manifest.ident().with_modifier(modifier()) } #[turbo_tasks::function] - async fn references(self_vc: DevManifestLoaderItemVc) -> Result { + async fn references(self_vc: ManifestLoaderItemVc) -> Result { let this = self_vc.await?; - let mut references = vec![SingleAssetReferenceVc::new( - this.manifest.manifest_chunk(), - dev_manifest_loader_chunk_reference_description(), - ) - .into()]; + let chunks = this.manifest.manifest_chunks(); - if let Some(chunk_data) = &*self_vc.chunk_data().await? { + let mut references: Vec<_> = chunks + .await? + .iter() + .map(|chunk| { + SingleAssetReferenceVc::new(*chunk, manifest_loader_chunk_reference_description()) + .into() + }) + .collect(); + + for chunk_data in &*self_vc.chunks_data().await? { references.extend(chunk_data.references().await?.iter().copied()); } @@ -93,14 +97,14 @@ impl ChunkItem for DevManifestLoaderItem { } #[turbo_tasks::value_impl] -impl EcmascriptChunkItem for DevManifestLoaderItem { +impl EcmascriptChunkItem for ManifestLoaderItem { #[turbo_tasks::function] async fn chunking_context(&self) -> Result { Ok(self.manifest.await?.chunking_context.into()) } #[turbo_tasks::function] - async fn content(self_vc: DevManifestLoaderItemVc) -> Result { + async fn content(self_vc: ManifestLoaderItemVc) -> Result { let this = &*self_vc.await?; let mut code = Vec::new(); @@ -111,14 +115,7 @@ impl EcmascriptChunkItem for DevManifestLoaderItem { // need the chunk path of the manifest chunk, relative from the output root. The // chunk is a servable file, which will contain the manifest chunk item, which // will perform the actual chunk traversal and generate load statements. - let chunk_server_data = if let Some(data) = &*self_vc.chunk_data().await? { - data.await? - } else { - bail!( - "chunk {} doesn't have chunk data", - this.manifest.manifest_chunk().ident().to_string().await?, - ); - }; + let chunks_server_data = &*self_vc.chunks_data().await?.iter().try_join().await?; // We also need the manifest chunk item's id, which points to a CJS module that // exports a promise for all of the necessary chunk loads. @@ -148,16 +145,21 @@ impl EcmascriptChunkItem for DevManifestLoaderItem { code, r#" __turbopack_export_value__((__turbopack_import__) => {{ - return __turbopack_load__({chunk_server_data}).then(() => {{ + return Promise.all({chunks_server_data}.map((chunk) => __turbopack_load__(chunk))).then(() => {{ return __turbopack_require__({item_id}); }}).then((chunks) => {{ - return Promise.all(chunks.map((chunk_path) => __turbopack_load__(chunk_path))); + return Promise.all(chunks.map((chunk) => __turbopack_load__(chunk))); }}).then(() => {{ return __turbopack_import__({dynamic_id}); }}); }}); "#, - chunk_server_data = StringifyJs(&chunk_server_data.runtime_chunk_data()), + chunks_server_data = StringifyJs( + &chunks_server_data + .iter() + .map(|chunk_data| EcmascriptChunkData::new(&chunk_data)) + .collect::>() + ), item_id = StringifyJs(item_id), dynamic_id = StringifyJs(dynamic_id), )?; diff --git a/crates/turbopack-dev/src/ecmascript/manifest/mod.rs b/crates/turbopack-ecmascript/src/manifest/mod.rs similarity index 100% rename from crates/turbopack-dev/src/ecmascript/manifest/mod.rs rename to crates/turbopack-ecmascript/src/manifest/mod.rs diff --git a/crates/turbopack-ecmascript/src/static_code.rs b/crates/turbopack-ecmascript/src/static_code.rs new file mode 100644 index 0000000000000..163d015c5de96 --- /dev/null +++ b/crates/turbopack-ecmascript/src/static_code.rs @@ -0,0 +1,54 @@ +use anyhow::{bail, Result}; +use turbo_tasks::Value; +use turbo_tasks_fs::FileSystemPathVc; +use turbopack_core::{ + code_builder::{CodeBuilder, CodeVc}, + context::{AssetContext, AssetContextVc}, + reference_type::ReferenceType, + source_asset::SourceAssetVc, +}; + +use crate::EcmascriptModuleAssetVc; + +/// Static ECMAScript file code, to be used as part of some code. +/// +/// Useful to transform partial runtime code files, which get concatenated into +/// the final runtime code, while keeping source map information. +#[turbo_tasks::value] +pub struct StaticEcmascriptCode { + asset_context: AssetContextVc, + asset: EcmascriptModuleAssetVc, +} + +#[turbo_tasks::value_impl] +impl StaticEcmascriptCodeVc { + /// Creates a new [`StaticEcmascriptCodeVc`]. + #[turbo_tasks::function] + pub async fn new(asset_context: AssetContextVc, asset_path: FileSystemPathVc) -> Result { + let asset = asset_context.process( + SourceAssetVc::new(asset_path).into(), + Value::new(ReferenceType::Undefined), + ); + let Some(asset) = EcmascriptModuleAssetVc::resolve_from(&asset).await? else { + bail!("asset is not an Ecmascript module") + }; + Ok(Self::cell(StaticEcmascriptCode { + asset_context, + asset, + })) + } + + /// Computes the contents of the asset and pushes it to + /// the code builder, including the source map if available. + #[turbo_tasks::function] + pub async fn code(self) -> Result { + let this = self.await?; + let runtime_base_content = this.asset.module_content_without_analysis().await?; + let mut code = CodeBuilder::default(); + code.push_source( + &runtime_base_content.inner_code, + runtime_base_content.source_map.map(|map| map.into()), + ); + Ok(CodeVc::cell(code.build())) + } +} diff --git a/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs b/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs index d602445939339..bb437e79afe59 100644 --- a/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs +++ b/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs @@ -11,9 +11,9 @@ use super::{asset::EcmascriptModulePartAssetVc, part_of_module, split_module}; use crate::{ chunk::{ EcmascriptChunkItem, EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, - EcmascriptChunkingContextVc, + EcmascriptChunkingContext, EcmascriptChunkingContextVc, }, - gen_content, + EcmascriptModuleContentVc, }; /// This is an implementation of [ChunkItem] for [EcmascriptModulePartAssetVc]. @@ -48,12 +48,17 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { let split_data = split_module(module.full_module); let parsed = part_of_module(split_data, module.part); - Ok(gen_content( - this.context, - this.module.analyze(), + let content = EcmascriptModuleContentVc::new( parsed, module.full_module.ident(), + this.context, + this.module.analyze(), availability_info, + ); + + Ok(EcmascriptChunkItemContentVc::new( + content, + this.context.has_react_refresh(), )) } diff --git a/crates/turbopack-tests/Cargo.toml b/crates/turbopack-tests/Cargo.toml index bafc54d128d1d..b8b77afa8703d 100644 --- a/crates/turbopack-tests/Cargo.toml +++ b/crates/turbopack-tests/Cargo.toml @@ -24,11 +24,13 @@ turbo-tasks = { workspace = true } turbo-tasks-env = { workspace = true } turbo-tasks-fs = { workspace = true } turbo-tasks-memory = { workspace = true } +turbopack-build = { workspace = true, features = ["test"] } turbopack-core = { workspace = true, features = ["issue_path"] } -turbopack-dev = { workspace = true } +turbopack-dev = { workspace = true, features = ["test"] } turbopack-ecmascript-plugins = { workspace = true, features = [ "transform_emotion", ] } +turbopack-ecmascript-runtime = { workspace = true } turbopack-env = { workspace = true } turbopack-test-utils = { workspace = true } diff --git a/crates/turbopack-tests/tests/snapshot.rs b/crates/turbopack-tests/tests/snapshot.rs index cff03bf154681..9f4b0524a0c79 100644 --- a/crates/turbopack-tests/tests/snapshot.rs +++ b/crates/turbopack-tests/tests/snapshot.rs @@ -28,10 +28,12 @@ use turbopack::{ transition::TransitionsByNameVc, ModuleAssetContextVc, }; +use turbopack_build::BuildChunkingContextVc; use turbopack_core::{ asset::{Asset, AssetVc}, chunk::{ - ChunkableAsset, ChunkableAssetVc, ChunkingContext, EvaluatableAssetVc, EvaluatableAssetsVc, + ChunkableAsset, ChunkableAssetVc, ChunkingContext, ChunkingContextVc, EvaluatableAssetVc, + EvaluatableAssetsVc, }, compile_time_defines, compile_time_info::CompileTimeInfo, @@ -47,13 +49,20 @@ use turbopack_ecmascript_plugins::transform::{ emotion::{EmotionTransformConfig, EmotionTransformer}, styled_components::{StyledComponentsTransformConfig, StyledComponentsTransformer}, }; +use turbopack_ecmascript_runtime::RuntimeType; use turbopack_env::ProcessEnvAssetVc; use turbopack_test_utils::snapshot::{diff, expected, matches_expected, snapshot_issues}; fn register() { + turbo_tasks::register(); + turbo_tasks_env::register(); + turbo_tasks_fs::register(); turbopack::register(); + turbopack_build::register(); turbopack_dev::register(); + turbopack_env::register(); turbopack_ecmascript_plugins::register(); + turbopack_ecmascript_runtime::register(); include!(concat!(env!("OUT_DIR"), "/register_test_snapshot.rs")); } @@ -71,11 +80,23 @@ static WORKSPACE_ROOT: Lazy = Lazy::new(|| { }); #[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] struct SnapshotOptions { #[serde(default = "default_browserslist")] browserslist: String, #[serde(default = "default_entry")] entry: String, + #[serde(default)] + runtime: Runtime, + #[serde(default = "default_runtime_type")] + runtime_type: RuntimeType, +} + +#[derive(Debug, Deserialize, Default)] +enum Runtime { + #[default] + Dev, + Build, } impl Default for SnapshotOptions { @@ -83,6 +104,8 @@ impl Default for SnapshotOptions { SnapshotOptions { browserslist: default_browserslist(), entry: default_entry(), + runtime: Default::default(), + runtime_type: default_runtime_type(), } } } @@ -97,6 +120,14 @@ fn default_entry() -> String { "input/index.js".to_owned() } +fn default_runtime_type() -> RuntimeType { + // We don't want all snapshot tests to also include the runtime every time, + // as this would be a lot of extra noise whenever we make a single change to + // the runtime. Instead, we only include the runtime in snapshots that + // specifically request it via "runtime": "Default". + RuntimeType::Dummy +} + #[testing::fixture("tests/snapshot/*/*/")] fn test(resource: PathBuf) { let resource = canonicalize(resource).unwrap(); @@ -257,9 +288,28 @@ async fn run_test(resource: &str) -> Result { let chunk_root_path = path.join("output"); let static_root_path = path.join("static"); - let chunking_context = - DevChunkingContextVc::builder(project_root, path, chunk_root_path, static_root_path, env) - .build(); + let chunking_context: ChunkingContextVc = match options.runtime { + Runtime::Dev => DevChunkingContextVc::builder( + project_root, + path, + chunk_root_path, + static_root_path, + env, + ) + .runtime_type(options.runtime_type) + .build() + .into(), + Runtime::Build => BuildChunkingContextVc::builder( + project_root, + path, + chunk_root_path, + static_root_path, + env, + ) + .runtime_type(options.runtime_type) + .build() + .into(), + }; let expected_paths = expected(chunk_root_path) .await? diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_bar_index_c8a3ce.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_bar_index_c8a3ce.js index dd42f965427ed..052122280c48e 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_bar_index_c8a3ce.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_bar_index_c8a3ce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/20803_bar_index_c8a3ce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/bar/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/bar/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "bar": ()=>bar diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_foo_index_5f9e1e.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_foo_index_5f9e1e.js index 3496950254509..bd904abbff469 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_foo_index_5f9e1e.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_foo_index_5f9e1e.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/20803_foo_index_5f9e1e.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "foo": ()=>foo diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js index 7b1e75eb42bc9..5dbe7de9fefde 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__([ { diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js index d80bcd5d793c1..7564c6a4047da 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$async_chunk$2f$input$2f$node_modules$2f$foo$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/foo/index.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$async_chunk$2f$input$2f$node_modules$2f$bar$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/bar/index.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_e0f91a.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_e0f91a.js new file mode 100644 index 0000000000000..64be0bd3af4d0 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_e0f91a.js @@ -0,0 +1,11 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_e0f91a.js", + {}, +]); +(globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ + "path": "output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_e0f91a.js", + "chunks": [ + "output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js" + ], + "source": "dynamic" +}); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_0d348e.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_0d348e.js index 67e3df5963889..b1f18dabab604 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_0d348e.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_0d348e.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/index.js (ecmascript)"]},{"path":"output/20803_bar_index_c8a3ce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/bar/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js index a0072ea486c81..b31762f5e984d 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js @@ -1,23 +1,23 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__((__turbopack_import__) => { - return __turbopack_load__({"path":"output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js","included":["[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk)"]}).then(() => { + return Promise.all([{"path":"output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js","included":["[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk)"]},"output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_e0f91a.js"].map((chunk) => __turbopack_load__(chunk))).then(() => { return __turbopack_require__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk)"); }).then((chunks) => { - return Promise.all(chunks.map((chunk_path) => __turbopack_load__(chunk_path))); + return Promise.all(chunks.map((chunk) => __turbopack_load__(chunk))); }).then(() => { return __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript)"); }); }); })()), -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/shared.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/shared.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$async_chunk$2f$input$2f$node_modules$2f$bar$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/bar/index.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$async_chunk$2f$input$2f$shared$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/shared.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/39e84_foo_index_4427e1.js b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/39e84_foo_index_4427e1.js index 7b2e7f7e8df33..ab71ba8cbe64f 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/39e84_foo_index_4427e1.js +++ b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/39e84_foo_index_4427e1.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/39e84_foo_index_4427e1.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "foo": ()=>foo diff --git a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js index d3d0d4cb321b8..c6483998cbffd 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$chunked$2f$input$2f$node_modules$2f$foo$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/node_modules/foo/index.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_e77e9f.js b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_e77e9f.js index 35770e1121614..a79ae22dbc06c 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_e77e9f.js +++ b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_e77e9f.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/index.js (ecmascript)"]},{"path":"output/39e84_foo_index_4427e1.js","included":["[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/node_modules/foo/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b1f0c2.js b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b1f0c2.js index b3526d8ff9a51..15daa5a53bd7b 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b1f0c2.js +++ b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b1f0c2.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/index.js (ecmascript)"]},{"path":"output/d1787_foo_index_dd389c.js","included":["[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/node_modules/foo/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js index a4414e220af1a..c5752e6dde5e2 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$shebang$2f$input$2f$node_modules$2f$foo$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/node_modules/foo/index.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/d1787_foo_index_dd389c.js b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/d1787_foo_index_dd389c.js index 6bcf5f5c08750..0a6ccdaeb21f8 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/d1787_foo_index_dd389c.js +++ b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/d1787_foo_index_dd389c.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/d1787_foo_index_dd389c.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "foo": ()=>foo diff --git a/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_6b0d2b.js b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_6b0d2b.js index 21a3fd426bba9..7967926d94813 100644 --- a/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_6b0d2b.js +++ b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_6b0d2b.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js index e2d14541ae402..556d6169fb21b 100644 --- a/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { if ("TURBOPACK compile-time truthy", 1) { console.log('DEFINED_VALUE'); diff --git a/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js index 0eb7d5b0c1288..1acb0655144ff 100644 --- a/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { ; diff --git a/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_fa9a30.js b/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_fa9a30.js index 93acd8dba7818..c81343827dcfa 100644 --- a/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_fa9a30.js +++ b/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_fa9a30.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/input/index.js (ecmascript)"]},{"path":"output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index.css","included":["[project]/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/input/index.css (css)"],"moduleChunks":["output/a587c_tests_snapshot_css_absolute-uri-import_input_withduplicateurl_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_other_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_other_c9a116.css","output/a587c_tests_snapshot_css_absolute-uri-import_input_withduplicateurl_c9a116.css"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_b5a149.css b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_b5a149.css similarity index 69% rename from crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_b5a149.css rename to crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_b5a149.css index b0d421d010a57..fe483417d7fe2 100644 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_b5a149.css +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_b5a149.css @@ -1,8 +1,8 @@ -/* chunk [workspace]/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_b5a149.css */ +/* chunk [workspace]/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_b5a149.css */ /* [project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css, css module) */ .foo-module-style__style__abf9e738 { color: blue; } -/*# sourceMappingURL=8697f_foo_style.module_b5a149.css.map*/ \ No newline at end of file +/*# sourceMappingURL=8697f_foo_style_module_b5a149.css.map*/ \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_b5a149.css.map b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_b5a149.css.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_b5a149.css.map rename to crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_b5a149.css.map diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module.css_7740ee._.js b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_css_7740ee._.js similarity index 75% rename from crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module.css_7740ee._.js rename to crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_css_7740ee._.js index 7a73e42c24e39..b8ff62e899ead 100644 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module.css_7740ee._.js +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_css_7740ee._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/8697f_foo_style.module.css_7740ee._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/8697f_foo_style_module_css_7740ee._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__({ "foo-module-style": "foo-module-style__style__abf9e738", @@ -9,4 +9,4 @@ __turbopack_export_value__({ })()), }]); -//# sourceMappingURL=8697f_foo_style.module.css_7740ee._.js.map \ No newline at end of file +//# sourceMappingURL=8697f_foo_style_module_css_7740ee._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module.css_7740ee._.js.map b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_css_7740ee._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module.css_7740ee._.js.map rename to crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_css_7740ee._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_fb38f0.css b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_fb38f0.css similarity index 74% rename from crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_fb38f0.css rename to crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_fb38f0.css index 119d606baa0c4..c3e49b9995fe1 100644 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_fb38f0.css +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_fb38f0.css @@ -2,4 +2,4 @@ .foo-module-style__style__abf9e738 { color: blue; } -/*# sourceMappingURL=8697f_foo_style.module_fb38f0.css.map*/ \ No newline at end of file +/*# sourceMappingURL=8697f_foo_style_module_fb38f0.css.map*/ \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_fb38f0.css.map b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_fb38f0.css.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style.module_fb38f0.css.map rename to crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_fb38f0.css.map diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_011705.js b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_011705.js new file mode 100644 index 0000000000000..43c13cb0ef627 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_011705.js @@ -0,0 +1,6 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/crates_turbopack-tests_tests_snapshot_css_css_input_index_011705.js", + {}, + {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/index.js (ecmascript)"]},{"path":"output/8697f_foo_style_module_css_7740ee._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)"]},{"path":"output/8697f_foo_style.css","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.css (css)"],"moduleChunks":["output/8697f_foo_style_c9a116.css"]},{"path":"output/crates_turbopack-tests_tests_snapshot_css_css_input_style.css","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.css (css)"],"moduleChunks":["output/crates_turbopack-tests_tests_snapshot_css_css_input_imported_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_css_input_style_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_css_input_imported_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_css_input_imported_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_css_input_imported_c9a116.css"]},{"path":"output/8697f_foo_style_module_b5a149.css","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css, css module)"],"moduleChunks":["output/8697f_foo_style_module_fb38f0.css"]},{"path":"output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.module.css (css, css module)"],"moduleChunks":["output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_fb38f0.css"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/index.js (ecmascript)"]} +]); +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_37a138.js.map b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_011705.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_37a138.js.map rename to crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_011705.js.map diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_37a138.js b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_37a138.js deleted file mode 100644 index 007b7a651beb4..0000000000000 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_37a138.js +++ /dev/null @@ -1,1738 +0,0 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/crates_turbopack-tests_tests_snapshot_css_css_input_index_37a138.js", - {}, - {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/index.js (ecmascript)"]},{"path":"output/8697f_foo_style.module.css_7740ee._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)"]},{"path":"output/8697f_foo_style.css","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.css (css)"],"moduleChunks":["output/8697f_foo_style_c9a116.css"]},{"path":"output/crates_turbopack-tests_tests_snapshot_css_css_input_style.css","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.css (css)"],"moduleChunks":["output/crates_turbopack-tests_tests_snapshot_css_css_input_imported_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_css_input_style_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_css_input_imported_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_css_input_imported_c9a116.css","output/crates_turbopack-tests_tests_snapshot_css_css_input_imported_c9a116.css"]},{"path":"output/8697f_foo_style.module_b5a149.css","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css, css module)"],"moduleChunks":["output/8697f_foo_style.module_fb38f0.css"]},{"path":"output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css","included":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.module.css (css, css module)"],"moduleChunks":["output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_fb38f0.css"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/css/css/input/index.js (ecmascript)"]} -]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_469b46.js b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_41af4f.js similarity index 77% rename from crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_469b46.js rename to crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_41af4f.js index bf3446711661e..b75d97fd9af61 100644 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_469b46.js +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_41af4f.js @@ -1,16 +1,16 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/crates_turbopack-tests_tests_snapshot_css_css_input_index_469b46.js", + "output/crates_turbopack-tests_tests_snapshot_css_css_input_index_41af4f.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/crates_turbopack-tests_tests_snapshot_css_css_input_index_469b46.js", + "path": "output/crates_turbopack-tests_tests_snapshot_css_css_input_index_41af4f.js", "chunks": [ "output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js", - "output/8697f_foo_style.module.css_7740ee._.js", + "output/8697f_foo_style_module_css_7740ee._.js", "output/8697f_foo_style.css", "output/crates_turbopack-tests_tests_snapshot_css_css_input_style.css", - "output/8697f_foo_style.module_b5a149.css", - "output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css" + "output/8697f_foo_style_module_b5a149.css", + "output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css" ], "source": "entry" }); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js index ff97561470eca..4e0eeab49dd84 100644 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.module.css (css module)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.module.css (css module)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__({ "another-composed-module-style": "another-composed-module-style__style__9bcf751c" + " " + __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)")["foo-module-style"], @@ -10,7 +10,7 @@ __turbopack_export_value__({ }); })()), -"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$css$2f$css$2f$input$2f$node_modules$2f$foo$2f$style$2e$module$2e$css__$28$css__module$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$css$2f$css$2f$input$2f$style$2e$module$2e$css__$28$css__module$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.module.css (css module)"); diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css similarity index 90% rename from crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css rename to crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css index 50ba1381ff20c..8248098dc11c0 100644 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css @@ -1,4 +1,4 @@ -/* chunk [workspace]/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css */ +/* chunk [workspace]/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css */ /* [project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.module.css (css, css module) */ .module-style__style__9bcf751c { color: magenta; @@ -15,4 +15,4 @@ } -/*# sourceMappingURL=crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css.map*/ \ No newline at end of file +/*# sourceMappingURL=crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css.map*/ \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css.map b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_b5a149.css.map rename to crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_b5a149.css.map diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_fb38f0.css b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_fb38f0.css similarity index 92% rename from crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_fb38f0.css rename to crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_fb38f0.css index bb6b71ea353ff..da7abc9a5bc75 100644 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_fb38f0.css +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_fb38f0.css @@ -12,4 +12,4 @@ .another-composed-module-style__style__9bcf751c { color: yellow; } -/*# sourceMappingURL=crates_turbopack-tests_tests_snapshot_css_css_input_style.module_fb38f0.css.map*/ \ No newline at end of file +/*# sourceMappingURL=crates_turbopack-tests_tests_snapshot_css_css_input_style_module_fb38f0.css.map*/ \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_fb38f0.css.map b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_fb38f0.css.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style.module_fb38f0.css.map rename to crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_style_module_fb38f0.css.map diff --git a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_index_a1c0c3.js b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_index_a1c0c3.js index 5ed78d38aa99c..b4b402485ab5b 100644 --- a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_index_a1c0c3.js +++ b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_index_a1c0c3.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_@emotion_react_index_a1c0c3.js", { -"[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "@emtion/react/index.js"; diff --git a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_jsx-dev-runtime_73b602.js b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_jsx-dev-runtime_73b602.js index b84fa110bff9d..fcc663afd65c8 100644 --- a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_jsx-dev-runtime_73b602.js +++ b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_jsx-dev-runtime_73b602.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_@emotion_react_jsx-dev-runtime_73b602.js", { -"[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/jsx-dev-runtime.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/jsx-dev-runtime.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "@emtion/react/jsx-dev-runtime.js"; diff --git a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_styled_index_fd4de2.js b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_styled_index_fd4de2.js index 6a13387f68078..0bf03cd394310 100644 --- a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_styled_index_fd4de2.js +++ b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_styled_index_fd4de2.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_@emotion_styled_index_fd4de2.js", { -"[project]/crates/turbopack-tests/tests/node_modules/@emotion/styled/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/@emotion/styled/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "@emtion/styled/index.js"; diff --git a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b080c4.js b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b080c4.js index 9a40e3c27baf7..b21a22a1b3541 100644 --- a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b080c4.js +++ b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b080c4.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/63a02_@emotion_react_jsx-dev-runtime_73b602.js","included":["[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/jsx-dev-runtime.js (ecmascript)"]},{"path":"output/63a02_@emotion_react_index_a1c0c3.js","included":["[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/index.js (ecmascript)"]},{"path":"output/63a02_@emotion_styled_index_fd4de2.js","included":["[project]/crates/turbopack-tests/tests/node_modules/@emotion/styled/index.js (ecmascript)"]},{"path":"output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/emotion/emotion/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/emotion/emotion/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js index 8d730c7fc1547..a6f054d974868 100644 --- a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/emotion/emotion/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/emotion/emotion/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f40$emotion$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/jsx-dev-runtime.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f40$emotion$2f$react$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/index.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js similarity index 72% rename from crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js rename to crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js index bbd886747f276..a073ed71afcf1 100644 --- a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/env/env/input/.env/.env.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/env/env/input/.env/.env.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const env = process.env = { ...process.env @@ -11,4 +11,4 @@ env["FOOBAR"] = foobar; }.call(this) }), }]); -//# sourceMappingURL=crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js.map \ No newline at end of file +//# sourceMappingURL=crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js.map b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js.map rename to crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js.map diff --git a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_29a23f.js b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_29a23f.js deleted file mode 100644 index 940fd535b1e8a..0000000000000 --- a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_29a23f.js +++ /dev/null @@ -1,1738 +0,0 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/crates_turbopack-tests_tests_snapshot_env_env_input_index_29a23f.js", - {}, - {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/env/env/input/index.js (ecmascript)"]},{"path":"output/crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/env/env/input/.env/.env.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/env/env/input/.env/.env.js (ecmascript)","[project]/crates/turbopack-tests/tests/snapshot/env/env/input/index.js (ecmascript)"]} -]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_936aa9.js b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_84512e.js similarity index 88% rename from crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_936aa9.js rename to crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_84512e.js index d2b6f6222469d..2336120582e64 100644 --- a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_936aa9.js +++ b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_84512e.js @@ -1,12 +1,12 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/crates_turbopack-tests_tests_snapshot_env_env_input_index_936aa9.js", + "output/crates_turbopack-tests_tests_snapshot_env_env_input_index_84512e.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/crates_turbopack-tests_tests_snapshot_env_env_input_index_936aa9.js", + "path": "output/crates_turbopack-tests_tests_snapshot_env_env_input_index_84512e.js", "chunks": [ "output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js", - "output/crates_turbopack-tests_tests_snapshot_env_env_input_.env_.env_b53fce.js" + "output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js" ], "source": "entry" }); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_8a0be0.js b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_8a0be0.js new file mode 100644 index 0000000000000..70d2dede604a1 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_8a0be0.js @@ -0,0 +1,6 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/crates_turbopack-tests_tests_snapshot_env_env_input_index_8a0be0.js", + {}, + {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/env/env/input/index.js (ecmascript)"]},{"path":"output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/env/env/input/.env/.env.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/env/env/input/.env/.env.js (ecmascript)","[project]/crates/turbopack-tests/tests/snapshot/env/env/input/index.js (ecmascript)"]} +]); +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_29a23f.js.map b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_8a0be0.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_29a23f.js.map rename to crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_8a0be0.js.map diff --git a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js index a73a7f988231a..268b4a68dcb46 100644 --- a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/env/env/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/env/env/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { console.log(process.env.FOOBAR); diff --git a/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js index 1ac4ea07743b6..525689736b00d 100644 --- a/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { console.log("hello world"); diff --git a/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_f59cc7.js b/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_f59cc7.js index 00d9330d5d92e..761ca75719015 100644 --- a/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_f59cc7.js +++ b/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_f59cc7.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_78b6bf.js b/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_78b6bf.js index b5e8880764033..9ff2e22b73134 100644 --- a/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_78b6bf.js +++ b/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_78b6bf.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/example/example/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/example/example/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js index 634665c0aa8fc..c59446b32b5e4 100644 --- a/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/example/example/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/example/example/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { console.log("hello world"); diff --git a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_289ae7.js b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_289ae7.js index 076674a4c8ff5..f139197c4787e 100644 --- a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_289ae7.js +++ b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_289ae7.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js index e566f531a9f85..3ee6384c2a39f 100644 --- a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/commonjs.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/commonjs.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { exports.hello = "World"; }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/c.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/c.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({}); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$2$2f$input$2f$commonjs$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/commonjs.js (ecmascript)"); @@ -14,7 +14,7 @@ __turbopack_cjs__(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turb ; })()), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/b.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/b.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({}); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$2$2f$input$2f$c$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/c.js (ecmascript)"); @@ -23,7 +23,7 @@ __turbopack_cjs__(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turb ; })()), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$2$2f$input$2f$b$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/b.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_3e96b7.js b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_3e96b7.js index 5f9df13220446..c367ef3fc0e21 100644 --- a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_3e96b7.js +++ b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_3e96b7.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js index 7d65f44072f47..148378f6ec471 100644 --- a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/exported.cjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/exported.cjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { module.exports = { foo: 1, @@ -8,7 +8,7 @@ module.exports = { }; }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/mod.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/mod.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({}); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$script$2f$input$2f$exported$2e$cjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/exported.cjs (ecmascript)"); @@ -18,7 +18,7 @@ __turbopack_cjs__(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turb console.log('Hoist test'); })()), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$script$2f$input$2f$mod$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/mod.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_537553.js b/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_537553.js index be59d90b341b6..0d96482b1c015 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_537553.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_537553.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js index 246f6e1c25de8..d8c26b474bc39 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/mod.cjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/mod.cjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/mod.cjs" @@ -9,7 +9,7 @@ const __TURBOPACK__import$2e$meta__ = { console.log(__TURBOPACK__import$2e$meta__.url); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$cjs$2f$input$2f$mod$2e$cjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/mod.cjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js index 189aa9b3a346b..c711a4b4fb664 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/mod.mjs" @@ -16,7 +16,7 @@ foo(); bar(); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$esm$2d$multiple$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_c00392.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_c00392.js index d6f027efb234b..695e4449271f8 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_c00392.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_c00392.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_6c9201.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_6c9201.js index c9b2cfbc731b7..07051cbffd5dc 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_6c9201.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_6c9201.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js index e33b845b65f11..c2e00df40bf3b 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/mod.mjs" @@ -9,7 +9,7 @@ const __TURBOPACK__import$2e$meta__ = { __TURBOPACK__import$2e$meta__.foo = 1; }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$esm$2d$mutable$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_6fcf7d.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_6fcf7d.js index 19af0fa2736fb..cf76459ff9cad 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_6fcf7d.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_6fcf7d.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js index b7435148efb52..7718863a7760c 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/mod.mjs" @@ -9,7 +9,7 @@ const __TURBOPACK__import$2e$meta__ = { console.log(__TURBOPACK__import$2e$meta__); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$esm$2d$object$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js index b477cfcceda6a..1ef0d068f75de 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/mod.mjs" @@ -9,7 +9,7 @@ const __TURBOPACK__import$2e$meta__ = { console.log(__TURBOPACK__import$2e$meta__.url); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$esm$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_c4c88a.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_c4c88a.js index 54ba2a78ff9a1..03b171fc957ae 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_c4c88a.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_c4c88a.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_988b57.js b/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_988b57.js index e8716224cd143..e53a977f20f38 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_988b57.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_988b57.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js index fb5349294207e..e45d06c4a7f10 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js @@ -1,10 +1,10 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/asset.txt (static)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/asset.txt (static)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__("/crates/turbopack-tests/tests/snapshot/import-meta/url/static/asset.05254cf2.txt"); })()), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/url/input/mod.mjs" @@ -15,7 +15,7 @@ console.log(assetUrl); fetch(assetUrl).then((res)=>res.text()).then(console.log); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$url$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_45c162.js b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_45c162.js index 72e7915a5132e..d86c70317a303 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_45c162.js +++ b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_45c162.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js index 045b70360ea03..878240bfea8f8 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js @@ -1,19 +1,19 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__((__turbopack_import__) => { - return __turbopack_load__({"path":"output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_4e74d3._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk)"]}).then(() => { + return Promise.all([{"path":"output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk)"]},"output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_36739f._.js"].map((chunk) => __turbopack_load__(chunk))).then(() => { return __turbopack_require__("[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk)"); }).then((chunks) => { - return Promise.all(chunks.map((chunk_path) => __turbopack_load__(chunk_path))); + return Promise.all(chunks.map((chunk) => __turbopack_load__(chunk))); }).then(() => { return __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript)"); }); }); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { __turbopack_require__("[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)")(__turbopack_import__).then(console.log); diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_1e2f57._.js b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_36739f._.js similarity index 78% rename from crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_1e2f57._.js rename to crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_36739f._.js index 1b2b157d7effd..9389bbcd0e244 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_1e2f57._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_36739f._.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_1e2f57._.js", + "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_36739f._.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_1e2f57._.js", + "path": "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_36739f._.js", "chunks": [ - "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js" + "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js" ], "source": "dynamic" }); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_4e74d3._.js b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js similarity index 83% rename from crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_4e74d3._.js rename to crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js index 8063210437fec..40dc3612284e4 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_4e74d3._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js @@ -1,15 +1,15 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_4e74d3._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__([ { - "path": "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js", + "path": "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js", "included": [ "[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript)" ] }, - "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_1e2f57._.js" + "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_d4d527._.js" ]); })()), diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_4e74d3._.js.map b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_4e74d3._.js.map rename to crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js similarity index 77% rename from crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js rename to crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js index 552ff8f97ab0d..292ed781234c7 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -10,4 +10,4 @@ const __TURBOPACK__default__export__ = "turbopack"; })()), }]); -//# sourceMappingURL=crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js.map \ No newline at end of file +//# sourceMappingURL=crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js.map b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel.mjs_536504._.js.map rename to crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_d4d527._.js b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_d4d527._.js new file mode 100644 index 0000000000000..7340760b7d2ec --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_d4d527._.js @@ -0,0 +1,11 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_d4d527._.js", + {}, +]); +(globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ + "path": "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_d4d527._.js", + "chunks": [ + "output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js" + ], + "source": "dynamic" +}); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-5f72a6.txt b/crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-b5c990.txt similarity index 59% rename from crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-5f72a6.txt rename to crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-b5c990.txt index 96d6665e07bcb..a3290a6eaf2cd 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-5f72a6.txt +++ b/crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-b5c990.txt @@ -3,7 +3,7 @@ PlainIssue { context: "[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json", category: "code generation", title: "Code generation for chunk item errored", - description: "An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n\nCaused by:\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n- Execution of module_factory failed\n- Execution of JsonChunkItem::content failed\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n at nested.?\n 1 | {\n 2 | \"nested\": {\n | v\n 3 + \"this-is\": \"invalid\" // lint-staged will remove trailing commas, so here's a comment\n | ^\n 4 | }\n 5 | }", + description: "An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n\nCaused by:\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n- Execution of EcmascriptChunkItemContentVc::module_factory failed\n- Execution of JsonChunkItem::content failed\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n at nested.?\n 1 | {\n 2 | \"nested\": {\n | v\n 3 + \"this-is\": \"invalid\" // lint-staged will remove trailing commas, so here's a comment\n | ^\n 4 | }\n 5 | }", detail: "", documentation_link: "", source: None, diff --git a/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_961ae2.js b/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_961ae2.js index 10f02270be3c2..82979f5f51001 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_961ae2.js +++ b/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_961ae2.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js index 1688834c38d2f..39f0840fe9233 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js @@ -2,14 +2,14 @@ "[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)": (() => {{ -throw new Error("An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n\nCaused by:\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n- Execution of module_factory failed\n- Execution of JsonChunkItem::content failed\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n at nested.?\n 1 | {\n 2 | \"nested\": {\n | v\n 3 + \"this-is\": \"invalid\" // lint-staged will remove trailing commas, so here's a comment\n | ^\n 4 | }\n 5 | }"); +throw new Error("An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n\nCaused by:\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n- Execution of EcmascriptChunkItemContentVc::module_factory failed\n- Execution of JsonChunkItem::content failed\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n at nested.?\n 1 | {\n 2 | \"nested\": {\n | v\n 3 + \"this-is\": \"invalid\" // lint-staged will remove trailing commas, so here's a comment\n | ^\n 4 | }\n 5 | }"); }}), -"[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/package.json (json)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/package.json (json)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__(JSON.parse("{\"name\":\"json-snapshot\"}")); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$json$2f$input$2f$package$2e$json__$28$json$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/package.json (json)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$json$2f$input$2f$invalid$2e$json__$28$json$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)"); diff --git a/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_9cd22f.js b/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_9cd22f.js index b750b8e5a20b0..e917b4f9004e4 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_9cd22f.js +++ b/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_9cd22f.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_9cd22f.js.map b/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_9cd22f.js.map index f3efabbe00c39..a12b83d3337ca 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_9cd22f.js.map +++ b/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_9cd22f.js.map @@ -1,4 +1,4 @@ { "version": 3, "sections": [] -} +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js index 5cac983b0de78..952ef49995225 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js @@ -1,10 +1,10 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.json (json)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.json (json)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__(JSON.parse("{\"js\":false}")); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -14,7 +14,7 @@ const __TURBOPACK__default__export__ = { }; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$order$2f$input$2f$posts$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.ts (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; @@ -27,4 +27,4 @@ if (!__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$test })()), }]); -//# sourceMappingURL=crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js.map +//# sourceMappingURL=crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js index 899816da356ef..995f72f5bb3ef 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const dne = __turbopack_require__((()=>{ const e = new Error("Cannot find module 'does-not-exist/path'"); diff --git a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_f8412b.js b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_f8412b.js index 4a119e898371a..5138c8c6023f8 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_f8412b.js +++ b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_f8412b.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_0b3e45.js b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_0b3e45.js index 45f6682203864..86b27a7b46800 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_0b3e45.js +++ b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_0b3e45.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js index 580490769ea50..9219f3a17146f 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { (()=>{ const e = new Error("Cannot find module 'does-not-exist/path'"); diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js index 40ee4cf588247..b77b2c4c7788b 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js @@ -1,19 +1,19 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__((__turbopack_import__) => { - return __turbopack_load__({"path":"output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_10fe7a._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk)"]}).then(() => { + return Promise.all([{"path":"output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk)"]},"output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_84c275._.js"].map((chunk) => __turbopack_load__(chunk))).then(() => { return __turbopack_require__("[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk)"); }).then((chunks) => { - return Promise.all(chunks.map((chunk_path) => __turbopack_load__(chunk_path))); + return Promise.all(chunks.map((chunk) => __turbopack_load__(chunk))); }).then(() => { return __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)"); }); }); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -21,7 +21,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "turbopack"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$static$2d$and$2d$dynamic$2f$input$2f$vercel$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_ec8693.js b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_ec8693.js index 2225c2e14d034..2e5e8d3351642 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_ec8693.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_ec8693.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_10fe7a._.js b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js similarity index 79% rename from crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_10fe7a._.js rename to crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js index 0642b9388d080..8ca2a6dcfdc25 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_10fe7a._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js @@ -1,15 +1,15 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_10fe7a._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__([ { - "path": "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js", + "path": "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js", "included": [ "[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)" ] }, - "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_b21398._.js" + "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_ab3761._.js" ]); })()), diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_10fe7a._.js.map b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_10fe7a._.js.map rename to crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js similarity index 80% rename from crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js rename to crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js index 1f7563eb5c0fb..c3a0c69bbee44 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -10,4 +10,4 @@ const __TURBOPACK__default__export__ = "turbopack"; })()), }]); -//# sourceMappingURL=a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js.map \ No newline at end of file +//# sourceMappingURL=a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js.map b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js.map rename to crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_b21398._.js b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_84c275._.js similarity index 81% rename from crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_b21398._.js rename to crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_84c275._.js index 70d747ea1832c..a3f28d2b7dea8 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_b21398._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_84c275._.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_b21398._.js", + "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_84c275._.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_b21398._.js", + "path": "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_84c275._.js", "chunks": [ - "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel.mjs_26aaf6._.js" + "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js" ], "source": "dynamic" }); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_ab3761._.js b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_ab3761._.js new file mode 100644 index 0000000000000..b25984d5b3683 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_ab3761._.js @@ -0,0 +1,11 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_ab3761._.js", + {}, +]); +(globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ + "path": "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_ab3761._.js", + "chunks": [ + "output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js" + ], + "source": "dynamic" +}); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_885269.js b/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_885269.js index 152c7e714acd1..df7aab2925d77 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_885269.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_885269.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js index d9f4bf425e0f1..bfb4ecbd29871 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js @@ -1,10 +1,10 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/vercel.svg (static)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/vercel.svg (static)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__("/crates/turbopack-tests/tests/snapshot/imports/static/static/vercel.957b9b16.svg"); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$static$2f$input$2f$vercel$2e$svg__$28$static$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/vercel.svg (static)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_31b659.js b/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_31b659.js index 53fe46a525bae..893b289c95793 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_31b659.js +++ b/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_31b659.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js index 8d81e144627c8..b722dfcef59c8 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/require.cjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/require.cjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { module.exports = "require"; }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/import.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/import.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -13,7 +13,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "import"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/pat.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/pat.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -21,7 +21,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "pat"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/dep/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/dep/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -29,7 +29,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "dep"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/foo.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/foo.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -37,7 +37,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "foo"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$subpath$2d$imports$2f$input$2f$foo$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/foo.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$subpath$2d$imports$2f$input$2f$dep$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/dep/index.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_667edf.js b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_667edf.js index 1dd789077ec36..3683242358c22 100644 --- a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_667edf.js +++ b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_667edf.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js index c6188ef10ff91..8b0fc5e0ac737 100644 --- a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__external__node$3a$fs__ = __turbopack_external_require__("node:fs", true); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js new file mode 100644 index 0000000000000..a8141d3b18d34 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js @@ -0,0 +1 @@ +console.log("Hello, world!"); diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/options.json b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/options.json new file mode 100644 index 0000000000000..07c8bcb1bcb64 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/options.json @@ -0,0 +1,4 @@ +{ + "runtime": "Build", + "runtimeType": "Default" +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js new file mode 100644 index 0000000000000..d409bc3eda3c5 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js @@ -0,0 +1,4 @@ +const CHUNK_PUBLIC_PATH = "output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js"; +const runtime = require("./[turbopack]_runtime.js"); +runtime.loadChunk("output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js"); +runtime.getOrInstantiateRuntimeModule("[project]/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js (ecmascript)", CHUNK_PUBLIC_PATH); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_0aa04e._.js.map b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_0aa04e._.js.map rename to crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js.map diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js new file mode 100644 index 0000000000000..0c44b4c604322 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js @@ -0,0 +1,11 @@ +module.exports = { + +"[project]/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, m: module, e: exports }) { !function() { + +console.log("Hello, world!"); + +}.call(this) }), + +}; + +//# sourceMappingURL=79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js.map b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js.map new file mode 100644 index 0000000000000..8fc8e4284ebea --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js.map @@ -0,0 +1,6 @@ +{ + "version": 3, + "sections": [ + {"offset": {"line": 4, "column": 0}, "map": {"version":3,"sources":["/turbopack/[project]/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js"],"sourcesContent":["console.log(\"Hello, world!\");\n"],"names":[],"mappings":"AAAA,QAAQ,IAAI"}}, + {"offset": {"line": 5, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":"A"}}] +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js new file mode 100644 index 0000000000000..7f4c2100e8ae9 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js @@ -0,0 +1,256 @@ +const RUNTIME_PUBLIC_PATH = "output/[turbopack]_runtime.js"; +; +; +; +; +; +const hasOwnProperty = Object.prototype.hasOwnProperty; +const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; +function defineProp(obj, name, options) { + if (!hasOwnProperty.call(obj, name)) Object.defineProperty(obj, name, options); +} +function esm(exports, getters) { + defineProp(exports, "__esModule", { + value: true + }); + if (toStringTag) defineProp(exports, toStringTag, { + value: "Module" + }); + for(const key in getters){ + defineProp(exports, key, { + get: getters[key], + enumerable: true + }); + } +} +function esmExport(module, getters) { + esm(module.namespaceObject = module.exports, getters); +} +function cjsExport(exports, props) { + for(const key in props){ + defineProp(exports, key, { + get: ()=>props[key], + enumerable: true + }); + } +} +function exportValue(module, value) { + module.exports = value; +} +function exportNamespace(module, namespace) { + module.exports = module.namespaceObject = namespace; +} +function createGetter(obj, key) { + return ()=>obj[key]; +} +const getProto = Object.getPrototypeOf ? (obj)=>Object.getPrototypeOf(obj) : (obj)=>obj.__proto__; +const LEAF_PROTOTYPES = [ + null, + getProto({}), + getProto([]), + getProto(getProto) +]; +function interopEsm(raw, ns, allowExportDefault) { + const getters = Object.create(null); + for(let current = raw; (typeof current === "object" || typeof current === "function") && !LEAF_PROTOTYPES.includes(current); current = getProto(current)){ + for (const key of Object.getOwnPropertyNames(current)){ + getters[key] = createGetter(raw, key); + } + } + if (!(allowExportDefault && "default" in getters)) { + getters["default"] = ()=>raw; + } + esm(ns, getters); +} +function esmImport(sourceModule, id) { + const module = getOrInstantiateModuleFromParent(id, sourceModule); + if (module.error) throw module.error; + if (module.namespaceObject) return module.namespaceObject; + const raw = module.exports; + const ns = module.namespaceObject = {}; + interopEsm(raw, ns, raw.__esModule); + return ns; +} +function commonJsRequire(sourceModule, id) { + const module = getOrInstantiateModuleFromParent(id, sourceModule); + if (module.error) throw module.error; + return module.exports; +} +function requireContext(sourceModule, map) { + function requireContext(id) { + const entry = map[id]; + if (!entry) { + throw new Error(`module ${id} is required from a require.context, but is not in the context`); + } + return commonJsRequireContext(entry, sourceModule); + } + requireContext.keys = ()=>{ + return Object.keys(map); + }; + requireContext.resolve = (id)=>{ + const entry = map[id]; + if (!entry) { + throw new Error(`module ${id} is resolved from a require.context, but is not in the context`); + } + return entry.id(); + }; + return requireContext; +} +function getChunkPath(chunkData) { + return typeof chunkData === "string" ? chunkData : chunkData.path; +} +; +var SourceType; +(function(SourceType) { + SourceType[SourceType["Runtime"] = 0] = "Runtime"; + SourceType[SourceType["Parent"] = 1] = "Parent"; +})(SourceType || (SourceType = {})); +; +const path = require("path"); +const relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, "."); +const RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot); +const moduleFactories = Object.create(null); +const moduleCache = Object.create(null); +function externalRequire(id, esm1 = false) { + let raw; + try { + raw = require(id); + } catch (err) { + throw new Error(`Failed to load external module ${id}: ${err}`); + } + if (!esm1 || raw.__esModule) { + return raw; + } + const ns = {}; + interopEsm(raw, ns, true); + return ns; +} +externalRequire.resolve = (id, options)=>{ + return require.resolve(id, options); +}; +function loadChunk(chunkPath) { + if (!chunkPath.endsWith(".js")) { + return; + } + const path = require("path"); + const resolved = require.resolve(path.resolve(RUNTIME_ROOT, chunkPath)); + delete require.cache[resolved]; + const chunkModules = require(resolved); + for (const [moduleId, moduleFactory] of Object.entries(chunkModules)){ + if (!moduleFactories[moduleId]) { + moduleFactories[moduleId] = moduleFactory; + } + } +} +function loadChunkAsync(source, chunkPath) { + return new Promise((resolve, reject)=>{ + try { + loadChunk(chunkPath); + } catch (err) { + reject(err); + return; + } + resolve(); + }); +} +function instantiateModule(id, source) { + const moduleFactory = moduleFactories[id]; + if (typeof moduleFactory !== "function") { + let instantiationReason; + switch(source.type){ + case SourceType.Runtime: + instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; + break; + case SourceType.Parent: + instantiationReason = `because it was required from module ${source.parentId}`; + break; + } + throw new Error(`Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`); + } + let parents; + switch(source.type){ + case SourceType.Runtime: + parents = []; + break; + case SourceType.Parent: + parents = [ + source.parentId + ]; + break; + } + const module1 = { + exports: {}, + error: undefined, + loaded: false, + id, + parents, + children: [], + namespaceObject: undefined + }; + moduleCache[id] = module1; + try { + moduleFactory.call(module1.exports, { + e: module1.exports, + r: commonJsRequire.bind(null, module1), + x: externalRequire, + f: requireContext.bind(null, module1), + i: esmImport.bind(null, module1), + s: esm.bind(null, module1.exports), + j: cjsExport.bind(null, module1.exports), + v: exportValue.bind(null, module1), + n: exportNamespace.bind(null, module1), + m: module1, + c: moduleCache, + l: loadChunkAsync.bind(null, { + type: SourceType.Parent, + parentId: id + }), + g: globalThis, + __dirname: module1.id.replace(/(^|\/)[\/]+$/, "") + }); + } catch (error) { + module1.error = error; + throw error; + } + module1.loaded = true; + if (module1.namespaceObject) { + interopEsm(module1.exports, module1.namespaceObject); + } + return module1; +} +function getOrInstantiateModuleFromParent(id, sourceModule) { + const module1 = moduleCache[id]; + if (sourceModule.children.indexOf(id) === -1) { + sourceModule.children.push(id); + } + if (module1) { + if (module1.parents.indexOf(sourceModule.id) === -1) { + module1.parents.push(sourceModule.id); + } + return module1; + } + return instantiateModule(id, { + type: SourceType.Parent, + parentId: sourceModule.id + }); +} +function instantiateRuntimeModule(moduleId, chunkPath) { + return instantiateModule(moduleId, { + type: SourceType.Runtime, + chunkPath + }); +} +function getOrInstantiateRuntimeModule(moduleId, chunkPath) { + const module1 = moduleCache[moduleId]; + if (module1) { + if (module1.error) { + throw module1.error; + } + return module1; + } + return instantiateRuntimeModule(moduleId, chunkPath); +} +module.exports = { + getOrInstantiateRuntimeModule, + loadChunk +}; \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map new file mode 100644 index 0000000000000..eebac27d14dce --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map @@ -0,0 +1,6 @@ +{ + "version": 3, + "sections": [ + {"offset": {"line": 1, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/shared/runtime-utils.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * TurboPack ECMAScript runtimes.\n *\n * It will be prepended to the runtime code of each runtime.\n */\n\n/* eslint-disable @next/next/no-assign-module-variable */\n\n/// \n\ninterface Exports {\n __esModule?: boolean;\n\n [key: string]: any;\n}\ntype EsmNamespaceObject = Record;\n\ninterface BaseModule {\n exports: Exports;\n error: Error | undefined;\n loaded: boolean;\n id: ModuleId;\n children: ModuleId[];\n parents: ModuleId[];\n namespaceObject?: EsmNamespaceObject;\n}\n\ninterface Module extends BaseModule {}\n\ntype RequireContextMap = Record;\n\ninterface RequireContextEntry {\n id: () => ModuleId;\n}\n\ninterface RequireContext {\n (moduleId: ModuleId): Exports | EsmNamespaceObject;\n keys(): ModuleId[];\n resolve(moduleId: ModuleId): ModuleId;\n}\n\ntype GetOrInstantiateModuleFromParent = (\n moduleId: ModuleId,\n parentModule: Module\n) => Module;\n\ntype CommonJsRequireContext = (\n entry: RequireContextEntry,\n parentModule: Module\n) => Exports;\n\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst toStringTag = typeof Symbol !== \"undefined\" && Symbol.toStringTag;\n\nfunction defineProp(\n obj: any,\n name: PropertyKey,\n options: PropertyDescriptor & ThisType\n) {\n if (!hasOwnProperty.call(obj, name))\n Object.defineProperty(obj, name, options);\n}\n\n/**\n * Adds the getters to the exports object.\n */\nfunction esm(exports: Exports, getters: Record any>) {\n defineProp(exports, \"__esModule\", { value: true });\n if (toStringTag) defineProp(exports, toStringTag, { value: \"Module\" });\n for (const key in getters) {\n defineProp(exports, key, { get: getters[key], enumerable: true });\n }\n}\n\n/**\n * Makes the module an ESM with exports\n */\nfunction esmExport(module: Module, getters: Record any>) {\n esm((module.namespaceObject = module.exports), getters);\n}\n\n/**\n * Adds the props to the exports object\n */\nfunction cjsExport(exports: Exports, props: Record) {\n for (const key in props) {\n defineProp(exports, key, { get: () => props[key], enumerable: true });\n }\n}\n\nfunction exportValue(module: Module, value: any) {\n module.exports = value;\n}\n\nfunction exportNamespace(module: Module, namespace: any) {\n module.exports = module.namespaceObject = namespace;\n}\n\nfunction createGetter(obj: Record, key: string) {\n return () => obj[key];\n}\n\n/**\n * @returns prototype of the object\n */\nconst getProto: (obj: any) => any = Object.getPrototypeOf\n ? (obj) => Object.getPrototypeOf(obj)\n : (obj) => obj.__proto__;\n\n/** Prototypes that are not expanded for exports */\nconst LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];\n\n/**\n * @param allowExportDefault\n * * `false`: will have the raw module as default export\n * * `true`: will have the default property as default export\n */\nfunction interopEsm(\n raw: Exports,\n ns: EsmNamespaceObject,\n allowExportDefault?: boolean\n) {\n const getters: { [s: string]: () => any } = Object.create(null);\n for (\n let current = raw;\n (typeof current === \"object\" || typeof current === \"function\") &&\n !LEAF_PROTOTYPES.includes(current);\n current = getProto(current)\n ) {\n for (const key of Object.getOwnPropertyNames(current)) {\n getters[key] = createGetter(raw, key);\n }\n }\n if (!(allowExportDefault && \"default\" in getters)) {\n getters[\"default\"] = () => raw;\n }\n esm(ns, getters);\n}\n\nfunction esmImport(sourceModule: Module, id: ModuleId): EsmNamespaceObject {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n if (module.namespaceObject) return module.namespaceObject;\n const raw = module.exports;\n const ns = (module.namespaceObject = {});\n interopEsm(raw, ns, raw.__esModule);\n return ns;\n}\n\nfunction commonJsRequire(sourceModule: Module, id: ModuleId): Exports {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n return module.exports;\n}\n\ntype RequireContextFactory = (map: RequireContextMap) => RequireContext;\n\nfunction requireContext(\n sourceModule: Module,\n map: RequireContextMap\n): RequireContext {\n function requireContext(id: ModuleId): Exports {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is required from a require.context, but is not in the context`\n );\n }\n\n return commonJsRequireContext(entry, sourceModule);\n }\n\n requireContext.keys = (): ModuleId[] => {\n return Object.keys(map);\n };\n\n requireContext.resolve = (id: ModuleId): ModuleId => {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is resolved from a require.context, but is not in the context`\n );\n }\n\n return entry.id();\n };\n\n return requireContext;\n}\n\n/**\n * Returns the path of a chunk defined by its data.\n */\nfunction getChunkPath(chunkData: ChunkData): ChunkPath {\n return typeof chunkData === \"string\" ? chunkData : chunkData.path;\n}\n"],"names":[],"mappings":";;;;;AAoDA,MAAM,iBAAiB,OAAO,UAAU;AACxC,MAAM,cAAc,OAAO,WAAW,eAAe,OAAO;AAE5D,SAAS,WACP,GAAQ,EACR,IAAiB,EACjB,OAA2C;IAE3C,IAAI,CAAC,eAAe,KAAK,KAAK,OAC5B,OAAO,eAAe,KAAK,MAAM;AACrC;AAKA,SAAS,IAAI,OAAgB,EAAE,OAAkC;IAC/D,WAAW,SAAS,cAAc;QAAE,OAAO;IAAK;IAChD,IAAI,aAAa,WAAW,SAAS,aAAa;QAAE,OAAO;IAAS;IACpE,IAAK,MAAM,OAAO,QAAS;QACzB,WAAW,SAAS,KAAK;YAAE,KAAK,OAAO,CAAC,IAAI;YAAE,YAAY;QAAK;IACjE;AACF;AAKA,SAAS,UAAU,MAAc,EAAE,OAAkC;IACnE,IAAK,OAAO,kBAAkB,OAAO,SAAU;AACjD;AAKA,SAAS,UAAU,OAAgB,EAAE,KAA0B;IAC7D,IAAK,MAAM,OAAO,MAAO;QACvB,WAAW,SAAS,KAAK;YAAE,KAAK,IAAM,KAAK,CAAC,IAAI;YAAE,YAAY;QAAK;IACrE;AACF;AAEA,SAAS,YAAY,MAAc,EAAE,KAAU;IAC7C,OAAO,UAAU;AACnB;AAEA,SAAS,gBAAgB,MAAc,EAAE,SAAc;IACrD,OAAO,UAAU,OAAO,kBAAkB;AAC5C;AAEA,SAAS,aAAa,GAAwB,EAAE,GAAW;IACzD,OAAO,IAAM,GAAG,CAAC,IAAI;AACvB;AAKA,MAAM,WAA8B,OAAO,iBACvC,CAAC,MAAQ,OAAO,eAAe,OAC/B,CAAC,MAAQ,IAAI;AAGjB,MAAM,kBAAkB;IAAC;IAAM,SAAS,CAAC;IAAI,SAAS,EAAE;IAAG,SAAS;CAAU;AAO9E,SAAS,WACP,GAAY,EACZ,EAAsB,EACtB,kBAA4B;IAE5B,MAAM,UAAsC,OAAO,OAAO;IAC1D,IACE,IAAI,UAAU,KACd,CAAC,OAAO,YAAY,YAAY,OAAO,YAAY,UAAU,KAC7D,CAAC,gBAAgB,SAAS,UAC1B,UAAU,SAAS,SACnB;QACA,KAAK,MAAM,OAAO,OAAO,oBAAoB,SAAU;YACrD,OAAO,CAAC,IAAI,GAAG,aAAa,KAAK;QACnC;IACF;IACA,IAAI,CAAC,CAAC,sBAAsB,aAAa,OAAO,GAAG;QACjD,OAAO,CAAC,UAAU,GAAG,IAAM;IAC7B;IACA,IAAI,IAAI;AACV;AAEA,SAAS,UAAU,YAAoB,EAAE,EAAY;IACnD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,IAAI,OAAO,iBAAiB,OAAO,OAAO;IAC1C,MAAM,MAAM,OAAO;IACnB,MAAM,KAAM,OAAO,kBAAkB,CAAC;IACtC,WAAW,KAAK,IAAI,IAAI;IACxB,OAAO;AACT;AAEA,SAAS,gBAAgB,YAAoB,EAAE,EAAY;IACzD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,OAAO,OAAO;AAChB;AAIA,SAAS,eACP,YAAoB,EACpB,GAAsB;IAEtB,SAAS,eAAe,EAAY;QAClC,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,uBAAuB,OAAO;IACvC;IAEA,eAAe,OAAO;QACpB,OAAO,OAAO,KAAK;IACrB;IAEA,eAAe,UAAU,CAAC;QACxB,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,MAAM;IACf;IAEA,OAAO;AACT;AAKA,SAAS,aAAa,SAAoB;IACxC,OAAO,OAAO,cAAc,WAAW,YAAY,UAAU;AAC/D"}}, + {"offset": {"line": 101, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/build/runtime.ts"],"sourcesContent":["/// \n\ndeclare var RUNTIME_PUBLIC_PATH: string;\n\nenum SourceType {\n /**\n * The module was instantiated because it was included in an evaluated chunk's\n * runtime.\n */\n Runtime = 0,\n /**\n * The module was instantiated because a parent module imported it.\n */\n Parent = 1,\n}\n\ntype SourceInfo =\n | {\n type: SourceType.Runtime;\n chunkPath: ChunkPath;\n }\n | {\n type: SourceType.Parent;\n parentId: ModuleId;\n };\n\ninterface TurbopackNodeBuildContext {\n e: Module[\"exports\"];\n r: CommonJsRequire;\n x: ExternalRequire;\n f: RequireContextFactory;\n i: EsmImport;\n s: EsmExport;\n j: typeof cjsExport;\n v: ExportValue;\n n: typeof exportNamespace;\n m: Module;\n c: ModuleCache;\n l: LoadChunk;\n g: typeof globalThis;\n __dirname: string;\n}\n\ntype ModuleFactory = (\n this: Module[\"exports\"],\n context: TurbopackNodeBuildContext\n) => undefined;\n\nconst path = require(\"path\");\nconst relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, \".\");\nconst RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot);\n\nconst moduleFactories: ModuleFactories = Object.create(null);\nconst moduleCache: ModuleCache = Object.create(null);\n\nfunction externalRequire(\n id: ModuleId,\n esm: boolean = false\n): Exports | EsmNamespaceObject {\n let raw;\n try {\n raw = require(id);\n } catch (err) {\n // TODO(alexkirsz) This can happen when a client-side module tries to load\n // an external module we don't provide a shim for (e.g. querystring, url).\n // For now, we fail semi-silently, but in the future this should be a\n // compilation error.\n throw new Error(`Failed to load external module ${id}: ${err}`);\n }\n if (!esm || raw.__esModule) {\n return raw;\n }\n const ns = {};\n interopEsm(raw, ns, true);\n return ns;\n}\nexternalRequire.resolve = (\n id: string,\n options?:\n | {\n paths?: string[] | undefined;\n }\n | undefined\n) => {\n return require.resolve(id, options);\n};\n\nfunction loadChunk(chunkPath: ChunkPath) {\n if (!chunkPath.endsWith(\".js\")) {\n // We only support loading JS chunks in Node.js.\n // This branch can be hit when trying to load a CSS chunk.\n return;\n }\n\n const path = require(\"path\");\n const resolved = require.resolve(path.resolve(RUNTIME_ROOT, chunkPath));\n delete require.cache[resolved];\n const chunkModules: ModuleFactories = require(resolved);\n\n for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) {\n if (!moduleFactories[moduleId]) {\n moduleFactories[moduleId] = moduleFactory;\n }\n }\n}\n\nfunction loadChunkAsync(source: SourceInfo, chunkPath: string): Promise {\n return new Promise((resolve, reject) => {\n try {\n loadChunk(chunkPath);\n } catch (err) {\n reject(err);\n return;\n }\n resolve();\n });\n}\n\nfunction instantiateModule(id: ModuleId, source: SourceInfo): Module {\n const moduleFactory = moduleFactories[id];\n if (typeof moduleFactory !== \"function\") {\n // This can happen if modules incorrectly handle HMR disposes/updates,\n // e.g. when they keep a `setTimeout` around which still executes old code\n // and contains e.g. a `require(\"something\")` call.\n let instantiationReason;\n switch (source.type) {\n case SourceType.Runtime:\n instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n instantiationReason = `because it was required from module ${source.parentId}`;\n break;\n }\n throw new Error(\n `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`\n );\n }\n\n let parents: ModuleId[];\n switch (source.type) {\n case SourceType.Runtime:\n parents = [];\n break;\n case SourceType.Parent:\n // No need to add this module as a child of the parent module here, this\n // has already been taken care of in `getOrInstantiateModuleFromParent`.\n parents = [source.parentId];\n break;\n }\n\n const module: Module = {\n exports: {},\n error: undefined,\n loaded: false,\n id,\n parents,\n children: [],\n namespaceObject: undefined,\n };\n moduleCache[id] = module;\n\n // NOTE(alexkirsz) This can fail when the module encounters a runtime error.\n try {\n moduleFactory.call(module.exports, {\n e: module.exports,\n r: commonJsRequire.bind(null, module),\n x: externalRequire,\n f: requireContext.bind(null, module),\n i: esmImport.bind(null, module),\n s: esm.bind(null, module.exports),\n j: cjsExport.bind(null, module.exports),\n v: exportValue.bind(null, module),\n n: exportNamespace.bind(null, module),\n m: module,\n c: moduleCache,\n l: loadChunkAsync.bind(null, { type: SourceType.Parent, parentId: id }),\n g: globalThis,\n __dirname: module.id.replace(/(^|\\/)[\\/]+$/, \"\"),\n });\n } catch (error) {\n module.error = error as any;\n throw error;\n }\n\n module.loaded = true;\n if (module.namespaceObject) {\n // in case of a circular dependency: cjs1 -> esm2 -> cjs1\n interopEsm(module.exports, module.namespaceObject);\n }\n\n return module;\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it if it is not cached.\n */\nfunction getOrInstantiateModuleFromParent(\n id: ModuleId,\n sourceModule: Module\n): Module {\n const module = moduleCache[id];\n\n if (sourceModule.children.indexOf(id) === -1) {\n sourceModule.children.push(id);\n }\n\n if (module) {\n if (module.parents.indexOf(sourceModule.id) === -1) {\n module.parents.push(sourceModule.id);\n }\n\n return module;\n }\n\n return instantiateModule(id, {\n type: SourceType.Parent,\n parentId: sourceModule.id,\n });\n}\n\n/**\n * Instantiates a runtime module.\n */\nfunction instantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it as a runtime module if it is not cached.\n */\nfunction getOrInstantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n const module = moduleCache[moduleId];\n if (module) {\n if (module.error) {\n throw module.error;\n }\n return module;\n }\n\n return instantiateRuntimeModule(moduleId, chunkPath);\n}\n\nmodule.exports = {\n getOrInstantiateRuntimeModule,\n loadChunk,\n};\n"],"names":[],"mappings":";IAIA;UAAK,UAAU;IAAV,WAAA,WAKH,aAAU,KAAV;IALG,WAAA,WASH,YAAS,KAAT;GATG,eAAA;;AA4CL,MAAM,OAAO,QAAQ;AACrB,MAAM,4BAA4B,KAAK,SAAS,qBAAqB;AACrE,MAAM,eAAe,KAAK,QAAQ,YAAY;AAE9C,MAAM,kBAAmC,OAAO,OAAO;AACvD,MAAM,cAA2B,OAAO,OAAO;AAE/C,SAAS,gBACP,EAAY,EACZ,OAAe,KAAK;IAEpB,IAAI;IACJ,IAAI;QACF,MAAM,QAAQ;IAChB,EAAE,OAAO,KAAK;QAKZ,MAAM,IAAI,MAAM,CAAC,+BAA+B,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC;IAChE;IACA,IAAI,CAAC,QAAO,IAAI,YAAY;QAC1B,OAAO;IACT;IACA,MAAM,KAAK,CAAC;IACZ,WAAW,KAAK,IAAI;IACpB,OAAO;AACT;AACA,gBAAgB,UAAU,CACxB,IACA;IAMA,OAAO,QAAQ,QAAQ,IAAI;AAC7B;AAEA,SAAS,UAAU,SAAoB;IACrC,IAAI,CAAC,UAAU,SAAS,QAAQ;QAG9B;IACF;IAEA,MAAM,OAAO,QAAQ;IACrB,MAAM,WAAW,QAAQ,QAAQ,KAAK,QAAQ,cAAc;IAC5D,OAAO,QAAQ,KAAK,CAAC,SAAS;IAC9B,MAAM,eAAgC,QAAQ;IAE9C,KAAK,MAAM,CAAC,UAAU,cAAc,IAAI,OAAO,QAAQ,cAAe;QACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9B,eAAe,CAAC,SAAS,GAAG;QAC9B;IACF;AACF;AAEA,SAAS,eAAe,MAAkB,EAAE,SAAiB;IAC3D,OAAO,IAAI,QAAc,CAAC,SAAS;QACjC,IAAI;YACF,UAAU;QACZ,EAAE,OAAO,KAAK;YACZ,OAAO;YACP;QACF;QACA;IACF;AACF;AAEA,SAAS,kBAAkB,EAAY,EAAE,MAAkB;IACzD,MAAM,gBAAgB,eAAe,CAAC,GAAG;IACzC,IAAI,OAAO,kBAAkB,YAAY;QAIvC,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,sBAAsB,CAAC,4BAA4B,EAAE,OAAO,UAAU,CAAC;gBACvE;YACF,KAAK,WAAW;gBACd,sBAAsB,CAAC,oCAAoC,EAAE,OAAO,SAAS,CAAC;gBAC9E;QACJ;QACA,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,oBAAoB,uFAAuF,CAAC;IAEjJ;IAEA,IAAI;IACJ,OAAQ,OAAO;QACb,KAAK,WAAW;YACd,UAAU,EAAE;YACZ;QACF,KAAK,WAAW;YAGd,UAAU;gBAAC,OAAO;aAAS;YAC3B;IACJ;IAEA,MAAM,UAAiB;QACrB,SAAS,CAAC;QACV,OAAO;QACP,QAAQ;QACR;QACA;QACA,UAAU,EAAE;QACZ,iBAAiB;IACnB;IACA,WAAW,CAAC,GAAG,GAAG;IAGlB,IAAI;QACF,cAAc,KAAK,QAAO,SAAS;YACjC,GAAG,QAAO;YACV,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;YAC7B,GAAG,UAAU,KAAK,MAAM;YACxB,GAAG,IAAI,KAAK,MAAM,QAAO;YACzB,GAAG,UAAU,KAAK,MAAM,QAAO;YAC/B,GAAG,YAAY,KAAK,MAAM;YAC1B,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;gBAAE,MAAM,WAAW;gBAAQ,UAAU;YAAG;YACrE,GAAG;YACH,WAAW,QAAO,GAAG,QAAQ,gBAAgB;QAC/C;IACF,EAAE,OAAO,OAAO;QACd,QAAO,QAAQ;QACf,MAAM;IACR;IAEA,QAAO,SAAS;IAChB,IAAI,QAAO,iBAAiB;QAE1B,WAAW,QAAO,SAAS,QAAO;IACpC;IAEA,OAAO;AACT;AAKA,SAAS,iCACP,EAAY,EACZ,YAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,GAAG;IAE9B,IAAI,aAAa,SAAS,QAAQ,QAAQ,CAAC,GAAG;QAC5C,aAAa,SAAS,KAAK;IAC7B;IAEA,IAAI,SAAQ;QACV,IAAI,QAAO,QAAQ,QAAQ,aAAa,QAAQ,CAAC,GAAG;YAClD,QAAO,QAAQ,KAAK,aAAa;QACnC;QAEA,OAAO;IACT;IAEA,OAAO,kBAAkB,IAAI;QAC3B,MAAM,WAAW;QACjB,UAAU,aAAa;IACzB;AACF;AAKA,SAAS,yBACP,QAAkB,EAClB,SAAoB;IAEpB,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,8BACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,SAAS;IACpC,IAAI,SAAQ;QACV,IAAI,QAAO,OAAO;YAChB,MAAM,QAAO;QACf;QACA,OAAO;IACT;IAEA,OAAO,yBAAyB,UAAU;AAC5C;AAEA,OAAO,UAAU;IACf;IACA;AACF"}}] +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js new file mode 100644 index 0000000000000..a8141d3b18d34 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js @@ -0,0 +1 @@ +console.log("Hello, world!"); diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/options.json b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/options.json new file mode 100644 index 0000000000000..71250c18cfcbc --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/options.json @@ -0,0 +1,3 @@ +{ + "runtimeType": "Default" +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_7fa8ff.js b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_7fa8ff.js new file mode 100644 index 0000000000000..11ffc876f6ba7 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_7fa8ff.js @@ -0,0 +1,11 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_7fa8ff.js", + {}, +]); +(globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ + "path": "output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_7fa8ff.js", + "chunks": [ + "output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js" + ], + "source": "entry" +}); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js new file mode 100644 index 0000000000000..8ce82643252e9 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js @@ -0,0 +1,10 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js", { + +"[project]/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { + +console.log("Hello, world!"); + +}.call(this) }), +}]); + +//# sourceMappingURL=79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js.map b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js.map new file mode 100644 index 0000000000000..6d5edea25e41c --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js.map @@ -0,0 +1,6 @@ +{ + "version": 3, + "sections": [ + {"offset": {"line": 4, "column": 0}, "map": {"version":3,"sources":["/turbopack/[project]/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js"],"sourcesContent":["console.log(\"Hello, world!\");\n"],"names":[],"mappings":"AAAA,QAAQ,IAAI"}}, + {"offset": {"line": 5, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":"A"}}] +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js new file mode 100644 index 0000000000000..6324d46eee421 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js @@ -0,0 +1,1033 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js", + {}, + {"otherChunks":[{"path":"output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js (ecmascript)"]} +]); +(() => { +if (!Array.isArray(globalThis.TURBOPACK)) { + return; +} +; +; +; +; +; +const hasOwnProperty = Object.prototype.hasOwnProperty; +const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; +function defineProp(obj, name, options) { + if (!hasOwnProperty.call(obj, name)) Object.defineProperty(obj, name, options); +} +function esm(exports, getters) { + defineProp(exports, "__esModule", { + value: true + }); + if (toStringTag) defineProp(exports, toStringTag, { + value: "Module" + }); + for(const key in getters){ + defineProp(exports, key, { + get: getters[key], + enumerable: true + }); + } +} +function esmExport(module, getters) { + esm(module.namespaceObject = module.exports, getters); +} +function cjsExport(exports, props) { + for(const key in props){ + defineProp(exports, key, { + get: ()=>props[key], + enumerable: true + }); + } +} +function exportValue(module, value) { + module.exports = value; +} +function exportNamespace(module, namespace) { + module.exports = module.namespaceObject = namespace; +} +function createGetter(obj, key) { + return ()=>obj[key]; +} +const getProto = Object.getPrototypeOf ? (obj)=>Object.getPrototypeOf(obj) : (obj)=>obj.__proto__; +const LEAF_PROTOTYPES = [ + null, + getProto({}), + getProto([]), + getProto(getProto) +]; +function interopEsm(raw, ns, allowExportDefault) { + const getters = Object.create(null); + for(let current = raw; (typeof current === "object" || typeof current === "function") && !LEAF_PROTOTYPES.includes(current); current = getProto(current)){ + for (const key of Object.getOwnPropertyNames(current)){ + getters[key] = createGetter(raw, key); + } + } + if (!(allowExportDefault && "default" in getters)) { + getters["default"] = ()=>raw; + } + esm(ns, getters); +} +function esmImport(sourceModule, id) { + const module = getOrInstantiateModuleFromParent(id, sourceModule); + if (module.error) throw module.error; + if (module.namespaceObject) return module.namespaceObject; + const raw = module.exports; + const ns = module.namespaceObject = {}; + interopEsm(raw, ns, raw.__esModule); + return ns; +} +function commonJsRequire(sourceModule, id) { + const module = getOrInstantiateModuleFromParent(id, sourceModule); + if (module.error) throw module.error; + return module.exports; +} +function requireContext(sourceModule, map) { + function requireContext(id) { + const entry = map[id]; + if (!entry) { + throw new Error(`module ${id} is required from a require.context, but is not in the context`); + } + return commonJsRequireContext(entry, sourceModule); + } + requireContext.keys = ()=>{ + return Object.keys(map); + }; + requireContext.resolve = (id)=>{ + const entry = map[id]; + if (!entry) { + throw new Error(`module ${id} is resolved from a require.context, but is not in the context`); + } + return entry.id(); + }; + return requireContext; +} +function getChunkPath(chunkData) { + return typeof chunkData === "string" ? chunkData : chunkData.path; +} +; +; +; +; +; +var SourceType; +(function(SourceType) { + SourceType[SourceType["Runtime"] = 0] = "Runtime"; + SourceType[SourceType["Parent"] = 1] = "Parent"; + SourceType[SourceType["Update"] = 2] = "Update"; +})(SourceType || (SourceType = {})); +; +const moduleFactories = Object.create(null); +const moduleCache = Object.create(null); +const moduleHotData = new Map(); +const moduleHotState = new Map(); +const runtimeModules = new Set(); +const moduleChunksMap = new Map(); +const chunkModulesMap = new Map(); +const runtimeChunkLists = new Set(); +const chunkListChunksMap = new Map(); +const chunkChunkListsMap = new Map(); +const commonJsRequireContext = (entry, sourceModule)=>{ + return entry.internal ? commonJsRequire(sourceModule, entry.id()) : externalRequire(entry.id(), false); +}; +function externalRequire(id, esm = false) { + let raw; + try { + raw = require(id); + } catch (err) { + throw new Error(`Failed to load external module ${id}: ${err}`); + } + if (!esm) { + return raw; + } + const ns = {}; + interopEsm(raw, ns, raw.__esModule); + return ns; +} +externalRequire.resolve = (id, options)=>{ + return require.resolve(id, options); +}; +const availableModules = new Map(); +const availableModuleChunks = new Map(); +async function loadChunk(source, chunkData) { + if (typeof chunkData === "string") { + return loadChunkPath(source, chunkData); + } + const includedList = chunkData.included || []; + const modulesPromises = includedList.map((included)=>{ + if (moduleFactories[included]) return true; + return availableModules.get(included); + }); + if (modulesPromises.length > 0 && modulesPromises.every((p)=>p)) { + return Promise.all(modulesPromises); + } + const includedModuleChunksList = chunkData.moduleChunks || []; + const moduleChunksPromises = includedModuleChunksList.map((included)=>{ + return availableModuleChunks.get(included); + }).filter((p)=>p); + let promise; + if (moduleChunksPromises.length > 0) { + if (moduleChunksPromises.length == includedModuleChunksList.length) { + return Promise.all(moduleChunksPromises); + } + const moduleChunksToLoad = new Set(); + for (const moduleChunk of includedModuleChunksList){ + if (!availableModuleChunks.has(moduleChunk)) { + moduleChunksToLoad.add(moduleChunk); + } + } + for (const moduleChunkToLoad of moduleChunksToLoad){ + const promise = loadChunkPath(source, moduleChunkToLoad); + availableModuleChunks.set(moduleChunkToLoad, promise); + moduleChunksPromises.push(promise); + } + promise = Promise.all(moduleChunksPromises); + } else { + promise = loadChunkPath(source, chunkData.path); + for (const includedModuleChunk of includedModuleChunksList){ + if (!availableModuleChunks.has(includedModuleChunk)) { + availableModuleChunks.set(includedModuleChunk, promise); + } + } + } + for (const included of includedList){ + if (!availableModules.has(included)) { + availableModules.set(included, promise); + } + } + return promise; +} +async function loadChunkPath(source, chunkPath) { + try { + await BACKEND.loadChunk(chunkPath, source); + } catch (error) { + let loadReason; + switch(source.type){ + case SourceType.Runtime: + loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; + break; + case SourceType.Parent: + loadReason = `from module ${source.parentId}`; + break; + case SourceType.Update: + loadReason = "from an HMR update"; + break; + } + throw new Error(`Failed to load chunk ${chunkPath} ${loadReason}${error ? `: ${error}` : ""}`); + } +} +function instantiateModule(id, source) { + const moduleFactory = moduleFactories[id]; + if (typeof moduleFactory !== "function") { + let instantiationReason; + switch(source.type){ + case SourceType.Runtime: + instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; + break; + case SourceType.Parent: + instantiationReason = `because it was required from module ${source.parentId}`; + break; + case SourceType.Update: + instantiationReason = "because of an HMR update"; + break; + } + throw new Error(`Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`); + } + const hotData = moduleHotData.get(id); + const { hot , hotState } = createModuleHot(hotData); + let parents; + switch(source.type){ + case SourceType.Runtime: + runtimeModules.add(id); + parents = []; + break; + case SourceType.Parent: + parents = [ + source.parentId + ]; + break; + case SourceType.Update: + parents = source.parents || []; + break; + } + const module = { + exports: {}, + error: undefined, + loaded: false, + id, + parents, + children: [], + namespaceObject: undefined, + hot + }; + moduleCache[id] = module; + moduleHotState.set(module, hotState); + try { + runModuleExecutionHooks(module, (refresh)=>{ + moduleFactory.call(module.exports, { + e: module.exports, + r: commonJsRequire.bind(null, module), + x: externalRequire, + f: requireContext.bind(null, module), + i: esmImport.bind(null, module), + s: esmExport.bind(null, module), + j: cjsExport.bind(null, module.exports), + v: exportValue.bind(null, module), + n: exportNamespace.bind(null, module), + m: module, + c: moduleCache, + l: loadChunk.bind(null, { + type: SourceType.Parent, + parentId: id + }), + g: globalThis, + k: refresh, + __dirname: module.id.replace(/(^|\/)[\/]+$/, "") + }); + }); + } catch (error) { + module.error = error; + throw error; + } + module.loaded = true; + if (module.namespaceObject && module.exports !== module.namespaceObject) { + interopEsm(module.exports, module.namespaceObject); + } + return module; +} +function runModuleExecutionHooks(module, executeModule) { + const cleanupReactRefreshIntercept = typeof globalThis.$RefreshInterceptModuleExecution$ === "function" ? globalThis.$RefreshInterceptModuleExecution$(module.id) : ()=>{}; + try { + executeModule({ + register: globalThis.$RefreshReg$, + signature: globalThis.$RefreshSig$ + }); + if ("$RefreshHelpers$" in globalThis) { + registerExportsAndSetupBoundaryForReactRefresh(module, globalThis.$RefreshHelpers$); + } + } catch (e) { + throw e; + } finally{ + cleanupReactRefreshIntercept(); + } +} +const getOrInstantiateModuleFromParent = (id, sourceModule)=>{ + if (!sourceModule.hot.active) { + console.warn(`Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update`); + } + const module = moduleCache[id]; + if (sourceModule.children.indexOf(id) === -1) { + sourceModule.children.push(id); + } + if (module) { + if (module.parents.indexOf(sourceModule.id) === -1) { + module.parents.push(sourceModule.id); + } + return module; + } + return instantiateModule(id, { + type: SourceType.Parent, + parentId: sourceModule.id + }); +}; +function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { + const currentExports = module.exports; + const prevExports = module.hot.data.prevExports ?? null; + helpers.registerExportsForReactRefresh(currentExports, module.id); + if (helpers.isReactRefreshBoundary(currentExports)) { + module.hot.dispose((data)=>{ + data.prevExports = currentExports; + }); + module.hot.accept(); + if (prevExports !== null) { + if (helpers.shouldInvalidateReactRefreshBoundary(prevExports, currentExports)) { + module.hot.invalidate(); + } else { + helpers.scheduleUpdate(); + } + } + } else { + const isNoLongerABoundary = prevExports !== null; + if (isNoLongerABoundary) { + module.hot.invalidate(); + } + } +} +function formatDependencyChain(dependencyChain) { + return `Dependency chain: ${dependencyChain.join(" -> ")}`; +} +function computeOutdatedModules(added, modified) { + const outdatedModules = new Set(); + const newModuleFactories = new Map(); + for (const [moduleId, entry] of added){ + if (entry != null) { + newModuleFactories.set(moduleId, _eval(entry)); + } + } + for (const [moduleId, entry] of modified){ + const effect = getAffectedModuleEffects(moduleId); + switch(effect.type){ + case "unaccepted": + throw new Error(`cannot apply update: unaccepted module. ${formatDependencyChain(effect.dependencyChain)}.`); + case "self-declined": + throw new Error(`cannot apply update: self-declined module. ${formatDependencyChain(effect.dependencyChain)}.`); + case "accepted": + newModuleFactories.set(moduleId, _eval(entry)); + for (const outdatedModuleId of effect.outdatedModules){ + outdatedModules.add(outdatedModuleId); + } + break; + } + } + return { + outdatedModules, + newModuleFactories + }; +} +function computeOutdatedSelfAcceptedModules(outdatedModules) { + const outdatedSelfAcceptedModules = []; + for (const moduleId of outdatedModules){ + const module = moduleCache[moduleId]; + const hotState = moduleHotState.get(module); + if (module && hotState.selfAccepted && !hotState.selfInvalidated) { + outdatedSelfAcceptedModules.push({ + moduleId, + errorHandler: hotState.selfAccepted + }); + } + } + return outdatedSelfAcceptedModules; +} +function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { + for (const [chunkPath, addedModuleIds] of chunksAddedModules){ + for (const moduleId of addedModuleIds){ + addModuleToChunk(moduleId, chunkPath); + } + } + const disposedModules = new Set(); + for (const [chunkPath, addedModuleIds] of chunksDeletedModules){ + for (const moduleId of addedModuleIds){ + if (removeModuleFromChunk(moduleId, chunkPath)) { + disposedModules.add(moduleId); + } + } + } + return { + disposedModules + }; +} +function disposePhase(outdatedModules, disposedModules) { + for (const moduleId of outdatedModules){ + disposeModule(moduleId, "replace"); + } + for (const moduleId of disposedModules){ + disposeModule(moduleId, "clear"); + } + const outdatedModuleParents = new Map(); + for (const moduleId of outdatedModules){ + const oldModule = moduleCache[moduleId]; + outdatedModuleParents.set(moduleId, oldModule?.parents); + delete moduleCache[moduleId]; + } + return { + outdatedModuleParents + }; +} +function disposeModule(moduleId, mode) { + const module = moduleCache[moduleId]; + if (!module) { + return; + } + const hotState = moduleHotState.get(module); + const data = {}; + for (const disposeHandler of hotState.disposeHandlers){ + disposeHandler(data); + } + module.hot.active = false; + moduleHotState.delete(module); + for (const childId of module.children){ + const child = moduleCache[childId]; + if (!child) { + continue; + } + const idx = child.parents.indexOf(module.id); + if (idx >= 0) { + child.parents.splice(idx, 1); + } + } + switch(mode){ + case "clear": + delete moduleCache[module.id]; + moduleHotData.delete(module.id); + break; + case "replace": + moduleHotData.set(module.id, data); + break; + default: + invariant(mode, (mode)=>`invalid mode: ${mode}`); + } +} +function applyPhase(outdatedSelfAcceptedModules, newModuleFactories, outdatedModuleParents) { + for (const [moduleId, factory] of newModuleFactories.entries()){ + moduleFactories[moduleId] = factory; + } + for (const { moduleId , errorHandler } of outdatedSelfAcceptedModules){ + try { + instantiateModule(moduleId, { + type: SourceType.Update, + parents: outdatedModuleParents.get(moduleId) + }); + } catch (err) { + if (typeof errorHandler === "function") { + try { + errorHandler(err, { + moduleId, + module: moduleCache[moduleId] + }); + } catch (_) {} + } + } + } +} +function invariant(never, computeMessage) { + throw new Error(`Invariant: ${computeMessage(never)}`); +} +function applyUpdate(chunkListPath, update) { + switch(update.type){ + case "ChunkListUpdate": + applyChunkListUpdate(chunkListPath, update); + break; + default: + invariant(update, (update)=>`Unknown update type: ${update.type}`); + } +} +function applyChunkListUpdate(chunkListPath, update) { + if (update.merged != null) { + for (const merged of update.merged){ + switch(merged.type){ + case "EcmascriptMergedUpdate": + applyEcmascriptMergedUpdate(chunkListPath, merged); + break; + default: + invariant(merged, (merged)=>`Unknown merged type: ${merged.type}`); + } + } + } + if (update.chunks != null) { + for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)){ + switch(chunkUpdate.type){ + case "added": + BACKEND.loadChunk(chunkPath, { + type: SourceType.Update + }); + break; + case "total": + BACKEND.reloadChunk?.(chunkPath); + break; + case "deleted": + BACKEND.unloadChunk?.(chunkPath); + break; + case "partial": + invariant(chunkUpdate.instruction, (instruction)=>`Unknown partial instruction: ${JSON.stringify(instruction)}.`); + default: + invariant(chunkUpdate, (chunkUpdate)=>`Unknown chunk update type: ${chunkUpdate.type}`); + } + } + } +} +function applyEcmascriptMergedUpdate(chunkPath, update) { + const { entries ={} , chunks ={} } = update; + const { added , modified , deleted , chunksAdded , chunksDeleted } = computeChangedModules(entries, chunks); + const { outdatedModules , newModuleFactories } = computeOutdatedModules(added, modified); + const outdatedSelfAcceptedModules = computeOutdatedSelfAcceptedModules(outdatedModules); + const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); + const { outdatedModuleParents } = disposePhase(outdatedModules, disposedModules); + applyPhase(outdatedSelfAcceptedModules, newModuleFactories, outdatedModuleParents); +} +function computeChangedModules(entries, updates) { + const chunksAdded = new Map(); + const chunksDeleted = new Map(); + const added = new Map(); + const modified = new Map(); + const deleted = new Set(); + for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)){ + switch(mergedChunkUpdate.type){ + case "added": + { + const updateAdded = new Set(mergedChunkUpdate.modules); + for (const moduleId of updateAdded){ + added.set(moduleId, entries[moduleId]); + } + chunksAdded.set(chunkPath, updateAdded); + break; + } + case "deleted": + { + const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); + for (const moduleId of updateDeleted){ + deleted.add(moduleId); + } + chunksDeleted.set(chunkPath, updateDeleted); + break; + } + case "partial": + { + const updateAdded = new Set(mergedChunkUpdate.added); + const updateDeleted = new Set(mergedChunkUpdate.deleted); + for (const moduleId of updateAdded){ + added.set(moduleId, entries[moduleId]); + } + for (const moduleId of updateDeleted){ + deleted.add(moduleId); + } + chunksAdded.set(chunkPath, updateAdded); + chunksDeleted.set(chunkPath, updateDeleted); + break; + } + default: + invariant(mergedChunkUpdate, (mergedChunkUpdate)=>`Unknown merged chunk update type: ${mergedChunkUpdate.type}`); + } + } + for (const moduleId of added.keys()){ + if (deleted.has(moduleId)) { + added.delete(moduleId); + deleted.delete(moduleId); + } + } + for (const [moduleId, entry] of Object.entries(entries)){ + if (!added.has(moduleId)) { + modified.set(moduleId, entry); + } + } + return { + added, + deleted, + modified, + chunksAdded, + chunksDeleted + }; +} +function getAffectedModuleEffects(moduleId) { + const outdatedModules = new Set(); + const queue = [ + { + moduleId, + dependencyChain: [] + } + ]; + let nextItem; + while(nextItem = queue.shift()){ + const { moduleId , dependencyChain } = nextItem; + if (moduleId != null) { + outdatedModules.add(moduleId); + } + if (moduleId === undefined) { + return { + type: "unaccepted", + dependencyChain + }; + } + const module = moduleCache[moduleId]; + const hotState = moduleHotState.get(module); + if (!module || hotState.selfAccepted && !hotState.selfInvalidated) { + continue; + } + if (hotState.selfDeclined) { + return { + type: "self-declined", + dependencyChain, + moduleId + }; + } + if (runtimeModules.has(moduleId)) { + queue.push({ + moduleId: undefined, + dependencyChain: [ + ...dependencyChain, + moduleId + ] + }); + continue; + } + for (const parentId of module.parents){ + const parent = moduleCache[parentId]; + if (!parent) { + continue; + } + queue.push({ + moduleId: parentId, + dependencyChain: [ + ...dependencyChain, + moduleId + ] + }); + } + } + return { + type: "accepted", + moduleId, + outdatedModules + }; +} +function handleApply(chunkListPath, update) { + switch(update.type){ + case "partial": + { + applyUpdate(chunkListPath, update.instruction); + break; + } + case "restart": + { + BACKEND.restart(); + break; + } + case "notFound": + { + if (runtimeChunkLists.has(chunkListPath)) { + BACKEND.restart(); + } else { + disposeChunkList(chunkListPath); + } + break; + } + default: + throw new Error(`Unknown update type: ${update.type}`); + } +} +function createModuleHot(hotData) { + const hotState = { + selfAccepted: false, + selfDeclined: false, + selfInvalidated: false, + disposeHandlers: [] + }; + const hot = { + active: true, + data: hotData ?? {}, + accept: (modules, _callback, _errorHandler)=>{ + if (modules === undefined) { + hotState.selfAccepted = true; + } else if (typeof modules === "function") { + hotState.selfAccepted = modules; + } else { + throw new Error("unsupported `accept` signature"); + } + }, + decline: (dep)=>{ + if (dep === undefined) { + hotState.selfDeclined = true; + } else { + throw new Error("unsupported `decline` signature"); + } + }, + dispose: (callback)=>{ + hotState.disposeHandlers.push(callback); + }, + addDisposeHandler: (callback)=>{ + hotState.disposeHandlers.push(callback); + }, + removeDisposeHandler: (callback)=>{ + const idx = hotState.disposeHandlers.indexOf(callback); + if (idx >= 0) { + hotState.disposeHandlers.splice(idx, 1); + } + }, + invalidate: ()=>{ + hotState.selfInvalidated = true; + }, + status: ()=>"idle", + addStatusHandler: (_handler)=>{}, + removeStatusHandler: (_handler)=>{} + }; + return { + hot, + hotState + }; +} +function addModuleToChunk(moduleId, chunkPath) { + let moduleChunks = moduleChunksMap.get(moduleId); + if (!moduleChunks) { + moduleChunks = new Set([ + chunkPath + ]); + moduleChunksMap.set(moduleId, moduleChunks); + } else { + moduleChunks.add(chunkPath); + } + let chunkModules = chunkModulesMap.get(chunkPath); + if (!chunkModules) { + chunkModules = new Set([ + moduleId + ]); + chunkModulesMap.set(chunkPath, chunkModules); + } else { + chunkModules.add(moduleId); + } +} +function getFirstModuleChunk(moduleId) { + const moduleChunkPaths = moduleChunksMap.get(moduleId); + if (moduleChunkPaths == null) { + return null; + } + return moduleChunkPaths.values().next().value; +} +function removeModuleFromChunk(moduleId, chunkPath) { + const moduleChunks = moduleChunksMap.get(moduleId); + moduleChunks.delete(chunkPath); + const chunkModules = chunkModulesMap.get(chunkPath); + chunkModules.delete(moduleId); + const noRemainingModules = chunkModules.size === 0; + if (noRemainingModules) { + chunkModulesMap.delete(chunkPath); + } + const noRemainingChunks = moduleChunks.size === 0; + if (noRemainingChunks) { + moduleChunksMap.delete(moduleId); + } + return noRemainingChunks; +} +function disposeChunkList(chunkListPath) { + const chunkPaths = chunkListChunksMap.get(chunkListPath); + if (chunkPaths == null) { + return false; + } + chunkListChunksMap.delete(chunkListPath); + for (const chunkPath of chunkPaths){ + const chunkChunkLists = chunkChunkListsMap.get(chunkPath); + chunkChunkLists.delete(chunkListPath); + if (chunkChunkLists.size === 0) { + chunkChunkListsMap.delete(chunkPath); + disposeChunk(chunkPath); + } + } + BACKEND.unloadChunk?.(chunkListPath); + return true; +} +function disposeChunk(chunkPath) { + BACKEND.unloadChunk?.(chunkPath); + const chunkModules = chunkModulesMap.get(chunkPath); + if (chunkModules == null) { + return false; + } + chunkModules.delete(chunkPath); + for (const moduleId of chunkModules){ + const moduleChunks = moduleChunksMap.get(moduleId); + moduleChunks.delete(chunkPath); + const noRemainingChunks = moduleChunks.size === 0; + if (noRemainingChunks) { + moduleChunksMap.delete(moduleId); + disposeModule(moduleId, "clear"); + availableModules.delete(moduleId); + } + } + return true; +} +function instantiateRuntimeModule(moduleId, chunkPath) { + return instantiateModule(moduleId, { + type: SourceType.Runtime, + chunkPath + }); +} +function getOrInstantiateRuntimeModule(moduleId, chunkPath) { + const module = moduleCache[moduleId]; + if (module) { + if (module.error) { + throw module.error; + } + return module; + } + return instantiateModule(moduleId, { + type: SourceType.Runtime, + chunkPath + }); +} +function registerChunkList(chunkUpdateProvider, chunkList) { + chunkUpdateProvider.push([ + chunkList.path, + handleApply.bind(null, chunkList.path) + ]); + const chunks = new Set(chunkList.chunks.map(getChunkPath)); + chunkListChunksMap.set(chunkList.path, chunks); + for (const chunkPath of chunks){ + let chunkChunkLists = chunkChunkListsMap.get(chunkPath); + if (!chunkChunkLists) { + chunkChunkLists = new Set([ + chunkList.path + ]); + chunkChunkListsMap.set(chunkPath, chunkChunkLists); + } else { + chunkChunkLists.add(chunkList.path); + } + } + if (chunkList.source === "entry") { + markChunkListAsRuntime(chunkList.path); + } +} +function markChunkListAsRuntime(chunkListPath) { + runtimeChunkLists.add(chunkListPath); +} +function registerChunk([chunkPath, chunkModules, runtimeParams]) { + for (const [moduleId, moduleFactory] of Object.entries(chunkModules)){ + if (!moduleFactories[moduleId]) { + moduleFactories[moduleId] = moduleFactory; + } + addModuleToChunk(moduleId, chunkPath); + } + return BACKEND.registerChunk(chunkPath, runtimeParams); +} +globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS ??= []; +const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS; +if (Array.isArray(chunkListsToRegister)) { + for (const chunkList of chunkListsToRegister){ + registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS, chunkList); + } +} +globalThis.TURBOPACK_CHUNK_LISTS = { + push: (chunkList)=>{ + registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS, chunkList); + } +}; +let BACKEND; +(()=>{ + BACKEND = { + async registerChunk (chunkPath1, params1) { + const resolver1 = getOrCreateResolver1(chunkPath1); + resolver1.resolve(); + if (params1 == null) { + return; + } + for (const otherChunkData1 of params1.otherChunks){ + const otherChunkPath1 = getChunkPath(otherChunkData1); + getOrCreateResolver1(otherChunkPath1); + } + await Promise.all(params1.otherChunks.map((otherChunkData1)=>loadChunk({ + type: SourceType.Runtime, + chunkPath: chunkPath1 + }, otherChunkData1))); + if (params1.runtimeModuleIds.length > 0) { + for (const moduleId1 of params1.runtimeModuleIds){ + getOrInstantiateRuntimeModule(moduleId1, chunkPath1); + } + } + }, + loadChunk (chunkPath1, source1) { + return doLoadChunk1(chunkPath1, source1); + }, + unloadChunk (chunkPath1) { + deleteResolver1(chunkPath1); + if (chunkPath1.endsWith(".css")) { + const links1 = document.querySelectorAll(`link[href="/${chunkPath1}"]`); + for (const link1 of Array.from(links1)){ + link1.remove(); + } + } else if (chunkPath1.endsWith(".js")) { + const scripts1 = document.querySelectorAll(`script[src="/${chunkPath1}"]`); + for (const script1 of Array.from(scripts1)){ + script1.remove(); + } + } else { + throw new Error(`can't infer type of chunk from path ${chunkPath1}`); + } + }, + reloadChunk (chunkPath1) { + return new Promise((resolve1, reject1)=>{ + if (!chunkPath1.endsWith(".css")) { + reject1(new Error("The DOM backend can only reload CSS chunks")); + return; + } + const encodedChunkPath1 = chunkPath1.split("/").map((p1)=>encodeURIComponent(p1)).join("/"); + const previousLink1 = document.querySelector(`link[rel=stylesheet][href^="/${encodedChunkPath1}"]`); + if (previousLink1 == null) { + reject1(new Error(`No link element found for chunk ${chunkPath1}`)); + return; + } + const link1 = document.createElement("link"); + link1.rel = "stylesheet"; + link1.href = `/${encodedChunkPath1}`; + link1.onerror = ()=>{ + reject1(); + }; + link1.onload = ()=>{ + previousLink1.remove(); + resolve1(); + }; + previousLink1.parentElement.insertBefore(link1, previousLink1.nextSibling); + }); + }, + restart: ()=>self.location.reload() + }; + const chunkResolvers1 = new Map(); + function getOrCreateResolver1(chunkPath1) { + let resolver1 = chunkResolvers1.get(chunkPath1); + if (!resolver1) { + let resolve1; + let reject1; + const promise1 = new Promise((innerResolve1, innerReject1)=>{ + resolve1 = innerResolve1; + reject1 = innerReject1; + }); + resolver1 = { + resolved: false, + promise: promise1, + resolve: ()=>{ + resolver1.resolved = true; + resolve1(); + }, + reject: reject1 + }; + chunkResolvers1.set(chunkPath1, resolver1); + } + return resolver1; + } + function deleteResolver1(chunkPath1) { + chunkResolvers1.delete(chunkPath1); + } + async function doLoadChunk1(chunkPath1, source1) { + const resolver1 = getOrCreateResolver1(chunkPath1); + if (resolver1.resolved) { + return resolver1.promise; + } + if (source1.type === SourceType.Runtime) { + if (chunkPath1.endsWith(".css")) { + resolver1.resolve(); + } + return resolver1.promise; + } + if (chunkPath1.endsWith(".css")) { + const link1 = document.createElement("link"); + link1.rel = "stylesheet"; + link1.href = `/${chunkPath1}`; + link1.onerror = ()=>{ + resolver1.reject(); + }; + link1.onload = ()=>{ + resolver1.resolve(); + }; + document.body.appendChild(link1); + } else if (chunkPath1.endsWith(".js")) { + const script1 = document.createElement("script"); + script1.src = `/${chunkPath1}`; + script1.onerror = ()=>{ + resolver1.reject(); + }; + document.body.appendChild(script1); + } else { + throw new Error(`can't infer type of chunk from path ${chunkPath1}`); + } + return resolver1.promise; + } +})(); +function _eval({ code , url , map }) { + code += `\n\n//# sourceURL=${location.origin}${url}`; + if (map) code += `\n//# sourceMappingURL=${map}`; + return eval(code); +} +const chunksToRegister = globalThis.TURBOPACK; +globalThis.TURBOPACK = { push: registerChunk }; +chunksToRegister.forEach(registerChunk); +})(); + + +//# sourceMappingURL=79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js.map b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js.map new file mode 100644 index 0000000000000..0bf04d6528ccd --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js.map @@ -0,0 +1,8 @@ +{ + "version": 3, + "sections": [ + {"offset": {"line": 9, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/shared/runtime-utils.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * TurboPack ECMAScript runtimes.\n *\n * It will be prepended to the runtime code of each runtime.\n */\n\n/* eslint-disable @next/next/no-assign-module-variable */\n\n/// \n\ninterface Exports {\n __esModule?: boolean;\n\n [key: string]: any;\n}\ntype EsmNamespaceObject = Record;\n\ninterface BaseModule {\n exports: Exports;\n error: Error | undefined;\n loaded: boolean;\n id: ModuleId;\n children: ModuleId[];\n parents: ModuleId[];\n namespaceObject?: EsmNamespaceObject;\n}\n\ninterface Module extends BaseModule {}\n\ntype RequireContextMap = Record;\n\ninterface RequireContextEntry {\n id: () => ModuleId;\n}\n\ninterface RequireContext {\n (moduleId: ModuleId): Exports | EsmNamespaceObject;\n keys(): ModuleId[];\n resolve(moduleId: ModuleId): ModuleId;\n}\n\ntype GetOrInstantiateModuleFromParent = (\n moduleId: ModuleId,\n parentModule: Module\n) => Module;\n\ntype CommonJsRequireContext = (\n entry: RequireContextEntry,\n parentModule: Module\n) => Exports;\n\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst toStringTag = typeof Symbol !== \"undefined\" && Symbol.toStringTag;\n\nfunction defineProp(\n obj: any,\n name: PropertyKey,\n options: PropertyDescriptor & ThisType\n) {\n if (!hasOwnProperty.call(obj, name))\n Object.defineProperty(obj, name, options);\n}\n\n/**\n * Adds the getters to the exports object.\n */\nfunction esm(exports: Exports, getters: Record any>) {\n defineProp(exports, \"__esModule\", { value: true });\n if (toStringTag) defineProp(exports, toStringTag, { value: \"Module\" });\n for (const key in getters) {\n defineProp(exports, key, { get: getters[key], enumerable: true });\n }\n}\n\n/**\n * Makes the module an ESM with exports\n */\nfunction esmExport(module: Module, getters: Record any>) {\n esm((module.namespaceObject = module.exports), getters);\n}\n\n/**\n * Adds the props to the exports object\n */\nfunction cjsExport(exports: Exports, props: Record) {\n for (const key in props) {\n defineProp(exports, key, { get: () => props[key], enumerable: true });\n }\n}\n\nfunction exportValue(module: Module, value: any) {\n module.exports = value;\n}\n\nfunction exportNamespace(module: Module, namespace: any) {\n module.exports = module.namespaceObject = namespace;\n}\n\nfunction createGetter(obj: Record, key: string) {\n return () => obj[key];\n}\n\n/**\n * @returns prototype of the object\n */\nconst getProto: (obj: any) => any = Object.getPrototypeOf\n ? (obj) => Object.getPrototypeOf(obj)\n : (obj) => obj.__proto__;\n\n/** Prototypes that are not expanded for exports */\nconst LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];\n\n/**\n * @param allowExportDefault\n * * `false`: will have the raw module as default export\n * * `true`: will have the default property as default export\n */\nfunction interopEsm(\n raw: Exports,\n ns: EsmNamespaceObject,\n allowExportDefault?: boolean\n) {\n const getters: { [s: string]: () => any } = Object.create(null);\n for (\n let current = raw;\n (typeof current === \"object\" || typeof current === \"function\") &&\n !LEAF_PROTOTYPES.includes(current);\n current = getProto(current)\n ) {\n for (const key of Object.getOwnPropertyNames(current)) {\n getters[key] = createGetter(raw, key);\n }\n }\n if (!(allowExportDefault && \"default\" in getters)) {\n getters[\"default\"] = () => raw;\n }\n esm(ns, getters);\n}\n\nfunction esmImport(sourceModule: Module, id: ModuleId): EsmNamespaceObject {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n if (module.namespaceObject) return module.namespaceObject;\n const raw = module.exports;\n const ns = (module.namespaceObject = {});\n interopEsm(raw, ns, raw.__esModule);\n return ns;\n}\n\nfunction commonJsRequire(sourceModule: Module, id: ModuleId): Exports {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n return module.exports;\n}\n\ntype RequireContextFactory = (map: RequireContextMap) => RequireContext;\n\nfunction requireContext(\n sourceModule: Module,\n map: RequireContextMap\n): RequireContext {\n function requireContext(id: ModuleId): Exports {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is required from a require.context, but is not in the context`\n );\n }\n\n return commonJsRequireContext(entry, sourceModule);\n }\n\n requireContext.keys = (): ModuleId[] => {\n return Object.keys(map);\n };\n\n requireContext.resolve = (id: ModuleId): ModuleId => {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is resolved from a require.context, but is not in the context`\n );\n }\n\n return entry.id();\n };\n\n return requireContext;\n}\n\n/**\n * Returns the path of a chunk defined by its data.\n */\nfunction getChunkPath(chunkData: ChunkData): ChunkPath {\n return typeof chunkData === \"string\" ? chunkData : chunkData.path;\n}\n"],"names":[],"mappings":";;;;;AAoDA,MAAM,iBAAiB,OAAO,UAAU;AACxC,MAAM,cAAc,OAAO,WAAW,eAAe,OAAO;AAE5D,SAAS,WACP,GAAQ,EACR,IAAiB,EACjB,OAA2C;IAE3C,IAAI,CAAC,eAAe,KAAK,KAAK,OAC5B,OAAO,eAAe,KAAK,MAAM;AACrC;AAKA,SAAS,IAAI,OAAgB,EAAE,OAAkC;IAC/D,WAAW,SAAS,cAAc;QAAE,OAAO;IAAK;IAChD,IAAI,aAAa,WAAW,SAAS,aAAa;QAAE,OAAO;IAAS;IACpE,IAAK,MAAM,OAAO,QAAS;QACzB,WAAW,SAAS,KAAK;YAAE,KAAK,OAAO,CAAC,IAAI;YAAE,YAAY;QAAK;IACjE;AACF;AAKA,SAAS,UAAU,MAAc,EAAE,OAAkC;IACnE,IAAK,OAAO,kBAAkB,OAAO,SAAU;AACjD;AAKA,SAAS,UAAU,OAAgB,EAAE,KAA0B;IAC7D,IAAK,MAAM,OAAO,MAAO;QACvB,WAAW,SAAS,KAAK;YAAE,KAAK,IAAM,KAAK,CAAC,IAAI;YAAE,YAAY;QAAK;IACrE;AACF;AAEA,SAAS,YAAY,MAAc,EAAE,KAAU;IAC7C,OAAO,UAAU;AACnB;AAEA,SAAS,gBAAgB,MAAc,EAAE,SAAc;IACrD,OAAO,UAAU,OAAO,kBAAkB;AAC5C;AAEA,SAAS,aAAa,GAAwB,EAAE,GAAW;IACzD,OAAO,IAAM,GAAG,CAAC,IAAI;AACvB;AAKA,MAAM,WAA8B,OAAO,iBACvC,CAAC,MAAQ,OAAO,eAAe,OAC/B,CAAC,MAAQ,IAAI;AAGjB,MAAM,kBAAkB;IAAC;IAAM,SAAS,CAAC;IAAI,SAAS,EAAE;IAAG,SAAS;CAAU;AAO9E,SAAS,WACP,GAAY,EACZ,EAAsB,EACtB,kBAA4B;IAE5B,MAAM,UAAsC,OAAO,OAAO;IAC1D,IACE,IAAI,UAAU,KACd,CAAC,OAAO,YAAY,YAAY,OAAO,YAAY,UAAU,KAC7D,CAAC,gBAAgB,SAAS,UAC1B,UAAU,SAAS,SACnB;QACA,KAAK,MAAM,OAAO,OAAO,oBAAoB,SAAU;YACrD,OAAO,CAAC,IAAI,GAAG,aAAa,KAAK;QACnC;IACF;IACA,IAAI,CAAC,CAAC,sBAAsB,aAAa,OAAO,GAAG;QACjD,OAAO,CAAC,UAAU,GAAG,IAAM;IAC7B;IACA,IAAI,IAAI;AACV;AAEA,SAAS,UAAU,YAAoB,EAAE,EAAY;IACnD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,IAAI,OAAO,iBAAiB,OAAO,OAAO;IAC1C,MAAM,MAAM,OAAO;IACnB,MAAM,KAAM,OAAO,kBAAkB,CAAC;IACtC,WAAW,KAAK,IAAI,IAAI;IACxB,OAAO;AACT;AAEA,SAAS,gBAAgB,YAAoB,EAAE,EAAY;IACzD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,OAAO,OAAO;AAChB;AAIA,SAAS,eACP,YAAoB,EACpB,GAAsB;IAEtB,SAAS,eAAe,EAAY;QAClC,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,uBAAuB,OAAO;IACvC;IAEA,eAAe,OAAO;QACpB,OAAO,OAAO,KAAK;IACrB;IAEA,eAAe,UAAU,CAAC;QACxB,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,MAAM;IACf;IAEA,OAAO;AACT;AAKA,SAAS,aAAa,SAAoB;IACxC,OAAO,OAAO,cAAc,WAAW,YAAY,UAAU;AAC/D"}}, + {"offset": {"line": 109, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/dev/runtime/base/runtime-base.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * Turbopack *development* ECMAScript runtimes.\n *\n * It will be appended to the runtime code of each runtime right after the\n * shared runtime utils.\n */\n\n/* eslint-disable @next/next/no-assign-module-variable */\n\n/// \n/// \n/// \n/// \n\n// This file must not use `import` and `export` statements. Otherwise, it\n// becomes impossible to augment interfaces declared in ``d files\n// (e.g. `Module`). Hence the need for `import()` here.\ntype RefreshRuntimeGlobals =\n import(\"@next/react-refresh-utils/dist/runtime\").RefreshRuntimeGlobals;\n\ndeclare var $RefreshHelpers$: RefreshRuntimeGlobals[\"$RefreshHelpers$\"];\ndeclare var $RefreshReg$: RefreshRuntimeGlobals[\"$RefreshReg$\"];\ndeclare var $RefreshSig$: RefreshRuntimeGlobals[\"$RefreshSig$\"];\ndeclare var $RefreshInterceptModuleExecution$:\n | RefreshRuntimeGlobals[\"$RefreshInterceptModuleExecution$\"];\n\ntype RefreshContext = {\n register: RefreshRuntimeGlobals[\"$RefreshReg$\"];\n signature: RefreshRuntimeGlobals[\"$RefreshSig$\"];\n};\n\n// @next/react-refresh-utils/internal/helpers\ntype RefreshHelpers = {\n registerExportsForReactRefresh(\n moduleExports: unknown,\n moduleID: string\n ): void;\n getRefreshBoundarySignature(moduleExports: unknown): Array;\n isReactRefreshBoundary(moduleExports: unknown): boolean;\n shouldInvalidateReactRefreshBoundary(\n prevExports: unknown,\n nextExports: unknown\n ): boolean;\n scheduleUpdate(): void;\n};\n\ninterface TurbopackDevContext {\n e: Module[\"exports\"];\n r: CommonJsRequire;\n x: ExternalRequire;\n f: RequireContextFactory;\n i: EsmImport;\n s: EsmExport;\n j: typeof cjsExport;\n v: ExportValue;\n n: typeof exportNamespace;\n m: Module;\n c: ModuleCache;\n l: LoadChunk;\n g: typeof globalThis;\n k: RefreshContext;\n __dirname: string;\n}\n\n// string encoding of a module factory (used in hmr updates)\ntype ModuleFactoryString = string;\n\ntype ModuleFactory = (\n this: Module[\"exports\"],\n context: TurbopackDevContext\n) => undefined;\n\ntype DevRuntimeParams = {\n otherChunks: ChunkData[];\n runtimeModuleIds: ModuleId[];\n};\n\ntype ChunkRegistration = [\n chunkPath: ChunkPath,\n chunkModules: ModuleFactories,\n params: DevRuntimeParams | undefined\n];\ntype ChunkList = {\n path: ChunkPath;\n chunks: ChunkData[];\n source: \"entry\" | \"dynamic\";\n};\n\nenum SourceType {\n /**\n * The module was instantiated because it was included in an evaluated chunk's\n * runtime.\n */\n Runtime = 0,\n /**\n * The module was instantiated because a parent module imported it.\n */\n Parent = 1,\n /**\n * The module was instantiated because it was included in a chunk's hot module\n * update.\n */\n Update = 2,\n}\n\ntype SourceInfo =\n | {\n type: SourceType.Runtime;\n chunkPath: ChunkPath;\n }\n | {\n type: SourceType.Parent;\n parentId: ModuleId;\n }\n | {\n type: SourceType.Update;\n parents?: ModuleId[];\n };\n\ninterface RuntimeBackend {\n registerChunk: (chunkPath: ChunkPath, params?: DevRuntimeParams) => void;\n loadChunk: (chunkPath: ChunkPath, source: SourceInfo) => Promise;\n reloadChunk?: (chunkPath: ChunkPath) => Promise;\n unloadChunk?: (chunkPath: ChunkPath) => void;\n\n restart: () => void;\n}\n\nconst moduleFactories: ModuleFactories = Object.create(null);\nconst moduleCache: ModuleCache = Object.create(null);\n/**\n * Maps module IDs to persisted data between executions of their hot module\n * implementation (`hot.data`).\n */\nconst moduleHotData: Map = new Map();\n/**\n * Maps module instances to their hot module state.\n */\nconst moduleHotState: Map = new Map();\n/**\n * Module IDs that are instantiated as part of the runtime of a chunk.\n */\nconst runtimeModules: Set = new Set();\n/**\n * Map from module ID to the chunks that contain this module.\n *\n * In HMR, we need to keep track of which modules are contained in which so\n * chunks. This is so we don't eagerly dispose of a module when it is removed\n * from chunk A, but still exists in chunk B.\n */\nconst moduleChunksMap: Map> = new Map();\n/**\n * Map from chunk path to all modules it contains.\n */\nconst chunkModulesMap: Map> = new Map();\n/**\n * Chunk lists that contain a runtime. When these chunk lists receive an update\n * that can't be reconciled with the current state of the page, we need to\n * reload the runtime entirely.\n */\nconst runtimeChunkLists: Set = new Set();\n/**\n * Map from chunk list to the chunk paths it contains.\n */\nconst chunkListChunksMap: Map> = new Map();\n/**\n * Map from chunk path to the chunk lists it belongs to.\n */\nconst chunkChunkListsMap: Map> = new Map();\n\nconst commonJsRequireContext: CommonJsRequireContext = (\n entry,\n sourceModule\n) => {\n return entry.internal\n ? commonJsRequire(sourceModule, entry.id())\n : externalRequire(entry.id(), false);\n};\n\nfunction externalRequire(\n id: ModuleId,\n esm: boolean = false\n): Exports | EsmNamespaceObject {\n let raw;\n try {\n raw = require(id);\n } catch (err) {\n // TODO(alexkirsz) This can happen when a client-side module tries to load\n // an external module we don't provide a shim for (e.g. querystring, url).\n // For now, we fail semi-silently, but in the future this should be a\n // compilation error.\n throw new Error(`Failed to load external module ${id}: ${err}`);\n }\n if (!esm) {\n return raw;\n }\n const ns = {};\n interopEsm(raw, ns, raw.__esModule);\n return ns;\n}\nexternalRequire.resolve = (\n id: string,\n options?:\n | {\n paths?: string[] | undefined;\n }\n | undefined\n) => {\n return require.resolve(id, options);\n};\n\nconst availableModules: Map | true> = new Map();\n\nconst availableModuleChunks: Map | true> = new Map();\n\nasync function loadChunk(\n source: SourceInfo,\n chunkData: ChunkData\n): Promise {\n if (typeof chunkData === \"string\") {\n return loadChunkPath(source, chunkData);\n }\n\n const includedList = chunkData.included || [];\n const modulesPromises = includedList.map((included) => {\n if (moduleFactories[included]) return true;\n return availableModules.get(included);\n });\n if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) {\n // When all included items are already loaded or loading, we can skip loading ourselves\n return Promise.all(modulesPromises);\n }\n\n const includedModuleChunksList = chunkData.moduleChunks || [];\n const moduleChunksPromises = includedModuleChunksList\n .map((included) => {\n // TODO(alexkirsz) Do we need this check?\n // if (moduleFactories[included]) return true;\n return availableModuleChunks.get(included);\n })\n .filter((p) => p);\n\n let promise;\n if (moduleChunksPromises.length > 0) {\n // Some module chunks are already loaded or loading.\n\n if (moduleChunksPromises.length == includedModuleChunksList.length) {\n // When all included module chunks are already loaded or loading, we can skip loading ourselves\n return Promise.all(moduleChunksPromises);\n }\n\n const moduleChunksToLoad: Set = new Set();\n for (const moduleChunk of includedModuleChunksList) {\n if (!availableModuleChunks.has(moduleChunk)) {\n moduleChunksToLoad.add(moduleChunk);\n }\n }\n\n for (const moduleChunkToLoad of moduleChunksToLoad) {\n const promise = loadChunkPath(source, moduleChunkToLoad);\n\n availableModuleChunks.set(moduleChunkToLoad, promise);\n\n moduleChunksPromises.push(promise);\n }\n\n promise = Promise.all(moduleChunksPromises);\n } else {\n promise = loadChunkPath(source, chunkData.path);\n\n // Mark all included module chunks as loading if they are not already loaded or loading.\n for (const includedModuleChunk of includedModuleChunksList) {\n if (!availableModuleChunks.has(includedModuleChunk)) {\n availableModuleChunks.set(includedModuleChunk, promise);\n }\n }\n }\n\n for (const included of includedList) {\n if (!availableModules.has(included)) {\n // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier.\n // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway.\n availableModules.set(included, promise);\n }\n }\n\n return promise;\n}\n\nasync function loadChunkPath(\n source: SourceInfo,\n chunkPath: ChunkPath\n): Promise {\n try {\n await BACKEND.loadChunk(chunkPath, source);\n } catch (error) {\n let loadReason;\n switch (source.type) {\n case SourceType.Runtime:\n loadReason = `as a runtime dependency of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n loadReason = `from module ${source.parentId}`;\n break;\n case SourceType.Update:\n loadReason = \"from an HMR update\";\n break;\n }\n throw new Error(\n `Failed to load chunk ${chunkPath} ${loadReason}${\n error ? `: ${error}` : \"\"\n }`\n );\n }\n}\n\nfunction instantiateModule(id: ModuleId, source: SourceInfo): Module {\n const moduleFactory = moduleFactories[id];\n if (typeof moduleFactory !== \"function\") {\n // This can happen if modules incorrectly handle HMR disposes/updates,\n // e.g. when they keep a `setTimeout` around which still executes old code\n // and contains e.g. a `require(\"something\")` call.\n let instantiationReason;\n switch (source.type) {\n case SourceType.Runtime:\n instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n instantiationReason = `because it was required from module ${source.parentId}`;\n break;\n case SourceType.Update:\n instantiationReason = \"because of an HMR update\";\n break;\n }\n throw new Error(\n `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`\n );\n }\n\n const hotData = moduleHotData.get(id)!;\n const { hot, hotState } = createModuleHot(hotData);\n\n let parents: ModuleId[];\n switch (source.type) {\n case SourceType.Runtime:\n runtimeModules.add(id);\n parents = [];\n break;\n case SourceType.Parent:\n // No need to add this module as a child of the parent module here, this\n // has already been taken care of in `getOrInstantiateModuleFromParent`.\n parents = [source.parentId];\n break;\n case SourceType.Update:\n parents = source.parents || [];\n break;\n }\n const module: Module = {\n exports: {},\n error: undefined,\n loaded: false,\n id,\n parents,\n children: [],\n namespaceObject: undefined,\n hot,\n };\n\n moduleCache[id] = module;\n moduleHotState.set(module, hotState);\n\n // NOTE(alexkirsz) This can fail when the module encounters a runtime error.\n try {\n runModuleExecutionHooks(module, (refresh) => {\n moduleFactory.call(module.exports, {\n e: module.exports,\n r: commonJsRequire.bind(null, module),\n x: externalRequire,\n f: requireContext.bind(null, module),\n i: esmImport.bind(null, module),\n s: esmExport.bind(null, module),\n j: cjsExport.bind(null, module.exports),\n v: exportValue.bind(null, module),\n n: exportNamespace.bind(null, module),\n m: module,\n c: moduleCache,\n l: loadChunk.bind(null, { type: SourceType.Parent, parentId: id }),\n g: globalThis,\n k: refresh,\n __dirname: module.id.replace(/(^|\\/)[\\/]+$/, \"\"),\n });\n });\n } catch (error) {\n module.error = error as any;\n throw error;\n }\n\n module.loaded = true;\n if (module.namespaceObject && module.exports !== module.namespaceObject) {\n // in case of a circular dependency: cjs1 -> esm2 -> cjs1\n interopEsm(module.exports, module.namespaceObject);\n }\n\n return module;\n}\n\n/**\n * NOTE(alexkirsz) Webpack has an \"module execution\" interception hook that\n * Next.js' React Refresh runtime hooks into to add module context to the\n * refresh registry.\n */\nfunction runModuleExecutionHooks(\n module: Module,\n executeModule: (ctx: RefreshContext) => void\n) {\n const cleanupReactRefreshIntercept =\n typeof globalThis.$RefreshInterceptModuleExecution$ === \"function\"\n ? globalThis.$RefreshInterceptModuleExecution$(module.id)\n : () => {};\n\n try {\n executeModule({\n register: globalThis.$RefreshReg$,\n signature: globalThis.$RefreshSig$,\n });\n\n if (\"$RefreshHelpers$\" in globalThis) {\n // This pattern can also be used to register the exports of\n // a module with the React Refresh runtime.\n registerExportsAndSetupBoundaryForReactRefresh(\n module,\n globalThis.$RefreshHelpers$\n );\n }\n } catch (e) {\n throw e;\n } finally {\n // Always cleanup the intercept, even if module execution failed.\n cleanupReactRefreshIntercept();\n }\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it if it is not cached.\n */\nconst getOrInstantiateModuleFromParent: GetOrInstantiateModuleFromParent = (\n id,\n sourceModule\n) => {\n if (!sourceModule.hot.active) {\n console.warn(\n `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update`\n );\n }\n\n const module = moduleCache[id];\n\n if (sourceModule.children.indexOf(id) === -1) {\n sourceModule.children.push(id);\n }\n\n if (module) {\n if (module.parents.indexOf(sourceModule.id) === -1) {\n module.parents.push(sourceModule.id);\n }\n\n return module;\n }\n\n return instantiateModule(id, {\n type: SourceType.Parent,\n parentId: sourceModule.id,\n });\n};\n\n/**\n * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts\n */\nfunction registerExportsAndSetupBoundaryForReactRefresh(\n module: Module,\n helpers: RefreshHelpers\n) {\n const currentExports = module.exports;\n const prevExports = module.hot.data.prevExports ?? null;\n\n helpers.registerExportsForReactRefresh(currentExports, module.id);\n\n // A module can be accepted automatically based on its exports, e.g. when\n // it is a Refresh Boundary.\n if (helpers.isReactRefreshBoundary(currentExports)) {\n // Save the previous exports on update so we can compare the boundary\n // signatures.\n module.hot.dispose((data) => {\n data.prevExports = currentExports;\n });\n // Unconditionally accept an update to this module, we'll check if it's\n // still a Refresh Boundary later.\n module.hot.accept();\n\n // This field is set when the previous version of this module was a\n // Refresh Boundary, letting us know we need to check for invalidation or\n // enqueue an update.\n if (prevExports !== null) {\n // A boundary can become ineligible if its exports are incompatible\n // with the previous exports.\n //\n // For example, if you add/remove/change exports, we'll want to\n // re-execute the importing modules, and force those components to\n // re-render. Similarly, if you convert a class component to a\n // function, we want to invalidate the boundary.\n if (\n helpers.shouldInvalidateReactRefreshBoundary(\n prevExports,\n currentExports\n )\n ) {\n module.hot.invalidate();\n } else {\n helpers.scheduleUpdate();\n }\n }\n } else {\n // Since we just executed the code for the module, it's possible that the\n // new exports made it ineligible for being a boundary.\n // We only care about the case when we were _previously_ a boundary,\n // because we already accepted this update (accidental side effect).\n const isNoLongerABoundary = prevExports !== null;\n if (isNoLongerABoundary) {\n module.hot.invalidate();\n }\n }\n}\n\nfunction formatDependencyChain(dependencyChain: ModuleId[]): string {\n return `Dependency chain: ${dependencyChain.join(\" -> \")}`;\n}\n\nfunction computeOutdatedModules(\n added: Map,\n modified: Map\n): { outdatedModules: Set; newModuleFactories: Map } {\n const outdatedModules = new Set();\n const newModuleFactories = new Map();\n\n for (const [moduleId, entry] of added) {\n if (entry != null) {\n newModuleFactories.set(moduleId, _eval(entry));\n }\n }\n\n for (const [moduleId, entry] of modified) {\n const effect = getAffectedModuleEffects(moduleId);\n\n switch (effect.type) {\n case \"unaccepted\":\n throw new Error(\n `cannot apply update: unaccepted module. ${formatDependencyChain(\n effect.dependencyChain\n )}.`\n );\n case \"self-declined\":\n throw new Error(\n `cannot apply update: self-declined module. ${formatDependencyChain(\n effect.dependencyChain\n )}.`\n );\n case \"accepted\":\n newModuleFactories.set(moduleId, _eval(entry));\n for (const outdatedModuleId of effect.outdatedModules) {\n outdatedModules.add(outdatedModuleId);\n }\n break;\n // TODO(alexkirsz) Dependencies: handle dependencies effects.\n }\n }\n\n return { outdatedModules, newModuleFactories };\n}\n\nfunction computeOutdatedSelfAcceptedModules(\n outdatedModules: Iterable\n): { moduleId: ModuleId; errorHandler: true | Function }[] {\n const outdatedSelfAcceptedModules = [];\n for (const moduleId of outdatedModules) {\n const module = moduleCache[moduleId];\n const hotState = moduleHotState.get(module)!;\n if (module && hotState.selfAccepted && !hotState.selfInvalidated) {\n outdatedSelfAcceptedModules.push({\n moduleId,\n errorHandler: hotState.selfAccepted,\n });\n }\n }\n return outdatedSelfAcceptedModules;\n}\n\n/**\n * Adds, deletes, and moves modules between chunks. This must happen before the\n * dispose phase as it needs to know which modules were removed from all chunks,\n * which we can only compute *after* taking care of added and moved modules.\n */\nfunction updateChunksPhase(\n chunksAddedModules: Map>,\n chunksDeletedModules: Map>\n): { disposedModules: Set } {\n for (const [chunkPath, addedModuleIds] of chunksAddedModules) {\n for (const moduleId of addedModuleIds) {\n addModuleToChunk(moduleId, chunkPath);\n }\n }\n\n const disposedModules: Set = new Set();\n for (const [chunkPath, addedModuleIds] of chunksDeletedModules) {\n for (const moduleId of addedModuleIds) {\n if (removeModuleFromChunk(moduleId, chunkPath)) {\n disposedModules.add(moduleId);\n }\n }\n }\n\n return { disposedModules };\n}\n\nfunction disposePhase(\n outdatedModules: Iterable,\n disposedModules: Set\n): { outdatedModuleParents: Map> } {\n for (const moduleId of outdatedModules) {\n disposeModule(moduleId, \"replace\");\n }\n\n for (const moduleId of disposedModules) {\n disposeModule(moduleId, \"clear\");\n }\n\n // Removing modules from the module cache is a separate step.\n // We also want to keep track of previous parents of the outdated modules.\n const outdatedModuleParents = new Map();\n for (const moduleId of outdatedModules) {\n const oldModule = moduleCache[moduleId];\n outdatedModuleParents.set(moduleId, oldModule?.parents);\n delete moduleCache[moduleId];\n }\n\n // TODO(alexkirsz) Dependencies: remove outdated dependency from module\n // children.\n\n return { outdatedModuleParents };\n}\n\n/**\n * Disposes of an instance of a module.\n *\n * Returns the persistent hot data that should be kept for the next module\n * instance.\n *\n * NOTE: mode = \"replace\" will not remove modules from the moduleCache.\n * This must be done in a separate step afterwards.\n * This is important because all modules need to be diposed to update the\n * parent/child relationships before they are actually removed from the moduleCache.\n * If this would be done in this method, following disposeModulecalls won't find\n * the module from the module id in the cache.\n */\nfunction disposeModule(moduleId: ModuleId, mode: \"clear\" | \"replace\") {\n const module = moduleCache[moduleId];\n if (!module) {\n return;\n }\n\n const hotState = moduleHotState.get(module)!;\n const data = {};\n\n // Run the `hot.dispose` handler, if any, passing in the persistent\n // `hot.data` object.\n for (const disposeHandler of hotState.disposeHandlers) {\n disposeHandler(data);\n }\n\n // This used to warn in `getOrInstantiateModuleFromParent` when a disposed\n // module is still importing other modules.\n module.hot.active = false;\n\n moduleHotState.delete(module);\n\n // TODO(alexkirsz) Dependencies: delete the module from outdated deps.\n\n // Remove the disposed module from its children's parents list.\n // It will be added back once the module re-instantiates and imports its\n // children again.\n for (const childId of module.children) {\n const child = moduleCache[childId];\n if (!child) {\n continue;\n }\n\n const idx = child.parents.indexOf(module.id);\n if (idx >= 0) {\n child.parents.splice(idx, 1);\n }\n }\n\n switch (mode) {\n case \"clear\":\n delete moduleCache[module.id];\n moduleHotData.delete(module.id);\n break;\n case \"replace\":\n moduleHotData.set(module.id, data);\n break;\n default:\n invariant(mode, (mode) => `invalid mode: ${mode}`);\n }\n}\n\nfunction applyPhase(\n outdatedSelfAcceptedModules: {\n moduleId: ModuleId;\n errorHandler: true | Function;\n }[],\n newModuleFactories: Map,\n outdatedModuleParents: Map>\n) {\n // Update module factories.\n for (const [moduleId, factory] of newModuleFactories.entries()) {\n moduleFactories[moduleId] = factory;\n }\n\n // TODO(alexkirsz) Run new runtime entries here.\n\n // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps.\n\n // Re-instantiate all outdated self-accepted modules.\n for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) {\n try {\n instantiateModule(moduleId, {\n type: SourceType.Update,\n parents: outdatedModuleParents.get(moduleId),\n });\n } catch (err) {\n if (typeof errorHandler === \"function\") {\n try {\n errorHandler(err, { moduleId, module: moduleCache[moduleId] });\n } catch (_) {\n // Ignore error.\n }\n }\n }\n }\n}\n\n/**\n * Utility function to ensure all variants of an enum are handled.\n */\nfunction invariant(never: never, computeMessage: (arg: any) => string): never {\n throw new Error(`Invariant: ${computeMessage(never)}`);\n}\n\nfunction applyUpdate(chunkListPath: ChunkPath, update: PartialUpdate) {\n switch (update.type) {\n case \"ChunkListUpdate\":\n applyChunkListUpdate(chunkListPath, update);\n break;\n default:\n invariant(update, (update) => `Unknown update type: ${update.type}`);\n }\n}\n\nfunction applyChunkListUpdate(\n chunkListPath: ChunkPath,\n update: ChunkListUpdate\n) {\n if (update.merged != null) {\n for (const merged of update.merged) {\n switch (merged.type) {\n case \"EcmascriptMergedUpdate\":\n applyEcmascriptMergedUpdate(chunkListPath, merged);\n break;\n default:\n invariant(merged, (merged) => `Unknown merged type: ${merged.type}`);\n }\n }\n }\n\n if (update.chunks != null) {\n for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) {\n switch (chunkUpdate.type) {\n case \"added\":\n BACKEND.loadChunk(chunkPath, { type: SourceType.Update });\n break;\n case \"total\":\n BACKEND.reloadChunk?.(chunkPath);\n break;\n case \"deleted\":\n BACKEND.unloadChunk?.(chunkPath);\n break;\n case \"partial\":\n invariant(\n chunkUpdate.instruction,\n (instruction) =>\n `Unknown partial instruction: ${JSON.stringify(instruction)}.`\n );\n default:\n invariant(\n chunkUpdate,\n (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}`\n );\n }\n }\n }\n}\n\nfunction applyEcmascriptMergedUpdate(\n chunkPath: ChunkPath,\n update: EcmascriptMergedUpdate\n) {\n const { entries = {}, chunks = {} } = update;\n const { added, modified, deleted, chunksAdded, chunksDeleted } =\n computeChangedModules(entries, chunks);\n const { outdatedModules, newModuleFactories } = computeOutdatedModules(\n added,\n modified\n );\n const outdatedSelfAcceptedModules =\n computeOutdatedSelfAcceptedModules(outdatedModules);\n const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted);\n const { outdatedModuleParents } = disposePhase(\n outdatedModules,\n disposedModules\n );\n applyPhase(\n outdatedSelfAcceptedModules,\n newModuleFactories,\n outdatedModuleParents\n );\n}\n\nfunction computeChangedModules(\n entries: Record,\n updates: Record\n): {\n added: Map;\n modified: Map;\n deleted: Set;\n chunksAdded: Map>;\n chunksDeleted: Map>;\n} {\n const chunksAdded = new Map();\n const chunksDeleted = new Map();\n const added: Map = new Map();\n const modified = new Map();\n const deleted: Set = new Set();\n\n for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) {\n switch (mergedChunkUpdate.type) {\n case \"added\": {\n const updateAdded = new Set(mergedChunkUpdate.modules);\n for (const moduleId of updateAdded) {\n added.set(moduleId, entries[moduleId]);\n }\n chunksAdded.set(chunkPath, updateAdded);\n break;\n }\n case \"deleted\": {\n // We could also use `mergedChunkUpdate.modules` here.\n const updateDeleted = new Set(chunkModulesMap.get(chunkPath));\n for (const moduleId of updateDeleted) {\n deleted.add(moduleId);\n }\n chunksDeleted.set(chunkPath, updateDeleted);\n break;\n }\n case \"partial\": {\n const updateAdded = new Set(mergedChunkUpdate.added);\n const updateDeleted = new Set(mergedChunkUpdate.deleted);\n for (const moduleId of updateAdded) {\n added.set(moduleId, entries[moduleId]);\n }\n for (const moduleId of updateDeleted) {\n deleted.add(moduleId);\n }\n chunksAdded.set(chunkPath, updateAdded);\n chunksDeleted.set(chunkPath, updateDeleted);\n break;\n }\n default:\n invariant(\n mergedChunkUpdate,\n (mergedChunkUpdate) =>\n `Unknown merged chunk update type: ${mergedChunkUpdate.type}`\n );\n }\n }\n\n // If a module was added from one chunk and deleted from another in the same update,\n // consider it to be modified, as it means the module was moved from one chunk to another\n // AND has new code in a single update.\n for (const moduleId of added.keys()) {\n if (deleted.has(moduleId)) {\n added.delete(moduleId);\n deleted.delete(moduleId);\n }\n }\n\n for (const [moduleId, entry] of Object.entries(entries)) {\n // Modules that haven't been added to any chunk but have new code are considered\n // to be modified.\n // This needs to be under the previous loop, as we need it to get rid of modules\n // that were added and deleted in the same update.\n if (!added.has(moduleId)) {\n modified.set(moduleId, entry);\n }\n }\n\n return { added, deleted, modified, chunksAdded, chunksDeleted };\n}\n\ntype ModuleEffect =\n | {\n type: \"unaccepted\";\n dependencyChain: ModuleId[];\n }\n | {\n type: \"self-declined\";\n dependencyChain: ModuleId[];\n moduleId: ModuleId;\n }\n | {\n type: \"accepted\";\n moduleId: ModuleId;\n outdatedModules: Set;\n };\n\nfunction getAffectedModuleEffects(moduleId: ModuleId): ModuleEffect {\n const outdatedModules: Set = new Set();\n\n type QueueItem = { moduleId?: ModuleId; dependencyChain: ModuleId[] };\n\n const queue: QueueItem[] = [\n {\n moduleId,\n dependencyChain: [],\n },\n ];\n\n let nextItem;\n while ((nextItem = queue.shift())) {\n const { moduleId, dependencyChain } = nextItem;\n\n if (moduleId != null) {\n outdatedModules.add(moduleId);\n }\n\n // We've arrived at the runtime of the chunk, which means that nothing\n // else above can accept this update.\n if (moduleId === undefined) {\n return {\n type: \"unaccepted\",\n dependencyChain,\n };\n }\n\n const module = moduleCache[moduleId];\n const hotState = moduleHotState.get(module)!;\n\n if (\n // The module is not in the cache. Since this is a \"modified\" update,\n // it means that the module was never instantiated before.\n !module || // The module accepted itself without invalidating globalThis.\n // TODO is that right?\n (hotState.selfAccepted && !hotState.selfInvalidated)\n ) {\n continue;\n }\n\n if (hotState.selfDeclined) {\n return {\n type: \"self-declined\",\n dependencyChain,\n moduleId,\n };\n }\n\n if (runtimeModules.has(moduleId)) {\n queue.push({\n moduleId: undefined,\n dependencyChain: [...dependencyChain, moduleId],\n });\n continue;\n }\n\n for (const parentId of module.parents) {\n const parent = moduleCache[parentId];\n\n if (!parent) {\n // TODO(alexkirsz) Is this even possible?\n continue;\n }\n\n // TODO(alexkirsz) Dependencies: check accepted and declined\n // dependencies here.\n\n queue.push({\n moduleId: parentId,\n dependencyChain: [...dependencyChain, moduleId],\n });\n }\n }\n\n return {\n type: \"accepted\",\n moduleId,\n outdatedModules,\n };\n}\n\nfunction handleApply(chunkListPath: ChunkPath, update: ServerMessage) {\n switch (update.type) {\n case \"partial\": {\n // This indicates that the update is can be applied to the current state of the application.\n applyUpdate(chunkListPath, update.instruction);\n break;\n }\n case \"restart\": {\n // This indicates that there is no way to apply the update to the\n // current state of the application, and that the application must be\n // restarted.\n BACKEND.restart();\n break;\n }\n case \"notFound\": {\n // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed,\n // or the page itself was deleted.\n // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to.\n // If it is a runtime chunk list, we restart the application.\n if (runtimeChunkLists.has(chunkListPath)) {\n BACKEND.restart();\n } else {\n disposeChunkList(chunkListPath);\n }\n break;\n }\n default:\n throw new Error(`Unknown update type: ${update.type}`);\n }\n}\n\nfunction createModuleHot(hotData: HotData): { hot: Hot; hotState: HotState } {\n const hotState: HotState = {\n selfAccepted: false,\n selfDeclined: false,\n selfInvalidated: false,\n disposeHandlers: [],\n };\n\n const hot: Hot = {\n // TODO(alexkirsz) This is not defined in the HMR API. It was used to\n // decide whether to warn whenever an HMR-disposed module required other\n // modules. We might want to remove it.\n active: true,\n\n data: hotData ?? {},\n\n // TODO(alexkirsz) Support full (dep, callback, errorHandler) form.\n accept: (\n modules?: string | string[] | AcceptErrorHandler,\n _callback?: AcceptCallback,\n _errorHandler?: AcceptErrorHandler\n ) => {\n if (modules === undefined) {\n hotState.selfAccepted = true;\n } else if (typeof modules === \"function\") {\n hotState.selfAccepted = modules;\n } else {\n throw new Error(\"unsupported `accept` signature\");\n }\n },\n\n decline: (dep) => {\n if (dep === undefined) {\n hotState.selfDeclined = true;\n } else {\n throw new Error(\"unsupported `decline` signature\");\n }\n },\n\n dispose: (callback) => {\n hotState.disposeHandlers.push(callback);\n },\n\n addDisposeHandler: (callback) => {\n hotState.disposeHandlers.push(callback);\n },\n\n removeDisposeHandler: (callback) => {\n const idx = hotState.disposeHandlers.indexOf(callback);\n if (idx >= 0) {\n hotState.disposeHandlers.splice(idx, 1);\n }\n },\n\n invalidate: () => {\n hotState.selfInvalidated = true;\n // TODO(alexkirsz) The original HMR code had management-related code\n // here.\n },\n\n // NOTE(alexkirsz) This is part of the management API, which we don't\n // implement, but the Next.js React Refresh runtime uses this to decide\n // whether to schedule an update.\n status: () => \"idle\",\n\n // NOTE(alexkirsz) Since we always return \"idle\" for now, these are no-ops.\n addStatusHandler: (_handler) => {},\n removeStatusHandler: (_handler) => {},\n };\n\n return { hot, hotState };\n}\n\n/**\n * Adds a module to a chunk.\n */\nfunction addModuleToChunk(moduleId: ModuleId, chunkPath: ChunkPath) {\n let moduleChunks = moduleChunksMap.get(moduleId);\n if (!moduleChunks) {\n moduleChunks = new Set([chunkPath]);\n moduleChunksMap.set(moduleId, moduleChunks);\n } else {\n moduleChunks.add(chunkPath);\n }\n\n let chunkModules = chunkModulesMap.get(chunkPath);\n if (!chunkModules) {\n chunkModules = new Set([moduleId]);\n chunkModulesMap.set(chunkPath, chunkModules);\n } else {\n chunkModules.add(moduleId);\n }\n}\n\n/**\n * Returns the first chunk that included a module.\n * This is used by the Node.js backend, hence why it's marked as unused in this\n * file.\n */\nfunction getFirstModuleChunk(moduleId: ModuleId) {\n const moduleChunkPaths = moduleChunksMap.get(moduleId);\n if (moduleChunkPaths == null) {\n return null;\n }\n\n return moduleChunkPaths.values().next().value;\n}\n\n/**\n * Removes a module from a chunk. Returns true there are no remaining chunks\n * including this module.\n */\nfunction removeModuleFromChunk(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): boolean {\n const moduleChunks = moduleChunksMap.get(moduleId)!;\n moduleChunks.delete(chunkPath);\n\n const chunkModules = chunkModulesMap.get(chunkPath)!;\n chunkModules.delete(moduleId);\n\n const noRemainingModules = chunkModules.size === 0;\n if (noRemainingModules) {\n chunkModulesMap.delete(chunkPath);\n }\n\n const noRemainingChunks = moduleChunks.size === 0;\n if (noRemainingChunks) {\n moduleChunksMap.delete(moduleId);\n }\n\n return noRemainingChunks;\n}\n\n/**\n * Diposes of a chunk list and its corresponding exclusive chunks.\n */\nfunction disposeChunkList(chunkListPath: ChunkPath): boolean {\n const chunkPaths = chunkListChunksMap.get(chunkListPath);\n if (chunkPaths == null) {\n return false;\n }\n chunkListChunksMap.delete(chunkListPath);\n\n for (const chunkPath of chunkPaths) {\n const chunkChunkLists = chunkChunkListsMap.get(chunkPath)!;\n chunkChunkLists.delete(chunkListPath);\n\n if (chunkChunkLists.size === 0) {\n chunkChunkListsMap.delete(chunkPath);\n disposeChunk(chunkPath);\n }\n }\n\n // We must also dispose of the chunk list's chunk itself to ensure it may\n // be reloaded properly in the future.\n BACKEND.unloadChunk?.(chunkListPath);\n\n return true;\n}\n\n/**\n * Disposes of a chunk and its corresponding exclusive modules.\n *\n * @returns Whether the chunk was disposed of.\n */\nfunction disposeChunk(chunkPath: ChunkPath): boolean {\n // This should happen whether or not the chunk has any modules in it. For instance,\n // CSS chunks have no modules in them, but they still need to be unloaded.\n BACKEND.unloadChunk?.(chunkPath);\n\n const chunkModules = chunkModulesMap.get(chunkPath);\n if (chunkModules == null) {\n return false;\n }\n chunkModules.delete(chunkPath);\n\n for (const moduleId of chunkModules) {\n const moduleChunks = moduleChunksMap.get(moduleId)!;\n moduleChunks.delete(chunkPath);\n\n const noRemainingChunks = moduleChunks.size === 0;\n if (noRemainingChunks) {\n moduleChunksMap.delete(moduleId);\n disposeModule(moduleId, \"clear\");\n availableModules.delete(moduleId);\n }\n }\n\n return true;\n}\n\n/**\n * Instantiates a runtime module.\n */\nfunction instantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Gets or instantiates a runtime module.\n */\nfunction getOrInstantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n const module = moduleCache[moduleId];\n if (module) {\n if (module.error) {\n throw module.error;\n }\n return module;\n }\n\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Subscribes to chunk list updates from the update server and applies them.\n */\nfunction registerChunkList(\n chunkUpdateProvider: ChunkUpdateProvider,\n chunkList: ChunkList\n) {\n chunkUpdateProvider.push([\n chunkList.path,\n handleApply.bind(null, chunkList.path),\n ]);\n\n // Adding chunks to chunk lists and vice versa.\n const chunks = new Set(chunkList.chunks.map(getChunkPath));\n chunkListChunksMap.set(chunkList.path, chunks);\n for (const chunkPath of chunks) {\n let chunkChunkLists = chunkChunkListsMap.get(chunkPath);\n if (!chunkChunkLists) {\n chunkChunkLists = new Set([chunkList.path]);\n chunkChunkListsMap.set(chunkPath, chunkChunkLists);\n } else {\n chunkChunkLists.add(chunkList.path);\n }\n }\n\n if (chunkList.source === \"entry\") {\n markChunkListAsRuntime(chunkList.path);\n }\n}\n\n/**\n * Marks a chunk list as a runtime chunk list. There can be more than one\n * runtime chunk list. For instance, integration tests can have multiple chunk\n * groups loaded at runtime, each with its own chunk list.\n */\nfunction markChunkListAsRuntime(chunkListPath: ChunkPath) {\n runtimeChunkLists.add(chunkListPath);\n}\n\nfunction registerChunk([\n chunkPath,\n chunkModules,\n runtimeParams,\n]: ChunkRegistration) {\n for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) {\n if (!moduleFactories[moduleId]) {\n moduleFactories[moduleId] = moduleFactory;\n }\n addModuleToChunk(moduleId, chunkPath);\n }\n\n return BACKEND.registerChunk(chunkPath, runtimeParams);\n}\n\nglobalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS ??= [];\n\nconst chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS;\nif (Array.isArray(chunkListsToRegister)) {\n for (const chunkList of chunkListsToRegister) {\n registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS, chunkList);\n }\n}\n\nglobalThis.TURBOPACK_CHUNK_LISTS = {\n push: (chunkList) => {\n registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS!, chunkList);\n },\n} satisfies ChunkListProvider;\n"],"names":[],"mappings":";;;;;IAyFA;UAAK,UAAU;IAAV,WAAA,WAKH,aAAU,KAAV;IALG,WAAA,WASH,YAAS,KAAT;IATG,WAAA,WAcH,YAAS,KAAT;GAdG,eAAA;;AAwCL,MAAM,kBAAmC,OAAO,OAAO;AACvD,MAAM,cAA2B,OAAO,OAAO;AAK/C,MAAM,gBAAwC,IAAI;AAIlD,MAAM,iBAAwC,IAAI;AAIlD,MAAM,iBAAgC,IAAI;AAQ1C,MAAM,kBAAiD,IAAI;AAI3D,MAAM,kBAAiD,IAAI;AAM3D,MAAM,oBAAoC,IAAI;AAI9C,MAAM,qBAAqD,IAAI;AAI/D,MAAM,qBAAqD,IAAI;AAE/D,MAAM,yBAAiD,CACrD,OACA;IAEA,OAAO,MAAM,WACT,gBAAgB,cAAc,MAAM,QACpC,gBAAgB,MAAM,MAAM;AAClC;AAEA,SAAS,gBACP,EAAY,EACZ,MAAe,KAAK;IAEpB,IAAI;IACJ,IAAI;QACF,MAAM,QAAQ;IAChB,EAAE,OAAO,KAAK;QAKZ,MAAM,IAAI,MAAM,CAAC,+BAA+B,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC;IAChE;IACA,IAAI,CAAC,KAAK;QACR,OAAO;IACT;IACA,MAAM,KAAK,CAAC;IACZ,WAAW,KAAK,IAAI,IAAI;IACxB,OAAO;AACT;AACA,gBAAgB,UAAU,CACxB,IACA;IAMA,OAAO,QAAQ,QAAQ,IAAI;AAC7B;AAEA,MAAM,mBAAuD,IAAI;AAEjE,MAAM,wBAA6D,IAAI;AAEvE,eAAe,UACb,MAAkB,EAClB,SAAoB;IAEpB,IAAI,OAAO,cAAc,UAAU;QACjC,OAAO,cAAc,QAAQ;IAC/B;IAEA,MAAM,eAAe,UAAU,YAAY,EAAE;IAC7C,MAAM,kBAAkB,aAAa,IAAI,CAAC;QACxC,IAAI,eAAe,CAAC,SAAS,EAAE,OAAO;QACtC,OAAO,iBAAiB,IAAI;IAC9B;IACA,IAAI,gBAAgB,SAAS,KAAK,gBAAgB,MAAM,CAAC,IAAM,IAAI;QAEjE,OAAO,QAAQ,IAAI;IACrB;IAEA,MAAM,2BAA2B,UAAU,gBAAgB,EAAE;IAC7D,MAAM,uBAAuB,yBAC1B,IAAI,CAAC;QAGJ,OAAO,sBAAsB,IAAI;IACnC,GACC,OAAO,CAAC,IAAM;IAEjB,IAAI;IACJ,IAAI,qBAAqB,SAAS,GAAG;QAGnC,IAAI,qBAAqB,UAAU,yBAAyB,QAAQ;YAElE,OAAO,QAAQ,IAAI;QACrB;QAEA,MAAM,qBAAqC,IAAI;QAC/C,KAAK,MAAM,eAAe,yBAA0B;YAClD,IAAI,CAAC,sBAAsB,IAAI,cAAc;gBAC3C,mBAAmB,IAAI;YACzB;QACF;QAEA,KAAK,MAAM,qBAAqB,mBAAoB;YAClD,MAAM,UAAU,cAAc,QAAQ;YAEtC,sBAAsB,IAAI,mBAAmB;YAE7C,qBAAqB,KAAK;QAC5B;QAEA,UAAU,QAAQ,IAAI;IACxB,OAAO;QACL,UAAU,cAAc,QAAQ,UAAU;QAG1C,KAAK,MAAM,uBAAuB,yBAA0B;YAC1D,IAAI,CAAC,sBAAsB,IAAI,sBAAsB;gBACnD,sBAAsB,IAAI,qBAAqB;YACjD;QACF;IACF;IAEA,KAAK,MAAM,YAAY,aAAc;QACnC,IAAI,CAAC,iBAAiB,IAAI,WAAW;YAGnC,iBAAiB,IAAI,UAAU;QACjC;IACF;IAEA,OAAO;AACT;AAEA,eAAe,cACb,MAAkB,EAClB,SAAoB;IAEpB,IAAI;QACF,MAAM,QAAQ,UAAU,WAAW;IACrC,EAAE,OAAO,OAAO;QACd,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,aAAa,CAAC,iCAAiC,EAAE,OAAO,UAAU,CAAC;gBACnE;YACF,KAAK,WAAW;gBACd,aAAa,CAAC,YAAY,EAAE,OAAO,SAAS,CAAC;gBAC7C;YACF,KAAK,WAAW;gBACd,aAAa;gBACb;QACJ;QACA,MAAM,IAAI,MACR,CAAC,qBAAqB,EAAE,UAAU,CAAC,EAAE,WAAW,EAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,GACxB,CAAC;IAEN;AACF;AAEA,SAAS,kBAAkB,EAAY,EAAE,MAAkB;IACzD,MAAM,gBAAgB,eAAe,CAAC,GAAG;IACzC,IAAI,OAAO,kBAAkB,YAAY;QAIvC,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,sBAAsB,CAAC,4BAA4B,EAAE,OAAO,UAAU,CAAC;gBACvE;YACF,KAAK,WAAW;gBACd,sBAAsB,CAAC,oCAAoC,EAAE,OAAO,SAAS,CAAC;gBAC9E;YACF,KAAK,WAAW;gBACd,sBAAsB;gBACtB;QACJ;QACA,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,oBAAoB,uFAAuF,CAAC;IAEjJ;IAEA,MAAM,UAAU,cAAc,IAAI;IAClC,MAAM,EAAE,IAAG,EAAE,SAAQ,EAAE,GAAG,gBAAgB;IAE1C,IAAI;IACJ,OAAQ,OAAO;QACb,KAAK,WAAW;YACd,eAAe,IAAI;YACnB,UAAU,EAAE;YACZ;QACF,KAAK,WAAW;YAGd,UAAU;gBAAC,OAAO;aAAS;YAC3B;QACF,KAAK,WAAW;YACd,UAAU,OAAO,WAAW,EAAE;YAC9B;IACJ;IACA,MAAM,SAAiB;QACrB,SAAS,CAAC;QACV,OAAO;QACP,QAAQ;QACR;QACA;QACA,UAAU,EAAE;QACZ,iBAAiB;QACjB;IACF;IAEA,WAAW,CAAC,GAAG,GAAG;IAClB,eAAe,IAAI,QAAQ;IAG3B,IAAI;QACF,wBAAwB,QAAQ,CAAC;YAC/B,cAAc,KAAK,OAAO,SAAS;gBACjC,GAAG,OAAO;gBACV,GAAG,gBAAgB,KAAK,MAAM;gBAC9B,GAAG;gBACH,GAAG,eAAe,KAAK,MAAM;gBAC7B,GAAG,UAAU,KAAK,MAAM;gBACxB,GAAG,UAAU,KAAK,MAAM;gBACxB,GAAG,UAAU,KAAK,MAAM,OAAO;gBAC/B,GAAG,YAAY,KAAK,MAAM;gBAC1B,GAAG,gBAAgB,KAAK,MAAM;gBAC9B,GAAG;gBACH,GAAG;gBACH,GAAG,UAAU,KAAK,MAAM;oBAAE,MAAM,WAAW;oBAAQ,UAAU;gBAAG;gBAChE,GAAG;gBACH,GAAG;gBACH,WAAW,OAAO,GAAG,QAAQ,gBAAgB;YAC/C;QACF;IACF,EAAE,OAAO,OAAO;QACd,OAAO,QAAQ;QACf,MAAM;IACR;IAEA,OAAO,SAAS;IAChB,IAAI,OAAO,mBAAmB,OAAO,YAAY,OAAO,iBAAiB;QAEvE,WAAW,OAAO,SAAS,OAAO;IACpC;IAEA,OAAO;AACT;AAOA,SAAS,wBACP,MAAc,EACd,aAA4C;IAE5C,MAAM,+BACJ,OAAO,WAAW,sCAAsC,aACpD,WAAW,kCAAkC,OAAO,MACpD,KAAO;IAEb,IAAI;QACF,cAAc;YACZ,UAAU,WAAW;YACrB,WAAW,WAAW;QACxB;QAEA,IAAI,sBAAsB,YAAY;YAGpC,+CACE,QACA,WAAW;QAEf;IACF,EAAE,OAAO,GAAG;QACV,MAAM;IACR,SAAU;QAER;IACF;AACF;AAKA,MAAM,mCAAqE,CACzE,IACA;IAEA,IAAI,CAAC,aAAa,IAAI,QAAQ;QAC5B,QAAQ,KACN,CAAC,4BAA4B,EAAE,GAAG,aAAa,EAAE,aAAa,GAAG,oCAAoC,CAAC;IAE1G;IAEA,MAAM,SAAS,WAAW,CAAC,GAAG;IAE9B,IAAI,aAAa,SAAS,QAAQ,QAAQ,CAAC,GAAG;QAC5C,aAAa,SAAS,KAAK;IAC7B;IAEA,IAAI,QAAQ;QACV,IAAI,OAAO,QAAQ,QAAQ,aAAa,QAAQ,CAAC,GAAG;YAClD,OAAO,QAAQ,KAAK,aAAa;QACnC;QAEA,OAAO;IACT;IAEA,OAAO,kBAAkB,IAAI;QAC3B,MAAM,WAAW;QACjB,UAAU,aAAa;IACzB;AACF;AAKA,SAAS,+CACP,MAAc,EACd,OAAuB;IAEvB,MAAM,iBAAiB,OAAO;IAC9B,MAAM,cAAc,OAAO,IAAI,KAAK,eAAe;IAEnD,QAAQ,+BAA+B,gBAAgB,OAAO;IAI9D,IAAI,QAAQ,uBAAuB,iBAAiB;QAGlD,OAAO,IAAI,QAAQ,CAAC;YAClB,KAAK,cAAc;QACrB;QAGA,OAAO,IAAI;QAKX,IAAI,gBAAgB,MAAM;YAQxB,IACE,QAAQ,qCACN,aACA,iBAEF;gBACA,OAAO,IAAI;YACb,OAAO;gBACL,QAAQ;YACV;QACF;IACF,OAAO;QAKL,MAAM,sBAAsB,gBAAgB;QAC5C,IAAI,qBAAqB;YACvB,OAAO,IAAI;QACb;IACF;AACF;AAEA,SAAS,sBAAsB,eAA2B;IACxD,OAAO,CAAC,kBAAkB,EAAE,gBAAgB,KAAK,QAAQ,CAAC;AAC5D;AAEA,SAAS,uBACP,KAAuD,EACvD,QAA8C;IAE9C,MAAM,kBAAkB,IAAI;IAC5B,MAAM,qBAAqB,IAAI;IAE/B,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,MAAO;QACrC,IAAI,SAAS,MAAM;YACjB,mBAAmB,IAAI,UAAU,MAAM;QACzC;IACF;IAEA,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,SAAU;QACxC,MAAM,SAAS,yBAAyB;QAExC,OAAQ,OAAO;YACb,KAAK;gBACH,MAAM,IAAI,MACR,CAAC,wCAAwC,EAAE,sBACzC,OAAO,iBACP,CAAC,CAAC;YAER,KAAK;gBACH,MAAM,IAAI,MACR,CAAC,2CAA2C,EAAE,sBAC5C,OAAO,iBACP,CAAC,CAAC;YAER,KAAK;gBACH,mBAAmB,IAAI,UAAU,MAAM;gBACvC,KAAK,MAAM,oBAAoB,OAAO,gBAAiB;oBACrD,gBAAgB,IAAI;gBACtB;gBACA;QAEJ;IACF;IAEA,OAAO;QAAE;QAAiB;IAAmB;AAC/C;AAEA,SAAS,mCACP,eAAmC;IAEnC,MAAM,8BAA8B,EAAE;IACtC,KAAK,MAAM,YAAY,gBAAiB;QACtC,MAAM,SAAS,WAAW,CAAC,SAAS;QACpC,MAAM,WAAW,eAAe,IAAI;QACpC,IAAI,UAAU,SAAS,gBAAgB,CAAC,SAAS,iBAAiB;YAChE,4BAA4B,KAAK;gBAC/B;gBACA,cAAc,SAAS;YACzB;QACF;IACF;IACA,OAAO;AACT;AAOA,SAAS,kBACP,kBAAiD,EACjD,oBAAmD;IAEnD,KAAK,MAAM,CAAC,WAAW,eAAe,IAAI,mBAAoB;QAC5D,KAAK,MAAM,YAAY,eAAgB;YACrC,iBAAiB,UAAU;QAC7B;IACF;IAEA,MAAM,kBAAiC,IAAI;IAC3C,KAAK,MAAM,CAAC,WAAW,eAAe,IAAI,qBAAsB;QAC9D,KAAK,MAAM,YAAY,eAAgB;YACrC,IAAI,sBAAsB,UAAU,YAAY;gBAC9C,gBAAgB,IAAI;YACtB;QACF;IACF;IAEA,OAAO;QAAE;IAAgB;AAC3B;AAEA,SAAS,aACP,eAAmC,EACnC,eAA8B;IAE9B,KAAK,MAAM,YAAY,gBAAiB;QACtC,cAAc,UAAU;IAC1B;IAEA,KAAK,MAAM,YAAY,gBAAiB;QACtC,cAAc,UAAU;IAC1B;IAIA,MAAM,wBAAwB,IAAI;IAClC,KAAK,MAAM,YAAY,gBAAiB;QACtC,MAAM,YAAY,WAAW,CAAC,SAAS;QACvC,sBAAsB,IAAI,UAAU,WAAW;QAC/C,OAAO,WAAW,CAAC,SAAS;IAC9B;IAKA,OAAO;QAAE;IAAsB;AACjC;AAeA,SAAS,cAAc,QAAkB,EAAE,IAAyB;IAClE,MAAM,SAAS,WAAW,CAAC,SAAS;IACpC,IAAI,CAAC,QAAQ;QACX;IACF;IAEA,MAAM,WAAW,eAAe,IAAI;IACpC,MAAM,OAAO,CAAC;IAId,KAAK,MAAM,kBAAkB,SAAS,gBAAiB;QACrD,eAAe;IACjB;IAIA,OAAO,IAAI,SAAS;IAEpB,eAAe,OAAO;IAOtB,KAAK,MAAM,WAAW,OAAO,SAAU;QACrC,MAAM,QAAQ,WAAW,CAAC,QAAQ;QAClC,IAAI,CAAC,OAAO;YACV;QACF;QAEA,MAAM,MAAM,MAAM,QAAQ,QAAQ,OAAO;QACzC,IAAI,OAAO,GAAG;YACZ,MAAM,QAAQ,OAAO,KAAK;QAC5B;IACF;IAEA,OAAQ;QACN,KAAK;YACH,OAAO,WAAW,CAAC,OAAO,GAAG;YAC7B,cAAc,OAAO,OAAO;YAC5B;QACF,KAAK;YACH,cAAc,IAAI,OAAO,IAAI;YAC7B;QACF;YACE,UAAU,MAAM,CAAC,OAAS,CAAC,cAAc,EAAE,KAAK,CAAC;IACrD;AACF;AAEA,SAAS,WACP,2BAGG,EACH,kBAAgD,EAChD,qBAAqD;IAGrD,KAAK,MAAM,CAAC,UAAU,QAAQ,IAAI,mBAAmB,UAAW;QAC9D,eAAe,CAAC,SAAS,GAAG;IAC9B;IAOA,KAAK,MAAM,EAAE,SAAQ,EAAE,aAAY,EAAE,IAAI,4BAA6B;QACpE,IAAI;YACF,kBAAkB,UAAU;gBAC1B,MAAM,WAAW;gBACjB,SAAS,sBAAsB,IAAI;YACrC;QACF,EAAE,OAAO,KAAK;YACZ,IAAI,OAAO,iBAAiB,YAAY;gBACtC,IAAI;oBACF,aAAa,KAAK;wBAAE;wBAAU,QAAQ,WAAW,CAAC,SAAS;oBAAC;gBAC9D,EAAE,OAAO,GAAG,CAEZ;YACF;QACF;IACF;AACF;AAKA,SAAS,UAAU,KAAY,EAAE,cAAoC;IACnE,MAAM,IAAI,MAAM,CAAC,WAAW,EAAE,eAAe,OAAO,CAAC;AACvD;AAEA,SAAS,YAAY,aAAwB,EAAE,MAAqB;IAClE,OAAQ,OAAO;QACb,KAAK;YACH,qBAAqB,eAAe;YACpC;QACF;YACE,UAAU,QAAQ,CAAC,SAAW,CAAC,qBAAqB,EAAE,OAAO,KAAK,CAAC;IACvE;AACF;AAEA,SAAS,qBACP,aAAwB,EACxB,MAAuB;IAEvB,IAAI,OAAO,UAAU,MAAM;QACzB,KAAK,MAAM,UAAU,OAAO,OAAQ;YAClC,OAAQ,OAAO;gBACb,KAAK;oBACH,4BAA4B,eAAe;oBAC3C;gBACF;oBACE,UAAU,QAAQ,CAAC,SAAW,CAAC,qBAAqB,EAAE,OAAO,KAAK,CAAC;YACvE;QACF;IACF;IAEA,IAAI,OAAO,UAAU,MAAM;QACzB,KAAK,MAAM,CAAC,WAAW,YAAY,IAAI,OAAO,QAAQ,OAAO,QAAS;YACpE,OAAQ,YAAY;gBAClB,KAAK;oBACH,QAAQ,UAAU,WAAW;wBAAE,MAAM,WAAW;oBAAO;oBACvD;gBACF,KAAK;oBACH,QAAQ,cAAc;oBACtB;gBACF,KAAK;oBACH,QAAQ,cAAc;oBACtB;gBACF,KAAK;oBACH,UACE,YAAY,aACZ,CAAC,cACC,CAAC,6BAA6B,EAAE,KAAK,UAAU,aAAa,CAAC,CAAC;gBAEpE;oBACE,UACE,aACA,CAAC,cAAgB,CAAC,2BAA2B,EAAE,YAAY,KAAK,CAAC;YAEvE;QACF;IACF;AACF;AAEA,SAAS,4BACP,SAAoB,EACpB,MAA8B;IAE9B,MAAM,EAAE,SAAU,CAAC,EAAC,EAAE,QAAS,CAAC,EAAC,EAAE,GAAG;IACtC,MAAM,EAAE,MAAK,EAAE,SAAQ,EAAE,QAAO,EAAE,YAAW,EAAE,cAAa,EAAE,GAC5D,sBAAsB,SAAS;IACjC,MAAM,EAAE,gBAAe,EAAE,mBAAkB,EAAE,GAAG,uBAC9C,OACA;IAEF,MAAM,8BACJ,mCAAmC;IACrC,MAAM,EAAE,gBAAe,EAAE,GAAG,kBAAkB,aAAa;IAC3D,MAAM,EAAE,sBAAqB,EAAE,GAAG,aAChC,iBACA;IAEF,WACE,6BACA,oBACA;AAEJ;AAEA,SAAS,sBACP,OAAgD,EAChD,OAAuD;IAQvD,MAAM,cAAc,IAAI;IACxB,MAAM,gBAAgB,IAAI;IAC1B,MAAM,QAA8C,IAAI;IACxD,MAAM,WAAW,IAAI;IACrB,MAAM,UAAyB,IAAI;IAEnC,KAAK,MAAM,CAAC,WAAW,kBAAkB,IAAI,OAAO,QAAQ,SAAU;QACpE,OAAQ,kBAAkB;YACxB,KAAK;gBAAS;oBACZ,MAAM,cAAc,IAAI,IAAI,kBAAkB;oBAC9C,KAAK,MAAM,YAAY,YAAa;wBAClC,MAAM,IAAI,UAAU,OAAO,CAAC,SAAS;oBACvC;oBACA,YAAY,IAAI,WAAW;oBAC3B;gBACF;YACA,KAAK;gBAAW;oBAEd,MAAM,gBAAgB,IAAI,IAAI,gBAAgB,IAAI;oBAClD,KAAK,MAAM,YAAY,cAAe;wBACpC,QAAQ,IAAI;oBACd;oBACA,cAAc,IAAI,WAAW;oBAC7B;gBACF;YACA,KAAK;gBAAW;oBACd,MAAM,cAAc,IAAI,IAAI,kBAAkB;oBAC9C,MAAM,gBAAgB,IAAI,IAAI,kBAAkB;oBAChD,KAAK,MAAM,YAAY,YAAa;wBAClC,MAAM,IAAI,UAAU,OAAO,CAAC,SAAS;oBACvC;oBACA,KAAK,MAAM,YAAY,cAAe;wBACpC,QAAQ,IAAI;oBACd;oBACA,YAAY,IAAI,WAAW;oBAC3B,cAAc,IAAI,WAAW;oBAC7B;gBACF;YACA;gBACE,UACE,mBACA,CAAC,oBACC,CAAC,kCAAkC,EAAE,kBAAkB,KAAK,CAAC;QAErE;IACF;IAKA,KAAK,MAAM,YAAY,MAAM,OAAQ;QACnC,IAAI,QAAQ,IAAI,WAAW;YACzB,MAAM,OAAO;YACb,QAAQ,OAAO;QACjB;IACF;IAEA,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,OAAO,QAAQ,SAAU;QAKvD,IAAI,CAAC,MAAM,IAAI,WAAW;YACxB,SAAS,IAAI,UAAU;QACzB;IACF;IAEA,OAAO;QAAE;QAAO;QAAS;QAAU;QAAa;IAAc;AAChE;AAkBA,SAAS,yBAAyB,QAAkB;IAClD,MAAM,kBAAiC,IAAI;IAI3C,MAAM,QAAqB;QACzB;YACE;YACA,iBAAiB,EAAE;QACrB;KACD;IAED,IAAI;IACJ,MAAQ,WAAW,MAAM,QAAU;QACjC,MAAM,EAAE,SAAQ,EAAE,gBAAe,EAAE,GAAG;QAEtC,IAAI,YAAY,MAAM;YACpB,gBAAgB,IAAI;QACtB;QAIA,IAAI,aAAa,WAAW;YAC1B,OAAO;gBACL,MAAM;gBACN;YACF;QACF;QAEA,MAAM,SAAS,WAAW,CAAC,SAAS;QACpC,MAAM,WAAW,eAAe,IAAI;QAEpC,IAGE,CAAC,UAEA,SAAS,gBAAgB,CAAC,SAAS,iBACpC;YACA;QACF;QAEA,IAAI,SAAS,cAAc;YACzB,OAAO;gBACL,MAAM;gBACN;gBACA;YACF;QACF;QAEA,IAAI,eAAe,IAAI,WAAW;YAChC,MAAM,KAAK;gBACT,UAAU;gBACV,iBAAiB;uBAAI;oBAAiB;iBAAS;YACjD;YACA;QACF;QAEA,KAAK,MAAM,YAAY,OAAO,QAAS;YACrC,MAAM,SAAS,WAAW,CAAC,SAAS;YAEpC,IAAI,CAAC,QAAQ;gBAEX;YACF;YAKA,MAAM,KAAK;gBACT,UAAU;gBACV,iBAAiB;uBAAI;oBAAiB;iBAAS;YACjD;QACF;IACF;IAEA,OAAO;QACL,MAAM;QACN;QACA;IACF;AACF;AAEA,SAAS,YAAY,aAAwB,EAAE,MAAqB;IAClE,OAAQ,OAAO;QACb,KAAK;YAAW;gBAEd,YAAY,eAAe,OAAO;gBAClC;YACF;QACA,KAAK;YAAW;gBAId,QAAQ;gBACR;YACF;QACA,KAAK;YAAY;gBAKf,IAAI,kBAAkB,IAAI,gBAAgB;oBACxC,QAAQ;gBACV,OAAO;oBACL,iBAAiB;gBACnB;gBACA;YACF;QACA;YACE,MAAM,IAAI,MAAM,CAAC,qBAAqB,EAAE,OAAO,KAAK,CAAC;IACzD;AACF;AAEA,SAAS,gBAAgB,OAAgB;IACvC,MAAM,WAAqB;QACzB,cAAc;QACd,cAAc;QACd,iBAAiB;QACjB,iBAAiB,EAAE;IACrB;IAEA,MAAM,MAAW;QAIf,QAAQ;QAER,MAAM,WAAW,CAAC;QAGlB,QAAQ,CACN,SACA,WACA;YAEA,IAAI,YAAY,WAAW;gBACzB,SAAS,eAAe;YAC1B,OAAO,IAAI,OAAO,YAAY,YAAY;gBACxC,SAAS,eAAe;YAC1B,OAAO;gBACL,MAAM,IAAI,MAAM;YAClB;QACF;QAEA,SAAS,CAAC;YACR,IAAI,QAAQ,WAAW;gBACrB,SAAS,eAAe;YAC1B,OAAO;gBACL,MAAM,IAAI,MAAM;YAClB;QACF;QAEA,SAAS,CAAC;YACR,SAAS,gBAAgB,KAAK;QAChC;QAEA,mBAAmB,CAAC;YAClB,SAAS,gBAAgB,KAAK;QAChC;QAEA,sBAAsB,CAAC;YACrB,MAAM,MAAM,SAAS,gBAAgB,QAAQ;YAC7C,IAAI,OAAO,GAAG;gBACZ,SAAS,gBAAgB,OAAO,KAAK;YACvC;QACF;QAEA,YAAY;YACV,SAAS,kBAAkB;QAG7B;QAKA,QAAQ,IAAM;QAGd,kBAAkB,CAAC,YAAc;QACjC,qBAAqB,CAAC,YAAc;IACtC;IAEA,OAAO;QAAE;QAAK;IAAS;AACzB;AAKA,SAAS,iBAAiB,QAAkB,EAAE,SAAoB;IAChE,IAAI,eAAe,gBAAgB,IAAI;IACvC,IAAI,CAAC,cAAc;QACjB,eAAe,IAAI,IAAI;YAAC;SAAU;QAClC,gBAAgB,IAAI,UAAU;IAChC,OAAO;QACL,aAAa,IAAI;IACnB;IAEA,IAAI,eAAe,gBAAgB,IAAI;IACvC,IAAI,CAAC,cAAc;QACjB,eAAe,IAAI,IAAI;YAAC;SAAS;QACjC,gBAAgB,IAAI,WAAW;IACjC,OAAO;QACL,aAAa,IAAI;IACnB;AACF;AAOA,SAAS,oBAAoB,QAAkB;IAC7C,MAAM,mBAAmB,gBAAgB,IAAI;IAC7C,IAAI,oBAAoB,MAAM;QAC5B,OAAO;IACT;IAEA,OAAO,iBAAiB,SAAS,OAAO;AAC1C;AAMA,SAAS,sBACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,eAAe,gBAAgB,IAAI;IACzC,aAAa,OAAO;IAEpB,MAAM,eAAe,gBAAgB,IAAI;IACzC,aAAa,OAAO;IAEpB,MAAM,qBAAqB,aAAa,SAAS;IACjD,IAAI,oBAAoB;QACtB,gBAAgB,OAAO;IACzB;IAEA,MAAM,oBAAoB,aAAa,SAAS;IAChD,IAAI,mBAAmB;QACrB,gBAAgB,OAAO;IACzB;IAEA,OAAO;AACT;AAKA,SAAS,iBAAiB,aAAwB;IAChD,MAAM,aAAa,mBAAmB,IAAI;IAC1C,IAAI,cAAc,MAAM;QACtB,OAAO;IACT;IACA,mBAAmB,OAAO;IAE1B,KAAK,MAAM,aAAa,WAAY;QAClC,MAAM,kBAAkB,mBAAmB,IAAI;QAC/C,gBAAgB,OAAO;QAEvB,IAAI,gBAAgB,SAAS,GAAG;YAC9B,mBAAmB,OAAO;YAC1B,aAAa;QACf;IACF;IAIA,QAAQ,cAAc;IAEtB,OAAO;AACT;AAOA,SAAS,aAAa,SAAoB;IAGxC,QAAQ,cAAc;IAEtB,MAAM,eAAe,gBAAgB,IAAI;IACzC,IAAI,gBAAgB,MAAM;QACxB,OAAO;IACT;IACA,aAAa,OAAO;IAEpB,KAAK,MAAM,YAAY,aAAc;QACnC,MAAM,eAAe,gBAAgB,IAAI;QACzC,aAAa,OAAO;QAEpB,MAAM,oBAAoB,aAAa,SAAS;QAChD,IAAI,mBAAmB;YACrB,gBAAgB,OAAO;YACvB,cAAc,UAAU;YACxB,iBAAiB,OAAO;QAC1B;IACF;IAEA,OAAO;AACT;AAKA,SAAS,yBACP,QAAkB,EAClB,SAAoB;IAEpB,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,8BACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,SAAS,WAAW,CAAC,SAAS;IACpC,IAAI,QAAQ;QACV,IAAI,OAAO,OAAO;YAChB,MAAM,OAAO;QACf;QACA,OAAO;IACT;IAEA,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,kBACP,mBAAwC,EACxC,SAAoB;IAEpB,oBAAoB,KAAK;QACvB,UAAU;QACV,YAAY,KAAK,MAAM,UAAU;KAClC;IAGD,MAAM,SAAS,IAAI,IAAI,UAAU,OAAO,IAAI;IAC5C,mBAAmB,IAAI,UAAU,MAAM;IACvC,KAAK,MAAM,aAAa,OAAQ;QAC9B,IAAI,kBAAkB,mBAAmB,IAAI;QAC7C,IAAI,CAAC,iBAAiB;YACpB,kBAAkB,IAAI,IAAI;gBAAC,UAAU;aAAK;YAC1C,mBAAmB,IAAI,WAAW;QACpC,OAAO;YACL,gBAAgB,IAAI,UAAU;QAChC;IACF;IAEA,IAAI,UAAU,WAAW,SAAS;QAChC,uBAAuB,UAAU;IACnC;AACF;AAOA,SAAS,uBAAuB,aAAwB;IACtD,kBAAkB,IAAI;AACxB;AAEA,SAAS,cAAc,CACrB,WACA,cACA,cACkB;IAClB,KAAK,MAAM,CAAC,UAAU,cAAc,IAAI,OAAO,QAAQ,cAAe;QACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9B,eAAe,CAAC,SAAS,GAAG;QAC9B;QACA,iBAAiB,UAAU;IAC7B;IAEA,OAAO,QAAQ,cAAc,WAAW;AAC1C;AAEA,WAAW,qCAAqC,EAAE;AAElD,MAAM,uBAAuB,WAAW;AACxC,IAAI,MAAM,QAAQ,uBAAuB;IACvC,KAAK,MAAM,aAAa,qBAAsB;QAC5C,kBAAkB,WAAW,kCAAkC;IACjE;AACF;AAEA,WAAW,wBAAwB;IACjC,MAAM,CAAC;QACL,kBAAkB,WAAW,kCAAmC;IAClE;AACF"}}, + {"offset": {"line": 891, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/dev/runtime/dom/runtime-backend-dom.ts"],"sourcesContent":["/**\n * This file contains the runtime code specific to the Turbopack development\n * ECMAScript DOM runtime.\n *\n * It will be appended to the base development runtime code.\n */\n\n/// \n\ntype ChunkResolver = {\n resolved: boolean;\n resolve: () => void;\n reject: (error?: Error) => void;\n promise: Promise;\n};\n\nlet BACKEND: RuntimeBackend;\n\n(() => {\n BACKEND = {\n async registerChunk(chunkPath, params) {\n const resolver = getOrCreateResolver(chunkPath);\n resolver.resolve();\n\n if (params == null) {\n return;\n }\n\n for (const otherChunkData of params.otherChunks) {\n const otherChunkPath = getChunkPath(otherChunkData);\n // Chunk might have started loading, so we want to avoid triggering another load.\n getOrCreateResolver(otherChunkPath);\n }\n\n // This waits for chunks to be loaded, but also marks included items as available.\n await Promise.all(\n params.otherChunks.map((otherChunkData) =>\n loadChunk({ type: SourceType.Runtime, chunkPath }, otherChunkData)\n )\n );\n\n if (params.runtimeModuleIds.length > 0) {\n for (const moduleId of params.runtimeModuleIds) {\n getOrInstantiateRuntimeModule(moduleId, chunkPath);\n }\n }\n },\n\n loadChunk(chunkPath, source) {\n return doLoadChunk(chunkPath, source);\n },\n\n unloadChunk(chunkPath) {\n deleteResolver(chunkPath);\n\n if (chunkPath.endsWith(\".css\")) {\n const links = document.querySelectorAll(`link[href=\"/${chunkPath}\"]`);\n for (const link of Array.from(links)) {\n link.remove();\n }\n } else if (chunkPath.endsWith(\".js\")) {\n // Unloading a JS chunk would have no effect, as it lives in the JS\n // runtime once evaluated.\n // However, we still want to remove the script tag from the DOM to keep\n // the HTML somewhat consistent from the user's perspective.\n const scripts = document.querySelectorAll(\n `script[src=\"/${chunkPath}\"]`\n );\n for (const script of Array.from(scripts)) {\n script.remove();\n }\n } else {\n throw new Error(`can't infer type of chunk from path ${chunkPath}`);\n }\n },\n\n reloadChunk(chunkPath) {\n return new Promise((resolve, reject) => {\n if (!chunkPath.endsWith(\".css\")) {\n reject(new Error(\"The DOM backend can only reload CSS chunks\"));\n return;\n }\n\n const encodedChunkPath = chunkPath\n .split(\"/\")\n .map((p) => encodeURIComponent(p))\n .join(\"/\");\n\n const previousLink = document.querySelector(\n `link[rel=stylesheet][href^=\"/${encodedChunkPath}\"]`\n );\n\n if (previousLink == null) {\n reject(new Error(`No link element found for chunk ${chunkPath}`));\n return;\n }\n\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = `/${encodedChunkPath}`;\n link.onerror = () => {\n reject();\n };\n link.onload = () => {\n // First load the new CSS, then remove the old one. This prevents visible\n // flickering that would happen in-between removing the previous CSS and\n // loading the new one.\n previousLink.remove();\n\n // CSS chunks do not register themselves, and as such must be marked as\n // loaded instantly.\n resolve();\n };\n\n // Make sure to insert the new CSS right after the previous one, so that\n // its precedence is higher.\n previousLink.parentElement!.insertBefore(\n link,\n previousLink.nextSibling\n );\n });\n },\n\n restart: () => self.location.reload(),\n };\n\n /**\n * Maps chunk paths to the corresponding resolver.\n */\n const chunkResolvers: Map = new Map();\n\n function getOrCreateResolver(chunkPath: ChunkPath): ChunkResolver {\n let resolver = chunkResolvers.get(chunkPath);\n if (!resolver) {\n let resolve: () => void;\n let reject: (error?: Error) => void;\n const promise = new Promise((innerResolve, innerReject) => {\n resolve = innerResolve;\n reject = innerReject;\n });\n resolver = {\n resolved: false,\n promise,\n resolve: () => {\n resolver!.resolved = true;\n resolve();\n },\n reject: reject!,\n };\n chunkResolvers.set(chunkPath, resolver);\n }\n return resolver;\n }\n\n function deleteResolver(chunkPath: ChunkPath) {\n chunkResolvers.delete(chunkPath);\n }\n\n /**\n * Loads the given chunk, and returns a promise that resolves once the chunk\n * has been loaded.\n */\n async function doLoadChunk(chunkPath: ChunkPath, source: SourceInfo) {\n const resolver = getOrCreateResolver(chunkPath);\n if (resolver.resolved) {\n return resolver.promise;\n }\n\n if (source.type === SourceType.Runtime) {\n // We don't need to load chunks references from runtime code, as they're already\n // present in the DOM.\n\n if (chunkPath.endsWith(\".css\")) {\n // CSS chunks do not register themselves, and as such must be marked as\n // loaded instantly.\n resolver.resolve();\n }\n\n // We need to wait for JS chunks to register themselves within `registerChunk`\n // before we can start instantiating runtime modules, hence the absence of\n // `resolver.resolve()` in this branch.\n\n return resolver.promise;\n }\n\n if (chunkPath.endsWith(\".css\")) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = `/${chunkPath}`;\n link.onerror = () => {\n resolver.reject();\n };\n link.onload = () => {\n // CSS chunks do not register themselves, and as such must be marked as\n // loaded instantly.\n resolver.resolve();\n };\n document.body.appendChild(link);\n } else if (chunkPath.endsWith(\".js\")) {\n const script = document.createElement(\"script\");\n script.src = `/${chunkPath}`;\n // We'll only mark the chunk as loaded once the script has been executed,\n // which happens in `registerChunk`. Hence the absence of `resolve()` in\n // this branch.\n script.onerror = () => {\n resolver.reject();\n };\n document.body.appendChild(script);\n } else {\n throw new Error(`can't infer type of chunk from path ${chunkPath}`);\n }\n\n return resolver.promise;\n }\n})();\n\nfunction _eval({ code, url, map }: EcmascriptModuleEntry): ModuleFactory {\n code += `\\n\\n//# sourceURL=${location.origin}${url}`;\n if (map) code += `\\n//# sourceMappingURL=${map}`;\n return eval(code);\n}\n"],"names":[],"mappings":"AAgBA,IAAI;AAEH,CAAA;IACC,UAAU;QACR,MAAM,eAAc,UAAS,EAAE,OAAM;YACnC,MAAM,YAAW,qBAAoB;YACrC,UAAS;YAET,IAAI,WAAU,MAAM;gBAClB;YACF;YAEA,KAAK,MAAM,mBAAkB,QAAO,YAAa;gBAC/C,MAAM,kBAAiB,aAAa;gBAEpC,qBAAoB;YACtB;YAGA,MAAM,QAAQ,IACZ,QAAO,YAAY,IAAI,CAAC,kBACtB,UAAU;oBAAE,MAAM,WAAW;oBAAS,WAAA;gBAAU,GAAG;YAIvD,IAAI,QAAO,iBAAiB,SAAS,GAAG;gBACtC,KAAK,MAAM,aAAY,QAAO,iBAAkB;oBAC9C,8BAA8B,WAAU;gBAC1C;YACF;QACF;QAEA,WAAU,UAAS,EAAE,OAAM;YACzB,OAAO,aAAY,YAAW;QAChC;QAEA,aAAY,UAAS;YACnB,gBAAe;YAEf,IAAI,WAAU,SAAS,SAAS;gBAC9B,MAAM,SAAQ,SAAS,iBAAiB,CAAC,YAAY,EAAE,WAAU,EAAE,CAAC;gBACpE,KAAK,MAAM,SAAQ,MAAM,KAAK,QAAQ;oBACpC,MAAK;gBACP;YACF,OAAO,IAAI,WAAU,SAAS,QAAQ;gBAKpC,MAAM,WAAU,SAAS,iBACvB,CAAC,aAAa,EAAE,WAAU,EAAE,CAAC;gBAE/B,KAAK,MAAM,WAAU,MAAM,KAAK,UAAU;oBACxC,QAAO;gBACT;YACF,OAAO;gBACL,MAAM,IAAI,MAAM,CAAC,oCAAoC,EAAE,WAAU,CAAC;YACpE;QACF;QAEA,aAAY,UAAS;YACnB,OAAO,IAAI,QAAc,CAAC,UAAS;gBACjC,IAAI,CAAC,WAAU,SAAS,SAAS;oBAC/B,QAAO,IAAI,MAAM;oBACjB;gBACF;gBAEA,MAAM,oBAAmB,WACtB,MAAM,KACN,IAAI,CAAC,KAAM,mBAAmB,KAC9B,KAAK;gBAER,MAAM,gBAAe,SAAS,cAC5B,CAAC,6BAA6B,EAAE,kBAAiB,EAAE,CAAC;gBAGtD,IAAI,iBAAgB,MAAM;oBACxB,QAAO,IAAI,MAAM,CAAC,gCAAgC,EAAE,WAAU,CAAC;oBAC/D;gBACF;gBAEA,MAAM,QAAO,SAAS,cAAc;gBACpC,MAAK,MAAM;gBACX,MAAK,OAAO,CAAC,CAAC,EAAE,kBAAiB,CAAC;gBAClC,MAAK,UAAU;oBACb;gBACF;gBACA,MAAK,SAAS;oBAIZ,cAAa;oBAIb;gBACF;gBAIA,cAAa,cAAe,aAC1B,OACA,cAAa;YAEjB;QACF;QAEA,SAAS,IAAM,KAAK,SAAS;IAC/B;IAKA,MAAM,kBAAgD,IAAI;IAE1D,SAAS,qBAAoB,UAAoB;QAC/C,IAAI,YAAW,gBAAe,IAAI;QAClC,IAAI,CAAC,WAAU;YACb,IAAI;YACJ,IAAI;YACJ,MAAM,WAAU,IAAI,QAAc,CAAC,eAAc;gBAC/C,WAAU;gBACV,UAAS;YACX;YACA,YAAW;gBACT,UAAU;gBACV,SAAA;gBACA,SAAS;oBACP,UAAU,WAAW;oBACrB;gBACF;gBACA,QAAQ;YACV;YACA,gBAAe,IAAI,YAAW;QAChC;QACA,OAAO;IACT;IAEA,SAAS,gBAAe,UAAoB;QAC1C,gBAAe,OAAO;IACxB;IAMA,eAAe,aAAY,UAAoB,EAAE,OAAkB;QACjE,MAAM,YAAW,qBAAoB;QACrC,IAAI,UAAS,UAAU;YACrB,OAAO,UAAS;QAClB;QAEA,IAAI,QAAO,SAAS,WAAW,SAAS;YAItC,IAAI,WAAU,SAAS,SAAS;gBAG9B,UAAS;YACX;YAMA,OAAO,UAAS;QAClB;QAEA,IAAI,WAAU,SAAS,SAAS;YAC9B,MAAM,QAAO,SAAS,cAAc;YACpC,MAAK,MAAM;YACX,MAAK,OAAO,CAAC,CAAC,EAAE,WAAU,CAAC;YAC3B,MAAK,UAAU;gBACb,UAAS;YACX;YACA,MAAK,SAAS;gBAGZ,UAAS;YACX;YACA,SAAS,KAAK,YAAY;QAC5B,OAAO,IAAI,WAAU,SAAS,QAAQ;YACpC,MAAM,UAAS,SAAS,cAAc;YACtC,QAAO,MAAM,CAAC,CAAC,EAAE,WAAU,CAAC;YAI5B,QAAO,UAAU;gBACf,UAAS;YACX;YACA,SAAS,KAAK,YAAY;QAC5B,OAAO;YACL,MAAM,IAAI,MAAM,CAAC,oCAAoC,EAAE,WAAU,CAAC;QACpE;QAEA,OAAO,UAAS;IAClB;AACF,CAAA;AAEA,SAAS,MAAM,EAAE,KAAI,EAAE,IAAG,EAAE,IAAG,EAAyB;IACtD,QAAQ,CAAC,kBAAkB,EAAE,SAAS,OAAO,EAAE,IAAI,CAAC;IACpD,IAAI,KAAK,QAAQ,CAAC,uBAAuB,EAAE,IAAI,CAAC;IAChD,OAAO,KAAK;AACd"}}, + {"offset": {"line": 1026, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":"A"}}] +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/63a02_styled-components_index_a35c8c.js b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/63a02_styled-components_index_a35c8c.js index ffa67593139c6..935e60fd10625 100644 --- a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/63a02_styled-components_index_a35c8c.js +++ b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/63a02_styled-components_index_a35c8c.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_styled-components_index_a35c8c.js", { -"[project]/crates/turbopack-tests/tests/node_modules/styled-components/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/styled-components/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "styled-components/index.js"; diff --git a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_afc482.js b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_afc482.js index d8806e4c3cb4b..0c1a0014ce6ba 100644 --- a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_afc482.js +++ b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_afc482.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/63a02_styled-components_index_a35c8c.js","included":["[project]/crates/turbopack-tests/tests/node_modules/styled-components/index.js (ecmascript)"]},{"path":"output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js index 8f627c3b29595..9bd06d096f897 100644 --- a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$styled$2d$components$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/styled-components/index.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/63a02_react_jsx-dev-runtime_7d1be7.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/63a02_react_jsx-dev-runtime_7d1be7.js index 2ac521365f259..4c68642ae350d 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/63a02_react_jsx-dev-runtime_7d1be7.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/63a02_react_jsx-dev-runtime_7d1be7.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_react_jsx-dev-runtime_7d1be7.js", { -"[project]/crates/turbopack-tests/tests/node_modules/react/jsx-dev-runtime.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/react/jsx-dev-runtime.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "react/jsx-dev-runtime.js"; diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/7b7bf_third_party_component_index_8e9ad8.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/7b7bf_third_party_component_index_8e9ad8.js index 0c94b724dbf2b..673755fcfe2a2 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/7b7bf_third_party_component_index_8e9ad8.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/7b7bf_third_party_component_index_8e9ad8.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/7b7bf_third_party_component_index_8e9ad8.js", { -"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/node_modules/third_party_component/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/node_modules/third_party_component/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>ThirdPartyComponent diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js index b29ba0c39c3c1..546b0c3b083ba 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js", { -"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/component/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/component/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>MyApp diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_4a3d65.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_4a3d65.js index 4a194d553e25a..7251c167d0a5b 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_4a3d65.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_4a3d65.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/63a02_react_jsx-dev-runtime_7d1be7.js","included":["[project]/crates/turbopack-tests/tests/node_modules/react/jsx-dev-runtime.js (ecmascript)"]},{"path":"output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js","included":["[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/component/index.js (ecmascript)"]},{"path":"output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/app/index.js (ecmascript)"]},{"path":"output/7b7bf_third_party_component_index_8e9ad8.js","included":["[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/node_modules/third_party_component/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/app/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js index adebee6837592..69a5d7d579820 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/app/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/app/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$swc_transforms$2f$mono_transforms$2f$input$2f$packages$2f$component$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/component/index.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$swc_transforms$2f$mono_transforms$2f$input$2f$node_modules$2f$third_party_component$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/node_modules/third_party_component/index.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/63a02_@swc_helpers____class_call_check_f08d44.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/63a02_@swc_helpers____class_call_check_f08d44.js index 5c42b178180be..6ed895e115793 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/63a02_@swc_helpers____class_call_check_f08d44.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/63a02_@swc_helpers____class_call_check_f08d44.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_@swc_helpers____class_call_check_f08d44.js", { -"[project]/crates/turbopack-tests/tests/node_modules/@swc/helpers/_/_class_call_check.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/@swc/helpers/_/_class_call_check.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "@swc/helpers/_/_class_call_check.js"; diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_9dcfd0.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_9dcfd0.js index 92c32027da470..4667303bb2126 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_9dcfd0.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_9dcfd0.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/63a02_@swc_helpers____class_call_check_f08d44.js","included":["[project]/crates/turbopack-tests/tests/node_modules/@swc/helpers/_/_class_call_check.js (ecmascript)"]},{"path":"output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js index a72448d2fbebb..98c23403d4c2e 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f40$swc$2f$helpers$2f$_$2f$_class_call_check$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/@swc/helpers/_/_class_call_check.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_8f1e58.js b/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_8f1e58.js index f31da5f173e91..a5a345adb85a1 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_8f1e58.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_8f1e58.js @@ -3,1736 +3,4 @@ {}, {"otherChunks":[{"path":"output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/index.js (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/index.js (ecmascript)"]} ]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js index 81098a19281c5..b8ba06d4cdb97 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/prop.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/prop.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$jsconfig$2d$baseurl$2f$input$2f$prop$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/prop.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$jsconfig$2d$baseurl$2f$input$2f$prop$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/prop.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_0aa04e._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_0aa04e._.js deleted file mode 100644 index 7675e4c7494ad..0000000000000 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_0aa04e._.js +++ /dev/null @@ -1,1738 +0,0 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_0aa04e._.js", - {}, - {"otherChunks":[{"path":"output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/index.ts (ecmascript)"]} -]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_9122ac._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_8fad73._.js similarity index 82% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_9122ac._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_8fad73._.js index e88de2463ce33..21753488477df 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_9122ac._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_8fad73._.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_9122ac._.js", + "output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_8fad73._.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_9122ac._.js", + "path": "output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_8fad73._.js", "chunks": [ - "output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js" + "output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js" ], "source": "entry" }); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_99f69d._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_99f69d._.js new file mode 100644 index 0000000000000..f59bd413aaeb0 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_99f69d._.js @@ -0,0 +1,6 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_99f69d._.js", + {}, + {"otherChunks":[{"path":"output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/index.ts (ecmascript)"]} +]); +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_a751eb._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_99f69d._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_a751eb._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_99f69d._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js similarity index 91% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js index 0d3eb7983b97b..6a05aca5a54f3 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$baseurl$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$baseurl$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/prop.ts (ecmascript)"); @@ -22,4 +22,4 @@ console.log(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$ })()), }]); -//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js.map \ No newline at end of file +//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index.ts_b53fce._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop.ts_ae3f0e._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js similarity index 67% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop.ts_ae3f0e._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js index 2e23c9f3ea756..ea50e6c09c340 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop.ts_ae3f0e._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_tsconfig-mod_prop.ts_ae3f0e._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_tsconfig-mod_prop_ts_2aa573._.js", { -"[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -10,4 +10,4 @@ const prop = 1; })()), }]); -//# sourceMappingURL=63a02_tsconfig-mod_prop.ts_ae3f0e._.js.map \ No newline at end of file +//# sourceMappingURL=63a02_tsconfig-mod_prop_ts_2aa573._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop.ts_2aa573._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop.ts_2aa573._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_a751eb._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_a751eb._.js deleted file mode 100644 index b96e1170da3e2..0000000000000 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_a751eb._.js +++ /dev/null @@ -1,1738 +0,0 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_a751eb._.js", - {}, - {"otherChunks":[{"path":"output/63a02_tsconfig-mod_prop.ts_2aa573._.js","included":["[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"]},{"path":"output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/input/index.ts (ecmascript)"]} -]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_1f521f._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_1f521f._.js new file mode 100644 index 0000000000000..c033147ccba37 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_1f521f._.js @@ -0,0 +1,6 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_1f521f._.js", + {}, + {"otherChunks":[{"path":"output/63a02_tsconfig-mod_prop_ts_2aa573._.js","included":["[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"]},{"path":"output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/input/index.ts (ecmascript)"]} +]); +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_a662d4._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_1f521f._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_a662d4._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_1f521f._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_bfc829._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_62d7aa._.js similarity index 69% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_bfc829._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_62d7aa._.js index 7dd18c93d86ae..db8f9c66db8b7 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_bfc829._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_62d7aa._.js @@ -1,12 +1,12 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_bfc829._.js", + "output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_62d7aa._.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_bfc829._.js", + "path": "output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_62d7aa._.js", "chunks": [ - "output/63a02_tsconfig-mod_prop.ts_2aa573._.js", - "output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js" + "output/63a02_tsconfig-mod_prop_ts_2aa573._.js", + "output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js" ], "source": "entry" }); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js similarity index 92% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js index 2fa70a98f2ca6..2403be0ae4c95 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$tsconfig$2d$mod$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$tsconfig$2d$mod$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"); @@ -14,4 +14,4 @@ console.log(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$ })()), }]); -//# sourceMappingURL=8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js.map \ No newline at end of file +//# sourceMappingURL=8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index.ts_b53fce._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop.ts_2aa573._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js similarity index 67% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop.ts_2aa573._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js index d2d0d7e25f4a3..12803026cf6a8 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop.ts_2aa573._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_tsconfig-mod_prop.ts_2aa573._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js", { -"[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -10,4 +10,4 @@ const prop = 1; })()), }]); -//# sourceMappingURL=63a02_tsconfig-mod_prop.ts_2aa573._.js.map \ No newline at end of file +//# sourceMappingURL=63a02_tsconfig-mod_prop_ts_ae3f0e._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop.ts_ae3f0e._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop.ts_ae3f0e._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_a662d4._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_a662d4._.js deleted file mode 100644 index 288c4b661fb0f..0000000000000 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_a662d4._.js +++ /dev/null @@ -1,1738 +0,0 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_a662d4._.js", - {}, - {"otherChunks":[{"path":"output/63a02_tsconfig-mod_prop.ts_ae3f0e._.js","included":["[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"]},{"path":"output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/input/index.ts (ecmascript)"]} -]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_31d3a0._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_93ee43._.js similarity index 71% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_31d3a0._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_93ee43._.js index 109b4c5ec51b2..fe3067f7031db 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_31d3a0._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_93ee43._.js @@ -1,12 +1,12 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_31d3a0._.js", + "output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_93ee43._.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_31d3a0._.js", + "path": "output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_93ee43._.js", "chunks": [ - "output/63a02_tsconfig-mod_prop.ts_ae3f0e._.js", - "output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js" + "output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js", + "output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js" ], "source": "entry" }); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js similarity index 93% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js index 5504d46efef10..8b062e3f6cfe6 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$tsconfig$2d$mod$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$tsconfig$2d$mod$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"); @@ -14,4 +14,4 @@ console.log(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$ })()), }]); -//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js.map \ No newline at end of file +//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index.ts_b53fce._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_ca2f6f._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_ca2f6f._.js new file mode 100644 index 0000000000000..033e81707a58f --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_ca2f6f._.js @@ -0,0 +1,6 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_ca2f6f._.js", + {}, + {"otherChunks":[{"path":"output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js","included":["[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"]},{"path":"output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/input/index.ts (ecmascript)"]} +]); +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_be3d7b._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_ca2f6f._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_be3d7b._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_ca2f6f._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_be3d7b._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_be3d7b._.js deleted file mode 100644 index 765269862787b..0000000000000 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_be3d7b._.js +++ /dev/null @@ -1,1738 +0,0 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_be3d7b._.js", - {}, - {"otherChunks":[{"path":"output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/index.ts (ecmascript)"]} -]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_5381a8._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_5381a8._.js new file mode 100644 index 0000000000000..244ee2fafb55e --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_5381a8._.js @@ -0,0 +1,6 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_5381a8._.js", + {}, + {"otherChunks":[{"path":"output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/index.ts (ecmascript)"]} +]); +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_38aae8._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_5381a8._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_38aae8._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_5381a8._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_ced665._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_64225d._.js similarity index 76% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_ced665._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_64225d._.js index f6fe0ff11c4d3..8beafcd75ad8e 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_ced665._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_64225d._.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_ced665._.js", + "output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_64225d._.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_ced665._.js", + "path": "output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_64225d._.js", "chunks": [ - "output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js" + "output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js" ], "source": "entry" }); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js similarity index 93% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js index a6fba069dd5e2..b1a211e853b3d 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2d$relative$2d$dir$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2d$relative$2d$dir$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/prop.ts (ecmascript)"); @@ -22,4 +22,4 @@ console.log(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$ })()), }]); -//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js.map \ No newline at end of file +//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index.ts_b53fce._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_38aae8._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_38aae8._.js deleted file mode 100644 index fa745333aa513..0000000000000 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_38aae8._.js +++ /dev/null @@ -1,1738 +0,0 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_38aae8._.js", - {}, - {"otherChunks":[{"path":"output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/index.ts (ecmascript)"]} -]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_385208._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_385208._.js new file mode 100644 index 0000000000000..ff5aa0acf2471 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_385208._.js @@ -0,0 +1,6 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_385208._.js", + {}, + {"otherChunks":[{"path":"output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/index.ts (ecmascript)"]} +]); +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_18c083._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_385208._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_18c083._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_385208._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_53300f._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_4121b1._.js similarity index 76% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_53300f._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_4121b1._.js index 41628194006ca..2da96c3ec5ad7 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_53300f._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_4121b1._.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_53300f._.js", + "output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_4121b1._.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_53300f._.js", + "path": "output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_4121b1._.js", "chunks": [ - "output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js" + "output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js" ], "source": "entry" }); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js similarity index 93% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js index 66eea00002b02..be6a10dea912b 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2d$without$2d$ext$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2d$without$2d$ext$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/prop.ts (ecmascript)"); @@ -22,4 +22,4 @@ console.log(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$ })()), }]); -//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js.map \ No newline at end of file +//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index.ts_b53fce._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_18c083._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_18c083._.js deleted file mode 100644 index cfc5d9b63be4f..0000000000000 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_18c083._.js +++ /dev/null @@ -1,1738 +0,0 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_18c083._.js", - {}, - {"otherChunks":[{"path":"output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/index.ts (ecmascript)"]} -]); -(() => { -if (!Array.isArray(globalThis.TURBOPACK)) { - return; -} -/* eslint-disable @next/next/no-assign-module-variable */ - -/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ -/** @typedef {import('../types').ModuleFactory} ModuleFactory */ - -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').ModuleId} ModuleId */ -/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ -/** @typedef {import('../types').ChunkList} ChunkList */ - -/** @typedef {import('../types').Module} Module */ -/** @typedef {import('../types').ChunkData} ChunkData */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ -/** @typedef {import('../types').SourceType} SourceType */ -/** @typedef {import('../types').SourceType.Runtime} SourceTypeRuntime */ -/** @typedef {import('../types').SourceType.Parent} SourceTypeParent */ -/** @typedef {import('../types').SourceType.Update} SourceTypeUpdate */ -/** @typedef {import('../types').Exports} Exports */ -/** @typedef {import('../types').EsmNamespaceObject} EsmNamespaceObject */ -/** @typedef {import('../types').RequireContext} RequireContext */ -/** @typedef {import('../types').RequireContextMap} RequireContextMap */ - -/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ -/** @typedef {import('../types').RefreshContext} RefreshContext */ -/** @typedef {import('../types/hot').Hot} Hot */ -/** @typedef {import('../types/hot').HotData} HotData */ -/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ -/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ -/** @typedef {import('../types/hot').HotState} HotState */ -/** @typedef {import('../types/protocol').PartialUpdate} PartialUpdate */ -/** @typedef {import('../types/protocol').ChunkListUpdate} ChunkListUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedUpdate} EcmascriptMergedUpdate */ -/** @typedef {import('../types/protocol').EcmascriptMergedChunkUpdate} EcmascriptMergedChunkUpdate */ -/** @typedef {import('../types/protocol').EcmascriptModuleEntry} EcmascriptModuleEntry */ - -/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ - -/** @type {Object.} */ -const moduleFactories = { __proto__: null }; -/** @type {Object.} */ -const moduleCache = { __proto__: null }; -/** - * Maps module IDs to persisted data between executions of their hot module - * implementation (`hot.data`). - * - * @type {Map} - */ -const moduleHotData = new Map(); -/** - * Maps module instances to their hot module state. - * - * @type {Map} - */ -const moduleHotState = new Map(); -/** - * Module IDs that are instantiated as part of the runtime of a chunk. - * - * @type {Set} - */ -const runtimeModules = new Set(); -/** - * Map from module ID to the chunks that contain this module. - * - * In HMR, we need to keep track of which modules are contained in which so - * chunks. This is so we don't eagerly dispose of a module when it is removed - * from chunk A, but still exists in chunk B. - * - * @type {Map>} - */ -const moduleChunksMap = new Map(); -/** - * Map from chunk path to all modules it contains. - * @type {Map>} - */ -const chunkModulesMap = new Map(); -/** - * Chunk lists that contain a runtime. When these chunk lists receive an update - * that can't be reconciled with the current state of the page, we need to - * reload the runtime entirely. - * @type {Set} - */ -const runtimeChunkLists = new Set(); -/** - * Map from chunk list to the chunk paths it contains. - * @type {Map>} - */ -const chunkListChunksMap = new Map(); -/** - * Map from chunk path to the chunk lists it belongs to. - * @type {Map>} - */ -const chunkChunkListsMap = new Map(); - -const hOP = Object.prototype.hasOwnProperty; - -const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; - -/** - * @param {any} obj - * @param {PropertyKey} name - * @param {PropertyDescriptor & ThisType} options - */ -function defineProp(obj, name, options) { - if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record any>} getters - */ -function esm(exports, getters) { - defineProp(exports, "__esModule", { value: true }); - if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); - for (const key in getters) { - defineProp(exports, key, { get: getters[key], enumerable: true }); - } -} - -/** - * Makes the module an ESM with exports - * - * @param {Module} module - * @param {Record any>} getters - */ -function makeEsm(module, getters) { - esm((module.namespaceObject = module.exports), getters); -} - -/** - * Adds the getters to the exports object - * - * @param {Exports} exports - * @param {Record} props - */ -function cjs(exports, props) { - for (const key in props) { - defineProp(exports, key, { get: () => props[key], enumerable: true }); - } -} - -/** - * @param {Module} module - * @param {any} value - */ -function exportValue(module, value) { - module.exports = value; -} - -/** - * @param {Module} module - * @param {any} namespace - */ -function exportNamespace(module, namespace) { - module.exports = module.namespaceObject = namespace; -} - -/** - * @param {Record} obj - * @param {string} key - */ -function createGetter(obj, key) { - return () => obj[key]; -} - -/** - * @param {any} obj - * @returns {any} prototype of the object - */ -const getProto = Object.getPrototypeOf - ? (obj) => Object.getPrototypeOf(obj) - : (obj) => obj.__proto__; - -/** Prototypes that are not expanded for exports */ -const LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)]; - -/** - * @param {Exports} raw - * @param {EsmNamespaceObject} ns - * @param {boolean} [allowExportDefault] false: will have the raw module as default export, true: will have the default property as default export - */ -function interopEsm(raw, ns, allowExportDefault) { - /** @type {Object. any>} */ - const getters = { __proto__: null }; - for ( - let current = raw; - (typeof current === "object" || typeof current === "function") && - !LEAF_PROTOTYPES.includes(current); - current = getProto(current) - ) { - for (const key of Object.getOwnPropertyNames(current)) { - getters[key] = createGetter(raw, key); - } - } - if (!(allowExportDefault && "default" in getters)) { - getters["default"] = () => raw; - } - esm(ns, getters); -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {EsmNamespaceObject} - */ -function esmImport(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - if (module.namespaceObject) return module.namespaceObject; - const raw = module.exports; - const ns = (module.namespaceObject = {}); - interopEsm(raw, ns, raw.__esModule); - return ns; -} - -/** - * @param {Module} sourceModule - * @param {ModuleId} id - * @returns {Exports} - */ -function commonJsRequire(sourceModule, id) { - const module = getOrInstantiateModuleFromParent(id, sourceModule); - if (module.error) throw module.error; - return module.exports; -} - -/** - * @param {Module} sourceModule - * @param {RequireContextMap} map - * @returns {RequireContext} - */ -function requireContext(sourceModule, map) { - /** - * @param {ModuleId} id - * @returns {Exports} - */ - function requireContext(id) { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is required from a require.context, but is not in the context` - ); - } - - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); - } - - /** - * @returns {ModuleId[]} - */ - requireContext.keys = () => { - return Object.keys(map); - }; - - /** - * @param {ModuleId} id - * @returns {ModuleId} - */ - requireContext.resolve = (id) => { - const entry = map[id]; - - if (!entry) { - throw new Error( - `module ${id} is resolved from a require.context, but is not in the context` - ); - } - - return entry.id(); - }; - - return requireContext; -} - -/** - * @param {ModuleId} id - * @param {boolean} esm - * @returns {Exports | EsmNamespaceObject} - */ -function externalRequire(id, esm) { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (name, opt) => { - return require.resolve(name, opt); -}; - -/** @type {Map | true>} */ -const availableModules = new Map(); - -/** @type {Map | true>} */ -const availableModuleChunks = new Map(); - -/** - * @param {SourceInfo} source - * @param {ChunkData} chunkData - * @returns {Promise} - */ -async function loadChunk(source, chunkData) { - if (typeof chunkData === "string") { - return loadChunkPath(source, chunkData); - } - - const includedList = chunkData.included || []; - const modulesPromises = includedList.map((included) => { - if (moduleFactories[included]) return true; - return availableModules.get(included); - }); - if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) { - // When all included items are already loaded or loading, we can skip loading ourselves - return Promise.all(modulesPromises); - } - - const includedModuleChunksList = chunkData.moduleChunks || []; - const moduleChunksPromises = includedModuleChunksList - .map((included) => { - // TODO(alexkirsz) Do we need this check? - // if (moduleFactories[included]) return true; - return availableModuleChunks.get(included); - }) - .filter((p) => p); - - let promise; - if (moduleChunksPromises.length > 0) { - // Some module chunks are already loaded or loading. - - if (moduleChunksPromises.length == includedModuleChunksList.length) { - // When all included module chunks are already loaded or loading, we can skip loading ourselves - return Promise.all(moduleChunksPromises); - } - - const moduleChunksToLoad = new Set(); - for (const moduleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(moduleChunk)) { - moduleChunksToLoad.add(moduleChunk); - } - } - - for (const moduleChunkToLoad of moduleChunksToLoad) { - const promise = loadChunkPath(source, moduleChunkToLoad); - - availableModuleChunks.set(moduleChunkToLoad, promise); - - moduleChunksPromises.push(promise); - } - - promise = Promise.all(moduleChunksPromises); - } else { - promise = loadChunkPath(source, chunkData.path); - - // Mark all included module chunks as loading if they are not already loaded or loading. - for (const includedModuleChunk of includedModuleChunksList) { - if (!availableModuleChunks.has(includedModuleChunk)) { - availableModuleChunks.set(includedModuleChunk, promise); - } - } - } - - for (const included of includedList) { - if (!availableModules.has(included)) { - // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier. - // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway. - availableModules.set(included, promise); - } - } - - return promise; -} - -/** - * @param {SourceInfo} source - * @param {ChunkPath} chunkPath - * @returns {Promise} - */ -async function loadChunkPath(source, chunkPath) { - try { - await BACKEND.loadChunk(chunkPath, source); - } catch (error) { - let loadReason; - switch (source.type) { - case SourceTypeRuntime: - loadReason = `as a runtime dependency of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - loadReason = `from module ${source.parentId}`; - break; - case SourceTypeUpdate: - loadReason = "from an HMR update"; - break; - } - throw new Error( - `Failed to load chunk ${chunkPath} ${loadReason}${ - error ? `: ${error}` : "" - }` - ); - } -} - -/** @type {SourceTypeRuntime} */ -const SourceTypeRuntime = 0; -/** @type {SourceTypeParent} */ -const SourceTypeParent = 1; -/** @type {SourceTypeUpdate} */ -const SourceTypeUpdate = 2; - -/** - * - * @param {ModuleId} id - * @param {SourceInfo} source - * @returns {Module} - */ -function instantiateModule(id, source) { - /** @type {ModuleFactory} */ - const moduleFactory = moduleFactories[id]; - if (typeof moduleFactory !== "function") { - // This can happen if modules incorrectly handle HMR disposes/updates, - // e.g. when they keep a `setTimeout` around which still executes old code - // and contains e.g. a `require("something")` call. - let instantiationReason; - switch (source.type) { - case SourceTypeRuntime: - instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`; - break; - case SourceTypeParent: - instantiationReason = `because it was required from module ${source.parentId}`; - break; - case SourceTypeUpdate: - instantiationReason = "because of an HMR update"; - break; - } - throw new Error( - `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` - ); - } - - const hotData = moduleHotData.get(id); - const { hot, hotState } = createModuleHot(hotData); - - /** @type {Module} */ - const module = { - exports: {}, - error: undefined, - loaded: false, - id, - parents: undefined, - children: [], - namespaceObject: undefined, - hot, - }; - moduleCache[id] = module; - moduleHotState.set(module, hotState); - - switch (source.type) { - case SourceTypeRuntime: - runtimeModules.add(id); - module.parents = []; - break; - case SourceTypeParent: - // No need to add this module as a child of the parent module here, this - // has already been taken care of in `getOrInstantiateModuleFromParent`. - module.parents = [source.parentId]; - break; - case SourceTypeUpdate: - module.parents = source.parents || []; - break; - } - - // NOTE(alexkirsz) This can fail when the module encounters a runtime error. - try { - runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: makeEsm.bind(null, module), - j: cjs.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceTypeParent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); - }); - } catch (error) { - module.error = error; - throw error; - } - - module.loaded = true; - if (module.namespaceObject && module.exports !== module.namespaceObject) { - // in case of a circular dependency: cjs1 -> esm2 -> cjs1 - interopEsm(module.exports, module.namespaceObject); - } - - return module; -} - -/** - * NOTE(alexkirsz) Webpack has an "module execution" interception hook that - * Next.js' React Refresh runtime hooks into to add module context to the - * refresh registry. - * - * @param {Module} module - * @param {(ctx: RefreshContext) => void} executeModule - */ -function runModuleExecutionHooks(module, executeModule) { - const cleanupReactRefreshIntercept = - typeof globalThis.$RefreshInterceptModuleExecution$ === "function" - ? globalThis.$RefreshInterceptModuleExecution$(module.id) - : () => {}; - - try { - executeModule({ - register: globalThis.$RefreshReg$, - signature: globalThis.$RefreshSig$, - }); - - if ("$RefreshHelpers$" in globalThis) { - // This pattern can also be used to register the exports of - // a module with the React Refresh runtime. - registerExportsAndSetupBoundaryForReactRefresh( - module, - globalThis.$RefreshHelpers$ - ); - } - } catch (e) { - throw e; - } finally { - // Always cleanup the intercept, even if module execution failed. - cleanupReactRefreshIntercept(); - } -} - -/** - * Retrieves a module from the cache, or instantiate it if it is not cached. - * - * @param {ModuleId} id - * @param {Module} sourceModule - * @returns {Module} - */ -function getOrInstantiateModuleFromParent(id, sourceModule) { - if (!sourceModule.hot.active) { - console.warn( - `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` - ); - } - - const module = moduleCache[id]; - - if (sourceModule.children.indexOf(id) === -1) { - sourceModule.children.push(id); - } - - if (module) { - if (module.parents.indexOf(sourceModule.id) === -1) { - module.parents.push(sourceModule.id); - } - - return module; - } - - return instantiateModule(id, { - type: SourceTypeParent, - parentId: sourceModule.id, - }); -} - -/** - * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts - * - * @param {Module} module - * @param {RefreshHelpers} helpers - */ -function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { - const currentExports = module.exports; - const prevExports = module.hot.data.prevExports ?? null; - - helpers.registerExportsForReactRefresh(currentExports, module.id); - - // A module can be accepted automatically based on its exports, e.g. when - // it is a Refresh Boundary. - if (helpers.isReactRefreshBoundary(currentExports)) { - // Save the previous exports on update so we can compare the boundary - // signatures. - module.hot.dispose((data) => { - data.prevExports = currentExports; - }); - // Unconditionally accept an update to this module, we'll check if it's - // still a Refresh Boundary later. - module.hot.accept(); - - // This field is set when the previous version of this module was a - // Refresh Boundary, letting us know we need to check for invalidation or - // enqueue an update. - if (prevExports !== null) { - // A boundary can become ineligible if its exports are incompatible - // with the previous exports. - // - // For example, if you add/remove/change exports, we'll want to - // re-execute the importing modules, and force those components to - // re-render. Similarly, if you convert a class component to a - // function, we want to invalidate the boundary. - if ( - helpers.shouldInvalidateReactRefreshBoundary( - prevExports, - currentExports - ) - ) { - module.hot.invalidate(); - } else { - helpers.scheduleUpdate(); - } - } - } else { - // Since we just executed the code for the module, it's possible that the - // new exports made it ineligible for being a boundary. - // We only care about the case when we were _previously_ a boundary, - // because we already accepted this update (accidental side effect). - const isNoLongerABoundary = prevExports !== null; - if (isNoLongerABoundary) { - module.hot.invalidate(); - } - } -} - -/** - * @param {ModuleId[]} dependencyChain - * @returns {string} - */ -function formatDependencyChain(dependencyChain) { - return `Dependency chain: ${dependencyChain.join(" -> ")}`; -} - -/** - * @param {EcmascriptModuleEntry} entry - * @returns {ModuleFactory} - * @private - */ -function _eval({ code, url, map }) { - code += `\n\n//# sourceURL=${location.origin}${url}`; - if (map) code += `\n//# sourceMappingURL=${map}`; - return eval(code); -} - -/** - * @param {Map} added - * @param {Map} modified - * @returns {{outdatedModules: Set, newModuleFactories: Map}} - */ -function computeOutdatedModules(added, modified) { - const outdatedModules = new Set(); - const newModuleFactories = new Map(); - - for (const [moduleId, entry] of added) { - if (entry != null) { - newModuleFactories.set(moduleId, _eval(entry)); - } - } - - for (const [moduleId, entry] of modified) { - const effect = getAffectedModuleEffects(moduleId); - - switch (effect.type) { - case "unaccepted": - throw new Error( - `cannot apply update: unaccepted module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "self-declined": - throw new Error( - `cannot apply update: self-declined module. ${formatDependencyChain( - effect.dependencyChain - )}.` - ); - case "accepted": - newModuleFactories.set(moduleId, _eval(entry)); - for (const outdatedModuleId of effect.outdatedModules) { - outdatedModules.add(outdatedModuleId); - } - break; - // TODO(alexkirsz) Dependencies: handle dependencies effects. - } - } - - return { outdatedModules, newModuleFactories }; -} - -/** - * @param {Iterable} outdatedModules - * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} - */ -function computeOutdatedSelfAcceptedModules(outdatedModules) { - const outdatedSelfAcceptedModules = []; - for (const moduleId of outdatedModules) { - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - if (module && hotState.selfAccepted && !hotState.selfInvalidated) { - outdatedSelfAcceptedModules.push({ - moduleId, - errorHandler: hotState.selfAccepted, - }); - } - } - return outdatedSelfAcceptedModules; -} - -/** - * Adds, deletes, and moves modules between chunks. This must happen before the - * dispose phase as it needs to know which modules were removed from all chunks, - * which we can only compute *after* taking care of added and moved modules. - * - * @param {Map>} chunksAddedModules - * @param {Map>} chunksDeletedModules - * @returns {{ disposedModules: Set }} - */ -function updateChunksPhase(chunksAddedModules, chunksDeletedModules) { - for (const [chunkPath, addedModuleIds] of chunksAddedModules) { - for (const moduleId of addedModuleIds) { - addModuleToChunk(moduleId, chunkPath); - } - } - - const disposedModules = new Set(); - for (const [chunkPath, addedModuleIds] of chunksDeletedModules) { - for (const moduleId of addedModuleIds) { - if (removeModuleFromChunk(moduleId, chunkPath)) { - disposedModules.add(moduleId); - } - } - } - - return { disposedModules }; -} - -/** - * @param {Iterable} outdatedModules - * @param {Set} disposedModules - * @return {{ outdatedModuleParents: Map> }} - */ -function disposePhase(outdatedModules, disposedModules) { - for (const moduleId of outdatedModules) { - disposeModule(moduleId, "replace"); - } - - for (const moduleId of disposedModules) { - disposeModule(moduleId, "clear"); - } - - // Removing modules from the module cache is a separate step. - // We also want to keep track of previous parents of the outdated modules. - const outdatedModuleParents = new Map(); - for (const moduleId of outdatedModules) { - const oldModule = moduleCache[moduleId]; - outdatedModuleParents.set(moduleId, oldModule?.parents); - delete moduleCache[moduleId]; - } - - // TODO(alexkirsz) Dependencies: remove outdated dependency from module - // children. - - return { outdatedModuleParents }; -} - -/** - * Disposes of an instance of a module. - * - * Returns the persistent hot data that should be kept for the next module - * instance. - * - * NOTE: mode = "replace" will not remove modules from the moduleCache. - * This must be done in a separate step afterwards. - * This is important because all modules need to be diposed to update the - * parent/child relationships before they are actually removed from the moduleCache. - * If this would be done in this method, following disposeModulecalls won't find - * the module from the module id in the cache. - * - * @param {ModuleId} moduleId - * @param {"clear" | "replace"} mode - */ -function disposeModule(moduleId, mode) { - const module = moduleCache[moduleId]; - if (!module) { - return; - } - - const hotState = moduleHotState.get(module); - const data = {}; - - // Run the `hot.dispose` handler, if any, passing in the persistent - // `hot.data` object. - for (const disposeHandler of hotState.disposeHandlers) { - disposeHandler(data); - } - - // This used to warn in `getOrInstantiateModuleFromParent` when a disposed - // module is still importing other modules. - module.hot.active = false; - - moduleHotState.delete(module); - - // TODO(alexkirsz) Dependencies: delete the module from outdated deps. - - // Remove the disposed module from its children's parents list. - // It will be added back once the module re-instantiates and imports its - // children again. - for (const childId of module.children) { - const child = moduleCache[childId]; - if (!child) { - continue; - } - - const idx = child.parents.indexOf(module.id); - if (idx >= 0) { - child.parents.splice(idx, 1); - } - } - - switch (mode) { - case "clear": - delete moduleCache[module.id]; - moduleHotData.delete(module.id); - break; - case "replace": - moduleHotData.set(module.id, data); - break; - default: - invariant(mode, (mode) => `invalid mode: ${mode}`); - } -} - -/** - * - * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules - * @param {Map} newModuleFactories - * @param {Map>} outdatedModuleParents - */ -function applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents -) { - // Update module factories. - for (const [moduleId, factory] of newModuleFactories.entries()) { - moduleFactories[moduleId] = factory; - } - - // TODO(alexkirsz) Run new runtime entries here. - - // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. - - // Re-instantiate all outdated self-accepted modules. - for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { - try { - instantiateModule(moduleId, { - type: SourceTypeUpdate, - parents: outdatedModuleParents.get(moduleId), - }); - } catch (err) { - if (typeof errorHandler === "function") { - try { - errorHandler(err, { moduleId, module: moduleCache[moduleId] }); - } catch (_) { - // Ignore error. - } - } - } - } -} - -/** - * Utility function to ensure all variants of an enum are handled. - * @param {never} never - * @param {(arg: any) => string} computeMessage - * @returns {never} - */ -function invariant(never, computeMessage) { - throw new Error(`Invariant: ${computeMessage(never)}`); -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {PartialUpdate} update - */ -function applyUpdate(chunkListPath, update) { - switch (update.type) { - case "ChunkListUpdate": - applyChunkListUpdate(chunkListPath, update); - break; - default: - invariant(update, (update) => `Unknown update type: ${update.type}`); - } -} - -/** - * - * @param {ChunkPath} chunkListPath - * @param {ChunkListUpdate} update - */ -function applyChunkListUpdate(chunkListPath, update) { - if (update.merged != null) { - for (const merged of update.merged) { - switch (merged.type) { - case "EcmascriptMergedUpdate": - applyEcmascriptMergedUpdate(chunkListPath, merged); - break; - default: - invariant(merged, (merged) => `Unknown merged type: ${merged.type}`); - } - } - } - - if (update.chunks != null) { - for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) { - switch (chunkUpdate.type) { - case "added": - BACKEND.loadChunk(chunkPath, { type: SourceTypeUpdate }); - break; - case "total": - BACKEND.reloadChunk?.(chunkPath); - break; - case "deleted": - BACKEND.unloadChunk?.(chunkPath); - break; - case "partial": - invariant( - chunkUpdate.instruction, - (instruction) => - `Unknown partial instruction: ${JSON.stringify(instruction)}.` - ); - default: - invariant( - chunkUpdate, - (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}` - ); - } - } - } -} - -/** - * @param {ChunkPath} chunkPath - * @param {EcmascriptMergedUpdate} update - */ -function applyEcmascriptMergedUpdate(chunkPath, update) { - const { entries = {}, chunks = {} } = update; - const { added, modified, deleted, chunksAdded, chunksDeleted } = - computeChangedModules(entries, chunks); - const { outdatedModules, newModuleFactories } = computeOutdatedModules( - added, - modified - ); - const outdatedSelfAcceptedModules = - computeOutdatedSelfAcceptedModules(outdatedModules); - const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted); - const { outdatedModuleParents } = disposePhase( - outdatedModules, - disposedModules - ); - applyPhase( - outdatedSelfAcceptedModules, - newModuleFactories, - outdatedModuleParents - ); -} - -/** - * @param {Record} entries - * @param {Record} updates - * @returns {{ - * added: Map, - * modified: Map, - * deleted: Set, - * chunksAdded: Map>, - * chunksDeleted: Map>, - * }} - */ -function computeChangedModules(entries, updates) { - const chunksAdded = new Map(); - const chunksDeleted = new Map(); - const added = new Map(); - const modified = new Map(); - const deleted = new Set(); - - for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) { - switch (mergedChunkUpdate.type) { - case "added": { - const updateAdded = new Set(mergedChunkUpdate.modules); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - chunksAdded.set(chunkPath, updateAdded); - break; - } - case "deleted": { - // We could also use `mergedChunkUpdate.modules` here. - const updateDeleted = new Set(chunkModulesMap.get(chunkPath)); - for (const moduleId of updateDeleted) { - deleted.add(moduleId); - } - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - case "partial": { - const updateAdded = new Set(mergedChunkUpdate.added); - const updateDeleted = new Set(mergedChunkUpdate.deleted); - for (const moduleId of updateAdded) { - added.set(moduleId, entries[moduleId]); - } - for (const moduleId of updateDeleted) { - deleted.add([moduleId, chunkPath]); - } - chunksAdded.set(chunkPath, updateAdded); - chunksDeleted.set(chunkPath, updateDeleted); - break; - } - default: - invariant( - mergedChunkUpdate, - (mergedChunkUpdate) => - `Unknown merged chunk update type: ${mergedChunkUpdate.type}` - ); - } - } - - // If a module was added from one chunk and deleted from another in the same update, - // consider it to be modified, as it means the module was moved from one chunk to another - // AND has new code in a single update. - for (const moduleId of added.keys()) { - if (deleted.has(moduleId)) { - added.delete(moduleId); - deleted.delete(moduleId); - } - } - - for (const [moduleId, entry] of Object.entries(entries)) { - // Modules that haven't been added to any chunk but have new code are considered - // to be modified. - // This needs to be under the previous loop, as we need it to get rid of modules - // that were added and deleted in the same update. - if (!added.has(moduleId)) { - modified.set(moduleId, entry); - } - } - - return { added, deleted, modified, chunksAdded, chunksDeleted }; -} - -/** - * - * @param {ModuleId} moduleId - * @returns {ModuleEffect} - */ -function getAffectedModuleEffects(moduleId) { - const outdatedModules = new Set(); - - /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ - - /** @type {QueueItem[]} */ - const queue = [ - { - moduleId, - dependencyChain: [], - }, - ]; - - while (queue.length > 0) { - const { moduleId, dependencyChain } = - /** @type {QueueItem} */ queue.shift(); - outdatedModules.add(moduleId); - - // We've arrived at the runtime of the chunk, which means that nothing - // else above can accept this update. - if (moduleId === undefined) { - return { - type: "unaccepted", - dependencyChain, - }; - } - - const module = moduleCache[moduleId]; - const hotState = moduleHotState.get(module); - - if ( - // The module is not in the cache. Since this is a "modified" update, - // it means that the module was never instantiated before. - !module || // The module accepted itself without invalidating globalThis. - // TODO is that right? - (hotState.selfAccepted && !hotState.selfInvalidated) - ) { - continue; - } - - if (hotState.selfDeclined) { - return { - type: "self-declined", - dependencyChain, - moduleId, - }; - } - - if (runtimeModules.has(moduleId)) { - queue.push({ - moduleId: undefined, - dependencyChain: [...dependencyChain, moduleId], - }); - continue; - } - - for (const parentId of module.parents) { - const parent = moduleCache[parentId]; - - if (!parent) { - // TODO(alexkirsz) Is this even possible? - continue; - } - - // TODO(alexkirsz) Dependencies: check accepted and declined - // dependencies here. - - queue.push({ - moduleId: parentId, - dependencyChain: [...dependencyChain, moduleId], - }); - } - } - - return { - type: "accepted", - moduleId, - outdatedModules, - }; -} - -/** - * @param {ChunkPath} chunkListPath - * @param {import('../types/protocol').ServerMessage} update - */ -function handleApply(chunkListPath, update) { - switch (update.type) { - case "partial": { - // This indicates that the update is can be applied to the current state of the application. - applyUpdate(chunkListPath, update.instruction); - break; - } - case "restart": { - // This indicates that there is no way to apply the update to the - // current state of the application, and that the application must be - // restarted. - BACKEND.restart(); - break; - } - case "notFound": { - // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed, - // or the page itself was deleted. - // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to. - // If it is a runtime chunk list, we restart the application. - if (runtimeChunkLists.has(chunkListPath)) { - BACKEND.restart(); - } else { - disposeChunkList(chunkListPath); - } - break; - } - default: - throw new Error(`Unknown update type: ${update.type}`); - } -} - -/** - * @param {HotData} [hotData] - * @returns {{hotState: HotState, hot: Hot}} - */ -function createModuleHot(hotData) { - /** @type {HotState} */ - const hotState = { - selfAccepted: false, - selfDeclined: false, - selfInvalidated: false, - disposeHandlers: [], - }; - - /** - * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. - * - * @param {string | string[] | AcceptErrorHandler} [dep] - * @param {AcceptCallback} [_callback] - * @param {AcceptErrorHandler} [_errorHandler] - */ - function accept(dep, _callback, _errorHandler) { - if (dep === undefined) { - hotState.selfAccepted = true; - } else if (typeof dep === "function") { - hotState.selfAccepted = dep; - } else { - throw new Error("unsupported `accept` signature"); - } - } - - /** @type {Hot} */ - const hot = { - // TODO(alexkirsz) This is not defined in the HMR API. It was used to - // decide whether to warn whenever an HMR-disposed module required other - // modules. We might want to remove it. - active: true, - - data: hotData ?? {}, - - accept: accept, - - decline: (dep) => { - if (dep === undefined) { - hotState.selfDeclined = true; - } else { - throw new Error("unsupported `decline` signature"); - } - }, - - dispose: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - addDisposeHandler: (callback) => { - hotState.disposeHandlers.push(callback); - }, - - removeDisposeHandler: (callback) => { - const idx = hotState.disposeHandlers.indexOf(callback); - if (idx >= 0) { - hotState.disposeHandlers.splice(idx, 1); - } - }, - - invalidate: () => { - hotState.selfInvalidated = true; - // TODO(alexkirsz) The original HMR code had management-related code - // here. - }, - - // NOTE(alexkirsz) This is part of the management API, which we don't - // implement, but the Next.js React Refresh runtime uses this to decide - // whether to schedule an update. - status: () => "idle", - - // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. - addStatusHandler: (_handler) => {}, - removeStatusHandler: (_handler) => {}, - }; - - return { hot, hotState }; -} - -/** - * Adds a module to a chunk. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - */ -function addModuleToChunk(moduleId, chunkPath) { - let moduleChunks = moduleChunksMap.get(moduleId); - if (!moduleChunks) { - moduleChunks = new Set([chunkPath]); - moduleChunksMap.set(moduleId, moduleChunks); - } else { - moduleChunks.add(chunkPath); - } - - let chunkModules = chunkModulesMap.get(chunkPath); - if (!chunkModules) { - chunkModules = new Set([moduleId]); - chunkModulesMap.set(chunkPath, chunkModules); - } else { - chunkModules.add(moduleId); - } -} - -/** - * Returns the first chunk that included a module. - * This is used by the Node.js backend, hence why it's marked as unused in this - * file. - * - * @type {GetFirstModuleChunk} - */ -function getFirstModuleChunk(moduleId) { - const moduleChunkPaths = moduleChunksMap.get(moduleId); - if (moduleChunkPaths == null) { - return null; - } - - return moduleChunkPaths.values().next().value; -} - -/** - * Removes a module from a chunk. Returns true there are no remaining chunks - * including this module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {boolean} - */ -function removeModuleFromChunk(moduleId, chunkPath) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - chunkModules.delete(moduleId); - - const noRemainingModules = chunkModules.size === 0; - if (noRemainingModules) { - chunkModulesMap.delete(chunkPath); - } - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - } - - return noRemainingChunks; -} - -/** - * Diposes of a chunk list and its corresponding exclusive chunks. - * - * @param {ChunkPath} chunkListPath - * @returns {boolean} Whether the chunk list was disposed of. - */ -function disposeChunkList(chunkListPath) { - const chunkPaths = chunkListChunksMap.get(chunkListPath); - if (chunkPaths == null) { - return false; - } - chunkListChunksMap.delete(chunkListPath); - - for (const chunkPath of chunkPaths) { - const chunkChunkLists = chunkChunkListsMap.get(chunkPath); - chunkChunkLists.delete(chunkListPath); - - if (chunkChunkLists.size === 0) { - chunkChunkListsMap.delete(chunkPath); - disposeChunk(chunkPath); - } - } - - // We must also dispose of the chunk list's chunk itself to ensure it may - // be reloaded properly in the future. - BACKEND.unloadChunk(chunkListPath); - - return true; -} - -/** - * Disposes of a chunk and its corresponding exclusive modules. - * - * @param {ChunkPath} chunkPath - * @returns {boolean} Whether the chunk was disposed of. - */ -function disposeChunk(chunkPath) { - // This should happen whether or not the chunk has any modules in it. For instance, - // CSS chunks have no modules in them, but they still need to be unloaded. - BACKEND.unloadChunk(chunkPath); - - const chunkModules = chunkModulesMap.get(chunkPath); - if (chunkModules == null) { - return false; - } - chunkModules.delete(chunkPath); - - for (const moduleId of chunkModules) { - const moduleChunks = moduleChunksMap.get(moduleId); - moduleChunks.delete(chunkPath); - - const noRemainingChunks = moduleChunks.size === 0; - if (noRemainingChunks) { - moduleChunksMap.delete(moduleId); - disposeModule(moduleId, "clear"); - availableModules.delete(moduleId); - } - } - - return true; -} - -/** - * Instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function instantiateRuntimeModule(moduleId, chunkPath) { - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Gets or instantiates a runtime module. - * - * @param {ModuleId} moduleId - * @param {ChunkPath} chunkPath - * @returns {Module} - */ -function getOrInstantiateRuntimeModule(moduleId, chunkPath) { - const module = moduleCache[moduleId]; - if (module) { - if (module.error) { - throw module.error; - } - return module; - } - - return instantiateModule(moduleId, { type: SourceTypeRuntime, chunkPath }); -} - -/** - * Returns the path of a chunk defined by its data. - * - * @param {ChunkData} chunkData - * @returns {ChunkPath} the chunk path - */ -function getChunkPath(chunkData) { - return typeof chunkData === "string" ? chunkData : chunkData.path; -} - -/** - * Subscribes to chunk list updates from the update server and applies them. - * - * @param {ChunkList} chunkList - */ -function registerChunkList(chunkList) { - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ - chunkList.path, - handleApply.bind(null, chunkList.path), - ]); - - // Adding chunks to chunk lists and vice versa. - const chunks = new Set(chunkList.chunks.map(getChunkPath)); - chunkListChunksMap.set(chunkList.path, chunks); - for (const chunkPath of chunks) { - let chunkChunkLists = chunkChunkListsMap.get(chunkPath); - if (!chunkChunkLists) { - chunkChunkLists = new Set([chunkList.path]); - chunkChunkListsMap.set(chunkPath, chunkChunkLists); - } else { - chunkChunkLists.add(chunkList.path); - } - } - - if (chunkList.source === "entry") { - markChunkListAsRuntime(chunkList.path); - } -} - -/** - * Marks a chunk list as a runtime chunk list. There can be more than one - * runtime chunk list. For instance, integration tests can have multiple chunk - * groups loaded at runtime, each with its own chunk list. - * - * @param {ChunkPath} chunkListPath - */ -function markChunkListAsRuntime(chunkListPath) { - runtimeChunkLists.add(chunkListPath); -} - -/** - * @param {ChunkRegistration} chunkRegistration - */ -function registerChunk([chunkPath, chunkModules, runtimeParams]) { - for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { - if (!moduleFactories[moduleId]) { - moduleFactories[moduleId] = moduleFactory; - } - addModuleToChunk(moduleId, chunkPath); - } - - return BACKEND.registerChunk(chunkPath, runtimeParams); -} - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; - -const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || []; -for (const chunkList of chunkListsToRegister) { - registerChunkList(chunkList); -} -globalThis.TURBOPACK_CHUNK_LISTS = { - push: (chunkList) => { - registerChunkList(chunkList); - }, -}; - -globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = - globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; -/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ -/** @typedef {import('../types/runtime.dom').ChunkResolver} ChunkResolver */ -/** @typedef {import('../types').ChunkPath} ChunkPath */ -/** @typedef {import('../types').SourceInfo} SourceInfo */ - -/** @type {RuntimeBackend} */ -let BACKEND; - -(() => { - BACKEND = { - async registerChunk(chunkPath, params) { - const resolver = getOrCreateResolver(chunkPath); - resolver.resolve(); - - if (params == null) { - return; - } - - for (const otherChunkData of params.otherChunks) { - const otherChunkPath = getChunkPath(otherChunkData); - // Chunk might have started loading, so we want to avoid triggering another load. - getOrCreateResolver(otherChunkPath); - } - - // This waits for chunks to be loaded, but also marks included items as available. - await Promise.all( - params.otherChunks.map((otherChunkData) => - loadChunk({ type: SourceTypeRuntime, chunkPath }, otherChunkData) - ) - ); - - if (params.runtimeModuleIds.length > 0) { - for (const moduleId of params.runtimeModuleIds) { - getOrInstantiateRuntimeModule(moduleId, chunkPath); - } - } - }, - - loadChunk(chunkPath, source) { - return doLoadChunk(chunkPath, source); - }, - - unloadChunk(chunkPath) { - deleteResolver(chunkPath); - - if (chunkPath.endsWith(".css")) { - const links = document.querySelectorAll(`link[href="/${chunkPath}"]`); - for (const link of Array.from(links)) { - link.remove(); - } - } else if (chunkPath.endsWith(".js")) { - // Unloading a JS chunk would have no effect, as it lives in the JS - // runtime once evaluated. - // However, we still want to remove the script tag from the DOM to keep - // the HTML somewhat consistent from the user's perspective. - const scripts = document.querySelectorAll( - `script[src="/${chunkPath}"]` - ); - for (const script of Array.from(scripts)) { - script.remove(); - } - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - }, - - reloadChunk(chunkPath) { - return new Promise((resolve, reject) => { - if (!chunkPath.endsWith(".css")) { - reject(new Error("The DOM backend can only reload CSS chunks")); - return; - } - - const encodedChunkPath = chunkPath - .split("/") - .map((p) => encodeURIComponent(p)) - .join("/"); - - const previousLink = document.querySelector( - `link[rel=stylesheet][href^="/${encodedChunkPath}"]` - ); - - if (previousLink == null) { - reject(new Error(`No link element found for chunk ${chunkPath}`)); - return; - } - - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${encodedChunkPath}`; - link.onerror = () => { - reject(); - }; - link.onload = () => { - // First load the new CSS, then remove the old one. This prevents visible - // flickering that would happen in-between removing the previous CSS and - // loading the new one. - previousLink.remove(); - - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolve(); - }; - - // Make sure to insert the new CSS right after the previous one, so that - // its precedence is higher. - previousLink.parentElement.insertBefore(link, previousLink.nextSibling); - }); - }, - - restart: () => self.location.reload(), - }; - - /** - * Maps chunk paths to the corresponding resolver. - * - * @type {Map} - */ - const chunkResolvers = new Map(); - - /** - * @param {ChunkPath} chunkPath - * @returns {ChunkResolver} - */ - function getOrCreateResolver(chunkPath) { - let resolver = chunkResolvers.get(chunkPath); - if (!resolver) { - let resolve; - let reject; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - resolver = { - resolved: false, - promise, - resolve: () => { - resolver.resolved = true; - resolve(); - }, - reject, - }; - chunkResolvers.set(chunkPath, resolver); - } - return resolver; - } - - function deleteResolver(chunkPath) { - chunkResolvers.delete(chunkPath); - } - - /** - * Loads the given chunk, and returns a promise that resolves once the chunk - * has been loaded. - * - * @param {ChunkPath} chunkPath - * @param {SourceInfo} source - */ - async function doLoadChunk(chunkPath, source) { - const resolver = getOrCreateResolver(chunkPath); - if (resolver.resolved) { - return resolver.promise; - } - - if (source.type === SourceTypeRuntime) { - // We don't need to load chunks references from runtime code, as they're already - // present in the DOM. - - if (chunkPath.endsWith(".css")) { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - } - - // We need to wait for JS chunks to register themselves within `registerChunk` - // before we can start instantiating runtime modules, hence the absence of - // `resolver.resolve()` in this branch. - - return resolver.promise; - } - - if (chunkPath.endsWith(".css")) { - const link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = `/${chunkPath}`; - link.onerror = () => { - resolver.reject(); - }; - link.onload = () => { - // CSS chunks do not register themselves, and as such must be marked as - // loaded instantly. - resolver.resolve(); - }; - document.body.appendChild(link); - } else if (chunkPath.endsWith(".js")) { - const script = document.createElement("script"); - script.src = `/${chunkPath}`; - // We'll only mark the chunk as loaded once the script has been executed, - // which happens in `registerChunk`. Hence the absence of `resolve()` in - // this branch. - script.onerror = () => { - resolver.reject(); - }; - document.body.appendChild(script); - } else { - throw new Error(`can't infer type of chunk from path ${chunkPath}`); - } - - return resolver.promise; - } -})(); -const chunksToRegister = globalThis.TURBOPACK; -globalThis.TURBOPACK = { push: registerChunk }; -chunksToRegister.forEach(registerChunk); -})(); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_3e6d5a._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_3e6d5a._.js new file mode 100644 index 0000000000000..c0cd7553848ff --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_3e6d5a._.js @@ -0,0 +1,6 @@ +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ + "output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_3e6d5a._.js", + {}, + {"otherChunks":[{"path":"output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/index.ts (ecmascript)"]}],"runtimeModuleIds":["[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/index.ts (ecmascript)"]} +]); +// Dummy runtime \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_3e6d5a._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_3e6d5a._.js.map new file mode 100644 index 0000000000000..a12b83d3337ca --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_3e6d5a._.js.map @@ -0,0 +1,4 @@ +{ + "version": 3, + "sections": [] +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js similarity index 91% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js index 985b3f0e960cd..b2c3b5f76600f 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ -(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js", { +(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, k: __turbopack_refresh__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/prop.ts (ecmascript)"); @@ -22,4 +22,4 @@ console.log(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$ })()), }]); -//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js.map \ No newline at end of file +//# sourceMappingURL=a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js.map b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js.map rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js.map diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_997596._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_db43e7._.js similarity index 82% rename from crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_997596._.js rename to crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_db43e7._.js index 6ae7c188dc602..7feabe2c6a97a 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_997596._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_db43e7._.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([ - "output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_997596._.js", + "output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_db43e7._.js", {}, ]); (globalThis.TURBOPACK_CHUNK_LISTS = globalThis.TURBOPACK_CHUNK_LISTS || []).push({ - "path": "output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_997596._.js", + "path": "output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_db43e7._.js", "chunks": [ - "output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index.ts_b53fce._.js" + "output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js" ], "source": "entry" }); \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa05b97dd27ad..861abbcc951c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -111,21 +111,23 @@ importers: specifiers: '@next/react-refresh-utils': ^13.0.6 '@types/node': ^18.11.11 - '@vercel/turbopack-dev': '*' + '@vercel/turbopack-ecmascript-runtime': '*' dependencies: '@next/react-refresh-utils': 13.0.6_react-refresh@0.12.0 - '@vercel/turbopack-dev': link:../../turbopack-dev/js + '@vercel/turbopack-ecmascript-runtime': link:../../turbopack-ecmascript-runtime/js devDependencies: '@types/node': 18.13.0 - crates/turbopack-dev/js: + crates/turbopack-ecmascript-runtime/js: specifiers: '@next/react-refresh-utils': ^13.0.6 '@types/node': ^18.11.11 + npm-run-all: ^4.1.5 dependencies: '@next/react-refresh-utils': 13.0.6_react-refresh@0.12.0 - devDependencies: '@types/node': 18.13.0 + devDependencies: + npm-run-all: 4.1.5 crates/turbopack-node/js: specifiers: @@ -2758,7 +2760,7 @@ packages: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 5.1.1 - '@types/node': 16.11.56 + '@types/node': 18.13.0 /@types/graceful-fs/4.1.6: resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==} From 376a043417c0df0c5acee59049a4b3d406f47f42 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 14:59:57 +0200 Subject: [PATCH 02/19] Remove generate_chunk from ChunkingContext interface --- .../turbopack-build/src/chunking_context.rs | 22 +++++++++---------- .../src/chunk/chunking_context.rs | 3 --- crates/turbopack-dev/src/chunking_context.rs | 22 +++++++++---------- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/crates/turbopack-build/src/chunking_context.rs b/crates/turbopack-build/src/chunking_context.rs index 3e3a92e036fd1..61f9865959944 100644 --- a/crates/turbopack-build/src/chunking_context.rs +++ b/crates/turbopack-build/src/chunking_context.rs @@ -147,6 +147,17 @@ impl BuildChunkingContextVc { Ok(asset) } + + #[turbo_tasks::function] + async fn generate_chunk(self, chunk: ChunkVc) -> Result { + Ok( + if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(chunk).await? { + EcmascriptBuildNodeChunkVc::new(self, ecmascript_chunk).into() + } else { + chunk.into() + }, + ) + } } impl BuildChunkingContextVc { @@ -305,17 +316,6 @@ impl ChunkingContext for BuildChunkingContext { Ok(AssetsVc::cell(assets)) } - - #[turbo_tasks::function] - async fn generate_chunk(self_vc: BuildChunkingContextVc, chunk: ChunkVc) -> Result { - Ok( - if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(chunk).await? { - EcmascriptBuildNodeChunkVc::new(self_vc, ecmascript_chunk).into() - } else { - chunk.into() - }, - ) - } } #[turbo_tasks::value_impl] diff --git a/crates/turbopack-core/src/chunk/chunking_context.rs b/crates/turbopack-core/src/chunk/chunking_context.rs index f047fa751f9bf..4eb5de3bca457 100644 --- a/crates/turbopack-core/src/chunk/chunking_context.rs +++ b/crates/turbopack-core/src/chunk/chunking_context.rs @@ -56,7 +56,4 @@ pub trait ChunkingContext { entry: ChunkVc, evaluatable_assets: EvaluatableAssetsVc, ) -> AssetsVc; - - /// Generate an output chunk asset for the given chunk. - fn generate_chunk(&self, chunk: ChunkVc) -> AssetVc; } diff --git a/crates/turbopack-dev/src/chunking_context.rs b/crates/turbopack-dev/src/chunking_context.rs index 5b980174929c0..fafaeebfcef0d 100644 --- a/crates/turbopack-dev/src/chunking_context.rs +++ b/crates/turbopack-dev/src/chunking_context.rs @@ -159,6 +159,17 @@ impl DevChunkingContextVc { ) -> AssetVc { EcmascriptDevChunkListVc::new(self_vc, entry_chunk, other_chunks, source).into() } + + #[turbo_tasks::function] + async fn generate_chunk(self, chunk: ChunkVc) -> Result { + Ok( + if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(chunk).await? { + EcmascriptDevChunkVc::new(self, ecmascript_chunk).into() + } else { + chunk.into() + }, + ) + } } #[turbo_tasks::value_impl] @@ -326,17 +337,6 @@ impl ChunkingContext for DevChunkingContext { Ok(AssetsVc::cell(assets)) } - - #[turbo_tasks::function] - async fn generate_chunk(self_vc: DevChunkingContextVc, chunk: ChunkVc) -> Result { - Ok( - if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(chunk).await? { - EcmascriptDevChunkVc::new(self_vc, ecmascript_chunk).into() - } else { - chunk.into() - }, - ) - } } #[turbo_tasks::value_impl] From b4ca2dd44711900371861d9a6f24456a72d27ec8 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 15:02:03 +0200 Subject: [PATCH 03/19] Fix typo: turbpack -> turbopack --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 29d67348886d5..0b14558a69b5c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -112,7 +112,7 @@ jobs: uses: technote-space/get-diff-action@v6 with: PATTERNS: | - crates/turbpack*/js/** + crates/turbopack*/js/** - name: Turborepo Rust related changes id: turborepo_rust From 8f1200d0ab176b5b96b238e22ab1d61bb44e172f Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 15:04:55 +0200 Subject: [PATCH 04/19] Add turbopack_typescript to Ok and Done jobs --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0b14558a69b5c..41f4fb3be3e88 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1221,6 +1221,7 @@ jobs: - rust_lint - rust_check - turbopack_rust_test1 + - turbopack_typescript - turborepo_rust_test - turbopack_rust_test_bench1 - turbopack_build_release @@ -1258,6 +1259,7 @@ jobs: subjob ${{needs.rust_lint.result}} "Rust lints" subjob ${{needs.rust_check.result}} "Rust checks" subjob ${{needs.turbopack_rust_test1.result}} "Turbopack Rust tests (linux)" + subjob ${{needs.turbopack_typescript.result}} "Turbopack Typescript checks" subjob ${{needs.turborepo_rust_test.result}} "TurboRepo Rust tests" subjob ${{needs.turbopack_rust_test_bench1.result}} "Turbopack Rust benchmark tests (linux)" subjob ${{needs.turbopack_build_release.result}} "Turbopack Release Build" @@ -1336,6 +1338,7 @@ jobs: - rust_check - turbopack_rust_test1 - turbopack_rust_test2 + - turbopack_typescript - turborepo_rust_test - turbopack_rust_test_bench1 - turbopack_rust_test_bench2 @@ -1376,6 +1379,7 @@ jobs: subjob ${{needs.rust_check.result}} "Rust checks" subjob ${{needs.turbopack_rust_test1.result}} "Turbopack Rust tests (linux)" subjob ${{needs.turbopack_rust_test2.result}} "Turbopack Rust tests (mac/win, non-blocking)" + subjob ${{needs.turbopack_typescript.result}} "Turbopack Typescript checks" subjob ${{needs.turborepo_rust_test.result}} "TurboRepo Rust tests" subjob ${{needs.turbopack_rust_test_bench1.result}} "Turbopack Rust benchmark tests (linux)" subjob ${{needs.turbopack_rust_test_bench2.result}} "Turbopack Rust benchmark tests (mac/win, non-blocking)" From 7999758b5d0dd4c8e400d04b4d6c531716d8174b Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 15:07:08 +0200 Subject: [PATCH 05/19] Simpler Setup Node.js command for pnpm --- .github/workflows/test.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 41f4fb3be3e88..5a227c1befcab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -465,9 +465,6 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 - with: - node-version: 16 - cache: pnpm - name: Install dependencies run: pnpm install -r --side-effects-cache false From 93051de5afbe3d8e8addef529e5afb1c7ab51e98 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 15:11:01 +0200 Subject: [PATCH 06/19] Correct Node.js setup action --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5a227c1befcab..f5dc65cf3aa85 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -464,7 +464,7 @@ jobs: uses: actions/checkout@v3 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: ./.github/actions/setup-node - name: Install dependencies run: pnpm install -r --side-effects-cache false From 691298eefa3ade0e860f15ac8a54e9874babad13 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 15:22:11 +0200 Subject: [PATCH 07/19] Fix type errors in webpack loaders --- .../js/src/transforms/webpack-loaders.ts | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/crates/turbopack-node/js/src/transforms/webpack-loaders.ts b/crates/turbopack-node/js/src/transforms/webpack-loaders.ts index 7dbac49a1b457..01e4a6ec2def1 100644 --- a/crates/turbopack-node/js/src/transforms/webpack-loaders.ts +++ b/crates/turbopack-node/js/src/transforms/webpack-loaders.ts @@ -22,8 +22,7 @@ type LoaderConfig = options: { [k: string]: unknown }; }; -// @ts-ignore -let runLoaders: typeof import("loader-runner"); +let runLoaders: typeof import("loader-runner")["runLoaders"]; try { ({ runLoaders } = require("@vercel/turbopack/loader-runner")); } catch { @@ -65,7 +64,7 @@ const LogType = Object.freeze({ const loaderFlag = "LOADER_EXECUTION"; -const cutOffByFlag = (stack, flag) => { +const cutOffByFlag = (stack: string, flag: string): string => { const errorStack = stack.split("\n"); for (let i = 0; i < errorStack.length; i++) { if (errorStack[i].includes(flag)) { @@ -76,10 +75,11 @@ const cutOffByFlag = (stack, flag) => { }; /** - * @param {string} stack stack trace - * @returns {string} stack trace without the loader execution flag included + * @param stack stack trace + * @returns stack trace without the loader execution flag included */ -const cutOffLoaderExecution = (stack) => cutOffByFlag(stack, loaderFlag); +const cutOffLoaderExecution = (stack: string): string => + cutOffByFlag(stack, loaderFlag); class DummySpan { traceChild() { @@ -126,25 +126,27 @@ const transform = ( }), emitWarning: makeErrorEmitter("warning", ipc), emitError: makeErrorEmitter("error", ipc), - getLogger: (name) => (type, args) => { - let trace; - switch (type) { - case LogType.warn: - case LogType.error: - case LogType.trace: - trace = cutOffLoaderExecution(new Error("Trace").stack) - .split("\n") - .slice(3); - break; - } - const logEntry = { - time: Date.now(), - type, - args, - trace, + getLogger(name: unknown) { + return (type: unknown, args: unknown) => { + let trace; + switch (type) { + case LogType.warn: + case LogType.error: + case LogType.trace: + trace = cutOffLoaderExecution(new Error("Trace").stack!) + .split("\n") + .slice(3); + break; + } + const logEntry = { + time: Date.now(), + type, + args, + trace, + }; + + this.hooks.log.call(name, logEntry); }; - - this.hooks.log.call(name, logEntry); }, }, From 32f0502da254bf1503f510838431a8369f3eb0dc Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 15:29:20 +0200 Subject: [PATCH 08/19] Update crates/turbopack-build/src/ecmascript/node/content.rs Co-authored-by: Tobias Koppers --- crates/turbopack-build/src/ecmascript/node/content.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/turbopack-build/src/ecmascript/node/content.rs b/crates/turbopack-build/src/ecmascript/node/content.rs index 4ecc05901879c..e796575cb0704 100644 --- a/crates/turbopack-build/src/ecmascript/node/content.rs +++ b/crates/turbopack-build/src/ecmascript/node/content.rs @@ -14,7 +14,7 @@ use turbopack_ecmascript::{chunk::EcmascriptChunkContentVc, utils::StringifyJs}; use super::chunk::EcmascriptBuildNodeChunkVc; use crate::BuildChunkingContextVc; -#[turbo_tasks::value(serialization = "none")] +#[turbo_tasks::value] pub(super) struct EcmascriptBuildNodeChunkContent { pub(super) content: EcmascriptChunkContentVc, pub(super) chunking_context: BuildChunkingContextVc, From deec081887df3c6e515171c42200e5862928f439 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 15:31:40 +0200 Subject: [PATCH 09/19] Fix module resolution in turbopack-cli --- crates/turbopack-cli/js/tsconfig.json | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/crates/turbopack-cli/js/tsconfig.json b/crates/turbopack-cli/js/tsconfig.json index bdc9e4dba9791..8603b598f7af9 100644 --- a/crates/turbopack-cli/js/tsconfig.json +++ b/crates/turbopack-cli/js/tsconfig.json @@ -5,14 +5,6 @@ "noFallthroughCasesInSwitch": true, "skipLibCheck": true, - // interop constraints - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - - // js support - "allowJs": true, - "checkJs": true, - // environment "jsx": "react-jsx", "lib": ["ESNext", "DOM"], @@ -21,7 +13,7 @@ // modules "baseUrl": ".", "module": "esnext", - "moduleResolution": "node", + "moduleResolution": "nodenext", "types": [], // emit From 807fc0284780be2d15227fad563b5681079f4865 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 15:43:36 +0200 Subject: [PATCH 10/19] Only import path once --- crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts b/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts index 37f87ce9ae31c..9cc7d2e86f07d 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts @@ -92,7 +92,6 @@ function loadChunk(chunkPath: ChunkPath) { return; } - const path = require("path"); const resolved = require.resolve(path.resolve(RUNTIME_ROOT, chunkPath)); delete require.cache[resolved]; const chunkModules: ModuleFactories = require(resolved); From ecc01c14205ebc3e9c2ea6ab6379d339cd3c280c Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 15:46:42 +0200 Subject: [PATCH 11/19] Update snapshots --- .../runtime/default_build_runtime/output/[turbopack]_runtime.js | 1 - .../default_build_runtime/output/[turbopack]_runtime.js.map | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js index 7f4c2100e8ae9..7646baa8198f9 100644 --- a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js @@ -132,7 +132,6 @@ function loadChunk(chunkPath) { if (!chunkPath.endsWith(".js")) { return; } - const path = require("path"); const resolved = require.resolve(path.resolve(RUNTIME_ROOT, chunkPath)); delete require.cache[resolved]; const chunkModules = require(resolved); diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map index eebac27d14dce..ebdd331e4aa9e 100644 --- a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map @@ -2,5 +2,5 @@ "version": 3, "sections": [ {"offset": {"line": 1, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/shared/runtime-utils.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * TurboPack ECMAScript runtimes.\n *\n * It will be prepended to the runtime code of each runtime.\n */\n\n/* eslint-disable @next/next/no-assign-module-variable */\n\n/// \n\ninterface Exports {\n __esModule?: boolean;\n\n [key: string]: any;\n}\ntype EsmNamespaceObject = Record;\n\ninterface BaseModule {\n exports: Exports;\n error: Error | undefined;\n loaded: boolean;\n id: ModuleId;\n children: ModuleId[];\n parents: ModuleId[];\n namespaceObject?: EsmNamespaceObject;\n}\n\ninterface Module extends BaseModule {}\n\ntype RequireContextMap = Record;\n\ninterface RequireContextEntry {\n id: () => ModuleId;\n}\n\ninterface RequireContext {\n (moduleId: ModuleId): Exports | EsmNamespaceObject;\n keys(): ModuleId[];\n resolve(moduleId: ModuleId): ModuleId;\n}\n\ntype GetOrInstantiateModuleFromParent = (\n moduleId: ModuleId,\n parentModule: Module\n) => Module;\n\ntype CommonJsRequireContext = (\n entry: RequireContextEntry,\n parentModule: Module\n) => Exports;\n\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst toStringTag = typeof Symbol !== \"undefined\" && Symbol.toStringTag;\n\nfunction defineProp(\n obj: any,\n name: PropertyKey,\n options: PropertyDescriptor & ThisType\n) {\n if (!hasOwnProperty.call(obj, name))\n Object.defineProperty(obj, name, options);\n}\n\n/**\n * Adds the getters to the exports object.\n */\nfunction esm(exports: Exports, getters: Record any>) {\n defineProp(exports, \"__esModule\", { value: true });\n if (toStringTag) defineProp(exports, toStringTag, { value: \"Module\" });\n for (const key in getters) {\n defineProp(exports, key, { get: getters[key], enumerable: true });\n }\n}\n\n/**\n * Makes the module an ESM with exports\n */\nfunction esmExport(module: Module, getters: Record any>) {\n esm((module.namespaceObject = module.exports), getters);\n}\n\n/**\n * Adds the props to the exports object\n */\nfunction cjsExport(exports: Exports, props: Record) {\n for (const key in props) {\n defineProp(exports, key, { get: () => props[key], enumerable: true });\n }\n}\n\nfunction exportValue(module: Module, value: any) {\n module.exports = value;\n}\n\nfunction exportNamespace(module: Module, namespace: any) {\n module.exports = module.namespaceObject = namespace;\n}\n\nfunction createGetter(obj: Record, key: string) {\n return () => obj[key];\n}\n\n/**\n * @returns prototype of the object\n */\nconst getProto: (obj: any) => any = Object.getPrototypeOf\n ? (obj) => Object.getPrototypeOf(obj)\n : (obj) => obj.__proto__;\n\n/** Prototypes that are not expanded for exports */\nconst LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];\n\n/**\n * @param allowExportDefault\n * * `false`: will have the raw module as default export\n * * `true`: will have the default property as default export\n */\nfunction interopEsm(\n raw: Exports,\n ns: EsmNamespaceObject,\n allowExportDefault?: boolean\n) {\n const getters: { [s: string]: () => any } = Object.create(null);\n for (\n let current = raw;\n (typeof current === \"object\" || typeof current === \"function\") &&\n !LEAF_PROTOTYPES.includes(current);\n current = getProto(current)\n ) {\n for (const key of Object.getOwnPropertyNames(current)) {\n getters[key] = createGetter(raw, key);\n }\n }\n if (!(allowExportDefault && \"default\" in getters)) {\n getters[\"default\"] = () => raw;\n }\n esm(ns, getters);\n}\n\nfunction esmImport(sourceModule: Module, id: ModuleId): EsmNamespaceObject {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n if (module.namespaceObject) return module.namespaceObject;\n const raw = module.exports;\n const ns = (module.namespaceObject = {});\n interopEsm(raw, ns, raw.__esModule);\n return ns;\n}\n\nfunction commonJsRequire(sourceModule: Module, id: ModuleId): Exports {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n return module.exports;\n}\n\ntype RequireContextFactory = (map: RequireContextMap) => RequireContext;\n\nfunction requireContext(\n sourceModule: Module,\n map: RequireContextMap\n): RequireContext {\n function requireContext(id: ModuleId): Exports {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is required from a require.context, but is not in the context`\n );\n }\n\n return commonJsRequireContext(entry, sourceModule);\n }\n\n requireContext.keys = (): ModuleId[] => {\n return Object.keys(map);\n };\n\n requireContext.resolve = (id: ModuleId): ModuleId => {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is resolved from a require.context, but is not in the context`\n );\n }\n\n return entry.id();\n };\n\n return requireContext;\n}\n\n/**\n * Returns the path of a chunk defined by its data.\n */\nfunction getChunkPath(chunkData: ChunkData): ChunkPath {\n return typeof chunkData === \"string\" ? chunkData : chunkData.path;\n}\n"],"names":[],"mappings":";;;;;AAoDA,MAAM,iBAAiB,OAAO,UAAU;AACxC,MAAM,cAAc,OAAO,WAAW,eAAe,OAAO;AAE5D,SAAS,WACP,GAAQ,EACR,IAAiB,EACjB,OAA2C;IAE3C,IAAI,CAAC,eAAe,KAAK,KAAK,OAC5B,OAAO,eAAe,KAAK,MAAM;AACrC;AAKA,SAAS,IAAI,OAAgB,EAAE,OAAkC;IAC/D,WAAW,SAAS,cAAc;QAAE,OAAO;IAAK;IAChD,IAAI,aAAa,WAAW,SAAS,aAAa;QAAE,OAAO;IAAS;IACpE,IAAK,MAAM,OAAO,QAAS;QACzB,WAAW,SAAS,KAAK;YAAE,KAAK,OAAO,CAAC,IAAI;YAAE,YAAY;QAAK;IACjE;AACF;AAKA,SAAS,UAAU,MAAc,EAAE,OAAkC;IACnE,IAAK,OAAO,kBAAkB,OAAO,SAAU;AACjD;AAKA,SAAS,UAAU,OAAgB,EAAE,KAA0B;IAC7D,IAAK,MAAM,OAAO,MAAO;QACvB,WAAW,SAAS,KAAK;YAAE,KAAK,IAAM,KAAK,CAAC,IAAI;YAAE,YAAY;QAAK;IACrE;AACF;AAEA,SAAS,YAAY,MAAc,EAAE,KAAU;IAC7C,OAAO,UAAU;AACnB;AAEA,SAAS,gBAAgB,MAAc,EAAE,SAAc;IACrD,OAAO,UAAU,OAAO,kBAAkB;AAC5C;AAEA,SAAS,aAAa,GAAwB,EAAE,GAAW;IACzD,OAAO,IAAM,GAAG,CAAC,IAAI;AACvB;AAKA,MAAM,WAA8B,OAAO,iBACvC,CAAC,MAAQ,OAAO,eAAe,OAC/B,CAAC,MAAQ,IAAI;AAGjB,MAAM,kBAAkB;IAAC;IAAM,SAAS,CAAC;IAAI,SAAS,EAAE;IAAG,SAAS;CAAU;AAO9E,SAAS,WACP,GAAY,EACZ,EAAsB,EACtB,kBAA4B;IAE5B,MAAM,UAAsC,OAAO,OAAO;IAC1D,IACE,IAAI,UAAU,KACd,CAAC,OAAO,YAAY,YAAY,OAAO,YAAY,UAAU,KAC7D,CAAC,gBAAgB,SAAS,UAC1B,UAAU,SAAS,SACnB;QACA,KAAK,MAAM,OAAO,OAAO,oBAAoB,SAAU;YACrD,OAAO,CAAC,IAAI,GAAG,aAAa,KAAK;QACnC;IACF;IACA,IAAI,CAAC,CAAC,sBAAsB,aAAa,OAAO,GAAG;QACjD,OAAO,CAAC,UAAU,GAAG,IAAM;IAC7B;IACA,IAAI,IAAI;AACV;AAEA,SAAS,UAAU,YAAoB,EAAE,EAAY;IACnD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,IAAI,OAAO,iBAAiB,OAAO,OAAO;IAC1C,MAAM,MAAM,OAAO;IACnB,MAAM,KAAM,OAAO,kBAAkB,CAAC;IACtC,WAAW,KAAK,IAAI,IAAI;IACxB,OAAO;AACT;AAEA,SAAS,gBAAgB,YAAoB,EAAE,EAAY;IACzD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,OAAO,OAAO;AAChB;AAIA,SAAS,eACP,YAAoB,EACpB,GAAsB;IAEtB,SAAS,eAAe,EAAY;QAClC,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,uBAAuB,OAAO;IACvC;IAEA,eAAe,OAAO;QACpB,OAAO,OAAO,KAAK;IACrB;IAEA,eAAe,UAAU,CAAC;QACxB,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,MAAM;IACf;IAEA,OAAO;AACT;AAKA,SAAS,aAAa,SAAoB;IACxC,OAAO,OAAO,cAAc,WAAW,YAAY,UAAU;AAC/D"}}, - {"offset": {"line": 101, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/build/runtime.ts"],"sourcesContent":["/// \n\ndeclare var RUNTIME_PUBLIC_PATH: string;\n\nenum SourceType {\n /**\n * The module was instantiated because it was included in an evaluated chunk's\n * runtime.\n */\n Runtime = 0,\n /**\n * The module was instantiated because a parent module imported it.\n */\n Parent = 1,\n}\n\ntype SourceInfo =\n | {\n type: SourceType.Runtime;\n chunkPath: ChunkPath;\n }\n | {\n type: SourceType.Parent;\n parentId: ModuleId;\n };\n\ninterface TurbopackNodeBuildContext {\n e: Module[\"exports\"];\n r: CommonJsRequire;\n x: ExternalRequire;\n f: RequireContextFactory;\n i: EsmImport;\n s: EsmExport;\n j: typeof cjsExport;\n v: ExportValue;\n n: typeof exportNamespace;\n m: Module;\n c: ModuleCache;\n l: LoadChunk;\n g: typeof globalThis;\n __dirname: string;\n}\n\ntype ModuleFactory = (\n this: Module[\"exports\"],\n context: TurbopackNodeBuildContext\n) => undefined;\n\nconst path = require(\"path\");\nconst relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, \".\");\nconst RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot);\n\nconst moduleFactories: ModuleFactories = Object.create(null);\nconst moduleCache: ModuleCache = Object.create(null);\n\nfunction externalRequire(\n id: ModuleId,\n esm: boolean = false\n): Exports | EsmNamespaceObject {\n let raw;\n try {\n raw = require(id);\n } catch (err) {\n // TODO(alexkirsz) This can happen when a client-side module tries to load\n // an external module we don't provide a shim for (e.g. querystring, url).\n // For now, we fail semi-silently, but in the future this should be a\n // compilation error.\n throw new Error(`Failed to load external module ${id}: ${err}`);\n }\n if (!esm || raw.__esModule) {\n return raw;\n }\n const ns = {};\n interopEsm(raw, ns, true);\n return ns;\n}\nexternalRequire.resolve = (\n id: string,\n options?:\n | {\n paths?: string[] | undefined;\n }\n | undefined\n) => {\n return require.resolve(id, options);\n};\n\nfunction loadChunk(chunkPath: ChunkPath) {\n if (!chunkPath.endsWith(\".js\")) {\n // We only support loading JS chunks in Node.js.\n // This branch can be hit when trying to load a CSS chunk.\n return;\n }\n\n const path = require(\"path\");\n const resolved = require.resolve(path.resolve(RUNTIME_ROOT, chunkPath));\n delete require.cache[resolved];\n const chunkModules: ModuleFactories = require(resolved);\n\n for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) {\n if (!moduleFactories[moduleId]) {\n moduleFactories[moduleId] = moduleFactory;\n }\n }\n}\n\nfunction loadChunkAsync(source: SourceInfo, chunkPath: string): Promise {\n return new Promise((resolve, reject) => {\n try {\n loadChunk(chunkPath);\n } catch (err) {\n reject(err);\n return;\n }\n resolve();\n });\n}\n\nfunction instantiateModule(id: ModuleId, source: SourceInfo): Module {\n const moduleFactory = moduleFactories[id];\n if (typeof moduleFactory !== \"function\") {\n // This can happen if modules incorrectly handle HMR disposes/updates,\n // e.g. when they keep a `setTimeout` around which still executes old code\n // and contains e.g. a `require(\"something\")` call.\n let instantiationReason;\n switch (source.type) {\n case SourceType.Runtime:\n instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n instantiationReason = `because it was required from module ${source.parentId}`;\n break;\n }\n throw new Error(\n `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`\n );\n }\n\n let parents: ModuleId[];\n switch (source.type) {\n case SourceType.Runtime:\n parents = [];\n break;\n case SourceType.Parent:\n // No need to add this module as a child of the parent module here, this\n // has already been taken care of in `getOrInstantiateModuleFromParent`.\n parents = [source.parentId];\n break;\n }\n\n const module: Module = {\n exports: {},\n error: undefined,\n loaded: false,\n id,\n parents,\n children: [],\n namespaceObject: undefined,\n };\n moduleCache[id] = module;\n\n // NOTE(alexkirsz) This can fail when the module encounters a runtime error.\n try {\n moduleFactory.call(module.exports, {\n e: module.exports,\n r: commonJsRequire.bind(null, module),\n x: externalRequire,\n f: requireContext.bind(null, module),\n i: esmImport.bind(null, module),\n s: esm.bind(null, module.exports),\n j: cjsExport.bind(null, module.exports),\n v: exportValue.bind(null, module),\n n: exportNamespace.bind(null, module),\n m: module,\n c: moduleCache,\n l: loadChunkAsync.bind(null, { type: SourceType.Parent, parentId: id }),\n g: globalThis,\n __dirname: module.id.replace(/(^|\\/)[\\/]+$/, \"\"),\n });\n } catch (error) {\n module.error = error as any;\n throw error;\n }\n\n module.loaded = true;\n if (module.namespaceObject) {\n // in case of a circular dependency: cjs1 -> esm2 -> cjs1\n interopEsm(module.exports, module.namespaceObject);\n }\n\n return module;\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it if it is not cached.\n */\nfunction getOrInstantiateModuleFromParent(\n id: ModuleId,\n sourceModule: Module\n): Module {\n const module = moduleCache[id];\n\n if (sourceModule.children.indexOf(id) === -1) {\n sourceModule.children.push(id);\n }\n\n if (module) {\n if (module.parents.indexOf(sourceModule.id) === -1) {\n module.parents.push(sourceModule.id);\n }\n\n return module;\n }\n\n return instantiateModule(id, {\n type: SourceType.Parent,\n parentId: sourceModule.id,\n });\n}\n\n/**\n * Instantiates a runtime module.\n */\nfunction instantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it as a runtime module if it is not cached.\n */\nfunction getOrInstantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n const module = moduleCache[moduleId];\n if (module) {\n if (module.error) {\n throw module.error;\n }\n return module;\n }\n\n return instantiateRuntimeModule(moduleId, chunkPath);\n}\n\nmodule.exports = {\n getOrInstantiateRuntimeModule,\n loadChunk,\n};\n"],"names":[],"mappings":";IAIA;UAAK,UAAU;IAAV,WAAA,WAKH,aAAU,KAAV;IALG,WAAA,WASH,YAAS,KAAT;GATG,eAAA;;AA4CL,MAAM,OAAO,QAAQ;AACrB,MAAM,4BAA4B,KAAK,SAAS,qBAAqB;AACrE,MAAM,eAAe,KAAK,QAAQ,YAAY;AAE9C,MAAM,kBAAmC,OAAO,OAAO;AACvD,MAAM,cAA2B,OAAO,OAAO;AAE/C,SAAS,gBACP,EAAY,EACZ,OAAe,KAAK;IAEpB,IAAI;IACJ,IAAI;QACF,MAAM,QAAQ;IAChB,EAAE,OAAO,KAAK;QAKZ,MAAM,IAAI,MAAM,CAAC,+BAA+B,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC;IAChE;IACA,IAAI,CAAC,QAAO,IAAI,YAAY;QAC1B,OAAO;IACT;IACA,MAAM,KAAK,CAAC;IACZ,WAAW,KAAK,IAAI;IACpB,OAAO;AACT;AACA,gBAAgB,UAAU,CACxB,IACA;IAMA,OAAO,QAAQ,QAAQ,IAAI;AAC7B;AAEA,SAAS,UAAU,SAAoB;IACrC,IAAI,CAAC,UAAU,SAAS,QAAQ;QAG9B;IACF;IAEA,MAAM,OAAO,QAAQ;IACrB,MAAM,WAAW,QAAQ,QAAQ,KAAK,QAAQ,cAAc;IAC5D,OAAO,QAAQ,KAAK,CAAC,SAAS;IAC9B,MAAM,eAAgC,QAAQ;IAE9C,KAAK,MAAM,CAAC,UAAU,cAAc,IAAI,OAAO,QAAQ,cAAe;QACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9B,eAAe,CAAC,SAAS,GAAG;QAC9B;IACF;AACF;AAEA,SAAS,eAAe,MAAkB,EAAE,SAAiB;IAC3D,OAAO,IAAI,QAAc,CAAC,SAAS;QACjC,IAAI;YACF,UAAU;QACZ,EAAE,OAAO,KAAK;YACZ,OAAO;YACP;QACF;QACA;IACF;AACF;AAEA,SAAS,kBAAkB,EAAY,EAAE,MAAkB;IACzD,MAAM,gBAAgB,eAAe,CAAC,GAAG;IACzC,IAAI,OAAO,kBAAkB,YAAY;QAIvC,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,sBAAsB,CAAC,4BAA4B,EAAE,OAAO,UAAU,CAAC;gBACvE;YACF,KAAK,WAAW;gBACd,sBAAsB,CAAC,oCAAoC,EAAE,OAAO,SAAS,CAAC;gBAC9E;QACJ;QACA,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,oBAAoB,uFAAuF,CAAC;IAEjJ;IAEA,IAAI;IACJ,OAAQ,OAAO;QACb,KAAK,WAAW;YACd,UAAU,EAAE;YACZ;QACF,KAAK,WAAW;YAGd,UAAU;gBAAC,OAAO;aAAS;YAC3B;IACJ;IAEA,MAAM,UAAiB;QACrB,SAAS,CAAC;QACV,OAAO;QACP,QAAQ;QACR;QACA;QACA,UAAU,EAAE;QACZ,iBAAiB;IACnB;IACA,WAAW,CAAC,GAAG,GAAG;IAGlB,IAAI;QACF,cAAc,KAAK,QAAO,SAAS;YACjC,GAAG,QAAO;YACV,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;YAC7B,GAAG,UAAU,KAAK,MAAM;YACxB,GAAG,IAAI,KAAK,MAAM,QAAO;YACzB,GAAG,UAAU,KAAK,MAAM,QAAO;YAC/B,GAAG,YAAY,KAAK,MAAM;YAC1B,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;gBAAE,MAAM,WAAW;gBAAQ,UAAU;YAAG;YACrE,GAAG;YACH,WAAW,QAAO,GAAG,QAAQ,gBAAgB;QAC/C;IACF,EAAE,OAAO,OAAO;QACd,QAAO,QAAQ;QACf,MAAM;IACR;IAEA,QAAO,SAAS;IAChB,IAAI,QAAO,iBAAiB;QAE1B,WAAW,QAAO,SAAS,QAAO;IACpC;IAEA,OAAO;AACT;AAKA,SAAS,iCACP,EAAY,EACZ,YAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,GAAG;IAE9B,IAAI,aAAa,SAAS,QAAQ,QAAQ,CAAC,GAAG;QAC5C,aAAa,SAAS,KAAK;IAC7B;IAEA,IAAI,SAAQ;QACV,IAAI,QAAO,QAAQ,QAAQ,aAAa,QAAQ,CAAC,GAAG;YAClD,QAAO,QAAQ,KAAK,aAAa;QACnC;QAEA,OAAO;IACT;IAEA,OAAO,kBAAkB,IAAI;QAC3B,MAAM,WAAW;QACjB,UAAU,aAAa;IACzB;AACF;AAKA,SAAS,yBACP,QAAkB,EAClB,SAAoB;IAEpB,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,8BACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,SAAS;IACpC,IAAI,SAAQ;QACV,IAAI,QAAO,OAAO;YAChB,MAAM,QAAO;QACf;QACA,OAAO;IACT;IAEA,OAAO,yBAAyB,UAAU;AAC5C;AAEA,OAAO,UAAU;IACf;IACA;AACF"}}] + {"offset": {"line": 101, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/build/runtime.ts"],"sourcesContent":["/// \n\ndeclare var RUNTIME_PUBLIC_PATH: string;\n\nenum SourceType {\n /**\n * The module was instantiated because it was included in an evaluated chunk's\n * runtime.\n */\n Runtime = 0,\n /**\n * The module was instantiated because a parent module imported it.\n */\n Parent = 1,\n}\n\ntype SourceInfo =\n | {\n type: SourceType.Runtime;\n chunkPath: ChunkPath;\n }\n | {\n type: SourceType.Parent;\n parentId: ModuleId;\n };\n\ninterface TurbopackNodeBuildContext {\n e: Module[\"exports\"];\n r: CommonJsRequire;\n x: ExternalRequire;\n f: RequireContextFactory;\n i: EsmImport;\n s: EsmExport;\n j: typeof cjsExport;\n v: ExportValue;\n n: typeof exportNamespace;\n m: Module;\n c: ModuleCache;\n l: LoadChunk;\n g: typeof globalThis;\n __dirname: string;\n}\n\ntype ModuleFactory = (\n this: Module[\"exports\"],\n context: TurbopackNodeBuildContext\n) => undefined;\n\nconst path = require(\"path\");\nconst relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, \".\");\nconst RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot);\n\nconst moduleFactories: ModuleFactories = Object.create(null);\nconst moduleCache: ModuleCache = Object.create(null);\n\nfunction externalRequire(\n id: ModuleId,\n esm: boolean = false\n): Exports | EsmNamespaceObject {\n let raw;\n try {\n raw = require(id);\n } catch (err) {\n // TODO(alexkirsz) This can happen when a client-side module tries to load\n // an external module we don't provide a shim for (e.g. querystring, url).\n // For now, we fail semi-silently, but in the future this should be a\n // compilation error.\n throw new Error(`Failed to load external module ${id}: ${err}`);\n }\n if (!esm || raw.__esModule) {\n return raw;\n }\n const ns = {};\n interopEsm(raw, ns, true);\n return ns;\n}\nexternalRequire.resolve = (\n id: string,\n options?:\n | {\n paths?: string[] | undefined;\n }\n | undefined\n) => {\n return require.resolve(id, options);\n};\n\nfunction loadChunk(chunkPath: ChunkPath) {\n if (!chunkPath.endsWith(\".js\")) {\n // We only support loading JS chunks in Node.js.\n // This branch can be hit when trying to load a CSS chunk.\n return;\n }\n\n const resolved = require.resolve(path.resolve(RUNTIME_ROOT, chunkPath));\n delete require.cache[resolved];\n const chunkModules: ModuleFactories = require(resolved);\n\n for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) {\n if (!moduleFactories[moduleId]) {\n moduleFactories[moduleId] = moduleFactory;\n }\n }\n}\n\nfunction loadChunkAsync(source: SourceInfo, chunkPath: string): Promise {\n return new Promise((resolve, reject) => {\n try {\n loadChunk(chunkPath);\n } catch (err) {\n reject(err);\n return;\n }\n resolve();\n });\n}\n\nfunction instantiateModule(id: ModuleId, source: SourceInfo): Module {\n const moduleFactory = moduleFactories[id];\n if (typeof moduleFactory !== \"function\") {\n // This can happen if modules incorrectly handle HMR disposes/updates,\n // e.g. when they keep a `setTimeout` around which still executes old code\n // and contains e.g. a `require(\"something\")` call.\n let instantiationReason;\n switch (source.type) {\n case SourceType.Runtime:\n instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n instantiationReason = `because it was required from module ${source.parentId}`;\n break;\n }\n throw new Error(\n `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`\n );\n }\n\n let parents: ModuleId[];\n switch (source.type) {\n case SourceType.Runtime:\n parents = [];\n break;\n case SourceType.Parent:\n // No need to add this module as a child of the parent module here, this\n // has already been taken care of in `getOrInstantiateModuleFromParent`.\n parents = [source.parentId];\n break;\n }\n\n const module: Module = {\n exports: {},\n error: undefined,\n loaded: false,\n id,\n parents,\n children: [],\n namespaceObject: undefined,\n };\n moduleCache[id] = module;\n\n // NOTE(alexkirsz) This can fail when the module encounters a runtime error.\n try {\n moduleFactory.call(module.exports, {\n e: module.exports,\n r: commonJsRequire.bind(null, module),\n x: externalRequire,\n f: requireContext.bind(null, module),\n i: esmImport.bind(null, module),\n s: esm.bind(null, module.exports),\n j: cjsExport.bind(null, module.exports),\n v: exportValue.bind(null, module),\n n: exportNamespace.bind(null, module),\n m: module,\n c: moduleCache,\n l: loadChunkAsync.bind(null, { type: SourceType.Parent, parentId: id }),\n g: globalThis,\n __dirname: module.id.replace(/(^|\\/)[\\/]+$/, \"\"),\n });\n } catch (error) {\n module.error = error as any;\n throw error;\n }\n\n module.loaded = true;\n if (module.namespaceObject) {\n // in case of a circular dependency: cjs1 -> esm2 -> cjs1\n interopEsm(module.exports, module.namespaceObject);\n }\n\n return module;\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it if it is not cached.\n */\nfunction getOrInstantiateModuleFromParent(\n id: ModuleId,\n sourceModule: Module\n): Module {\n const module = moduleCache[id];\n\n if (sourceModule.children.indexOf(id) === -1) {\n sourceModule.children.push(id);\n }\n\n if (module) {\n if (module.parents.indexOf(sourceModule.id) === -1) {\n module.parents.push(sourceModule.id);\n }\n\n return module;\n }\n\n return instantiateModule(id, {\n type: SourceType.Parent,\n parentId: sourceModule.id,\n });\n}\n\n/**\n * Instantiates a runtime module.\n */\nfunction instantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it as a runtime module if it is not cached.\n */\nfunction getOrInstantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n const module = moduleCache[moduleId];\n if (module) {\n if (module.error) {\n throw module.error;\n }\n return module;\n }\n\n return instantiateRuntimeModule(moduleId, chunkPath);\n}\n\nmodule.exports = {\n getOrInstantiateRuntimeModule,\n loadChunk,\n};\n"],"names":[],"mappings":";IAIA;UAAK,UAAU;IAAV,WAAA,WAKH,aAAU,KAAV;IALG,WAAA,WASH,YAAS,KAAT;GATG,eAAA;;AA4CL,MAAM,OAAO,QAAQ;AACrB,MAAM,4BAA4B,KAAK,SAAS,qBAAqB;AACrE,MAAM,eAAe,KAAK,QAAQ,YAAY;AAE9C,MAAM,kBAAmC,OAAO,OAAO;AACvD,MAAM,cAA2B,OAAO,OAAO;AAE/C,SAAS,gBACP,EAAY,EACZ,OAAe,KAAK;IAEpB,IAAI;IACJ,IAAI;QACF,MAAM,QAAQ;IAChB,EAAE,OAAO,KAAK;QAKZ,MAAM,IAAI,MAAM,CAAC,+BAA+B,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC;IAChE;IACA,IAAI,CAAC,QAAO,IAAI,YAAY;QAC1B,OAAO;IACT;IACA,MAAM,KAAK,CAAC;IACZ,WAAW,KAAK,IAAI;IACpB,OAAO;AACT;AACA,gBAAgB,UAAU,CACxB,IACA;IAMA,OAAO,QAAQ,QAAQ,IAAI;AAC7B;AAEA,SAAS,UAAU,SAAoB;IACrC,IAAI,CAAC,UAAU,SAAS,QAAQ;QAG9B;IACF;IAEA,MAAM,WAAW,QAAQ,QAAQ,KAAK,QAAQ,cAAc;IAC5D,OAAO,QAAQ,KAAK,CAAC,SAAS;IAC9B,MAAM,eAAgC,QAAQ;IAE9C,KAAK,MAAM,CAAC,UAAU,cAAc,IAAI,OAAO,QAAQ,cAAe;QACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9B,eAAe,CAAC,SAAS,GAAG;QAC9B;IACF;AACF;AAEA,SAAS,eAAe,MAAkB,EAAE,SAAiB;IAC3D,OAAO,IAAI,QAAc,CAAC,SAAS;QACjC,IAAI;YACF,UAAU;QACZ,EAAE,OAAO,KAAK;YACZ,OAAO;YACP;QACF;QACA;IACF;AACF;AAEA,SAAS,kBAAkB,EAAY,EAAE,MAAkB;IACzD,MAAM,gBAAgB,eAAe,CAAC,GAAG;IACzC,IAAI,OAAO,kBAAkB,YAAY;QAIvC,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,sBAAsB,CAAC,4BAA4B,EAAE,OAAO,UAAU,CAAC;gBACvE;YACF,KAAK,WAAW;gBACd,sBAAsB,CAAC,oCAAoC,EAAE,OAAO,SAAS,CAAC;gBAC9E;QACJ;QACA,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,oBAAoB,uFAAuF,CAAC;IAEjJ;IAEA,IAAI;IACJ,OAAQ,OAAO;QACb,KAAK,WAAW;YACd,UAAU,EAAE;YACZ;QACF,KAAK,WAAW;YAGd,UAAU;gBAAC,OAAO;aAAS;YAC3B;IACJ;IAEA,MAAM,UAAiB;QACrB,SAAS,CAAC;QACV,OAAO;QACP,QAAQ;QACR;QACA;QACA,UAAU,EAAE;QACZ,iBAAiB;IACnB;IACA,WAAW,CAAC,GAAG,GAAG;IAGlB,IAAI;QACF,cAAc,KAAK,QAAO,SAAS;YACjC,GAAG,QAAO;YACV,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;YAC7B,GAAG,UAAU,KAAK,MAAM;YACxB,GAAG,IAAI,KAAK,MAAM,QAAO;YACzB,GAAG,UAAU,KAAK,MAAM,QAAO;YAC/B,GAAG,YAAY,KAAK,MAAM;YAC1B,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;gBAAE,MAAM,WAAW;gBAAQ,UAAU;YAAG;YACrE,GAAG;YACH,WAAW,QAAO,GAAG,QAAQ,gBAAgB;QAC/C;IACF,EAAE,OAAO,OAAO;QACd,QAAO,QAAQ;QACf,MAAM;IACR;IAEA,QAAO,SAAS;IAChB,IAAI,QAAO,iBAAiB;QAE1B,WAAW,QAAO,SAAS,QAAO;IACpC;IAEA,OAAO;AACT;AAKA,SAAS,iCACP,EAAY,EACZ,YAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,GAAG;IAE9B,IAAI,aAAa,SAAS,QAAQ,QAAQ,CAAC,GAAG;QAC5C,aAAa,SAAS,KAAK;IAC7B;IAEA,IAAI,SAAQ;QACV,IAAI,QAAO,QAAQ,QAAQ,aAAa,QAAQ,CAAC,GAAG;YAClD,QAAO,QAAQ,KAAK,aAAa;QACnC;QAEA,OAAO;IACT;IAEA,OAAO,kBAAkB,IAAI;QAC3B,MAAM,WAAW;QACjB,UAAU,aAAa;IACzB;AACF;AAKA,SAAS,yBACP,QAAkB,EAClB,SAAoB;IAEpB,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,8BACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,SAAS;IACpC,IAAI,SAAQ;QACV,IAAI,QAAO,OAAO;YAChB,MAAM,QAAO;QACf;QACA,OAAO;IACT;IAEA,OAAO,yBAAyB,UAAU;AAC5C;AAEA,OAAO,UAAU;IACf;IACA;AACF"}}] } \ No newline at end of file From dabc9fd3d5e7e8b0ea43844f2aff70c25ef1d9cb Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 17:32:13 +0200 Subject: [PATCH 12/19] Only add externals when the chunking context supports it --- .../js/src/build/runtime.ts | 15 ++++ .../js/src/dev/runtime/base/dummy.ts | 6 ++ .../js/src/dev/runtime/base/extensions.d.ts | 4 - .../js/src/dev/runtime/base/runtime-base.ts | 82 +++++-------------- .../dev/runtime/dom/runtime-backend-dom.ts | 11 +++ .../runtime/nodejs/runtime-backend-nodejs.ts | 58 +++++++++++++ .../dev/runtime/none/runtime-backend-none.ts | 11 +++ .../js/src/shared/runtime-types.d.ts | 2 - crates/turbopack-ecmascript/src/chunk/item.rs | 22 +++-- crates/turbopack-ecmascript/src/lib.rs | 8 +- .../src/references/esm/base.rs | 14 +++- .../src/references/require_context.rs | 24 ++++-- .../src/tree_shake/chunk_item.rs | 5 +- 13 files changed, 167 insertions(+), 95 deletions(-) diff --git a/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts b/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts index 9cc7d2e86f07d..4c3be2f716d51 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/build/runtime.ts @@ -24,6 +24,12 @@ type SourceInfo = parentId: ModuleId; }; +interface RequireContextEntry { + external: boolean; +} + +type ExternalRequire = (id: ModuleId) => Exports | EsmNamespaceObject; + interface TurbopackNodeBuildContext { e: Module["exports"]; r: CommonJsRequire; @@ -53,6 +59,15 @@ const RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot); const moduleFactories: ModuleFactories = Object.create(null); const moduleCache: ModuleCache = Object.create(null); +function commonJsRequireContext( + entry: RequireContextEntry, + sourceModule: Module +): Exports { + return entry.external + ? externalRequire(entry.id(), false) + : commonJsRequire(sourceModule, entry.id()); +} + function externalRequire( id: ModuleId, esm: boolean = false diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts index 942a535df01bb..ac710dd2edd87 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts @@ -7,3 +7,9 @@ declare var BACKEND: RuntimeBackend; declare var _eval: (code: EcmascriptModuleEntry) => any; +/** + * Adds additional properties to the `TurbopackDevBaseContext` interface. + */ +declare var augmentContext: ( + context: TurbopackDevBaseContext +) => TurbopackDevContext; diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/extensions.d.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/extensions.d.ts index a4eb01fa5d7fa..89e3b33fe610a 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/extensions.d.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/extensions.d.ts @@ -3,10 +3,6 @@ * runtime (e.g. `module.hot`). */ -interface RequireContextEntry { - internal: boolean; -} - declare const enum HotUpdateStatus { idle = "idle", } diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/runtime-base.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/runtime-base.ts index 76dfc8575dabc..11ddaa884ea24 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/runtime-base.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/runtime-base.ts @@ -45,10 +45,9 @@ type RefreshHelpers = { scheduleUpdate(): void; }; -interface TurbopackDevContext { +interface TurbopackDevBaseContext { e: Module["exports"]; r: CommonJsRequire; - x: ExternalRequire; f: RequireContextFactory; i: EsmImport; s: EsmExport; @@ -63,6 +62,8 @@ interface TurbopackDevContext { __dirname: string; } +interface TurbopackDevContext extends TurbopackDevBaseContext {} + // string encoding of a module factory (used in hmr updates) type ModuleFactoryString = string; @@ -169,47 +170,6 @@ const chunkListChunksMap: Map> = new Map(); */ const chunkChunkListsMap: Map> = new Map(); -const commonJsRequireContext: CommonJsRequireContext = ( - entry, - sourceModule -) => { - return entry.internal - ? commonJsRequire(sourceModule, entry.id()) - : externalRequire(entry.id(), false); -}; - -function externalRequire( - id: ModuleId, - esm: boolean = false -): Exports | EsmNamespaceObject { - let raw; - try { - raw = require(id); - } catch (err) { - // TODO(alexkirsz) This can happen when a client-side module tries to load - // an external module we don't provide a shim for (e.g. querystring, url). - // For now, we fail semi-silently, but in the future this should be a - // compilation error. - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = ( - id: string, - options?: - | { - paths?: string[] | undefined; - } - | undefined -) => { - return require.resolve(id, options); -}; - const availableModules: Map | true> = new Map(); const availableModuleChunks: Map | true> = new Map(); @@ -373,23 +333,25 @@ function instantiateModule(id: ModuleId, source: SourceInfo): Module { // NOTE(alexkirsz) This can fail when the module encounters a runtime error. try { runModuleExecutionHooks(module, (refresh) => { - moduleFactory.call(module.exports, { - e: module.exports, - r: commonJsRequire.bind(null, module), - x: externalRequire, - f: requireContext.bind(null, module), - i: esmImport.bind(null, module), - s: esmExport.bind(null, module), - j: cjsExport.bind(null, module.exports), - v: exportValue.bind(null, module), - n: exportNamespace.bind(null, module), - m: module, - c: moduleCache, - l: loadChunk.bind(null, { type: SourceType.Parent, parentId: id }), - g: globalThis, - k: refresh, - __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), - }); + moduleFactory.call( + module.exports, + augmentContext({ + e: module.exports, + r: commonJsRequire.bind(null, module), + f: requireContext.bind(null, module), + i: esmImport.bind(null, module), + s: esmExport.bind(null, module), + j: cjsExport.bind(null, module.exports), + v: exportValue.bind(null, module), + n: exportNamespace.bind(null, module), + m: module, + c: moduleCache, + l: loadChunk.bind(null, { type: SourceType.Parent, parentId: id }), + g: globalThis, + k: refresh, + __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), + }) + ); }); } catch (error) { module.error = error as any; diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/runtime-backend-dom.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/runtime-backend-dom.ts index 2fba6341a31c4..b3eb55f583fce 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/runtime-backend-dom.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/dom/runtime-backend-dom.ts @@ -16,6 +16,17 @@ type ChunkResolver = { let BACKEND: RuntimeBackend; +function augmentContext(context: TurbopackDevBaseContext): TurbopackDevContext { + return context; +} + +function commonJsRequireContext( + entry: RequireContextEntry, + sourceModule: Module +): Exports { + return commonJsRequire(sourceModule, entry.id()); +} + (() => { BACKEND = { async registerChunk(chunkPath, params) { diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/runtime-backend-nodejs.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/runtime-backend-nodejs.ts index 654f6a577939e..2a08b17381367 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/runtime-backend-nodejs.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/nodejs/runtime-backend-nodejs.ts @@ -7,6 +7,64 @@ /// +interface RequireContextEntry { + // Only the Node.js backend has this flag. + external: boolean; +} + +type ExternalRequire = (id: ModuleId) => Exports | EsmNamespaceObject; + +interface TurbopackDevContext { + x: ExternalRequire; +} + +function commonJsRequireContext( + entry: RequireContextEntry, + sourceModule: Module +): Exports { + return entry.external + ? externalRequire(entry.id(), false) + : commonJsRequire(sourceModule, entry.id()); +} + +function externalRequire( + id: ModuleId, + esm: boolean = false +): Exports | EsmNamespaceObject { + let raw; + try { + raw = require(id); + } catch (err) { + // TODO(alexkirsz) This can happen when a client-side module tries to load + // an external module we don't provide a shim for (e.g. querystring, url). + // For now, we fail semi-silently, but in the future this should be a + // compilation error. + throw new Error(`Failed to load external module ${id}: ${err}`); + } + if (!esm) { + return raw; + } + const ns = {}; + interopEsm(raw, ns, raw.__esModule); + return ns; +} +externalRequire.resolve = ( + id: string, + options?: + | { + paths?: string[] | undefined; + } + | undefined +) => { + return require.resolve(id, options); +}; + +function augmentContext(context: TurbopackDevBaseContext): TurbopackDevContext { + const nodejsContext = context as TurbopackDevContext; + nodejsContext.x = externalRequire; + return nodejsContext; +} + let BACKEND: RuntimeBackend; (() => { diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/runtime-backend-none.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/runtime-backend-none.ts index 5f0443bcc235f..56230aabaf516 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/runtime-backend-none.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/none/runtime-backend-none.ts @@ -15,6 +15,17 @@ type ChunkRunner = { let BACKEND: RuntimeBackend; +function augmentContext(context: TurbopackDevBaseContext): TurbopackDevContext { + return context; +} + +function commonJsRequireContext( + entry: RequireContextEntry, + sourceModule: Module +): Exports { + return commonJsRequire(sourceModule, entry.id()); +} + (() => { BACKEND = { // The "none" runtime expects all chunks within the same chunk group to be diff --git a/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-types.d.ts b/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-types.d.ts index 84581ac8f665d..f9ed380b10767 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-types.d.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/shared/runtime-types.d.ts @@ -29,8 +29,6 @@ type EsmImport = ( type EsmExport = (exportGetters: Record any>) => void; type ExportValue = (value: any) => void; -type ExternalRequire = (id: ModuleId) => Exports | EsmNamespaceObject; - type LoadChunk = (chunkPath: ChunkPath) => Promise | undefined; type ModuleCache = Record; diff --git a/crates/turbopack-ecmascript/src/chunk/item.rs b/crates/turbopack-ecmascript/src/chunk/item.rs index 650e40d521087..3c86efe3e6f17 100644 --- a/crates/turbopack-ecmascript/src/chunk/item.rs +++ b/crates/turbopack-ecmascript/src/chunk/item.rs @@ -3,16 +3,15 @@ use std::io::Write; use anyhow::Result; use serde::{Deserialize, Serialize}; use turbo_tasks::{ - primitives::{BoolVc, StringVc}, - trace::TraceRawVcs, - Value, ValueToString, + debug::ValueDebugFormat, primitives::StringVc, trace::TraceRawVcs, Value, ValueToString, }; use turbo_tasks_fs::rope::Rope; use turbopack_core::{ asset::AssetVc, chunk::{ availability_info::AvailabilityInfo, available_assets::AvailableAssetsVc, ChunkItem, - ChunkItemVc, ChunkableAssetVc, ChunkingContextVc, FromChunkableAsset, ModuleIdVc, + ChunkItemVc, ChunkableAssetVc, ChunkingContext, ChunkingContextVc, FromChunkableAsset, + ModuleIdVc, }, code_builder::{CodeBuilder, CodeVc}, error::PrettyPrintError, @@ -25,7 +24,6 @@ use super::{ }; use crate::{ manifest::{chunk_asset::ManifestChunkAssetVc, loader_item::ManifestLoaderItemVc}, - utils::FormatIter, EcmascriptModuleContentVc, ParseResultSourceMapVc, }; @@ -43,9 +41,10 @@ impl EcmascriptChunkItemContentVc { #[turbo_tasks::function] pub async fn new( content: EcmascriptModuleContentVc, - has_react_refresh: BoolVc, + context: EcmascriptChunkingContextVc, ) -> Result { - let refresh = *has_react_refresh.await?; + let refresh = *context.has_react_refresh().await?; + let externals = *context.environment().node_externals().await?; let content = content.await?; Ok(EcmascriptChunkItemContent { @@ -54,11 +53,13 @@ impl EcmascriptChunkItemContentVc { options: if content.is_esm { EcmascriptChunkItemOptions { refresh, + externals, ..Default::default() } } else { EcmascriptChunkItemOptions { refresh, + externals, // These things are not available in ESM module: true, exports: true, @@ -76,7 +77,6 @@ impl EcmascriptChunkItemContentVc { let this = self.await?; let mut args = vec![ "r: __turbopack_require__", - "x: __turbopack_external_require__", "f: __turbopack_require_context__", "i: __turbopack_import__", "s: __turbopack_esm__", @@ -89,6 +89,9 @@ impl EcmascriptChunkItemContentVc { // HACK "__dirname", ]; + if this.options.externals { + args.push("x: __turbopack_external_require__"); + } if this.options.refresh { args.push("k: __turbopack_refresh__"); } @@ -128,6 +131,9 @@ pub struct EcmascriptChunkItemOptions { /// Whether this chunk item's module factory should include an `exports` /// argument. pub exports: bool, + /// Whether this chunk item's module factory should include a + /// `__turbopack_external_require__` argument. + pub externals: bool, pub this: bool, pub placeholder_for_future_extensions: (), } diff --git a/crates/turbopack-ecmascript/src/lib.rs b/crates/turbopack-ecmascript/src/lib.rs index f026ec6fc9419..0b3ef9c7a6212 100644 --- a/crates/turbopack-ecmascript/src/lib.rs +++ b/crates/turbopack-ecmascript/src/lib.rs @@ -73,8 +73,7 @@ use turbopack_core::{ pub use self::references::AnalyzeEcmascriptModuleResultVc; use self::{ chunk::{ - placeable::EcmascriptExportsReadRef, EcmascriptChunkItemContentVc, - EcmascriptChunkingContext, EcmascriptExportsVc, + placeable::EcmascriptExportsReadRef, EcmascriptChunkItemContentVc, EcmascriptExportsVc, }, code_gen::{ CodeGen, CodeGenerateableWithAvailabilityInfo, CodeGenerateableWithAvailabilityInfoVc, @@ -436,10 +435,7 @@ impl EcmascriptChunkItem for ModuleChunkItem { ) -> Result { let this = self_vc.await?; let content = this.module.module_content(this.context, availability_info); - Ok(EcmascriptChunkItemContentVc::new( - content, - this.context.has_react_refresh(), - )) + Ok(EcmascriptChunkItemContentVc::new(content, this.context)) } } diff --git a/crates/turbopack-ecmascript/src/references/esm/base.rs b/crates/turbopack-ecmascript/src/references/esm/base.rs index 15a14d950d862..2298c91b0629e 100644 --- a/crates/turbopack-ecmascript/src/references/esm/base.rs +++ b/crates/turbopack-ecmascript/src/references/esm/base.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, bail, Result}; use lazy_static::lazy_static; use swc_core::{ common::DUMMY_SP, @@ -9,8 +9,8 @@ use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; use turbopack_core::{ asset::Asset, chunk::{ - ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkingType, ChunkingTypeOptionVc, - ModuleId, + ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkingContext, ChunkingType, + ChunkingTypeOptionVc, ModuleId, }, issue::{IssueSeverity, OptionIssueSourceVc}, reference::{AssetReference, AssetReferenceVc}, @@ -23,7 +23,10 @@ use turbopack_core::{ use crate::{ analyzer::imports::ImportAnnotations, - chunk::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkingContextVc}, + chunk::{ + EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkingContext, + EcmascriptChunkingContextVc, + }, code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, create_visitor, magic_identifier, references::util::{request_to_string, throw_module_not_found_expr}, @@ -242,6 +245,9 @@ impl CodeGenerateable for EsmAssetReference { })); } ReferencedAsset::OriginalReferenceTypeExternal(request) => { + if !*context.environment().node_externals().await? { + bail!("the chunking context does not support Node.js external modules"); + } let request = request.clone(); visitors.push(create_visitor!(visit_mut_program(program: &mut Program) { // TODO Technically this should insert a ESM external, but we don't support that yet diff --git a/crates/turbopack-ecmascript/src/references/require_context.rs b/crates/turbopack-ecmascript/src/references/require_context.rs index 17d4d50bf8a09..a206bb5d3d5e5 100644 --- a/crates/turbopack-ecmascript/src/references/require_context.rs +++ b/crates/turbopack-ecmascript/src/references/require_context.rs @@ -22,7 +22,8 @@ use turbopack_core::{ asset::{Asset, AssetContentVc, AssetVc}, chunk::{ availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, - ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkableAssetVc, ChunkingContextVc, + ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkableAssetVc, ChunkingContext, + ChunkingContextVc, }, ident::AssetIdentVc, issue::{IssueSeverityVc, OptionIssueSourceVc}, @@ -38,7 +39,8 @@ use crate::{ chunk::{ EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkVc, - EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, + EcmascriptChunkingContext, EcmascriptChunkingContextVc, EcmascriptExports, + EcmascriptExportsVc, }, chunk_group_files_asset::ChunkGroupFilesAssetVc, code_gen::{CodeGenerateable, CodeGeneration, CodeGenerationVc}, @@ -455,11 +457,19 @@ impl EcmascriptChunkItem for RequireContextChunkItem { let prop = KeyValueProp { key: PropName::Str(key.as_str().into()), - value: quote_expr!( - "{ internal: $internal, id: () => $id }", - internal: Expr = pm.is_internal_import().into(), - id: Expr = pm.apply(Expr::Lit(Lit::Str(entry.origin_relative.as_str().into()))), - ), + value: match *self.context.environment().node_externals().await? { + true => quote_expr!( + "{ external: $external, id: () => $id }", + external: Expr = !pm.is_internal_import().into(), + id: Expr = + pm.apply(Expr::Lit(Lit::Str(entry.origin_relative.as_str().into()))), + ), + false => quote_expr!( + "{ id: () => $id }", + id: Expr = + pm.apply(Expr::Lit(Lit::Str(entry.origin_relative.as_str().into()))), + ), + }, }; context_map diff --git a/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs b/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs index bb437e79afe59..33ae457f7e7a6 100644 --- a/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs +++ b/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs @@ -56,10 +56,7 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { availability_info, ); - Ok(EcmascriptChunkItemContentVc::new( - content, - this.context.has_react_refresh(), - )) + Ok(EcmascriptChunkItemContentVc::new(content, this.context)) } #[turbo_tasks::function] From f3c1c96dd99867f7f1655b8f0205b77f90c5d096 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 17:36:31 +0200 Subject: [PATCH 13/19] Missing import --- crates/turbopack-ecmascript/src/chunk/item.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/turbopack-ecmascript/src/chunk/item.rs b/crates/turbopack-ecmascript/src/chunk/item.rs index 3c86efe3e6f17..3d7a75b6c97d8 100644 --- a/crates/turbopack-ecmascript/src/chunk/item.rs +++ b/crates/turbopack-ecmascript/src/chunk/item.rs @@ -2,9 +2,7 @@ use std::io::Write; use anyhow::Result; use serde::{Deserialize, Serialize}; -use turbo_tasks::{ - debug::ValueDebugFormat, primitives::StringVc, trace::TraceRawVcs, Value, ValueToString, -}; +use turbo_tasks::{primitives::StringVc, trace::TraceRawVcs, Value, ValueToString}; use turbo_tasks_fs::rope::Rope; use turbopack_core::{ asset::AssetVc, @@ -24,6 +22,7 @@ use super::{ }; use crate::{ manifest::{chunk_asset::ManifestChunkAssetVc, loader_item::ManifestLoaderItemVc}, + utils::FormatIter, EcmascriptModuleContentVc, ParseResultSourceMapVc, }; From 7cc8c34210d33d0738dcb5bbfd1729d882fa38b0 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 17:47:27 +0200 Subject: [PATCH 14/19] Add comment to link to WEB-1112 --- crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs b/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs index 5c87c2d8f3a27..6774f0325da17 100644 --- a/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs +++ b/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs @@ -106,6 +106,8 @@ impl EcmascriptBuildNodeEvaluateChunkVc { if let Some(other_chunk_public_path) = output_root.get_path_to(other_chunk_path) { writedoc!( code, + // TODO(WEB-1112) This should call `require()` directly, perhaps as an argument + // to `loadChunk`. r#" runtime.loadChunk({}); "#, From bde928e63d012b923a61da13f8687672f092053d Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 17:49:13 +0200 Subject: [PATCH 15/19] Add dummy commonJsRequireContext definition for the base runtime --- .../js/src/dev/runtime/base/dummy.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts index ac710dd2edd87..5f31bdcf44568 100644 --- a/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts +++ b/crates/turbopack-ecmascript-runtime/js/src/dev/runtime/base/dummy.ts @@ -13,3 +13,4 @@ declare var _eval: (code: EcmascriptModuleEntry) => any; declare var augmentContext: ( context: TurbopackDevBaseContext ) => TurbopackDevContext; +declare var commonJsRequireContext: CommonJsRequireContext; From 840c6f2ecdb31919f87f0369c9e7bb62ce31e420 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 17:50:22 +0200 Subject: [PATCH 16/19] Fix type inference --- crates/turbopack-ecmascript/src/references/require_context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/turbopack-ecmascript/src/references/require_context.rs b/crates/turbopack-ecmascript/src/references/require_context.rs index a206bb5d3d5e5..f3fba27961099 100644 --- a/crates/turbopack-ecmascript/src/references/require_context.rs +++ b/crates/turbopack-ecmascript/src/references/require_context.rs @@ -460,7 +460,7 @@ impl EcmascriptChunkItem for RequireContextChunkItem { value: match *self.context.environment().node_externals().await? { true => quote_expr!( "{ external: $external, id: () => $id }", - external: Expr = !pm.is_internal_import().into(), + external: Expr = (!pm.is_internal_import()).into(), id: Expr = pm.apply(Expr::Lit(Lit::Str(entry.origin_relative.as_str().into()))), ), From dac4b0b20c20bc5acf1facdf53e64943b160d411 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 17:50:39 +0200 Subject: [PATCH 17/19] Unused import --- crates/turbopack-ecmascript/src/references/require_context.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/turbopack-ecmascript/src/references/require_context.rs b/crates/turbopack-ecmascript/src/references/require_context.rs index f3fba27961099..dceaa441e82d1 100644 --- a/crates/turbopack-ecmascript/src/references/require_context.rs +++ b/crates/turbopack-ecmascript/src/references/require_context.rs @@ -39,8 +39,7 @@ use crate::{ chunk::{ EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkVc, - EcmascriptChunkingContext, EcmascriptChunkingContextVc, EcmascriptExports, - EcmascriptExportsVc, + EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, }, chunk_group_files_asset::ChunkGroupFilesAssetVc, code_gen::{CodeGenerateable, CodeGeneration, CodeGenerationVc}, From bcb319ee68c886f7008b5370912e837961797310 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 18:08:31 +0200 Subject: [PATCH 18/19] Update snapshots --- .../output/20803_bar_index_c8a3ce.js | 2 +- .../output/20803_foo_index_5f9e1e.js | 2 +- ...t_basic_async_chunk_input_import_571bb9.js | 2 +- ...t_basic_async_chunk_input_import_a29514.js | 2 +- ...ot_basic_async_chunk_input_index_b53fce.js | 6 ++-- .../chunked/output/39e84_foo_index_4427e1.js | 2 +- ...apshot_basic_chunked_input_index_b53fce.js | 2 +- ...apshot_basic_shebang_input_index_b53fce.js | 2 +- .../shebang/output/d1787_foo_index_dd389c.js | 2 +- ...shot_comptime_define_input_index_b53fce.js | 2 +- ..._absolute-uri-import_input_index_b53fce.js | 2 +- .../8697f_foo_style_module_css_7740ee._.js | 2 +- ...sts_snapshot_css_css_input_index_b53fce.js | 4 +-- .../63a02_@emotion_react_index_a1c0c3.js | 2 +- ...2_@emotion_react_jsx-dev-runtime_73b602.js | 2 +- .../63a02_@emotion_styled_index_fd4de2.js | 2 +- ...shot_emotion_emotion_input_index_b53fce.js | 2 +- ...snapshot_env_env_input__env__env_b53fce.js | 2 +- ...sts_snapshot_env_env_input_index_b53fce.js | 2 +- ...entrry_runtime_entry_input_index_b53fce.js | 2 +- ...shot_example_example_input_index_b53fce.js | 2 +- ...ot_export-alls_cjs-2_input_index_b53fce.js | 8 ++--- ...port-alls_cjs-script_input_index_b53fce.js | 6 ++-- ...shot_import-meta_cjs_input_index_b53fce.js | 4 +-- ...rt-meta_esm-multiple_input_index_b53fce.js | 4 +-- ...ort-meta_esm-mutable_input_index_b53fce.js | 4 +-- ...port-meta_esm-object_input_index_b53fce.js | 4 +-- ...shot_import-meta_esm_input_index_b53fce.js | 4 +-- ...shot_import-meta_url_input_index_b53fce.js | 6 ++-- ...shot_imports_dynamic_input_index_b53fce.js | 4 +-- ...ports_dynamic_input_vercel_mjs_4e74d3._.js | 2 +- ...ports_dynamic_input_vercel_mjs_536504._.js | 2 +- ...napshot_imports_json_input_index_b53fce.js | 4 +-- ...apshot_imports_order_input_index_b53fce.js | 6 ++-- ...ts_resolve_error_cjs_input_index_b53fce.js | 2 +- ...ts_resolve_error_esm_input_index_b53fce.js | 2 +- ...s_static-and-dynamic_input_index_b53fce.js | 6 ++-- ...c-and-dynamic_input_vercel_mjs_10fe7a._.js | 2 +- ...c-and-dynamic_input_vercel_mjs_26aaf6._.js | 2 +- ...pshot_imports_static_input_index_b53fce.js | 4 +-- ...orts_subpath-imports_input_index_b53fce.js | 12 +++---- ...neration for chunk item errored-2613b6.txt | 14 ++++++++ ...de_protocol_external_input_index_b53fce.js | 12 +++---- ...rotocol_external_input_index_b53fce.js.map | 4 +-- ...efault_build_runtime_input_index_e254c5.js | 2 +- .../output/[turbopack]_runtime.js | 4 +++ .../output/[turbopack]_runtime.js.map | 2 +- ..._default_dev_runtime_input_index_b53fce.js | 2 +- ..._default_dev_runtime_input_index_e60ecd.js | 32 ++++++------------- ...ault_dev_runtime_input_index_e60ecd.js.map | 6 ++-- .../63a02_styled-components_index_a35c8c.js | 2 +- ...ts_styled_components_input_index_b53fce.js | 2 +- .../63a02_react_jsx-dev-runtime_7d1be7.js | 2 +- ...b7bf_third_party_component_index_8e9ad8.js | 2 +- ...s_input_packages_component_index_b0e6f8.js | 2 +- ...nsforms_input_packages_app_index_b53fce.js | 2 +- ...@swc_helpers____class_call_check_f08d44.js | 2 +- ...ransforms_preset_env_input_index_b53fce.js | 2 +- ...ipt_jsconfig-baseurl_input_index_b53fce.js | 4 +-- ...sconfig-baseurl_input_index_ts_b53fce._.js | 4 +-- .../63a02_tsconfig-mod_prop_ts_2aa573._.js | 2 +- ...odule-full-path_input_index_ts_b53fce._.js | 2 +- .../63a02_tsconfig-mod_prop_ts_ae3f0e._.js | 2 +- ...-extends-module_input_index_ts_b53fce._.js | 2 +- ...ds-relative-dir_input_index_ts_b53fce._.js | 4 +-- ...nds-without-ext_input_index_ts_b53fce._.js | 4 +-- ...sconfig-extends_input_index_ts_b53fce._.js | 4 +-- 67 files changed, 128 insertions(+), 130 deletions(-) create mode 100644 crates/turbopack-tests/tests/snapshot/node/node_protocol_external/issues/Code generation for chunk item errored-2613b6.txt diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_bar_index_c8a3ce.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_bar_index_c8a3ce.js index 052122280c48e..22e849970868a 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_bar_index_c8a3ce.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_bar_index_c8a3ce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/20803_bar_index_c8a3ce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/bar/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/bar/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "bar": ()=>bar diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_foo_index_5f9e1e.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_foo_index_5f9e1e.js index bd904abbff469..7152987e48c84 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_foo_index_5f9e1e.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/20803_foo_index_5f9e1e.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/20803_foo_index_5f9e1e.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "foo": ()=>foo diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js index 5dbe7de9fefde..9ef43f8f1186d 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__([ { diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js index 7564c6a4047da..c869f4e129627 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_a29514.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$async_chunk$2f$input$2f$node_modules$2f$foo$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/foo/index.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$async_chunk$2f$input$2f$node_modules$2f$bar$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/bar/index.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js index b31762f5e984d..e8bbbbfa05bc6 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__((__turbopack_import__) => { return Promise.all([{"path":"output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_571bb9.js","included":["[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/import.js (ecmascript, manifest chunk)"]},"output/crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_e0f91a.js"].map((chunk) => __turbopack_load__(chunk))).then(() => { @@ -13,11 +13,11 @@ __turbopack_export_value__((__turbopack_import__) => { }); })()), -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/shared.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/shared.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$async_chunk$2f$input$2f$node_modules$2f$bar$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/node_modules/bar/index.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$async_chunk$2f$input$2f$shared$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/async_chunk/input/shared.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/39e84_foo_index_4427e1.js b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/39e84_foo_index_4427e1.js index ab71ba8cbe64f..516543ba49207 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/39e84_foo_index_4427e1.js +++ b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/39e84_foo_index_4427e1.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/39e84_foo_index_4427e1.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "foo": ()=>foo diff --git a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js index c6483998cbffd..d2c18cd681634 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/basic/chunked/output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$chunked$2f$input$2f$node_modules$2f$foo$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/chunked/input/node_modules/foo/index.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js index c5752e6dde5e2..48e6263da0b0c 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$basic$2f$shebang$2f$input$2f$node_modules$2f$foo$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/node_modules/foo/index.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/d1787_foo_index_dd389c.js b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/d1787_foo_index_dd389c.js index 0a6ccdaeb21f8..b109f97bcc8b2 100644 --- a/crates/turbopack-tests/tests/snapshot/basic/shebang/output/d1787_foo_index_dd389c.js +++ b/crates/turbopack-tests/tests/snapshot/basic/shebang/output/d1787_foo_index_dd389c.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/d1787_foo_index_dd389c.js", { -"[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/basic/shebang/input/node_modules/foo/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "foo": ()=>foo diff --git a/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js index 556d6169fb21b..5f0dc8c6109de 100644 --- a/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { if ("TURBOPACK compile-time truthy", 1) { console.log('DEFINED_VALUE'); diff --git a/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js index 1acb0655144ff..a2b32e8d99fa1 100644 --- a/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_css_absolute-uri-import_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/css/absolute-uri-import/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { ; diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_css_7740ee._.js b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_css_7740ee._.js index b8ff62e899ead..d52b3f7612128 100644 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_css_7740ee._.js +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/8697f_foo_style_module_css_7740ee._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/8697f_foo_style_module_css_7740ee._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__({ "foo-module-style": "foo-module-style__style__abf9e738", diff --git a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js index 4e0eeab49dd84..d9bf8243d0038 100644 --- a/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/css/css/output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_css_css_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.module.css (css module)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.module.css (css module)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__({ "another-composed-module-style": "another-composed-module-style__style__9bcf751c" + " " + __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)")["foo-module-style"], @@ -10,7 +10,7 @@ __turbopack_export_value__({ }); })()), -"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/css/css/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$css$2f$css$2f$input$2f$node_modules$2f$foo$2f$style$2e$module$2e$css__$28$css__module$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/css/css/input/node_modules/foo/style.module.css (css module)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$css$2f$css$2f$input$2f$style$2e$module$2e$css__$28$css__module$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/css/css/input/style.module.css (css module)"); diff --git a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_index_a1c0c3.js b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_index_a1c0c3.js index b4b402485ab5b..29ff8c8d79078 100644 --- a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_index_a1c0c3.js +++ b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_index_a1c0c3.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_@emotion_react_index_a1c0c3.js", { -"[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "@emtion/react/index.js"; diff --git a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_jsx-dev-runtime_73b602.js b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_jsx-dev-runtime_73b602.js index fcc663afd65c8..cc32c288c4382 100644 --- a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_jsx-dev-runtime_73b602.js +++ b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_react_jsx-dev-runtime_73b602.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_@emotion_react_jsx-dev-runtime_73b602.js", { -"[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/jsx-dev-runtime.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/jsx-dev-runtime.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "@emtion/react/jsx-dev-runtime.js"; diff --git a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_styled_index_fd4de2.js b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_styled_index_fd4de2.js index 0bf03cd394310..11a9c7a09b941 100644 --- a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_styled_index_fd4de2.js +++ b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/63a02_@emotion_styled_index_fd4de2.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_@emotion_styled_index_fd4de2.js", { -"[project]/crates/turbopack-tests/tests/node_modules/@emotion/styled/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/@emotion/styled/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "@emtion/styled/index.js"; diff --git a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js index a6f054d974868..6fea75ce17e68 100644 --- a/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/emotion/emotion/output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_emotion_emotion_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/emotion/emotion/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/emotion/emotion/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f40$emotion$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/jsx-dev-runtime.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f40$emotion$2f$react$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/@emotion/react/index.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js index a073ed71afcf1..f9d5774e70e97 100644 --- a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_env_env_input__env__env_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/env/env/input/.env/.env.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/env/env/input/.env/.env.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const env = process.env = { ...process.env diff --git a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js index 268b4a68dcb46..b8e4eb4ee62c7 100644 --- a/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/env/env/output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_env_env_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/env/env/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/env/env/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { console.log(process.env.FOOBAR); diff --git a/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js index 525689736b00d..532438abe23c2 100644 --- a/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_evaluated_entrry_runtime_entry_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/evaluated_entrry/runtime_entry/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { console.log("hello world"); diff --git a/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js index c59446b32b5e4..7d1fae54cf410 100644 --- a/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/example/example/output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_example_example_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/example/example/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/example/example/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { console.log("hello world"); diff --git a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js index 3ee6384c2a39f..248841e26133d 100644 --- a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-2_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/commonjs.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/commonjs.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { exports.hello = "World"; }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/c.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/c.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({}); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$2$2f$input$2f$commonjs$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/commonjs.js (ecmascript)"); @@ -14,7 +14,7 @@ __turbopack_cjs__(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turb ; })()), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/b.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/b.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({}); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$2$2f$input$2f$c$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/c.js (ecmascript)"); @@ -23,7 +23,7 @@ __turbopack_cjs__(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turb ; })()), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$2$2f$input$2f$b$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-2/input/b.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js index 148378f6ec471..6d3bd128dda10 100644 --- a/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_export-alls_cjs-script_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/exported.cjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/exported.cjs (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { module.exports = { foo: 1, @@ -8,7 +8,7 @@ module.exports = { }; }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/mod.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/mod.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({}); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$script$2f$input$2f$exported$2e$cjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/exported.cjs (ecmascript)"); @@ -18,7 +18,7 @@ __turbopack_cjs__(__TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turb console.log('Hoist test'); })()), -"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$export$2d$alls$2f$cjs$2d$script$2f$input$2f$mod$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/export-alls/cjs-script/input/mod.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js index d8c26b474bc39..0ab1c61623db7 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/cjs/output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_cjs_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/mod.cjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/mod.cjs (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/mod.cjs" @@ -9,7 +9,7 @@ const __TURBOPACK__import$2e$meta__ = { console.log(__TURBOPACK__import$2e$meta__.url); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$cjs$2f$input$2f$mod$2e$cjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/cjs/input/mod.cjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js index c711a4b4fb664..afd15c47cc8ba 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_import-meta_esm-multiple_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/mod.mjs" @@ -16,7 +16,7 @@ foo(); bar(); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$esm$2d$multiple$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-multiple/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js index c2e00df40bf3b..a82359ac0121a 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_esm-mutable_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/mod.mjs" @@ -9,7 +9,7 @@ const __TURBOPACK__import$2e$meta__ = { __TURBOPACK__import$2e$meta__.foo = 1; }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$esm$2d$mutable$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-mutable/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js index 7718863a7760c..38140d281b02f 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_esm-object_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/mod.mjs" @@ -9,7 +9,7 @@ const __TURBOPACK__import$2e$meta__ = { console.log(__TURBOPACK__import$2e$meta__); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$esm$2d$object$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm-object/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js index 1ef0d068f75de..c7ec914df16db 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/esm/output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_esm_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/mod.mjs" @@ -9,7 +9,7 @@ const __TURBOPACK__import$2e$meta__ = { console.log(__TURBOPACK__import$2e$meta__.url); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$esm$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/esm/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js index e45d06c4a7f10..be44c8d3d2f7f 100644 --- a/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/import-meta/url/output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js @@ -1,10 +1,10 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_import-meta_url_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/asset.txt (static)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/asset.txt (static)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__("/crates/turbopack-tests/tests/snapshot/import-meta/url/static/asset.05254cf2.txt"); })()), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/mod.mjs (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const __TURBOPACK__import$2e$meta__ = { url: "file:///ROOT/crates/turbopack-tests/tests/snapshot/import-meta/url/input/mod.mjs" @@ -15,7 +15,7 @@ console.log(assetUrl); fetch(assetUrl).then((res)=>res.text()).then(console.log); }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$import$2d$meta$2f$url$2f$input$2f$mod$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/import-meta/url/input/mod.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js index 878240bfea8f8..0f56280e925bf 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__((__turbopack_import__) => { return Promise.all([{"path":"output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk)"]},"output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_36739f._.js"].map((chunk) => __turbopack_load__(chunk))).then(() => { @@ -13,7 +13,7 @@ __turbopack_export_value__((__turbopack_import__) => { }); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { __turbopack_require__("[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)")(__turbopack_import__).then(console.log); diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js index 40dc3612284e4..764de5faec7a5 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_4e74d3._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript, manifest chunk)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__([ { diff --git a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js index 292ed781234c7..eb859a1fb880f 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/dynamic/output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_dynamic_input_vercel_mjs_536504._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ diff --git a/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js index 39f0840fe9233..d95eee1e8894e 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js @@ -5,11 +5,11 @@ throw new Error("An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n\nCaused by:\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n- Execution of EcmascriptChunkItemContentVc::module_factory failed\n- Execution of JsonChunkItem::content failed\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n at nested.?\n 1 | {\n 2 | \"nested\": {\n | v\n 3 + \"this-is\": \"invalid\" // lint-staged will remove trailing commas, so here's a comment\n | ^\n 4 | }\n 5 | }"); }}), -"[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/package.json (json)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/package.json (json)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__(JSON.parse("{\"name\":\"json-snapshot\"}")); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$json$2f$input$2f$package$2e$json__$28$json$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/package.json (json)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$json$2f$input$2f$invalid$2e$json__$28$json$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)"); diff --git a/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js index 952ef49995225..83d397cfc2cd5 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/order/output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js @@ -1,10 +1,10 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_order_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.json (json)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.json (json)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__(JSON.parse("{\"js\":false}")); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -14,7 +14,7 @@ const __TURBOPACK__default__export__ = { }; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$order$2f$input$2f$posts$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/order/input/posts.ts (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js index 995f72f5bb3ef..df41cb55ae1bd 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_cjs_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_cjs/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { const dne = __turbopack_require__((()=>{ const e = new Error("Cannot find module 'does-not-exist/path'"); diff --git a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js index 9219f3a17146f..6d5542af105e4 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_imports_resolve_error_esm_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/resolve_error_esm/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { (()=>{ const e = new Error("Cannot find module 'does-not-exist/path'"); diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js index b77b2c4c7788b..aef687e9f75cd 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_imports_static-and-dynamic_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk, loader)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__((__turbopack_import__) => { return Promise.all([{"path":"output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js","included":["[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk)"]},"output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_84c275._.js"].map((chunk) => __turbopack_load__(chunk))).then(() => { @@ -13,7 +13,7 @@ __turbopack_export_value__((__turbopack_import__) => { }); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -21,7 +21,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "turbopack"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$static$2d$and$2d$dynamic$2f$input$2f$vercel$2e$mjs__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js index 8ca2a6dcfdc25..9a2cac05af651 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_10fe7a._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript, manifest chunk)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__([ { diff --git a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js index c3a0c69bbee44..b9638efff0628 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_imports_static-and-dynamic_input_vercel_mjs_26aaf6._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static-and-dynamic/input/vercel.mjs (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ diff --git a/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js index bfb4ecbd29871..318eeb576528a 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/static/output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js @@ -1,10 +1,10 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_static_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/vercel.svg (static)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/vercel.svg (static)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { __turbopack_export_value__("/crates/turbopack-tests/tests/snapshot/imports/static/static/vercel.957b9b16.svg"); })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$static$2f$input$2f$vercel$2e$svg__$28$static$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/static/input/vercel.svg (static)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js index b722dfcef59c8..2ac3c3d1f1e8b 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js @@ -1,11 +1,11 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_imports_subpath-imports_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/require.cjs (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/require.cjs (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { module.exports = "require"; }.call(this) }), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/import.mjs (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/import.mjs (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -13,7 +13,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "import"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/pat.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/pat.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -21,7 +21,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "pat"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/dep/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/dep/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -29,7 +29,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "dep"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/foo.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/foo.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>__TURBOPACK__default__export__ @@ -37,7 +37,7 @@ __turbopack_esm__({ const __TURBOPACK__default__export__ = "foo"; })()), -"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$subpath$2d$imports$2f$input$2f$foo$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/foo.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$imports$2f$subpath$2d$imports$2f$input$2f$dep$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/imports/subpath-imports/input/dep/index.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/issues/Code generation for chunk item errored-2613b6.txt b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/issues/Code generation for chunk item errored-2613b6.txt new file mode 100644 index 0000000000000..cd84cfdf89290 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/issues/Code generation for chunk item errored-2613b6.txt @@ -0,0 +1,14 @@ +PlainIssue { + severity: Error, + context: "[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js", + category: "code generation", + title: "Code generation for chunk item errored", + description: "An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)\n\nCaused by:\n- the chunking context does not support Node.js external modules\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)\n- Execution of EcmascriptChunkItemContentVc::module_factory failed\n- Execution of EcmascriptChunkItemContentVc::new failed\n- Execution of EcmascriptModuleContentVc::new failed\n- Execution of EsmAssetReference::code_generation failed\n- the chunking context does not support Node.js external modules", + detail: "", + documentation_link: "", + source: None, + sub_issues: [], + processing_path: Some( + [], + ), +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js index 8b0fc5e0ac737..c0959d7cf4daa 100644 --- a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js @@ -1,12 +1,8 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)": (() => {{ -var __TURBOPACK__external__node$3a$fs__ = __turbopack_external_require__("node:fs", true); -"__TURBOPACK__ecmascript__hoisting__location__"; -; +throw new Error("An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)\n\nCaused by:\n- the chunking context does not support Node.js external modules\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)\n- Execution of EcmascriptChunkItemContentVc::module_factory failed\n- Execution of EcmascriptChunkItemContentVc::new failed\n- Execution of EcmascriptModuleContentVc::new failed\n- Execution of EsmAssetReference::code_generation failed\n- the chunking context does not support Node.js external modules"); -})()), -}]); - -//# sourceMappingURL=79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map \ No newline at end of file +}}), +}]); \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map index e998c77728e14..a12b83d3337ca 100644 --- a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map +++ b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map @@ -1,6 +1,4 @@ { "version": 3, - "sections": [ - {"offset": {"line": 4, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":""}}, - {"offset": {"line": 7, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":"A"}}] + "sections": [] } \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js index 0c44b4c604322..3ed57e11cf57b 100644 --- a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js @@ -1,6 +1,6 @@ module.exports = { -"[project]/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, m: module, e: exports }) { !function() { console.log("Hello, world!"); diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js index 7646baa8198f9..3e7bcd672f5e7 100644 --- a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js @@ -106,11 +106,15 @@ var SourceType; SourceType[SourceType["Parent"] = 1] = "Parent"; })(SourceType || (SourceType = {})); ; +; const path = require("path"); const relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, "."); const RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot); const moduleFactories = Object.create(null); const moduleCache = Object.create(null); +function commonJsRequireContext(entry, sourceModule) { + return entry.external ? externalRequire(entry.id(), false) : commonJsRequire(sourceModule, entry.id()); +} function externalRequire(id, esm1 = false) { let raw; try { diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map index ebdd331e4aa9e..7f5d7b10a38b6 100644 --- a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/[turbopack]_runtime.js.map @@ -2,5 +2,5 @@ "version": 3, "sections": [ {"offset": {"line": 1, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/shared/runtime-utils.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * TurboPack ECMAScript runtimes.\n *\n * It will be prepended to the runtime code of each runtime.\n */\n\n/* eslint-disable @next/next/no-assign-module-variable */\n\n/// \n\ninterface Exports {\n __esModule?: boolean;\n\n [key: string]: any;\n}\ntype EsmNamespaceObject = Record;\n\ninterface BaseModule {\n exports: Exports;\n error: Error | undefined;\n loaded: boolean;\n id: ModuleId;\n children: ModuleId[];\n parents: ModuleId[];\n namespaceObject?: EsmNamespaceObject;\n}\n\ninterface Module extends BaseModule {}\n\ntype RequireContextMap = Record;\n\ninterface RequireContextEntry {\n id: () => ModuleId;\n}\n\ninterface RequireContext {\n (moduleId: ModuleId): Exports | EsmNamespaceObject;\n keys(): ModuleId[];\n resolve(moduleId: ModuleId): ModuleId;\n}\n\ntype GetOrInstantiateModuleFromParent = (\n moduleId: ModuleId,\n parentModule: Module\n) => Module;\n\ntype CommonJsRequireContext = (\n entry: RequireContextEntry,\n parentModule: Module\n) => Exports;\n\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst toStringTag = typeof Symbol !== \"undefined\" && Symbol.toStringTag;\n\nfunction defineProp(\n obj: any,\n name: PropertyKey,\n options: PropertyDescriptor & ThisType\n) {\n if (!hasOwnProperty.call(obj, name))\n Object.defineProperty(obj, name, options);\n}\n\n/**\n * Adds the getters to the exports object.\n */\nfunction esm(exports: Exports, getters: Record any>) {\n defineProp(exports, \"__esModule\", { value: true });\n if (toStringTag) defineProp(exports, toStringTag, { value: \"Module\" });\n for (const key in getters) {\n defineProp(exports, key, { get: getters[key], enumerable: true });\n }\n}\n\n/**\n * Makes the module an ESM with exports\n */\nfunction esmExport(module: Module, getters: Record any>) {\n esm((module.namespaceObject = module.exports), getters);\n}\n\n/**\n * Adds the props to the exports object\n */\nfunction cjsExport(exports: Exports, props: Record) {\n for (const key in props) {\n defineProp(exports, key, { get: () => props[key], enumerable: true });\n }\n}\n\nfunction exportValue(module: Module, value: any) {\n module.exports = value;\n}\n\nfunction exportNamespace(module: Module, namespace: any) {\n module.exports = module.namespaceObject = namespace;\n}\n\nfunction createGetter(obj: Record, key: string) {\n return () => obj[key];\n}\n\n/**\n * @returns prototype of the object\n */\nconst getProto: (obj: any) => any = Object.getPrototypeOf\n ? (obj) => Object.getPrototypeOf(obj)\n : (obj) => obj.__proto__;\n\n/** Prototypes that are not expanded for exports */\nconst LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];\n\n/**\n * @param allowExportDefault\n * * `false`: will have the raw module as default export\n * * `true`: will have the default property as default export\n */\nfunction interopEsm(\n raw: Exports,\n ns: EsmNamespaceObject,\n allowExportDefault?: boolean\n) {\n const getters: { [s: string]: () => any } = Object.create(null);\n for (\n let current = raw;\n (typeof current === \"object\" || typeof current === \"function\") &&\n !LEAF_PROTOTYPES.includes(current);\n current = getProto(current)\n ) {\n for (const key of Object.getOwnPropertyNames(current)) {\n getters[key] = createGetter(raw, key);\n }\n }\n if (!(allowExportDefault && \"default\" in getters)) {\n getters[\"default\"] = () => raw;\n }\n esm(ns, getters);\n}\n\nfunction esmImport(sourceModule: Module, id: ModuleId): EsmNamespaceObject {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n if (module.namespaceObject) return module.namespaceObject;\n const raw = module.exports;\n const ns = (module.namespaceObject = {});\n interopEsm(raw, ns, raw.__esModule);\n return ns;\n}\n\nfunction commonJsRequire(sourceModule: Module, id: ModuleId): Exports {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n return module.exports;\n}\n\ntype RequireContextFactory = (map: RequireContextMap) => RequireContext;\n\nfunction requireContext(\n sourceModule: Module,\n map: RequireContextMap\n): RequireContext {\n function requireContext(id: ModuleId): Exports {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is required from a require.context, but is not in the context`\n );\n }\n\n return commonJsRequireContext(entry, sourceModule);\n }\n\n requireContext.keys = (): ModuleId[] => {\n return Object.keys(map);\n };\n\n requireContext.resolve = (id: ModuleId): ModuleId => {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is resolved from a require.context, but is not in the context`\n );\n }\n\n return entry.id();\n };\n\n return requireContext;\n}\n\n/**\n * Returns the path of a chunk defined by its data.\n */\nfunction getChunkPath(chunkData: ChunkData): ChunkPath {\n return typeof chunkData === \"string\" ? chunkData : chunkData.path;\n}\n"],"names":[],"mappings":";;;;;AAoDA,MAAM,iBAAiB,OAAO,UAAU;AACxC,MAAM,cAAc,OAAO,WAAW,eAAe,OAAO;AAE5D,SAAS,WACP,GAAQ,EACR,IAAiB,EACjB,OAA2C;IAE3C,IAAI,CAAC,eAAe,KAAK,KAAK,OAC5B,OAAO,eAAe,KAAK,MAAM;AACrC;AAKA,SAAS,IAAI,OAAgB,EAAE,OAAkC;IAC/D,WAAW,SAAS,cAAc;QAAE,OAAO;IAAK;IAChD,IAAI,aAAa,WAAW,SAAS,aAAa;QAAE,OAAO;IAAS;IACpE,IAAK,MAAM,OAAO,QAAS;QACzB,WAAW,SAAS,KAAK;YAAE,KAAK,OAAO,CAAC,IAAI;YAAE,YAAY;QAAK;IACjE;AACF;AAKA,SAAS,UAAU,MAAc,EAAE,OAAkC;IACnE,IAAK,OAAO,kBAAkB,OAAO,SAAU;AACjD;AAKA,SAAS,UAAU,OAAgB,EAAE,KAA0B;IAC7D,IAAK,MAAM,OAAO,MAAO;QACvB,WAAW,SAAS,KAAK;YAAE,KAAK,IAAM,KAAK,CAAC,IAAI;YAAE,YAAY;QAAK;IACrE;AACF;AAEA,SAAS,YAAY,MAAc,EAAE,KAAU;IAC7C,OAAO,UAAU;AACnB;AAEA,SAAS,gBAAgB,MAAc,EAAE,SAAc;IACrD,OAAO,UAAU,OAAO,kBAAkB;AAC5C;AAEA,SAAS,aAAa,GAAwB,EAAE,GAAW;IACzD,OAAO,IAAM,GAAG,CAAC,IAAI;AACvB;AAKA,MAAM,WAA8B,OAAO,iBACvC,CAAC,MAAQ,OAAO,eAAe,OAC/B,CAAC,MAAQ,IAAI;AAGjB,MAAM,kBAAkB;IAAC;IAAM,SAAS,CAAC;IAAI,SAAS,EAAE;IAAG,SAAS;CAAU;AAO9E,SAAS,WACP,GAAY,EACZ,EAAsB,EACtB,kBAA4B;IAE5B,MAAM,UAAsC,OAAO,OAAO;IAC1D,IACE,IAAI,UAAU,KACd,CAAC,OAAO,YAAY,YAAY,OAAO,YAAY,UAAU,KAC7D,CAAC,gBAAgB,SAAS,UAC1B,UAAU,SAAS,SACnB;QACA,KAAK,MAAM,OAAO,OAAO,oBAAoB,SAAU;YACrD,OAAO,CAAC,IAAI,GAAG,aAAa,KAAK;QACnC;IACF;IACA,IAAI,CAAC,CAAC,sBAAsB,aAAa,OAAO,GAAG;QACjD,OAAO,CAAC,UAAU,GAAG,IAAM;IAC7B;IACA,IAAI,IAAI;AACV;AAEA,SAAS,UAAU,YAAoB,EAAE,EAAY;IACnD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,IAAI,OAAO,iBAAiB,OAAO,OAAO;IAC1C,MAAM,MAAM,OAAO;IACnB,MAAM,KAAM,OAAO,kBAAkB,CAAC;IACtC,WAAW,KAAK,IAAI,IAAI;IACxB,OAAO;AACT;AAEA,SAAS,gBAAgB,YAAoB,EAAE,EAAY;IACzD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,OAAO,OAAO;AAChB;AAIA,SAAS,eACP,YAAoB,EACpB,GAAsB;IAEtB,SAAS,eAAe,EAAY;QAClC,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,uBAAuB,OAAO;IACvC;IAEA,eAAe,OAAO;QACpB,OAAO,OAAO,KAAK;IACrB;IAEA,eAAe,UAAU,CAAC;QACxB,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,MAAM;IACf;IAEA,OAAO;AACT;AAKA,SAAS,aAAa,SAAoB;IACxC,OAAO,OAAO,cAAc,WAAW,YAAY,UAAU;AAC/D"}}, - {"offset": {"line": 101, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/build/runtime.ts"],"sourcesContent":["/// \n\ndeclare var RUNTIME_PUBLIC_PATH: string;\n\nenum SourceType {\n /**\n * The module was instantiated because it was included in an evaluated chunk's\n * runtime.\n */\n Runtime = 0,\n /**\n * The module was instantiated because a parent module imported it.\n */\n Parent = 1,\n}\n\ntype SourceInfo =\n | {\n type: SourceType.Runtime;\n chunkPath: ChunkPath;\n }\n | {\n type: SourceType.Parent;\n parentId: ModuleId;\n };\n\ninterface TurbopackNodeBuildContext {\n e: Module[\"exports\"];\n r: CommonJsRequire;\n x: ExternalRequire;\n f: RequireContextFactory;\n i: EsmImport;\n s: EsmExport;\n j: typeof cjsExport;\n v: ExportValue;\n n: typeof exportNamespace;\n m: Module;\n c: ModuleCache;\n l: LoadChunk;\n g: typeof globalThis;\n __dirname: string;\n}\n\ntype ModuleFactory = (\n this: Module[\"exports\"],\n context: TurbopackNodeBuildContext\n) => undefined;\n\nconst path = require(\"path\");\nconst relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, \".\");\nconst RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot);\n\nconst moduleFactories: ModuleFactories = Object.create(null);\nconst moduleCache: ModuleCache = Object.create(null);\n\nfunction externalRequire(\n id: ModuleId,\n esm: boolean = false\n): Exports | EsmNamespaceObject {\n let raw;\n try {\n raw = require(id);\n } catch (err) {\n // TODO(alexkirsz) This can happen when a client-side module tries to load\n // an external module we don't provide a shim for (e.g. querystring, url).\n // For now, we fail semi-silently, but in the future this should be a\n // compilation error.\n throw new Error(`Failed to load external module ${id}: ${err}`);\n }\n if (!esm || raw.__esModule) {\n return raw;\n }\n const ns = {};\n interopEsm(raw, ns, true);\n return ns;\n}\nexternalRequire.resolve = (\n id: string,\n options?:\n | {\n paths?: string[] | undefined;\n }\n | undefined\n) => {\n return require.resolve(id, options);\n};\n\nfunction loadChunk(chunkPath: ChunkPath) {\n if (!chunkPath.endsWith(\".js\")) {\n // We only support loading JS chunks in Node.js.\n // This branch can be hit when trying to load a CSS chunk.\n return;\n }\n\n const resolved = require.resolve(path.resolve(RUNTIME_ROOT, chunkPath));\n delete require.cache[resolved];\n const chunkModules: ModuleFactories = require(resolved);\n\n for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) {\n if (!moduleFactories[moduleId]) {\n moduleFactories[moduleId] = moduleFactory;\n }\n }\n}\n\nfunction loadChunkAsync(source: SourceInfo, chunkPath: string): Promise {\n return new Promise((resolve, reject) => {\n try {\n loadChunk(chunkPath);\n } catch (err) {\n reject(err);\n return;\n }\n resolve();\n });\n}\n\nfunction instantiateModule(id: ModuleId, source: SourceInfo): Module {\n const moduleFactory = moduleFactories[id];\n if (typeof moduleFactory !== \"function\") {\n // This can happen if modules incorrectly handle HMR disposes/updates,\n // e.g. when they keep a `setTimeout` around which still executes old code\n // and contains e.g. a `require(\"something\")` call.\n let instantiationReason;\n switch (source.type) {\n case SourceType.Runtime:\n instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n instantiationReason = `because it was required from module ${source.parentId}`;\n break;\n }\n throw new Error(\n `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`\n );\n }\n\n let parents: ModuleId[];\n switch (source.type) {\n case SourceType.Runtime:\n parents = [];\n break;\n case SourceType.Parent:\n // No need to add this module as a child of the parent module here, this\n // has already been taken care of in `getOrInstantiateModuleFromParent`.\n parents = [source.parentId];\n break;\n }\n\n const module: Module = {\n exports: {},\n error: undefined,\n loaded: false,\n id,\n parents,\n children: [],\n namespaceObject: undefined,\n };\n moduleCache[id] = module;\n\n // NOTE(alexkirsz) This can fail when the module encounters a runtime error.\n try {\n moduleFactory.call(module.exports, {\n e: module.exports,\n r: commonJsRequire.bind(null, module),\n x: externalRequire,\n f: requireContext.bind(null, module),\n i: esmImport.bind(null, module),\n s: esm.bind(null, module.exports),\n j: cjsExport.bind(null, module.exports),\n v: exportValue.bind(null, module),\n n: exportNamespace.bind(null, module),\n m: module,\n c: moduleCache,\n l: loadChunkAsync.bind(null, { type: SourceType.Parent, parentId: id }),\n g: globalThis,\n __dirname: module.id.replace(/(^|\\/)[\\/]+$/, \"\"),\n });\n } catch (error) {\n module.error = error as any;\n throw error;\n }\n\n module.loaded = true;\n if (module.namespaceObject) {\n // in case of a circular dependency: cjs1 -> esm2 -> cjs1\n interopEsm(module.exports, module.namespaceObject);\n }\n\n return module;\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it if it is not cached.\n */\nfunction getOrInstantiateModuleFromParent(\n id: ModuleId,\n sourceModule: Module\n): Module {\n const module = moduleCache[id];\n\n if (sourceModule.children.indexOf(id) === -1) {\n sourceModule.children.push(id);\n }\n\n if (module) {\n if (module.parents.indexOf(sourceModule.id) === -1) {\n module.parents.push(sourceModule.id);\n }\n\n return module;\n }\n\n return instantiateModule(id, {\n type: SourceType.Parent,\n parentId: sourceModule.id,\n });\n}\n\n/**\n * Instantiates a runtime module.\n */\nfunction instantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it as a runtime module if it is not cached.\n */\nfunction getOrInstantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n const module = moduleCache[moduleId];\n if (module) {\n if (module.error) {\n throw module.error;\n }\n return module;\n }\n\n return instantiateRuntimeModule(moduleId, chunkPath);\n}\n\nmodule.exports = {\n getOrInstantiateRuntimeModule,\n loadChunk,\n};\n"],"names":[],"mappings":";IAIA;UAAK,UAAU;IAAV,WAAA,WAKH,aAAU,KAAV;IALG,WAAA,WASH,YAAS,KAAT;GATG,eAAA;;AA4CL,MAAM,OAAO,QAAQ;AACrB,MAAM,4BAA4B,KAAK,SAAS,qBAAqB;AACrE,MAAM,eAAe,KAAK,QAAQ,YAAY;AAE9C,MAAM,kBAAmC,OAAO,OAAO;AACvD,MAAM,cAA2B,OAAO,OAAO;AAE/C,SAAS,gBACP,EAAY,EACZ,OAAe,KAAK;IAEpB,IAAI;IACJ,IAAI;QACF,MAAM,QAAQ;IAChB,EAAE,OAAO,KAAK;QAKZ,MAAM,IAAI,MAAM,CAAC,+BAA+B,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC;IAChE;IACA,IAAI,CAAC,QAAO,IAAI,YAAY;QAC1B,OAAO;IACT;IACA,MAAM,KAAK,CAAC;IACZ,WAAW,KAAK,IAAI;IACpB,OAAO;AACT;AACA,gBAAgB,UAAU,CACxB,IACA;IAMA,OAAO,QAAQ,QAAQ,IAAI;AAC7B;AAEA,SAAS,UAAU,SAAoB;IACrC,IAAI,CAAC,UAAU,SAAS,QAAQ;QAG9B;IACF;IAEA,MAAM,WAAW,QAAQ,QAAQ,KAAK,QAAQ,cAAc;IAC5D,OAAO,QAAQ,KAAK,CAAC,SAAS;IAC9B,MAAM,eAAgC,QAAQ;IAE9C,KAAK,MAAM,CAAC,UAAU,cAAc,IAAI,OAAO,QAAQ,cAAe;QACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9B,eAAe,CAAC,SAAS,GAAG;QAC9B;IACF;AACF;AAEA,SAAS,eAAe,MAAkB,EAAE,SAAiB;IAC3D,OAAO,IAAI,QAAc,CAAC,SAAS;QACjC,IAAI;YACF,UAAU;QACZ,EAAE,OAAO,KAAK;YACZ,OAAO;YACP;QACF;QACA;IACF;AACF;AAEA,SAAS,kBAAkB,EAAY,EAAE,MAAkB;IACzD,MAAM,gBAAgB,eAAe,CAAC,GAAG;IACzC,IAAI,OAAO,kBAAkB,YAAY;QAIvC,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,sBAAsB,CAAC,4BAA4B,EAAE,OAAO,UAAU,CAAC;gBACvE;YACF,KAAK,WAAW;gBACd,sBAAsB,CAAC,oCAAoC,EAAE,OAAO,SAAS,CAAC;gBAC9E;QACJ;QACA,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,oBAAoB,uFAAuF,CAAC;IAEjJ;IAEA,IAAI;IACJ,OAAQ,OAAO;QACb,KAAK,WAAW;YACd,UAAU,EAAE;YACZ;QACF,KAAK,WAAW;YAGd,UAAU;gBAAC,OAAO;aAAS;YAC3B;IACJ;IAEA,MAAM,UAAiB;QACrB,SAAS,CAAC;QACV,OAAO;QACP,QAAQ;QACR;QACA;QACA,UAAU,EAAE;QACZ,iBAAiB;IACnB;IACA,WAAW,CAAC,GAAG,GAAG;IAGlB,IAAI;QACF,cAAc,KAAK,QAAO,SAAS;YACjC,GAAG,QAAO;YACV,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;YAC7B,GAAG,UAAU,KAAK,MAAM;YACxB,GAAG,IAAI,KAAK,MAAM,QAAO;YACzB,GAAG,UAAU,KAAK,MAAM,QAAO;YAC/B,GAAG,YAAY,KAAK,MAAM;YAC1B,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;gBAAE,MAAM,WAAW;gBAAQ,UAAU;YAAG;YACrE,GAAG;YACH,WAAW,QAAO,GAAG,QAAQ,gBAAgB;QAC/C;IACF,EAAE,OAAO,OAAO;QACd,QAAO,QAAQ;QACf,MAAM;IACR;IAEA,QAAO,SAAS;IAChB,IAAI,QAAO,iBAAiB;QAE1B,WAAW,QAAO,SAAS,QAAO;IACpC;IAEA,OAAO;AACT;AAKA,SAAS,iCACP,EAAY,EACZ,YAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,GAAG;IAE9B,IAAI,aAAa,SAAS,QAAQ,QAAQ,CAAC,GAAG;QAC5C,aAAa,SAAS,KAAK;IAC7B;IAEA,IAAI,SAAQ;QACV,IAAI,QAAO,QAAQ,QAAQ,aAAa,QAAQ,CAAC,GAAG;YAClD,QAAO,QAAQ,KAAK,aAAa;QACnC;QAEA,OAAO;IACT;IAEA,OAAO,kBAAkB,IAAI;QAC3B,MAAM,WAAW;QACjB,UAAU,aAAa;IACzB;AACF;AAKA,SAAS,yBACP,QAAkB,EAClB,SAAoB;IAEpB,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,8BACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,SAAS;IACpC,IAAI,SAAQ;QACV,IAAI,QAAO,OAAO;YAChB,MAAM,QAAO;QACf;QACA,OAAO;IACT;IAEA,OAAO,yBAAyB,UAAU;AAC5C;AAEA,OAAO,UAAU;IACf;IACA;AACF"}}] + {"offset": {"line": 101, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/build/runtime.ts"],"sourcesContent":["/// \n\ndeclare var RUNTIME_PUBLIC_PATH: string;\n\nenum SourceType {\n /**\n * The module was instantiated because it was included in an evaluated chunk's\n * runtime.\n */\n Runtime = 0,\n /**\n * The module was instantiated because a parent module imported it.\n */\n Parent = 1,\n}\n\ntype SourceInfo =\n | {\n type: SourceType.Runtime;\n chunkPath: ChunkPath;\n }\n | {\n type: SourceType.Parent;\n parentId: ModuleId;\n };\n\ninterface RequireContextEntry {\n external: boolean;\n}\n\ntype ExternalRequire = (id: ModuleId) => Exports | EsmNamespaceObject;\n\ninterface TurbopackNodeBuildContext {\n e: Module[\"exports\"];\n r: CommonJsRequire;\n x: ExternalRequire;\n f: RequireContextFactory;\n i: EsmImport;\n s: EsmExport;\n j: typeof cjsExport;\n v: ExportValue;\n n: typeof exportNamespace;\n m: Module;\n c: ModuleCache;\n l: LoadChunk;\n g: typeof globalThis;\n __dirname: string;\n}\n\ntype ModuleFactory = (\n this: Module[\"exports\"],\n context: TurbopackNodeBuildContext\n) => undefined;\n\nconst path = require(\"path\");\nconst relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, \".\");\nconst RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot);\n\nconst moduleFactories: ModuleFactories = Object.create(null);\nconst moduleCache: ModuleCache = Object.create(null);\n\nfunction commonJsRequireContext(\n entry: RequireContextEntry,\n sourceModule: Module\n): Exports {\n return entry.external\n ? externalRequire(entry.id(), false)\n : commonJsRequire(sourceModule, entry.id());\n}\n\nfunction externalRequire(\n id: ModuleId,\n esm: boolean = false\n): Exports | EsmNamespaceObject {\n let raw;\n try {\n raw = require(id);\n } catch (err) {\n // TODO(alexkirsz) This can happen when a client-side module tries to load\n // an external module we don't provide a shim for (e.g. querystring, url).\n // For now, we fail semi-silently, but in the future this should be a\n // compilation error.\n throw new Error(`Failed to load external module ${id}: ${err}`);\n }\n if (!esm || raw.__esModule) {\n return raw;\n }\n const ns = {};\n interopEsm(raw, ns, true);\n return ns;\n}\nexternalRequire.resolve = (\n id: string,\n options?:\n | {\n paths?: string[] | undefined;\n }\n | undefined\n) => {\n return require.resolve(id, options);\n};\n\nfunction loadChunk(chunkPath: ChunkPath) {\n if (!chunkPath.endsWith(\".js\")) {\n // We only support loading JS chunks in Node.js.\n // This branch can be hit when trying to load a CSS chunk.\n return;\n }\n\n const resolved = require.resolve(path.resolve(RUNTIME_ROOT, chunkPath));\n delete require.cache[resolved];\n const chunkModules: ModuleFactories = require(resolved);\n\n for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) {\n if (!moduleFactories[moduleId]) {\n moduleFactories[moduleId] = moduleFactory;\n }\n }\n}\n\nfunction loadChunkAsync(source: SourceInfo, chunkPath: string): Promise {\n return new Promise((resolve, reject) => {\n try {\n loadChunk(chunkPath);\n } catch (err) {\n reject(err);\n return;\n }\n resolve();\n });\n}\n\nfunction instantiateModule(id: ModuleId, source: SourceInfo): Module {\n const moduleFactory = moduleFactories[id];\n if (typeof moduleFactory !== \"function\") {\n // This can happen if modules incorrectly handle HMR disposes/updates,\n // e.g. when they keep a `setTimeout` around which still executes old code\n // and contains e.g. a `require(\"something\")` call.\n let instantiationReason;\n switch (source.type) {\n case SourceType.Runtime:\n instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n instantiationReason = `because it was required from module ${source.parentId}`;\n break;\n }\n throw new Error(\n `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`\n );\n }\n\n let parents: ModuleId[];\n switch (source.type) {\n case SourceType.Runtime:\n parents = [];\n break;\n case SourceType.Parent:\n // No need to add this module as a child of the parent module here, this\n // has already been taken care of in `getOrInstantiateModuleFromParent`.\n parents = [source.parentId];\n break;\n }\n\n const module: Module = {\n exports: {},\n error: undefined,\n loaded: false,\n id,\n parents,\n children: [],\n namespaceObject: undefined,\n };\n moduleCache[id] = module;\n\n // NOTE(alexkirsz) This can fail when the module encounters a runtime error.\n try {\n moduleFactory.call(module.exports, {\n e: module.exports,\n r: commonJsRequire.bind(null, module),\n x: externalRequire,\n f: requireContext.bind(null, module),\n i: esmImport.bind(null, module),\n s: esm.bind(null, module.exports),\n j: cjsExport.bind(null, module.exports),\n v: exportValue.bind(null, module),\n n: exportNamespace.bind(null, module),\n m: module,\n c: moduleCache,\n l: loadChunkAsync.bind(null, { type: SourceType.Parent, parentId: id }),\n g: globalThis,\n __dirname: module.id.replace(/(^|\\/)[\\/]+$/, \"\"),\n });\n } catch (error) {\n module.error = error as any;\n throw error;\n }\n\n module.loaded = true;\n if (module.namespaceObject) {\n // in case of a circular dependency: cjs1 -> esm2 -> cjs1\n interopEsm(module.exports, module.namespaceObject);\n }\n\n return module;\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it if it is not cached.\n */\nfunction getOrInstantiateModuleFromParent(\n id: ModuleId,\n sourceModule: Module\n): Module {\n const module = moduleCache[id];\n\n if (sourceModule.children.indexOf(id) === -1) {\n sourceModule.children.push(id);\n }\n\n if (module) {\n if (module.parents.indexOf(sourceModule.id) === -1) {\n module.parents.push(sourceModule.id);\n }\n\n return module;\n }\n\n return instantiateModule(id, {\n type: SourceType.Parent,\n parentId: sourceModule.id,\n });\n}\n\n/**\n * Instantiates a runtime module.\n */\nfunction instantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it as a runtime module if it is not cached.\n */\nfunction getOrInstantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n const module = moduleCache[moduleId];\n if (module) {\n if (module.error) {\n throw module.error;\n }\n return module;\n }\n\n return instantiateRuntimeModule(moduleId, chunkPath);\n}\n\nmodule.exports = {\n getOrInstantiateRuntimeModule,\n loadChunk,\n};\n"],"names":[],"mappings":";IAIA;UAAK,UAAU;IAAV,WAAA,WAKH,aAAU,KAAV;IALG,WAAA,WASH,YAAS,KAAT;GATG,eAAA;;;AAkDL,MAAM,OAAO,QAAQ;AACrB,MAAM,4BAA4B,KAAK,SAAS,qBAAqB;AACrE,MAAM,eAAe,KAAK,QAAQ,YAAY;AAE9C,MAAM,kBAAmC,OAAO,OAAO;AACvD,MAAM,cAA2B,OAAO,OAAO;AAE/C,SAAS,uBACP,KAA0B,EAC1B,YAAoB;IAEpB,OAAO,MAAM,WACT,gBAAgB,MAAM,MAAM,SAC5B,gBAAgB,cAAc,MAAM;AAC1C;AAEA,SAAS,gBACP,EAAY,EACZ,OAAe,KAAK;IAEpB,IAAI;IACJ,IAAI;QACF,MAAM,QAAQ;IAChB,EAAE,OAAO,KAAK;QAKZ,MAAM,IAAI,MAAM,CAAC,+BAA+B,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC;IAChE;IACA,IAAI,CAAC,QAAO,IAAI,YAAY;QAC1B,OAAO;IACT;IACA,MAAM,KAAK,CAAC;IACZ,WAAW,KAAK,IAAI;IACpB,OAAO;AACT;AACA,gBAAgB,UAAU,CACxB,IACA;IAMA,OAAO,QAAQ,QAAQ,IAAI;AAC7B;AAEA,SAAS,UAAU,SAAoB;IACrC,IAAI,CAAC,UAAU,SAAS,QAAQ;QAG9B;IACF;IAEA,MAAM,WAAW,QAAQ,QAAQ,KAAK,QAAQ,cAAc;IAC5D,OAAO,QAAQ,KAAK,CAAC,SAAS;IAC9B,MAAM,eAAgC,QAAQ;IAE9C,KAAK,MAAM,CAAC,UAAU,cAAc,IAAI,OAAO,QAAQ,cAAe;QACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9B,eAAe,CAAC,SAAS,GAAG;QAC9B;IACF;AACF;AAEA,SAAS,eAAe,MAAkB,EAAE,SAAiB;IAC3D,OAAO,IAAI,QAAc,CAAC,SAAS;QACjC,IAAI;YACF,UAAU;QACZ,EAAE,OAAO,KAAK;YACZ,OAAO;YACP;QACF;QACA;IACF;AACF;AAEA,SAAS,kBAAkB,EAAY,EAAE,MAAkB;IACzD,MAAM,gBAAgB,eAAe,CAAC,GAAG;IACzC,IAAI,OAAO,kBAAkB,YAAY;QAIvC,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,sBAAsB,CAAC,4BAA4B,EAAE,OAAO,UAAU,CAAC;gBACvE;YACF,KAAK,WAAW;gBACd,sBAAsB,CAAC,oCAAoC,EAAE,OAAO,SAAS,CAAC;gBAC9E;QACJ;QACA,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,oBAAoB,uFAAuF,CAAC;IAEjJ;IAEA,IAAI;IACJ,OAAQ,OAAO;QACb,KAAK,WAAW;YACd,UAAU,EAAE;YACZ;QACF,KAAK,WAAW;YAGd,UAAU;gBAAC,OAAO;aAAS;YAC3B;IACJ;IAEA,MAAM,UAAiB;QACrB,SAAS,CAAC;QACV,OAAO;QACP,QAAQ;QACR;QACA;QACA,UAAU,EAAE;QACZ,iBAAiB;IACnB;IACA,WAAW,CAAC,GAAG,GAAG;IAGlB,IAAI;QACF,cAAc,KAAK,QAAO,SAAS;YACjC,GAAG,QAAO;YACV,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;YAC7B,GAAG,UAAU,KAAK,MAAM;YACxB,GAAG,IAAI,KAAK,MAAM,QAAO;YACzB,GAAG,UAAU,KAAK,MAAM,QAAO;YAC/B,GAAG,YAAY,KAAK,MAAM;YAC1B,GAAG,gBAAgB,KAAK,MAAM;YAC9B,GAAG;YACH,GAAG;YACH,GAAG,eAAe,KAAK,MAAM;gBAAE,MAAM,WAAW;gBAAQ,UAAU;YAAG;YACrE,GAAG;YACH,WAAW,QAAO,GAAG,QAAQ,gBAAgB;QAC/C;IACF,EAAE,OAAO,OAAO;QACd,QAAO,QAAQ;QACf,MAAM;IACR;IAEA,QAAO,SAAS;IAChB,IAAI,QAAO,iBAAiB;QAE1B,WAAW,QAAO,SAAS,QAAO;IACpC;IAEA,OAAO;AACT;AAKA,SAAS,iCACP,EAAY,EACZ,YAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,GAAG;IAE9B,IAAI,aAAa,SAAS,QAAQ,QAAQ,CAAC,GAAG;QAC5C,aAAa,SAAS,KAAK;IAC7B;IAEA,IAAI,SAAQ;QACV,IAAI,QAAO,QAAQ,QAAQ,aAAa,QAAQ,CAAC,GAAG;YAClD,QAAO,QAAQ,KAAK,aAAa;QACnC;QAEA,OAAO;IACT;IAEA,OAAO,kBAAkB,IAAI;QAC3B,MAAM,WAAW;QACjB,UAAU,aAAa;IACzB;AACF;AAKA,SAAS,yBACP,QAAkB,EAClB,SAAoB;IAEpB,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,8BACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,UAAS,WAAW,CAAC,SAAS;IACpC,IAAI,SAAQ;QACV,IAAI,QAAO,OAAO;YAChB,MAAM,QAAO;QACf;QACA,OAAO;IACT;IAEA,OAAO,yBAAyB,UAAU;AAC5C;AAEA,OAAO,UAAU;IACf;IACA;AACF"}}] } \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js index 8ce82643252e9..21ec739734384 100644 --- a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/input/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { console.log("Hello, world!"); diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js index 6324d46eee421..586c9c2080b9f 100644 --- a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js @@ -112,6 +112,7 @@ function getChunkPath(chunkData) { ; ; ; +; var SourceType; (function(SourceType) { SourceType[SourceType["Runtime"] = 0] = "Runtime"; @@ -129,26 +130,6 @@ const chunkModulesMap = new Map(); const runtimeChunkLists = new Set(); const chunkListChunksMap = new Map(); const chunkChunkListsMap = new Map(); -const commonJsRequireContext = (entry, sourceModule)=>{ - return entry.internal ? commonJsRequire(sourceModule, entry.id()) : externalRequire(entry.id(), false); -}; -function externalRequire(id, esm = false) { - let raw; - try { - raw = require(id); - } catch (err) { - throw new Error(`Failed to load external module ${id}: ${err}`); - } - if (!esm) { - return raw; - } - const ns = {}; - interopEsm(raw, ns, raw.__esModule); - return ns; -} -externalRequire.resolve = (id, options)=>{ - return require.resolve(id, options); -}; const availableModules = new Map(); const availableModuleChunks = new Map(); async function loadChunk(source, chunkData) { @@ -266,10 +247,9 @@ function instantiateModule(id, source) { moduleHotState.set(module, hotState); try { runModuleExecutionHooks(module, (refresh)=>{ - moduleFactory.call(module.exports, { + moduleFactory.call(module.exports, augmentContext({ e: module.exports, r: commonJsRequire.bind(null, module), - x: externalRequire, f: requireContext.bind(null, module), i: esmImport.bind(null, module), s: esmExport.bind(null, module), @@ -285,7 +265,7 @@ function instantiateModule(id, source) { g: globalThis, k: refresh, __dirname: module.id.replace(/(^|\/)[\/]+$/, "") - }); + })); }); } catch (error) { module.error = error; @@ -890,6 +870,12 @@ globalThis.TURBOPACK_CHUNK_LISTS = { } }; let BACKEND; +function augmentContext(context1) { + return context1; +} +function commonJsRequireContext(entry1, sourceModule1) { + return commonJsRequire(sourceModule1, entry1.id()); +} (()=>{ BACKEND = { async registerChunk (chunkPath1, params1) { diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js.map b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js.map index 0bf04d6528ccd..1ff8534d7d6b7 100644 --- a/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js.map +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_dev_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_dev_runtime_input_index_e60ecd.js.map @@ -2,7 +2,7 @@ "version": 3, "sections": [ {"offset": {"line": 9, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/shared/runtime-utils.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * TurboPack ECMAScript runtimes.\n *\n * It will be prepended to the runtime code of each runtime.\n */\n\n/* eslint-disable @next/next/no-assign-module-variable */\n\n/// \n\ninterface Exports {\n __esModule?: boolean;\n\n [key: string]: any;\n}\ntype EsmNamespaceObject = Record;\n\ninterface BaseModule {\n exports: Exports;\n error: Error | undefined;\n loaded: boolean;\n id: ModuleId;\n children: ModuleId[];\n parents: ModuleId[];\n namespaceObject?: EsmNamespaceObject;\n}\n\ninterface Module extends BaseModule {}\n\ntype RequireContextMap = Record;\n\ninterface RequireContextEntry {\n id: () => ModuleId;\n}\n\ninterface RequireContext {\n (moduleId: ModuleId): Exports | EsmNamespaceObject;\n keys(): ModuleId[];\n resolve(moduleId: ModuleId): ModuleId;\n}\n\ntype GetOrInstantiateModuleFromParent = (\n moduleId: ModuleId,\n parentModule: Module\n) => Module;\n\ntype CommonJsRequireContext = (\n entry: RequireContextEntry,\n parentModule: Module\n) => Exports;\n\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst toStringTag = typeof Symbol !== \"undefined\" && Symbol.toStringTag;\n\nfunction defineProp(\n obj: any,\n name: PropertyKey,\n options: PropertyDescriptor & ThisType\n) {\n if (!hasOwnProperty.call(obj, name))\n Object.defineProperty(obj, name, options);\n}\n\n/**\n * Adds the getters to the exports object.\n */\nfunction esm(exports: Exports, getters: Record any>) {\n defineProp(exports, \"__esModule\", { value: true });\n if (toStringTag) defineProp(exports, toStringTag, { value: \"Module\" });\n for (const key in getters) {\n defineProp(exports, key, { get: getters[key], enumerable: true });\n }\n}\n\n/**\n * Makes the module an ESM with exports\n */\nfunction esmExport(module: Module, getters: Record any>) {\n esm((module.namespaceObject = module.exports), getters);\n}\n\n/**\n * Adds the props to the exports object\n */\nfunction cjsExport(exports: Exports, props: Record) {\n for (const key in props) {\n defineProp(exports, key, { get: () => props[key], enumerable: true });\n }\n}\n\nfunction exportValue(module: Module, value: any) {\n module.exports = value;\n}\n\nfunction exportNamespace(module: Module, namespace: any) {\n module.exports = module.namespaceObject = namespace;\n}\n\nfunction createGetter(obj: Record, key: string) {\n return () => obj[key];\n}\n\n/**\n * @returns prototype of the object\n */\nconst getProto: (obj: any) => any = Object.getPrototypeOf\n ? (obj) => Object.getPrototypeOf(obj)\n : (obj) => obj.__proto__;\n\n/** Prototypes that are not expanded for exports */\nconst LEAF_PROTOTYPES = [null, getProto({}), getProto([]), getProto(getProto)];\n\n/**\n * @param allowExportDefault\n * * `false`: will have the raw module as default export\n * * `true`: will have the default property as default export\n */\nfunction interopEsm(\n raw: Exports,\n ns: EsmNamespaceObject,\n allowExportDefault?: boolean\n) {\n const getters: { [s: string]: () => any } = Object.create(null);\n for (\n let current = raw;\n (typeof current === \"object\" || typeof current === \"function\") &&\n !LEAF_PROTOTYPES.includes(current);\n current = getProto(current)\n ) {\n for (const key of Object.getOwnPropertyNames(current)) {\n getters[key] = createGetter(raw, key);\n }\n }\n if (!(allowExportDefault && \"default\" in getters)) {\n getters[\"default\"] = () => raw;\n }\n esm(ns, getters);\n}\n\nfunction esmImport(sourceModule: Module, id: ModuleId): EsmNamespaceObject {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n if (module.namespaceObject) return module.namespaceObject;\n const raw = module.exports;\n const ns = (module.namespaceObject = {});\n interopEsm(raw, ns, raw.__esModule);\n return ns;\n}\n\nfunction commonJsRequire(sourceModule: Module, id: ModuleId): Exports {\n const module = getOrInstantiateModuleFromParent(id, sourceModule);\n if (module.error) throw module.error;\n return module.exports;\n}\n\ntype RequireContextFactory = (map: RequireContextMap) => RequireContext;\n\nfunction requireContext(\n sourceModule: Module,\n map: RequireContextMap\n): RequireContext {\n function requireContext(id: ModuleId): Exports {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is required from a require.context, but is not in the context`\n );\n }\n\n return commonJsRequireContext(entry, sourceModule);\n }\n\n requireContext.keys = (): ModuleId[] => {\n return Object.keys(map);\n };\n\n requireContext.resolve = (id: ModuleId): ModuleId => {\n const entry = map[id];\n\n if (!entry) {\n throw new Error(\n `module ${id} is resolved from a require.context, but is not in the context`\n );\n }\n\n return entry.id();\n };\n\n return requireContext;\n}\n\n/**\n * Returns the path of a chunk defined by its data.\n */\nfunction getChunkPath(chunkData: ChunkData): ChunkPath {\n return typeof chunkData === \"string\" ? chunkData : chunkData.path;\n}\n"],"names":[],"mappings":";;;;;AAoDA,MAAM,iBAAiB,OAAO,UAAU;AACxC,MAAM,cAAc,OAAO,WAAW,eAAe,OAAO;AAE5D,SAAS,WACP,GAAQ,EACR,IAAiB,EACjB,OAA2C;IAE3C,IAAI,CAAC,eAAe,KAAK,KAAK,OAC5B,OAAO,eAAe,KAAK,MAAM;AACrC;AAKA,SAAS,IAAI,OAAgB,EAAE,OAAkC;IAC/D,WAAW,SAAS,cAAc;QAAE,OAAO;IAAK;IAChD,IAAI,aAAa,WAAW,SAAS,aAAa;QAAE,OAAO;IAAS;IACpE,IAAK,MAAM,OAAO,QAAS;QACzB,WAAW,SAAS,KAAK;YAAE,KAAK,OAAO,CAAC,IAAI;YAAE,YAAY;QAAK;IACjE;AACF;AAKA,SAAS,UAAU,MAAc,EAAE,OAAkC;IACnE,IAAK,OAAO,kBAAkB,OAAO,SAAU;AACjD;AAKA,SAAS,UAAU,OAAgB,EAAE,KAA0B;IAC7D,IAAK,MAAM,OAAO,MAAO;QACvB,WAAW,SAAS,KAAK;YAAE,KAAK,IAAM,KAAK,CAAC,IAAI;YAAE,YAAY;QAAK;IACrE;AACF;AAEA,SAAS,YAAY,MAAc,EAAE,KAAU;IAC7C,OAAO,UAAU;AACnB;AAEA,SAAS,gBAAgB,MAAc,EAAE,SAAc;IACrD,OAAO,UAAU,OAAO,kBAAkB;AAC5C;AAEA,SAAS,aAAa,GAAwB,EAAE,GAAW;IACzD,OAAO,IAAM,GAAG,CAAC,IAAI;AACvB;AAKA,MAAM,WAA8B,OAAO,iBACvC,CAAC,MAAQ,OAAO,eAAe,OAC/B,CAAC,MAAQ,IAAI;AAGjB,MAAM,kBAAkB;IAAC;IAAM,SAAS,CAAC;IAAI,SAAS,EAAE;IAAG,SAAS;CAAU;AAO9E,SAAS,WACP,GAAY,EACZ,EAAsB,EACtB,kBAA4B;IAE5B,MAAM,UAAsC,OAAO,OAAO;IAC1D,IACE,IAAI,UAAU,KACd,CAAC,OAAO,YAAY,YAAY,OAAO,YAAY,UAAU,KAC7D,CAAC,gBAAgB,SAAS,UAC1B,UAAU,SAAS,SACnB;QACA,KAAK,MAAM,OAAO,OAAO,oBAAoB,SAAU;YACrD,OAAO,CAAC,IAAI,GAAG,aAAa,KAAK;QACnC;IACF;IACA,IAAI,CAAC,CAAC,sBAAsB,aAAa,OAAO,GAAG;QACjD,OAAO,CAAC,UAAU,GAAG,IAAM;IAC7B;IACA,IAAI,IAAI;AACV;AAEA,SAAS,UAAU,YAAoB,EAAE,EAAY;IACnD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,IAAI,OAAO,iBAAiB,OAAO,OAAO;IAC1C,MAAM,MAAM,OAAO;IACnB,MAAM,KAAM,OAAO,kBAAkB,CAAC;IACtC,WAAW,KAAK,IAAI,IAAI;IACxB,OAAO;AACT;AAEA,SAAS,gBAAgB,YAAoB,EAAE,EAAY;IACzD,MAAM,SAAS,iCAAiC,IAAI;IACpD,IAAI,OAAO,OAAO,MAAM,OAAO;IAC/B,OAAO,OAAO;AAChB;AAIA,SAAS,eACP,YAAoB,EACpB,GAAsB;IAEtB,SAAS,eAAe,EAAY;QAClC,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,uBAAuB,OAAO;IACvC;IAEA,eAAe,OAAO;QACpB,OAAO,OAAO,KAAK;IACrB;IAEA,eAAe,UAAU,CAAC;QACxB,MAAM,QAAQ,GAAG,CAAC,GAAG;QAErB,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,8DAA8D,CAAC;QAEhF;QAEA,OAAO,MAAM;IACf;IAEA,OAAO;AACT;AAKA,SAAS,aAAa,SAAoB;IACxC,OAAO,OAAO,cAAc,WAAW,YAAY,UAAU;AAC/D"}}, - {"offset": {"line": 109, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/dev/runtime/base/runtime-base.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * Turbopack *development* ECMAScript runtimes.\n *\n * It will be appended to the runtime code of each runtime right after the\n * shared runtime utils.\n */\n\n/* eslint-disable @next/next/no-assign-module-variable */\n\n/// \n/// \n/// \n/// \n\n// This file must not use `import` and `export` statements. Otherwise, it\n// becomes impossible to augment interfaces declared in ``d files\n// (e.g. `Module`). Hence the need for `import()` here.\ntype RefreshRuntimeGlobals =\n import(\"@next/react-refresh-utils/dist/runtime\").RefreshRuntimeGlobals;\n\ndeclare var $RefreshHelpers$: RefreshRuntimeGlobals[\"$RefreshHelpers$\"];\ndeclare var $RefreshReg$: RefreshRuntimeGlobals[\"$RefreshReg$\"];\ndeclare var $RefreshSig$: RefreshRuntimeGlobals[\"$RefreshSig$\"];\ndeclare var $RefreshInterceptModuleExecution$:\n | RefreshRuntimeGlobals[\"$RefreshInterceptModuleExecution$\"];\n\ntype RefreshContext = {\n register: RefreshRuntimeGlobals[\"$RefreshReg$\"];\n signature: RefreshRuntimeGlobals[\"$RefreshSig$\"];\n};\n\n// @next/react-refresh-utils/internal/helpers\ntype RefreshHelpers = {\n registerExportsForReactRefresh(\n moduleExports: unknown,\n moduleID: string\n ): void;\n getRefreshBoundarySignature(moduleExports: unknown): Array;\n isReactRefreshBoundary(moduleExports: unknown): boolean;\n shouldInvalidateReactRefreshBoundary(\n prevExports: unknown,\n nextExports: unknown\n ): boolean;\n scheduleUpdate(): void;\n};\n\ninterface TurbopackDevContext {\n e: Module[\"exports\"];\n r: CommonJsRequire;\n x: ExternalRequire;\n f: RequireContextFactory;\n i: EsmImport;\n s: EsmExport;\n j: typeof cjsExport;\n v: ExportValue;\n n: typeof exportNamespace;\n m: Module;\n c: ModuleCache;\n l: LoadChunk;\n g: typeof globalThis;\n k: RefreshContext;\n __dirname: string;\n}\n\n// string encoding of a module factory (used in hmr updates)\ntype ModuleFactoryString = string;\n\ntype ModuleFactory = (\n this: Module[\"exports\"],\n context: TurbopackDevContext\n) => undefined;\n\ntype DevRuntimeParams = {\n otherChunks: ChunkData[];\n runtimeModuleIds: ModuleId[];\n};\n\ntype ChunkRegistration = [\n chunkPath: ChunkPath,\n chunkModules: ModuleFactories,\n params: DevRuntimeParams | undefined\n];\ntype ChunkList = {\n path: ChunkPath;\n chunks: ChunkData[];\n source: \"entry\" | \"dynamic\";\n};\n\nenum SourceType {\n /**\n * The module was instantiated because it was included in an evaluated chunk's\n * runtime.\n */\n Runtime = 0,\n /**\n * The module was instantiated because a parent module imported it.\n */\n Parent = 1,\n /**\n * The module was instantiated because it was included in a chunk's hot module\n * update.\n */\n Update = 2,\n}\n\ntype SourceInfo =\n | {\n type: SourceType.Runtime;\n chunkPath: ChunkPath;\n }\n | {\n type: SourceType.Parent;\n parentId: ModuleId;\n }\n | {\n type: SourceType.Update;\n parents?: ModuleId[];\n };\n\ninterface RuntimeBackend {\n registerChunk: (chunkPath: ChunkPath, params?: DevRuntimeParams) => void;\n loadChunk: (chunkPath: ChunkPath, source: SourceInfo) => Promise;\n reloadChunk?: (chunkPath: ChunkPath) => Promise;\n unloadChunk?: (chunkPath: ChunkPath) => void;\n\n restart: () => void;\n}\n\nconst moduleFactories: ModuleFactories = Object.create(null);\nconst moduleCache: ModuleCache = Object.create(null);\n/**\n * Maps module IDs to persisted data between executions of their hot module\n * implementation (`hot.data`).\n */\nconst moduleHotData: Map = new Map();\n/**\n * Maps module instances to their hot module state.\n */\nconst moduleHotState: Map = new Map();\n/**\n * Module IDs that are instantiated as part of the runtime of a chunk.\n */\nconst runtimeModules: Set = new Set();\n/**\n * Map from module ID to the chunks that contain this module.\n *\n * In HMR, we need to keep track of which modules are contained in which so\n * chunks. This is so we don't eagerly dispose of a module when it is removed\n * from chunk A, but still exists in chunk B.\n */\nconst moduleChunksMap: Map> = new Map();\n/**\n * Map from chunk path to all modules it contains.\n */\nconst chunkModulesMap: Map> = new Map();\n/**\n * Chunk lists that contain a runtime. When these chunk lists receive an update\n * that can't be reconciled with the current state of the page, we need to\n * reload the runtime entirely.\n */\nconst runtimeChunkLists: Set = new Set();\n/**\n * Map from chunk list to the chunk paths it contains.\n */\nconst chunkListChunksMap: Map> = new Map();\n/**\n * Map from chunk path to the chunk lists it belongs to.\n */\nconst chunkChunkListsMap: Map> = new Map();\n\nconst commonJsRequireContext: CommonJsRequireContext = (\n entry,\n sourceModule\n) => {\n return entry.internal\n ? commonJsRequire(sourceModule, entry.id())\n : externalRequire(entry.id(), false);\n};\n\nfunction externalRequire(\n id: ModuleId,\n esm: boolean = false\n): Exports | EsmNamespaceObject {\n let raw;\n try {\n raw = require(id);\n } catch (err) {\n // TODO(alexkirsz) This can happen when a client-side module tries to load\n // an external module we don't provide a shim for (e.g. querystring, url).\n // For now, we fail semi-silently, but in the future this should be a\n // compilation error.\n throw new Error(`Failed to load external module ${id}: ${err}`);\n }\n if (!esm) {\n return raw;\n }\n const ns = {};\n interopEsm(raw, ns, raw.__esModule);\n return ns;\n}\nexternalRequire.resolve = (\n id: string,\n options?:\n | {\n paths?: string[] | undefined;\n }\n | undefined\n) => {\n return require.resolve(id, options);\n};\n\nconst availableModules: Map | true> = new Map();\n\nconst availableModuleChunks: Map | true> = new Map();\n\nasync function loadChunk(\n source: SourceInfo,\n chunkData: ChunkData\n): Promise {\n if (typeof chunkData === \"string\") {\n return loadChunkPath(source, chunkData);\n }\n\n const includedList = chunkData.included || [];\n const modulesPromises = includedList.map((included) => {\n if (moduleFactories[included]) return true;\n return availableModules.get(included);\n });\n if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) {\n // When all included items are already loaded or loading, we can skip loading ourselves\n return Promise.all(modulesPromises);\n }\n\n const includedModuleChunksList = chunkData.moduleChunks || [];\n const moduleChunksPromises = includedModuleChunksList\n .map((included) => {\n // TODO(alexkirsz) Do we need this check?\n // if (moduleFactories[included]) return true;\n return availableModuleChunks.get(included);\n })\n .filter((p) => p);\n\n let promise;\n if (moduleChunksPromises.length > 0) {\n // Some module chunks are already loaded or loading.\n\n if (moduleChunksPromises.length == includedModuleChunksList.length) {\n // When all included module chunks are already loaded or loading, we can skip loading ourselves\n return Promise.all(moduleChunksPromises);\n }\n\n const moduleChunksToLoad: Set = new Set();\n for (const moduleChunk of includedModuleChunksList) {\n if (!availableModuleChunks.has(moduleChunk)) {\n moduleChunksToLoad.add(moduleChunk);\n }\n }\n\n for (const moduleChunkToLoad of moduleChunksToLoad) {\n const promise = loadChunkPath(source, moduleChunkToLoad);\n\n availableModuleChunks.set(moduleChunkToLoad, promise);\n\n moduleChunksPromises.push(promise);\n }\n\n promise = Promise.all(moduleChunksPromises);\n } else {\n promise = loadChunkPath(source, chunkData.path);\n\n // Mark all included module chunks as loading if they are not already loaded or loading.\n for (const includedModuleChunk of includedModuleChunksList) {\n if (!availableModuleChunks.has(includedModuleChunk)) {\n availableModuleChunks.set(includedModuleChunk, promise);\n }\n }\n }\n\n for (const included of includedList) {\n if (!availableModules.has(included)) {\n // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier.\n // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway.\n availableModules.set(included, promise);\n }\n }\n\n return promise;\n}\n\nasync function loadChunkPath(\n source: SourceInfo,\n chunkPath: ChunkPath\n): Promise {\n try {\n await BACKEND.loadChunk(chunkPath, source);\n } catch (error) {\n let loadReason;\n switch (source.type) {\n case SourceType.Runtime:\n loadReason = `as a runtime dependency of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n loadReason = `from module ${source.parentId}`;\n break;\n case SourceType.Update:\n loadReason = \"from an HMR update\";\n break;\n }\n throw new Error(\n `Failed to load chunk ${chunkPath} ${loadReason}${\n error ? `: ${error}` : \"\"\n }`\n );\n }\n}\n\nfunction instantiateModule(id: ModuleId, source: SourceInfo): Module {\n const moduleFactory = moduleFactories[id];\n if (typeof moduleFactory !== \"function\") {\n // This can happen if modules incorrectly handle HMR disposes/updates,\n // e.g. when they keep a `setTimeout` around which still executes old code\n // and contains e.g. a `require(\"something\")` call.\n let instantiationReason;\n switch (source.type) {\n case SourceType.Runtime:\n instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n instantiationReason = `because it was required from module ${source.parentId}`;\n break;\n case SourceType.Update:\n instantiationReason = \"because of an HMR update\";\n break;\n }\n throw new Error(\n `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`\n );\n }\n\n const hotData = moduleHotData.get(id)!;\n const { hot, hotState } = createModuleHot(hotData);\n\n let parents: ModuleId[];\n switch (source.type) {\n case SourceType.Runtime:\n runtimeModules.add(id);\n parents = [];\n break;\n case SourceType.Parent:\n // No need to add this module as a child of the parent module here, this\n // has already been taken care of in `getOrInstantiateModuleFromParent`.\n parents = [source.parentId];\n break;\n case SourceType.Update:\n parents = source.parents || [];\n break;\n }\n const module: Module = {\n exports: {},\n error: undefined,\n loaded: false,\n id,\n parents,\n children: [],\n namespaceObject: undefined,\n hot,\n };\n\n moduleCache[id] = module;\n moduleHotState.set(module, hotState);\n\n // NOTE(alexkirsz) This can fail when the module encounters a runtime error.\n try {\n runModuleExecutionHooks(module, (refresh) => {\n moduleFactory.call(module.exports, {\n e: module.exports,\n r: commonJsRequire.bind(null, module),\n x: externalRequire,\n f: requireContext.bind(null, module),\n i: esmImport.bind(null, module),\n s: esmExport.bind(null, module),\n j: cjsExport.bind(null, module.exports),\n v: exportValue.bind(null, module),\n n: exportNamespace.bind(null, module),\n m: module,\n c: moduleCache,\n l: loadChunk.bind(null, { type: SourceType.Parent, parentId: id }),\n g: globalThis,\n k: refresh,\n __dirname: module.id.replace(/(^|\\/)[\\/]+$/, \"\"),\n });\n });\n } catch (error) {\n module.error = error as any;\n throw error;\n }\n\n module.loaded = true;\n if (module.namespaceObject && module.exports !== module.namespaceObject) {\n // in case of a circular dependency: cjs1 -> esm2 -> cjs1\n interopEsm(module.exports, module.namespaceObject);\n }\n\n return module;\n}\n\n/**\n * NOTE(alexkirsz) Webpack has an \"module execution\" interception hook that\n * Next.js' React Refresh runtime hooks into to add module context to the\n * refresh registry.\n */\nfunction runModuleExecutionHooks(\n module: Module,\n executeModule: (ctx: RefreshContext) => void\n) {\n const cleanupReactRefreshIntercept =\n typeof globalThis.$RefreshInterceptModuleExecution$ === \"function\"\n ? globalThis.$RefreshInterceptModuleExecution$(module.id)\n : () => {};\n\n try {\n executeModule({\n register: globalThis.$RefreshReg$,\n signature: globalThis.$RefreshSig$,\n });\n\n if (\"$RefreshHelpers$\" in globalThis) {\n // This pattern can also be used to register the exports of\n // a module with the React Refresh runtime.\n registerExportsAndSetupBoundaryForReactRefresh(\n module,\n globalThis.$RefreshHelpers$\n );\n }\n } catch (e) {\n throw e;\n } finally {\n // Always cleanup the intercept, even if module execution failed.\n cleanupReactRefreshIntercept();\n }\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it if it is not cached.\n */\nconst getOrInstantiateModuleFromParent: GetOrInstantiateModuleFromParent = (\n id,\n sourceModule\n) => {\n if (!sourceModule.hot.active) {\n console.warn(\n `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update`\n );\n }\n\n const module = moduleCache[id];\n\n if (sourceModule.children.indexOf(id) === -1) {\n sourceModule.children.push(id);\n }\n\n if (module) {\n if (module.parents.indexOf(sourceModule.id) === -1) {\n module.parents.push(sourceModule.id);\n }\n\n return module;\n }\n\n return instantiateModule(id, {\n type: SourceType.Parent,\n parentId: sourceModule.id,\n });\n};\n\n/**\n * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts\n */\nfunction registerExportsAndSetupBoundaryForReactRefresh(\n module: Module,\n helpers: RefreshHelpers\n) {\n const currentExports = module.exports;\n const prevExports = module.hot.data.prevExports ?? null;\n\n helpers.registerExportsForReactRefresh(currentExports, module.id);\n\n // A module can be accepted automatically based on its exports, e.g. when\n // it is a Refresh Boundary.\n if (helpers.isReactRefreshBoundary(currentExports)) {\n // Save the previous exports on update so we can compare the boundary\n // signatures.\n module.hot.dispose((data) => {\n data.prevExports = currentExports;\n });\n // Unconditionally accept an update to this module, we'll check if it's\n // still a Refresh Boundary later.\n module.hot.accept();\n\n // This field is set when the previous version of this module was a\n // Refresh Boundary, letting us know we need to check for invalidation or\n // enqueue an update.\n if (prevExports !== null) {\n // A boundary can become ineligible if its exports are incompatible\n // with the previous exports.\n //\n // For example, if you add/remove/change exports, we'll want to\n // re-execute the importing modules, and force those components to\n // re-render. Similarly, if you convert a class component to a\n // function, we want to invalidate the boundary.\n if (\n helpers.shouldInvalidateReactRefreshBoundary(\n prevExports,\n currentExports\n )\n ) {\n module.hot.invalidate();\n } else {\n helpers.scheduleUpdate();\n }\n }\n } else {\n // Since we just executed the code for the module, it's possible that the\n // new exports made it ineligible for being a boundary.\n // We only care about the case when we were _previously_ a boundary,\n // because we already accepted this update (accidental side effect).\n const isNoLongerABoundary = prevExports !== null;\n if (isNoLongerABoundary) {\n module.hot.invalidate();\n }\n }\n}\n\nfunction formatDependencyChain(dependencyChain: ModuleId[]): string {\n return `Dependency chain: ${dependencyChain.join(\" -> \")}`;\n}\n\nfunction computeOutdatedModules(\n added: Map,\n modified: Map\n): { outdatedModules: Set; newModuleFactories: Map } {\n const outdatedModules = new Set();\n const newModuleFactories = new Map();\n\n for (const [moduleId, entry] of added) {\n if (entry != null) {\n newModuleFactories.set(moduleId, _eval(entry));\n }\n }\n\n for (const [moduleId, entry] of modified) {\n const effect = getAffectedModuleEffects(moduleId);\n\n switch (effect.type) {\n case \"unaccepted\":\n throw new Error(\n `cannot apply update: unaccepted module. ${formatDependencyChain(\n effect.dependencyChain\n )}.`\n );\n case \"self-declined\":\n throw new Error(\n `cannot apply update: self-declined module. ${formatDependencyChain(\n effect.dependencyChain\n )}.`\n );\n case \"accepted\":\n newModuleFactories.set(moduleId, _eval(entry));\n for (const outdatedModuleId of effect.outdatedModules) {\n outdatedModules.add(outdatedModuleId);\n }\n break;\n // TODO(alexkirsz) Dependencies: handle dependencies effects.\n }\n }\n\n return { outdatedModules, newModuleFactories };\n}\n\nfunction computeOutdatedSelfAcceptedModules(\n outdatedModules: Iterable\n): { moduleId: ModuleId; errorHandler: true | Function }[] {\n const outdatedSelfAcceptedModules = [];\n for (const moduleId of outdatedModules) {\n const module = moduleCache[moduleId];\n const hotState = moduleHotState.get(module)!;\n if (module && hotState.selfAccepted && !hotState.selfInvalidated) {\n outdatedSelfAcceptedModules.push({\n moduleId,\n errorHandler: hotState.selfAccepted,\n });\n }\n }\n return outdatedSelfAcceptedModules;\n}\n\n/**\n * Adds, deletes, and moves modules between chunks. This must happen before the\n * dispose phase as it needs to know which modules were removed from all chunks,\n * which we can only compute *after* taking care of added and moved modules.\n */\nfunction updateChunksPhase(\n chunksAddedModules: Map>,\n chunksDeletedModules: Map>\n): { disposedModules: Set } {\n for (const [chunkPath, addedModuleIds] of chunksAddedModules) {\n for (const moduleId of addedModuleIds) {\n addModuleToChunk(moduleId, chunkPath);\n }\n }\n\n const disposedModules: Set = new Set();\n for (const [chunkPath, addedModuleIds] of chunksDeletedModules) {\n for (const moduleId of addedModuleIds) {\n if (removeModuleFromChunk(moduleId, chunkPath)) {\n disposedModules.add(moduleId);\n }\n }\n }\n\n return { disposedModules };\n}\n\nfunction disposePhase(\n outdatedModules: Iterable,\n disposedModules: Set\n): { outdatedModuleParents: Map> } {\n for (const moduleId of outdatedModules) {\n disposeModule(moduleId, \"replace\");\n }\n\n for (const moduleId of disposedModules) {\n disposeModule(moduleId, \"clear\");\n }\n\n // Removing modules from the module cache is a separate step.\n // We also want to keep track of previous parents of the outdated modules.\n const outdatedModuleParents = new Map();\n for (const moduleId of outdatedModules) {\n const oldModule = moduleCache[moduleId];\n outdatedModuleParents.set(moduleId, oldModule?.parents);\n delete moduleCache[moduleId];\n }\n\n // TODO(alexkirsz) Dependencies: remove outdated dependency from module\n // children.\n\n return { outdatedModuleParents };\n}\n\n/**\n * Disposes of an instance of a module.\n *\n * Returns the persistent hot data that should be kept for the next module\n * instance.\n *\n * NOTE: mode = \"replace\" will not remove modules from the moduleCache.\n * This must be done in a separate step afterwards.\n * This is important because all modules need to be diposed to update the\n * parent/child relationships before they are actually removed from the moduleCache.\n * If this would be done in this method, following disposeModulecalls won't find\n * the module from the module id in the cache.\n */\nfunction disposeModule(moduleId: ModuleId, mode: \"clear\" | \"replace\") {\n const module = moduleCache[moduleId];\n if (!module) {\n return;\n }\n\n const hotState = moduleHotState.get(module)!;\n const data = {};\n\n // Run the `hot.dispose` handler, if any, passing in the persistent\n // `hot.data` object.\n for (const disposeHandler of hotState.disposeHandlers) {\n disposeHandler(data);\n }\n\n // This used to warn in `getOrInstantiateModuleFromParent` when a disposed\n // module is still importing other modules.\n module.hot.active = false;\n\n moduleHotState.delete(module);\n\n // TODO(alexkirsz) Dependencies: delete the module from outdated deps.\n\n // Remove the disposed module from its children's parents list.\n // It will be added back once the module re-instantiates and imports its\n // children again.\n for (const childId of module.children) {\n const child = moduleCache[childId];\n if (!child) {\n continue;\n }\n\n const idx = child.parents.indexOf(module.id);\n if (idx >= 0) {\n child.parents.splice(idx, 1);\n }\n }\n\n switch (mode) {\n case \"clear\":\n delete moduleCache[module.id];\n moduleHotData.delete(module.id);\n break;\n case \"replace\":\n moduleHotData.set(module.id, data);\n break;\n default:\n invariant(mode, (mode) => `invalid mode: ${mode}`);\n }\n}\n\nfunction applyPhase(\n outdatedSelfAcceptedModules: {\n moduleId: ModuleId;\n errorHandler: true | Function;\n }[],\n newModuleFactories: Map,\n outdatedModuleParents: Map>\n) {\n // Update module factories.\n for (const [moduleId, factory] of newModuleFactories.entries()) {\n moduleFactories[moduleId] = factory;\n }\n\n // TODO(alexkirsz) Run new runtime entries here.\n\n // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps.\n\n // Re-instantiate all outdated self-accepted modules.\n for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) {\n try {\n instantiateModule(moduleId, {\n type: SourceType.Update,\n parents: outdatedModuleParents.get(moduleId),\n });\n } catch (err) {\n if (typeof errorHandler === \"function\") {\n try {\n errorHandler(err, { moduleId, module: moduleCache[moduleId] });\n } catch (_) {\n // Ignore error.\n }\n }\n }\n }\n}\n\n/**\n * Utility function to ensure all variants of an enum are handled.\n */\nfunction invariant(never: never, computeMessage: (arg: any) => string): never {\n throw new Error(`Invariant: ${computeMessage(never)}`);\n}\n\nfunction applyUpdate(chunkListPath: ChunkPath, update: PartialUpdate) {\n switch (update.type) {\n case \"ChunkListUpdate\":\n applyChunkListUpdate(chunkListPath, update);\n break;\n default:\n invariant(update, (update) => `Unknown update type: ${update.type}`);\n }\n}\n\nfunction applyChunkListUpdate(\n chunkListPath: ChunkPath,\n update: ChunkListUpdate\n) {\n if (update.merged != null) {\n for (const merged of update.merged) {\n switch (merged.type) {\n case \"EcmascriptMergedUpdate\":\n applyEcmascriptMergedUpdate(chunkListPath, merged);\n break;\n default:\n invariant(merged, (merged) => `Unknown merged type: ${merged.type}`);\n }\n }\n }\n\n if (update.chunks != null) {\n for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) {\n switch (chunkUpdate.type) {\n case \"added\":\n BACKEND.loadChunk(chunkPath, { type: SourceType.Update });\n break;\n case \"total\":\n BACKEND.reloadChunk?.(chunkPath);\n break;\n case \"deleted\":\n BACKEND.unloadChunk?.(chunkPath);\n break;\n case \"partial\":\n invariant(\n chunkUpdate.instruction,\n (instruction) =>\n `Unknown partial instruction: ${JSON.stringify(instruction)}.`\n );\n default:\n invariant(\n chunkUpdate,\n (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}`\n );\n }\n }\n }\n}\n\nfunction applyEcmascriptMergedUpdate(\n chunkPath: ChunkPath,\n update: EcmascriptMergedUpdate\n) {\n const { entries = {}, chunks = {} } = update;\n const { added, modified, deleted, chunksAdded, chunksDeleted } =\n computeChangedModules(entries, chunks);\n const { outdatedModules, newModuleFactories } = computeOutdatedModules(\n added,\n modified\n );\n const outdatedSelfAcceptedModules =\n computeOutdatedSelfAcceptedModules(outdatedModules);\n const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted);\n const { outdatedModuleParents } = disposePhase(\n outdatedModules,\n disposedModules\n );\n applyPhase(\n outdatedSelfAcceptedModules,\n newModuleFactories,\n outdatedModuleParents\n );\n}\n\nfunction computeChangedModules(\n entries: Record,\n updates: Record\n): {\n added: Map;\n modified: Map;\n deleted: Set;\n chunksAdded: Map>;\n chunksDeleted: Map>;\n} {\n const chunksAdded = new Map();\n const chunksDeleted = new Map();\n const added: Map = new Map();\n const modified = new Map();\n const deleted: Set = new Set();\n\n for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) {\n switch (mergedChunkUpdate.type) {\n case \"added\": {\n const updateAdded = new Set(mergedChunkUpdate.modules);\n for (const moduleId of updateAdded) {\n added.set(moduleId, entries[moduleId]);\n }\n chunksAdded.set(chunkPath, updateAdded);\n break;\n }\n case \"deleted\": {\n // We could also use `mergedChunkUpdate.modules` here.\n const updateDeleted = new Set(chunkModulesMap.get(chunkPath));\n for (const moduleId of updateDeleted) {\n deleted.add(moduleId);\n }\n chunksDeleted.set(chunkPath, updateDeleted);\n break;\n }\n case \"partial\": {\n const updateAdded = new Set(mergedChunkUpdate.added);\n const updateDeleted = new Set(mergedChunkUpdate.deleted);\n for (const moduleId of updateAdded) {\n added.set(moduleId, entries[moduleId]);\n }\n for (const moduleId of updateDeleted) {\n deleted.add(moduleId);\n }\n chunksAdded.set(chunkPath, updateAdded);\n chunksDeleted.set(chunkPath, updateDeleted);\n break;\n }\n default:\n invariant(\n mergedChunkUpdate,\n (mergedChunkUpdate) =>\n `Unknown merged chunk update type: ${mergedChunkUpdate.type}`\n );\n }\n }\n\n // If a module was added from one chunk and deleted from another in the same update,\n // consider it to be modified, as it means the module was moved from one chunk to another\n // AND has new code in a single update.\n for (const moduleId of added.keys()) {\n if (deleted.has(moduleId)) {\n added.delete(moduleId);\n deleted.delete(moduleId);\n }\n }\n\n for (const [moduleId, entry] of Object.entries(entries)) {\n // Modules that haven't been added to any chunk but have new code are considered\n // to be modified.\n // This needs to be under the previous loop, as we need it to get rid of modules\n // that were added and deleted in the same update.\n if (!added.has(moduleId)) {\n modified.set(moduleId, entry);\n }\n }\n\n return { added, deleted, modified, chunksAdded, chunksDeleted };\n}\n\ntype ModuleEffect =\n | {\n type: \"unaccepted\";\n dependencyChain: ModuleId[];\n }\n | {\n type: \"self-declined\";\n dependencyChain: ModuleId[];\n moduleId: ModuleId;\n }\n | {\n type: \"accepted\";\n moduleId: ModuleId;\n outdatedModules: Set;\n };\n\nfunction getAffectedModuleEffects(moduleId: ModuleId): ModuleEffect {\n const outdatedModules: Set = new Set();\n\n type QueueItem = { moduleId?: ModuleId; dependencyChain: ModuleId[] };\n\n const queue: QueueItem[] = [\n {\n moduleId,\n dependencyChain: [],\n },\n ];\n\n let nextItem;\n while ((nextItem = queue.shift())) {\n const { moduleId, dependencyChain } = nextItem;\n\n if (moduleId != null) {\n outdatedModules.add(moduleId);\n }\n\n // We've arrived at the runtime of the chunk, which means that nothing\n // else above can accept this update.\n if (moduleId === undefined) {\n return {\n type: \"unaccepted\",\n dependencyChain,\n };\n }\n\n const module = moduleCache[moduleId];\n const hotState = moduleHotState.get(module)!;\n\n if (\n // The module is not in the cache. Since this is a \"modified\" update,\n // it means that the module was never instantiated before.\n !module || // The module accepted itself without invalidating globalThis.\n // TODO is that right?\n (hotState.selfAccepted && !hotState.selfInvalidated)\n ) {\n continue;\n }\n\n if (hotState.selfDeclined) {\n return {\n type: \"self-declined\",\n dependencyChain,\n moduleId,\n };\n }\n\n if (runtimeModules.has(moduleId)) {\n queue.push({\n moduleId: undefined,\n dependencyChain: [...dependencyChain, moduleId],\n });\n continue;\n }\n\n for (const parentId of module.parents) {\n const parent = moduleCache[parentId];\n\n if (!parent) {\n // TODO(alexkirsz) Is this even possible?\n continue;\n }\n\n // TODO(alexkirsz) Dependencies: check accepted and declined\n // dependencies here.\n\n queue.push({\n moduleId: parentId,\n dependencyChain: [...dependencyChain, moduleId],\n });\n }\n }\n\n return {\n type: \"accepted\",\n moduleId,\n outdatedModules,\n };\n}\n\nfunction handleApply(chunkListPath: ChunkPath, update: ServerMessage) {\n switch (update.type) {\n case \"partial\": {\n // This indicates that the update is can be applied to the current state of the application.\n applyUpdate(chunkListPath, update.instruction);\n break;\n }\n case \"restart\": {\n // This indicates that there is no way to apply the update to the\n // current state of the application, and that the application must be\n // restarted.\n BACKEND.restart();\n break;\n }\n case \"notFound\": {\n // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed,\n // or the page itself was deleted.\n // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to.\n // If it is a runtime chunk list, we restart the application.\n if (runtimeChunkLists.has(chunkListPath)) {\n BACKEND.restart();\n } else {\n disposeChunkList(chunkListPath);\n }\n break;\n }\n default:\n throw new Error(`Unknown update type: ${update.type}`);\n }\n}\n\nfunction createModuleHot(hotData: HotData): { hot: Hot; hotState: HotState } {\n const hotState: HotState = {\n selfAccepted: false,\n selfDeclined: false,\n selfInvalidated: false,\n disposeHandlers: [],\n };\n\n const hot: Hot = {\n // TODO(alexkirsz) This is not defined in the HMR API. It was used to\n // decide whether to warn whenever an HMR-disposed module required other\n // modules. We might want to remove it.\n active: true,\n\n data: hotData ?? {},\n\n // TODO(alexkirsz) Support full (dep, callback, errorHandler) form.\n accept: (\n modules?: string | string[] | AcceptErrorHandler,\n _callback?: AcceptCallback,\n _errorHandler?: AcceptErrorHandler\n ) => {\n if (modules === undefined) {\n hotState.selfAccepted = true;\n } else if (typeof modules === \"function\") {\n hotState.selfAccepted = modules;\n } else {\n throw new Error(\"unsupported `accept` signature\");\n }\n },\n\n decline: (dep) => {\n if (dep === undefined) {\n hotState.selfDeclined = true;\n } else {\n throw new Error(\"unsupported `decline` signature\");\n }\n },\n\n dispose: (callback) => {\n hotState.disposeHandlers.push(callback);\n },\n\n addDisposeHandler: (callback) => {\n hotState.disposeHandlers.push(callback);\n },\n\n removeDisposeHandler: (callback) => {\n const idx = hotState.disposeHandlers.indexOf(callback);\n if (idx >= 0) {\n hotState.disposeHandlers.splice(idx, 1);\n }\n },\n\n invalidate: () => {\n hotState.selfInvalidated = true;\n // TODO(alexkirsz) The original HMR code had management-related code\n // here.\n },\n\n // NOTE(alexkirsz) This is part of the management API, which we don't\n // implement, but the Next.js React Refresh runtime uses this to decide\n // whether to schedule an update.\n status: () => \"idle\",\n\n // NOTE(alexkirsz) Since we always return \"idle\" for now, these are no-ops.\n addStatusHandler: (_handler) => {},\n removeStatusHandler: (_handler) => {},\n };\n\n return { hot, hotState };\n}\n\n/**\n * Adds a module to a chunk.\n */\nfunction addModuleToChunk(moduleId: ModuleId, chunkPath: ChunkPath) {\n let moduleChunks = moduleChunksMap.get(moduleId);\n if (!moduleChunks) {\n moduleChunks = new Set([chunkPath]);\n moduleChunksMap.set(moduleId, moduleChunks);\n } else {\n moduleChunks.add(chunkPath);\n }\n\n let chunkModules = chunkModulesMap.get(chunkPath);\n if (!chunkModules) {\n chunkModules = new Set([moduleId]);\n chunkModulesMap.set(chunkPath, chunkModules);\n } else {\n chunkModules.add(moduleId);\n }\n}\n\n/**\n * Returns the first chunk that included a module.\n * This is used by the Node.js backend, hence why it's marked as unused in this\n * file.\n */\nfunction getFirstModuleChunk(moduleId: ModuleId) {\n const moduleChunkPaths = moduleChunksMap.get(moduleId);\n if (moduleChunkPaths == null) {\n return null;\n }\n\n return moduleChunkPaths.values().next().value;\n}\n\n/**\n * Removes a module from a chunk. Returns true there are no remaining chunks\n * including this module.\n */\nfunction removeModuleFromChunk(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): boolean {\n const moduleChunks = moduleChunksMap.get(moduleId)!;\n moduleChunks.delete(chunkPath);\n\n const chunkModules = chunkModulesMap.get(chunkPath)!;\n chunkModules.delete(moduleId);\n\n const noRemainingModules = chunkModules.size === 0;\n if (noRemainingModules) {\n chunkModulesMap.delete(chunkPath);\n }\n\n const noRemainingChunks = moduleChunks.size === 0;\n if (noRemainingChunks) {\n moduleChunksMap.delete(moduleId);\n }\n\n return noRemainingChunks;\n}\n\n/**\n * Diposes of a chunk list and its corresponding exclusive chunks.\n */\nfunction disposeChunkList(chunkListPath: ChunkPath): boolean {\n const chunkPaths = chunkListChunksMap.get(chunkListPath);\n if (chunkPaths == null) {\n return false;\n }\n chunkListChunksMap.delete(chunkListPath);\n\n for (const chunkPath of chunkPaths) {\n const chunkChunkLists = chunkChunkListsMap.get(chunkPath)!;\n chunkChunkLists.delete(chunkListPath);\n\n if (chunkChunkLists.size === 0) {\n chunkChunkListsMap.delete(chunkPath);\n disposeChunk(chunkPath);\n }\n }\n\n // We must also dispose of the chunk list's chunk itself to ensure it may\n // be reloaded properly in the future.\n BACKEND.unloadChunk?.(chunkListPath);\n\n return true;\n}\n\n/**\n * Disposes of a chunk and its corresponding exclusive modules.\n *\n * @returns Whether the chunk was disposed of.\n */\nfunction disposeChunk(chunkPath: ChunkPath): boolean {\n // This should happen whether or not the chunk has any modules in it. For instance,\n // CSS chunks have no modules in them, but they still need to be unloaded.\n BACKEND.unloadChunk?.(chunkPath);\n\n const chunkModules = chunkModulesMap.get(chunkPath);\n if (chunkModules == null) {\n return false;\n }\n chunkModules.delete(chunkPath);\n\n for (const moduleId of chunkModules) {\n const moduleChunks = moduleChunksMap.get(moduleId)!;\n moduleChunks.delete(chunkPath);\n\n const noRemainingChunks = moduleChunks.size === 0;\n if (noRemainingChunks) {\n moduleChunksMap.delete(moduleId);\n disposeModule(moduleId, \"clear\");\n availableModules.delete(moduleId);\n }\n }\n\n return true;\n}\n\n/**\n * Instantiates a runtime module.\n */\nfunction instantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Gets or instantiates a runtime module.\n */\nfunction getOrInstantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n const module = moduleCache[moduleId];\n if (module) {\n if (module.error) {\n throw module.error;\n }\n return module;\n }\n\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Subscribes to chunk list updates from the update server and applies them.\n */\nfunction registerChunkList(\n chunkUpdateProvider: ChunkUpdateProvider,\n chunkList: ChunkList\n) {\n chunkUpdateProvider.push([\n chunkList.path,\n handleApply.bind(null, chunkList.path),\n ]);\n\n // Adding chunks to chunk lists and vice versa.\n const chunks = new Set(chunkList.chunks.map(getChunkPath));\n chunkListChunksMap.set(chunkList.path, chunks);\n for (const chunkPath of chunks) {\n let chunkChunkLists = chunkChunkListsMap.get(chunkPath);\n if (!chunkChunkLists) {\n chunkChunkLists = new Set([chunkList.path]);\n chunkChunkListsMap.set(chunkPath, chunkChunkLists);\n } else {\n chunkChunkLists.add(chunkList.path);\n }\n }\n\n if (chunkList.source === \"entry\") {\n markChunkListAsRuntime(chunkList.path);\n }\n}\n\n/**\n * Marks a chunk list as a runtime chunk list. There can be more than one\n * runtime chunk list. For instance, integration tests can have multiple chunk\n * groups loaded at runtime, each with its own chunk list.\n */\nfunction markChunkListAsRuntime(chunkListPath: ChunkPath) {\n runtimeChunkLists.add(chunkListPath);\n}\n\nfunction registerChunk([\n chunkPath,\n chunkModules,\n runtimeParams,\n]: ChunkRegistration) {\n for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) {\n if (!moduleFactories[moduleId]) {\n moduleFactories[moduleId] = moduleFactory;\n }\n addModuleToChunk(moduleId, chunkPath);\n }\n\n return BACKEND.registerChunk(chunkPath, runtimeParams);\n}\n\nglobalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS ??= [];\n\nconst chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS;\nif (Array.isArray(chunkListsToRegister)) {\n for (const chunkList of chunkListsToRegister) {\n registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS, chunkList);\n }\n}\n\nglobalThis.TURBOPACK_CHUNK_LISTS = {\n push: (chunkList) => {\n registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS!, chunkList);\n },\n} satisfies ChunkListProvider;\n"],"names":[],"mappings":";;;;;IAyFA;UAAK,UAAU;IAAV,WAAA,WAKH,aAAU,KAAV;IALG,WAAA,WASH,YAAS,KAAT;IATG,WAAA,WAcH,YAAS,KAAT;GAdG,eAAA;;AAwCL,MAAM,kBAAmC,OAAO,OAAO;AACvD,MAAM,cAA2B,OAAO,OAAO;AAK/C,MAAM,gBAAwC,IAAI;AAIlD,MAAM,iBAAwC,IAAI;AAIlD,MAAM,iBAAgC,IAAI;AAQ1C,MAAM,kBAAiD,IAAI;AAI3D,MAAM,kBAAiD,IAAI;AAM3D,MAAM,oBAAoC,IAAI;AAI9C,MAAM,qBAAqD,IAAI;AAI/D,MAAM,qBAAqD,IAAI;AAE/D,MAAM,yBAAiD,CACrD,OACA;IAEA,OAAO,MAAM,WACT,gBAAgB,cAAc,MAAM,QACpC,gBAAgB,MAAM,MAAM;AAClC;AAEA,SAAS,gBACP,EAAY,EACZ,MAAe,KAAK;IAEpB,IAAI;IACJ,IAAI;QACF,MAAM,QAAQ;IAChB,EAAE,OAAO,KAAK;QAKZ,MAAM,IAAI,MAAM,CAAC,+BAA+B,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC;IAChE;IACA,IAAI,CAAC,KAAK;QACR,OAAO;IACT;IACA,MAAM,KAAK,CAAC;IACZ,WAAW,KAAK,IAAI,IAAI;IACxB,OAAO;AACT;AACA,gBAAgB,UAAU,CACxB,IACA;IAMA,OAAO,QAAQ,QAAQ,IAAI;AAC7B;AAEA,MAAM,mBAAuD,IAAI;AAEjE,MAAM,wBAA6D,IAAI;AAEvE,eAAe,UACb,MAAkB,EAClB,SAAoB;IAEpB,IAAI,OAAO,cAAc,UAAU;QACjC,OAAO,cAAc,QAAQ;IAC/B;IAEA,MAAM,eAAe,UAAU,YAAY,EAAE;IAC7C,MAAM,kBAAkB,aAAa,IAAI,CAAC;QACxC,IAAI,eAAe,CAAC,SAAS,EAAE,OAAO;QACtC,OAAO,iBAAiB,IAAI;IAC9B;IACA,IAAI,gBAAgB,SAAS,KAAK,gBAAgB,MAAM,CAAC,IAAM,IAAI;QAEjE,OAAO,QAAQ,IAAI;IACrB;IAEA,MAAM,2BAA2B,UAAU,gBAAgB,EAAE;IAC7D,MAAM,uBAAuB,yBAC1B,IAAI,CAAC;QAGJ,OAAO,sBAAsB,IAAI;IACnC,GACC,OAAO,CAAC,IAAM;IAEjB,IAAI;IACJ,IAAI,qBAAqB,SAAS,GAAG;QAGnC,IAAI,qBAAqB,UAAU,yBAAyB,QAAQ;YAElE,OAAO,QAAQ,IAAI;QACrB;QAEA,MAAM,qBAAqC,IAAI;QAC/C,KAAK,MAAM,eAAe,yBAA0B;YAClD,IAAI,CAAC,sBAAsB,IAAI,cAAc;gBAC3C,mBAAmB,IAAI;YACzB;QACF;QAEA,KAAK,MAAM,qBAAqB,mBAAoB;YAClD,MAAM,UAAU,cAAc,QAAQ;YAEtC,sBAAsB,IAAI,mBAAmB;YAE7C,qBAAqB,KAAK;QAC5B;QAEA,UAAU,QAAQ,IAAI;IACxB,OAAO;QACL,UAAU,cAAc,QAAQ,UAAU;QAG1C,KAAK,MAAM,uBAAuB,yBAA0B;YAC1D,IAAI,CAAC,sBAAsB,IAAI,sBAAsB;gBACnD,sBAAsB,IAAI,qBAAqB;YACjD;QACF;IACF;IAEA,KAAK,MAAM,YAAY,aAAc;QACnC,IAAI,CAAC,iBAAiB,IAAI,WAAW;YAGnC,iBAAiB,IAAI,UAAU;QACjC;IACF;IAEA,OAAO;AACT;AAEA,eAAe,cACb,MAAkB,EAClB,SAAoB;IAEpB,IAAI;QACF,MAAM,QAAQ,UAAU,WAAW;IACrC,EAAE,OAAO,OAAO;QACd,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,aAAa,CAAC,iCAAiC,EAAE,OAAO,UAAU,CAAC;gBACnE;YACF,KAAK,WAAW;gBACd,aAAa,CAAC,YAAY,EAAE,OAAO,SAAS,CAAC;gBAC7C;YACF,KAAK,WAAW;gBACd,aAAa;gBACb;QACJ;QACA,MAAM,IAAI,MACR,CAAC,qBAAqB,EAAE,UAAU,CAAC,EAAE,WAAW,EAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,GACxB,CAAC;IAEN;AACF;AAEA,SAAS,kBAAkB,EAAY,EAAE,MAAkB;IACzD,MAAM,gBAAgB,eAAe,CAAC,GAAG;IACzC,IAAI,OAAO,kBAAkB,YAAY;QAIvC,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,sBAAsB,CAAC,4BAA4B,EAAE,OAAO,UAAU,CAAC;gBACvE;YACF,KAAK,WAAW;gBACd,sBAAsB,CAAC,oCAAoC,EAAE,OAAO,SAAS,CAAC;gBAC9E;YACF,KAAK,WAAW;gBACd,sBAAsB;gBACtB;QACJ;QACA,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,oBAAoB,uFAAuF,CAAC;IAEjJ;IAEA,MAAM,UAAU,cAAc,IAAI;IAClC,MAAM,EAAE,IAAG,EAAE,SAAQ,EAAE,GAAG,gBAAgB;IAE1C,IAAI;IACJ,OAAQ,OAAO;QACb,KAAK,WAAW;YACd,eAAe,IAAI;YACnB,UAAU,EAAE;YACZ;QACF,KAAK,WAAW;YAGd,UAAU;gBAAC,OAAO;aAAS;YAC3B;QACF,KAAK,WAAW;YACd,UAAU,OAAO,WAAW,EAAE;YAC9B;IACJ;IACA,MAAM,SAAiB;QACrB,SAAS,CAAC;QACV,OAAO;QACP,QAAQ;QACR;QACA;QACA,UAAU,EAAE;QACZ,iBAAiB;QACjB;IACF;IAEA,WAAW,CAAC,GAAG,GAAG;IAClB,eAAe,IAAI,QAAQ;IAG3B,IAAI;QACF,wBAAwB,QAAQ,CAAC;YAC/B,cAAc,KAAK,OAAO,SAAS;gBACjC,GAAG,OAAO;gBACV,GAAG,gBAAgB,KAAK,MAAM;gBAC9B,GAAG;gBACH,GAAG,eAAe,KAAK,MAAM;gBAC7B,GAAG,UAAU,KAAK,MAAM;gBACxB,GAAG,UAAU,KAAK,MAAM;gBACxB,GAAG,UAAU,KAAK,MAAM,OAAO;gBAC/B,GAAG,YAAY,KAAK,MAAM;gBAC1B,GAAG,gBAAgB,KAAK,MAAM;gBAC9B,GAAG;gBACH,GAAG;gBACH,GAAG,UAAU,KAAK,MAAM;oBAAE,MAAM,WAAW;oBAAQ,UAAU;gBAAG;gBAChE,GAAG;gBACH,GAAG;gBACH,WAAW,OAAO,GAAG,QAAQ,gBAAgB;YAC/C;QACF;IACF,EAAE,OAAO,OAAO;QACd,OAAO,QAAQ;QACf,MAAM;IACR;IAEA,OAAO,SAAS;IAChB,IAAI,OAAO,mBAAmB,OAAO,YAAY,OAAO,iBAAiB;QAEvE,WAAW,OAAO,SAAS,OAAO;IACpC;IAEA,OAAO;AACT;AAOA,SAAS,wBACP,MAAc,EACd,aAA4C;IAE5C,MAAM,+BACJ,OAAO,WAAW,sCAAsC,aACpD,WAAW,kCAAkC,OAAO,MACpD,KAAO;IAEb,IAAI;QACF,cAAc;YACZ,UAAU,WAAW;YACrB,WAAW,WAAW;QACxB;QAEA,IAAI,sBAAsB,YAAY;YAGpC,+CACE,QACA,WAAW;QAEf;IACF,EAAE,OAAO,GAAG;QACV,MAAM;IACR,SAAU;QAER;IACF;AACF;AAKA,MAAM,mCAAqE,CACzE,IACA;IAEA,IAAI,CAAC,aAAa,IAAI,QAAQ;QAC5B,QAAQ,KACN,CAAC,4BAA4B,EAAE,GAAG,aAAa,EAAE,aAAa,GAAG,oCAAoC,CAAC;IAE1G;IAEA,MAAM,SAAS,WAAW,CAAC,GAAG;IAE9B,IAAI,aAAa,SAAS,QAAQ,QAAQ,CAAC,GAAG;QAC5C,aAAa,SAAS,KAAK;IAC7B;IAEA,IAAI,QAAQ;QACV,IAAI,OAAO,QAAQ,QAAQ,aAAa,QAAQ,CAAC,GAAG;YAClD,OAAO,QAAQ,KAAK,aAAa;QACnC;QAEA,OAAO;IACT;IAEA,OAAO,kBAAkB,IAAI;QAC3B,MAAM,WAAW;QACjB,UAAU,aAAa;IACzB;AACF;AAKA,SAAS,+CACP,MAAc,EACd,OAAuB;IAEvB,MAAM,iBAAiB,OAAO;IAC9B,MAAM,cAAc,OAAO,IAAI,KAAK,eAAe;IAEnD,QAAQ,+BAA+B,gBAAgB,OAAO;IAI9D,IAAI,QAAQ,uBAAuB,iBAAiB;QAGlD,OAAO,IAAI,QAAQ,CAAC;YAClB,KAAK,cAAc;QACrB;QAGA,OAAO,IAAI;QAKX,IAAI,gBAAgB,MAAM;YAQxB,IACE,QAAQ,qCACN,aACA,iBAEF;gBACA,OAAO,IAAI;YACb,OAAO;gBACL,QAAQ;YACV;QACF;IACF,OAAO;QAKL,MAAM,sBAAsB,gBAAgB;QAC5C,IAAI,qBAAqB;YACvB,OAAO,IAAI;QACb;IACF;AACF;AAEA,SAAS,sBAAsB,eAA2B;IACxD,OAAO,CAAC,kBAAkB,EAAE,gBAAgB,KAAK,QAAQ,CAAC;AAC5D;AAEA,SAAS,uBACP,KAAuD,EACvD,QAA8C;IAE9C,MAAM,kBAAkB,IAAI;IAC5B,MAAM,qBAAqB,IAAI;IAE/B,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,MAAO;QACrC,IAAI,SAAS,MAAM;YACjB,mBAAmB,IAAI,UAAU,MAAM;QACzC;IACF;IAEA,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,SAAU;QACxC,MAAM,SAAS,yBAAyB;QAExC,OAAQ,OAAO;YACb,KAAK;gBACH,MAAM,IAAI,MACR,CAAC,wCAAwC,EAAE,sBACzC,OAAO,iBACP,CAAC,CAAC;YAER,KAAK;gBACH,MAAM,IAAI,MACR,CAAC,2CAA2C,EAAE,sBAC5C,OAAO,iBACP,CAAC,CAAC;YAER,KAAK;gBACH,mBAAmB,IAAI,UAAU,MAAM;gBACvC,KAAK,MAAM,oBAAoB,OAAO,gBAAiB;oBACrD,gBAAgB,IAAI;gBACtB;gBACA;QAEJ;IACF;IAEA,OAAO;QAAE;QAAiB;IAAmB;AAC/C;AAEA,SAAS,mCACP,eAAmC;IAEnC,MAAM,8BAA8B,EAAE;IACtC,KAAK,MAAM,YAAY,gBAAiB;QACtC,MAAM,SAAS,WAAW,CAAC,SAAS;QACpC,MAAM,WAAW,eAAe,IAAI;QACpC,IAAI,UAAU,SAAS,gBAAgB,CAAC,SAAS,iBAAiB;YAChE,4BAA4B,KAAK;gBAC/B;gBACA,cAAc,SAAS;YACzB;QACF;IACF;IACA,OAAO;AACT;AAOA,SAAS,kBACP,kBAAiD,EACjD,oBAAmD;IAEnD,KAAK,MAAM,CAAC,WAAW,eAAe,IAAI,mBAAoB;QAC5D,KAAK,MAAM,YAAY,eAAgB;YACrC,iBAAiB,UAAU;QAC7B;IACF;IAEA,MAAM,kBAAiC,IAAI;IAC3C,KAAK,MAAM,CAAC,WAAW,eAAe,IAAI,qBAAsB;QAC9D,KAAK,MAAM,YAAY,eAAgB;YACrC,IAAI,sBAAsB,UAAU,YAAY;gBAC9C,gBAAgB,IAAI;YACtB;QACF;IACF;IAEA,OAAO;QAAE;IAAgB;AAC3B;AAEA,SAAS,aACP,eAAmC,EACnC,eAA8B;IAE9B,KAAK,MAAM,YAAY,gBAAiB;QACtC,cAAc,UAAU;IAC1B;IAEA,KAAK,MAAM,YAAY,gBAAiB;QACtC,cAAc,UAAU;IAC1B;IAIA,MAAM,wBAAwB,IAAI;IAClC,KAAK,MAAM,YAAY,gBAAiB;QACtC,MAAM,YAAY,WAAW,CAAC,SAAS;QACvC,sBAAsB,IAAI,UAAU,WAAW;QAC/C,OAAO,WAAW,CAAC,SAAS;IAC9B;IAKA,OAAO;QAAE;IAAsB;AACjC;AAeA,SAAS,cAAc,QAAkB,EAAE,IAAyB;IAClE,MAAM,SAAS,WAAW,CAAC,SAAS;IACpC,IAAI,CAAC,QAAQ;QACX;IACF;IAEA,MAAM,WAAW,eAAe,IAAI;IACpC,MAAM,OAAO,CAAC;IAId,KAAK,MAAM,kBAAkB,SAAS,gBAAiB;QACrD,eAAe;IACjB;IAIA,OAAO,IAAI,SAAS;IAEpB,eAAe,OAAO;IAOtB,KAAK,MAAM,WAAW,OAAO,SAAU;QACrC,MAAM,QAAQ,WAAW,CAAC,QAAQ;QAClC,IAAI,CAAC,OAAO;YACV;QACF;QAEA,MAAM,MAAM,MAAM,QAAQ,QAAQ,OAAO;QACzC,IAAI,OAAO,GAAG;YACZ,MAAM,QAAQ,OAAO,KAAK;QAC5B;IACF;IAEA,OAAQ;QACN,KAAK;YACH,OAAO,WAAW,CAAC,OAAO,GAAG;YAC7B,cAAc,OAAO,OAAO;YAC5B;QACF,KAAK;YACH,cAAc,IAAI,OAAO,IAAI;YAC7B;QACF;YACE,UAAU,MAAM,CAAC,OAAS,CAAC,cAAc,EAAE,KAAK,CAAC;IACrD;AACF;AAEA,SAAS,WACP,2BAGG,EACH,kBAAgD,EAChD,qBAAqD;IAGrD,KAAK,MAAM,CAAC,UAAU,QAAQ,IAAI,mBAAmB,UAAW;QAC9D,eAAe,CAAC,SAAS,GAAG;IAC9B;IAOA,KAAK,MAAM,EAAE,SAAQ,EAAE,aAAY,EAAE,IAAI,4BAA6B;QACpE,IAAI;YACF,kBAAkB,UAAU;gBAC1B,MAAM,WAAW;gBACjB,SAAS,sBAAsB,IAAI;YACrC;QACF,EAAE,OAAO,KAAK;YACZ,IAAI,OAAO,iBAAiB,YAAY;gBACtC,IAAI;oBACF,aAAa,KAAK;wBAAE;wBAAU,QAAQ,WAAW,CAAC,SAAS;oBAAC;gBAC9D,EAAE,OAAO,GAAG,CAEZ;YACF;QACF;IACF;AACF;AAKA,SAAS,UAAU,KAAY,EAAE,cAAoC;IACnE,MAAM,IAAI,MAAM,CAAC,WAAW,EAAE,eAAe,OAAO,CAAC;AACvD;AAEA,SAAS,YAAY,aAAwB,EAAE,MAAqB;IAClE,OAAQ,OAAO;QACb,KAAK;YACH,qBAAqB,eAAe;YACpC;QACF;YACE,UAAU,QAAQ,CAAC,SAAW,CAAC,qBAAqB,EAAE,OAAO,KAAK,CAAC;IACvE;AACF;AAEA,SAAS,qBACP,aAAwB,EACxB,MAAuB;IAEvB,IAAI,OAAO,UAAU,MAAM;QACzB,KAAK,MAAM,UAAU,OAAO,OAAQ;YAClC,OAAQ,OAAO;gBACb,KAAK;oBACH,4BAA4B,eAAe;oBAC3C;gBACF;oBACE,UAAU,QAAQ,CAAC,SAAW,CAAC,qBAAqB,EAAE,OAAO,KAAK,CAAC;YACvE;QACF;IACF;IAEA,IAAI,OAAO,UAAU,MAAM;QACzB,KAAK,MAAM,CAAC,WAAW,YAAY,IAAI,OAAO,QAAQ,OAAO,QAAS;YACpE,OAAQ,YAAY;gBAClB,KAAK;oBACH,QAAQ,UAAU,WAAW;wBAAE,MAAM,WAAW;oBAAO;oBACvD;gBACF,KAAK;oBACH,QAAQ,cAAc;oBACtB;gBACF,KAAK;oBACH,QAAQ,cAAc;oBACtB;gBACF,KAAK;oBACH,UACE,YAAY,aACZ,CAAC,cACC,CAAC,6BAA6B,EAAE,KAAK,UAAU,aAAa,CAAC,CAAC;gBAEpE;oBACE,UACE,aACA,CAAC,cAAgB,CAAC,2BAA2B,EAAE,YAAY,KAAK,CAAC;YAEvE;QACF;IACF;AACF;AAEA,SAAS,4BACP,SAAoB,EACpB,MAA8B;IAE9B,MAAM,EAAE,SAAU,CAAC,EAAC,EAAE,QAAS,CAAC,EAAC,EAAE,GAAG;IACtC,MAAM,EAAE,MAAK,EAAE,SAAQ,EAAE,QAAO,EAAE,YAAW,EAAE,cAAa,EAAE,GAC5D,sBAAsB,SAAS;IACjC,MAAM,EAAE,gBAAe,EAAE,mBAAkB,EAAE,GAAG,uBAC9C,OACA;IAEF,MAAM,8BACJ,mCAAmC;IACrC,MAAM,EAAE,gBAAe,EAAE,GAAG,kBAAkB,aAAa;IAC3D,MAAM,EAAE,sBAAqB,EAAE,GAAG,aAChC,iBACA;IAEF,WACE,6BACA,oBACA;AAEJ;AAEA,SAAS,sBACP,OAAgD,EAChD,OAAuD;IAQvD,MAAM,cAAc,IAAI;IACxB,MAAM,gBAAgB,IAAI;IAC1B,MAAM,QAA8C,IAAI;IACxD,MAAM,WAAW,IAAI;IACrB,MAAM,UAAyB,IAAI;IAEnC,KAAK,MAAM,CAAC,WAAW,kBAAkB,IAAI,OAAO,QAAQ,SAAU;QACpE,OAAQ,kBAAkB;YACxB,KAAK;gBAAS;oBACZ,MAAM,cAAc,IAAI,IAAI,kBAAkB;oBAC9C,KAAK,MAAM,YAAY,YAAa;wBAClC,MAAM,IAAI,UAAU,OAAO,CAAC,SAAS;oBACvC;oBACA,YAAY,IAAI,WAAW;oBAC3B;gBACF;YACA,KAAK;gBAAW;oBAEd,MAAM,gBAAgB,IAAI,IAAI,gBAAgB,IAAI;oBAClD,KAAK,MAAM,YAAY,cAAe;wBACpC,QAAQ,IAAI;oBACd;oBACA,cAAc,IAAI,WAAW;oBAC7B;gBACF;YACA,KAAK;gBAAW;oBACd,MAAM,cAAc,IAAI,IAAI,kBAAkB;oBAC9C,MAAM,gBAAgB,IAAI,IAAI,kBAAkB;oBAChD,KAAK,MAAM,YAAY,YAAa;wBAClC,MAAM,IAAI,UAAU,OAAO,CAAC,SAAS;oBACvC;oBACA,KAAK,MAAM,YAAY,cAAe;wBACpC,QAAQ,IAAI;oBACd;oBACA,YAAY,IAAI,WAAW;oBAC3B,cAAc,IAAI,WAAW;oBAC7B;gBACF;YACA;gBACE,UACE,mBACA,CAAC,oBACC,CAAC,kCAAkC,EAAE,kBAAkB,KAAK,CAAC;QAErE;IACF;IAKA,KAAK,MAAM,YAAY,MAAM,OAAQ;QACnC,IAAI,QAAQ,IAAI,WAAW;YACzB,MAAM,OAAO;YACb,QAAQ,OAAO;QACjB;IACF;IAEA,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,OAAO,QAAQ,SAAU;QAKvD,IAAI,CAAC,MAAM,IAAI,WAAW;YACxB,SAAS,IAAI,UAAU;QACzB;IACF;IAEA,OAAO;QAAE;QAAO;QAAS;QAAU;QAAa;IAAc;AAChE;AAkBA,SAAS,yBAAyB,QAAkB;IAClD,MAAM,kBAAiC,IAAI;IAI3C,MAAM,QAAqB;QACzB;YACE;YACA,iBAAiB,EAAE;QACrB;KACD;IAED,IAAI;IACJ,MAAQ,WAAW,MAAM,QAAU;QACjC,MAAM,EAAE,SAAQ,EAAE,gBAAe,EAAE,GAAG;QAEtC,IAAI,YAAY,MAAM;YACpB,gBAAgB,IAAI;QACtB;QAIA,IAAI,aAAa,WAAW;YAC1B,OAAO;gBACL,MAAM;gBACN;YACF;QACF;QAEA,MAAM,SAAS,WAAW,CAAC,SAAS;QACpC,MAAM,WAAW,eAAe,IAAI;QAEpC,IAGE,CAAC,UAEA,SAAS,gBAAgB,CAAC,SAAS,iBACpC;YACA;QACF;QAEA,IAAI,SAAS,cAAc;YACzB,OAAO;gBACL,MAAM;gBACN;gBACA;YACF;QACF;QAEA,IAAI,eAAe,IAAI,WAAW;YAChC,MAAM,KAAK;gBACT,UAAU;gBACV,iBAAiB;uBAAI;oBAAiB;iBAAS;YACjD;YACA;QACF;QAEA,KAAK,MAAM,YAAY,OAAO,QAAS;YACrC,MAAM,SAAS,WAAW,CAAC,SAAS;YAEpC,IAAI,CAAC,QAAQ;gBAEX;YACF;YAKA,MAAM,KAAK;gBACT,UAAU;gBACV,iBAAiB;uBAAI;oBAAiB;iBAAS;YACjD;QACF;IACF;IAEA,OAAO;QACL,MAAM;QACN;QACA;IACF;AACF;AAEA,SAAS,YAAY,aAAwB,EAAE,MAAqB;IAClE,OAAQ,OAAO;QACb,KAAK;YAAW;gBAEd,YAAY,eAAe,OAAO;gBAClC;YACF;QACA,KAAK;YAAW;gBAId,QAAQ;gBACR;YACF;QACA,KAAK;YAAY;gBAKf,IAAI,kBAAkB,IAAI,gBAAgB;oBACxC,QAAQ;gBACV,OAAO;oBACL,iBAAiB;gBACnB;gBACA;YACF;QACA;YACE,MAAM,IAAI,MAAM,CAAC,qBAAqB,EAAE,OAAO,KAAK,CAAC;IACzD;AACF;AAEA,SAAS,gBAAgB,OAAgB;IACvC,MAAM,WAAqB;QACzB,cAAc;QACd,cAAc;QACd,iBAAiB;QACjB,iBAAiB,EAAE;IACrB;IAEA,MAAM,MAAW;QAIf,QAAQ;QAER,MAAM,WAAW,CAAC;QAGlB,QAAQ,CACN,SACA,WACA;YAEA,IAAI,YAAY,WAAW;gBACzB,SAAS,eAAe;YAC1B,OAAO,IAAI,OAAO,YAAY,YAAY;gBACxC,SAAS,eAAe;YAC1B,OAAO;gBACL,MAAM,IAAI,MAAM;YAClB;QACF;QAEA,SAAS,CAAC;YACR,IAAI,QAAQ,WAAW;gBACrB,SAAS,eAAe;YAC1B,OAAO;gBACL,MAAM,IAAI,MAAM;YAClB;QACF;QAEA,SAAS,CAAC;YACR,SAAS,gBAAgB,KAAK;QAChC;QAEA,mBAAmB,CAAC;YAClB,SAAS,gBAAgB,KAAK;QAChC;QAEA,sBAAsB,CAAC;YACrB,MAAM,MAAM,SAAS,gBAAgB,QAAQ;YAC7C,IAAI,OAAO,GAAG;gBACZ,SAAS,gBAAgB,OAAO,KAAK;YACvC;QACF;QAEA,YAAY;YACV,SAAS,kBAAkB;QAG7B;QAKA,QAAQ,IAAM;QAGd,kBAAkB,CAAC,YAAc;QACjC,qBAAqB,CAAC,YAAc;IACtC;IAEA,OAAO;QAAE;QAAK;IAAS;AACzB;AAKA,SAAS,iBAAiB,QAAkB,EAAE,SAAoB;IAChE,IAAI,eAAe,gBAAgB,IAAI;IACvC,IAAI,CAAC,cAAc;QACjB,eAAe,IAAI,IAAI;YAAC;SAAU;QAClC,gBAAgB,IAAI,UAAU;IAChC,OAAO;QACL,aAAa,IAAI;IACnB;IAEA,IAAI,eAAe,gBAAgB,IAAI;IACvC,IAAI,CAAC,cAAc;QACjB,eAAe,IAAI,IAAI;YAAC;SAAS;QACjC,gBAAgB,IAAI,WAAW;IACjC,OAAO;QACL,aAAa,IAAI;IACnB;AACF;AAOA,SAAS,oBAAoB,QAAkB;IAC7C,MAAM,mBAAmB,gBAAgB,IAAI;IAC7C,IAAI,oBAAoB,MAAM;QAC5B,OAAO;IACT;IAEA,OAAO,iBAAiB,SAAS,OAAO;AAC1C;AAMA,SAAS,sBACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,eAAe,gBAAgB,IAAI;IACzC,aAAa,OAAO;IAEpB,MAAM,eAAe,gBAAgB,IAAI;IACzC,aAAa,OAAO;IAEpB,MAAM,qBAAqB,aAAa,SAAS;IACjD,IAAI,oBAAoB;QACtB,gBAAgB,OAAO;IACzB;IAEA,MAAM,oBAAoB,aAAa,SAAS;IAChD,IAAI,mBAAmB;QACrB,gBAAgB,OAAO;IACzB;IAEA,OAAO;AACT;AAKA,SAAS,iBAAiB,aAAwB;IAChD,MAAM,aAAa,mBAAmB,IAAI;IAC1C,IAAI,cAAc,MAAM;QACtB,OAAO;IACT;IACA,mBAAmB,OAAO;IAE1B,KAAK,MAAM,aAAa,WAAY;QAClC,MAAM,kBAAkB,mBAAmB,IAAI;QAC/C,gBAAgB,OAAO;QAEvB,IAAI,gBAAgB,SAAS,GAAG;YAC9B,mBAAmB,OAAO;YAC1B,aAAa;QACf;IACF;IAIA,QAAQ,cAAc;IAEtB,OAAO;AACT;AAOA,SAAS,aAAa,SAAoB;IAGxC,QAAQ,cAAc;IAEtB,MAAM,eAAe,gBAAgB,IAAI;IACzC,IAAI,gBAAgB,MAAM;QACxB,OAAO;IACT;IACA,aAAa,OAAO;IAEpB,KAAK,MAAM,YAAY,aAAc;QACnC,MAAM,eAAe,gBAAgB,IAAI;QACzC,aAAa,OAAO;QAEpB,MAAM,oBAAoB,aAAa,SAAS;QAChD,IAAI,mBAAmB;YACrB,gBAAgB,OAAO;YACvB,cAAc,UAAU;YACxB,iBAAiB,OAAO;QAC1B;IACF;IAEA,OAAO;AACT;AAKA,SAAS,yBACP,QAAkB,EAClB,SAAoB;IAEpB,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,8BACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,SAAS,WAAW,CAAC,SAAS;IACpC,IAAI,QAAQ;QACV,IAAI,OAAO,OAAO;YAChB,MAAM,OAAO;QACf;QACA,OAAO;IACT;IAEA,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,kBACP,mBAAwC,EACxC,SAAoB;IAEpB,oBAAoB,KAAK;QACvB,UAAU;QACV,YAAY,KAAK,MAAM,UAAU;KAClC;IAGD,MAAM,SAAS,IAAI,IAAI,UAAU,OAAO,IAAI;IAC5C,mBAAmB,IAAI,UAAU,MAAM;IACvC,KAAK,MAAM,aAAa,OAAQ;QAC9B,IAAI,kBAAkB,mBAAmB,IAAI;QAC7C,IAAI,CAAC,iBAAiB;YACpB,kBAAkB,IAAI,IAAI;gBAAC,UAAU;aAAK;YAC1C,mBAAmB,IAAI,WAAW;QACpC,OAAO;YACL,gBAAgB,IAAI,UAAU;QAChC;IACF;IAEA,IAAI,UAAU,WAAW,SAAS;QAChC,uBAAuB,UAAU;IACnC;AACF;AAOA,SAAS,uBAAuB,aAAwB;IACtD,kBAAkB,IAAI;AACxB;AAEA,SAAS,cAAc,CACrB,WACA,cACA,cACkB;IAClB,KAAK,MAAM,CAAC,UAAU,cAAc,IAAI,OAAO,QAAQ,cAAe;QACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9B,eAAe,CAAC,SAAS,GAAG;QAC9B;QACA,iBAAiB,UAAU;IAC7B;IAEA,OAAO,QAAQ,cAAc,WAAW;AAC1C;AAEA,WAAW,qCAAqC,EAAE;AAElD,MAAM,uBAAuB,WAAW;AACxC,IAAI,MAAM,QAAQ,uBAAuB;IACvC,KAAK,MAAM,aAAa,qBAAsB;QAC5C,kBAAkB,WAAW,kCAAkC;IACjE;AACF;AAEA,WAAW,wBAAwB;IACjC,MAAM,CAAC;QACL,kBAAkB,WAAW,kCAAmC;IAClE;AACF"}}, - {"offset": {"line": 891, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/dev/runtime/dom/runtime-backend-dom.ts"],"sourcesContent":["/**\n * This file contains the runtime code specific to the Turbopack development\n * ECMAScript DOM runtime.\n *\n * It will be appended to the base development runtime code.\n */\n\n/// \n\ntype ChunkResolver = {\n resolved: boolean;\n resolve: () => void;\n reject: (error?: Error) => void;\n promise: Promise;\n};\n\nlet BACKEND: RuntimeBackend;\n\n(() => {\n BACKEND = {\n async registerChunk(chunkPath, params) {\n const resolver = getOrCreateResolver(chunkPath);\n resolver.resolve();\n\n if (params == null) {\n return;\n }\n\n for (const otherChunkData of params.otherChunks) {\n const otherChunkPath = getChunkPath(otherChunkData);\n // Chunk might have started loading, so we want to avoid triggering another load.\n getOrCreateResolver(otherChunkPath);\n }\n\n // This waits for chunks to be loaded, but also marks included items as available.\n await Promise.all(\n params.otherChunks.map((otherChunkData) =>\n loadChunk({ type: SourceType.Runtime, chunkPath }, otherChunkData)\n )\n );\n\n if (params.runtimeModuleIds.length > 0) {\n for (const moduleId of params.runtimeModuleIds) {\n getOrInstantiateRuntimeModule(moduleId, chunkPath);\n }\n }\n },\n\n loadChunk(chunkPath, source) {\n return doLoadChunk(chunkPath, source);\n },\n\n unloadChunk(chunkPath) {\n deleteResolver(chunkPath);\n\n if (chunkPath.endsWith(\".css\")) {\n const links = document.querySelectorAll(`link[href=\"/${chunkPath}\"]`);\n for (const link of Array.from(links)) {\n link.remove();\n }\n } else if (chunkPath.endsWith(\".js\")) {\n // Unloading a JS chunk would have no effect, as it lives in the JS\n // runtime once evaluated.\n // However, we still want to remove the script tag from the DOM to keep\n // the HTML somewhat consistent from the user's perspective.\n const scripts = document.querySelectorAll(\n `script[src=\"/${chunkPath}\"]`\n );\n for (const script of Array.from(scripts)) {\n script.remove();\n }\n } else {\n throw new Error(`can't infer type of chunk from path ${chunkPath}`);\n }\n },\n\n reloadChunk(chunkPath) {\n return new Promise((resolve, reject) => {\n if (!chunkPath.endsWith(\".css\")) {\n reject(new Error(\"The DOM backend can only reload CSS chunks\"));\n return;\n }\n\n const encodedChunkPath = chunkPath\n .split(\"/\")\n .map((p) => encodeURIComponent(p))\n .join(\"/\");\n\n const previousLink = document.querySelector(\n `link[rel=stylesheet][href^=\"/${encodedChunkPath}\"]`\n );\n\n if (previousLink == null) {\n reject(new Error(`No link element found for chunk ${chunkPath}`));\n return;\n }\n\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = `/${encodedChunkPath}`;\n link.onerror = () => {\n reject();\n };\n link.onload = () => {\n // First load the new CSS, then remove the old one. This prevents visible\n // flickering that would happen in-between removing the previous CSS and\n // loading the new one.\n previousLink.remove();\n\n // CSS chunks do not register themselves, and as such must be marked as\n // loaded instantly.\n resolve();\n };\n\n // Make sure to insert the new CSS right after the previous one, so that\n // its precedence is higher.\n previousLink.parentElement!.insertBefore(\n link,\n previousLink.nextSibling\n );\n });\n },\n\n restart: () => self.location.reload(),\n };\n\n /**\n * Maps chunk paths to the corresponding resolver.\n */\n const chunkResolvers: Map = new Map();\n\n function getOrCreateResolver(chunkPath: ChunkPath): ChunkResolver {\n let resolver = chunkResolvers.get(chunkPath);\n if (!resolver) {\n let resolve: () => void;\n let reject: (error?: Error) => void;\n const promise = new Promise((innerResolve, innerReject) => {\n resolve = innerResolve;\n reject = innerReject;\n });\n resolver = {\n resolved: false,\n promise,\n resolve: () => {\n resolver!.resolved = true;\n resolve();\n },\n reject: reject!,\n };\n chunkResolvers.set(chunkPath, resolver);\n }\n return resolver;\n }\n\n function deleteResolver(chunkPath: ChunkPath) {\n chunkResolvers.delete(chunkPath);\n }\n\n /**\n * Loads the given chunk, and returns a promise that resolves once the chunk\n * has been loaded.\n */\n async function doLoadChunk(chunkPath: ChunkPath, source: SourceInfo) {\n const resolver = getOrCreateResolver(chunkPath);\n if (resolver.resolved) {\n return resolver.promise;\n }\n\n if (source.type === SourceType.Runtime) {\n // We don't need to load chunks references from runtime code, as they're already\n // present in the DOM.\n\n if (chunkPath.endsWith(\".css\")) {\n // CSS chunks do not register themselves, and as such must be marked as\n // loaded instantly.\n resolver.resolve();\n }\n\n // We need to wait for JS chunks to register themselves within `registerChunk`\n // before we can start instantiating runtime modules, hence the absence of\n // `resolver.resolve()` in this branch.\n\n return resolver.promise;\n }\n\n if (chunkPath.endsWith(\".css\")) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = `/${chunkPath}`;\n link.onerror = () => {\n resolver.reject();\n };\n link.onload = () => {\n // CSS chunks do not register themselves, and as such must be marked as\n // loaded instantly.\n resolver.resolve();\n };\n document.body.appendChild(link);\n } else if (chunkPath.endsWith(\".js\")) {\n const script = document.createElement(\"script\");\n script.src = `/${chunkPath}`;\n // We'll only mark the chunk as loaded once the script has been executed,\n // which happens in `registerChunk`. Hence the absence of `resolve()` in\n // this branch.\n script.onerror = () => {\n resolver.reject();\n };\n document.body.appendChild(script);\n } else {\n throw new Error(`can't infer type of chunk from path ${chunkPath}`);\n }\n\n return resolver.promise;\n }\n})();\n\nfunction _eval({ code, url, map }: EcmascriptModuleEntry): ModuleFactory {\n code += `\\n\\n//# sourceURL=${location.origin}${url}`;\n if (map) code += `\\n//# sourceMappingURL=${map}`;\n return eval(code);\n}\n"],"names":[],"mappings":"AAgBA,IAAI;AAEH,CAAA;IACC,UAAU;QACR,MAAM,eAAc,UAAS,EAAE,OAAM;YACnC,MAAM,YAAW,qBAAoB;YACrC,UAAS;YAET,IAAI,WAAU,MAAM;gBAClB;YACF;YAEA,KAAK,MAAM,mBAAkB,QAAO,YAAa;gBAC/C,MAAM,kBAAiB,aAAa;gBAEpC,qBAAoB;YACtB;YAGA,MAAM,QAAQ,IACZ,QAAO,YAAY,IAAI,CAAC,kBACtB,UAAU;oBAAE,MAAM,WAAW;oBAAS,WAAA;gBAAU,GAAG;YAIvD,IAAI,QAAO,iBAAiB,SAAS,GAAG;gBACtC,KAAK,MAAM,aAAY,QAAO,iBAAkB;oBAC9C,8BAA8B,WAAU;gBAC1C;YACF;QACF;QAEA,WAAU,UAAS,EAAE,OAAM;YACzB,OAAO,aAAY,YAAW;QAChC;QAEA,aAAY,UAAS;YACnB,gBAAe;YAEf,IAAI,WAAU,SAAS,SAAS;gBAC9B,MAAM,SAAQ,SAAS,iBAAiB,CAAC,YAAY,EAAE,WAAU,EAAE,CAAC;gBACpE,KAAK,MAAM,SAAQ,MAAM,KAAK,QAAQ;oBACpC,MAAK;gBACP;YACF,OAAO,IAAI,WAAU,SAAS,QAAQ;gBAKpC,MAAM,WAAU,SAAS,iBACvB,CAAC,aAAa,EAAE,WAAU,EAAE,CAAC;gBAE/B,KAAK,MAAM,WAAU,MAAM,KAAK,UAAU;oBACxC,QAAO;gBACT;YACF,OAAO;gBACL,MAAM,IAAI,MAAM,CAAC,oCAAoC,EAAE,WAAU,CAAC;YACpE;QACF;QAEA,aAAY,UAAS;YACnB,OAAO,IAAI,QAAc,CAAC,UAAS;gBACjC,IAAI,CAAC,WAAU,SAAS,SAAS;oBAC/B,QAAO,IAAI,MAAM;oBACjB;gBACF;gBAEA,MAAM,oBAAmB,WACtB,MAAM,KACN,IAAI,CAAC,KAAM,mBAAmB,KAC9B,KAAK;gBAER,MAAM,gBAAe,SAAS,cAC5B,CAAC,6BAA6B,EAAE,kBAAiB,EAAE,CAAC;gBAGtD,IAAI,iBAAgB,MAAM;oBACxB,QAAO,IAAI,MAAM,CAAC,gCAAgC,EAAE,WAAU,CAAC;oBAC/D;gBACF;gBAEA,MAAM,QAAO,SAAS,cAAc;gBACpC,MAAK,MAAM;gBACX,MAAK,OAAO,CAAC,CAAC,EAAE,kBAAiB,CAAC;gBAClC,MAAK,UAAU;oBACb;gBACF;gBACA,MAAK,SAAS;oBAIZ,cAAa;oBAIb;gBACF;gBAIA,cAAa,cAAe,aAC1B,OACA,cAAa;YAEjB;QACF;QAEA,SAAS,IAAM,KAAK,SAAS;IAC/B;IAKA,MAAM,kBAAgD,IAAI;IAE1D,SAAS,qBAAoB,UAAoB;QAC/C,IAAI,YAAW,gBAAe,IAAI;QAClC,IAAI,CAAC,WAAU;YACb,IAAI;YACJ,IAAI;YACJ,MAAM,WAAU,IAAI,QAAc,CAAC,eAAc;gBAC/C,WAAU;gBACV,UAAS;YACX;YACA,YAAW;gBACT,UAAU;gBACV,SAAA;gBACA,SAAS;oBACP,UAAU,WAAW;oBACrB;gBACF;gBACA,QAAQ;YACV;YACA,gBAAe,IAAI,YAAW;QAChC;QACA,OAAO;IACT;IAEA,SAAS,gBAAe,UAAoB;QAC1C,gBAAe,OAAO;IACxB;IAMA,eAAe,aAAY,UAAoB,EAAE,OAAkB;QACjE,MAAM,YAAW,qBAAoB;QACrC,IAAI,UAAS,UAAU;YACrB,OAAO,UAAS;QAClB;QAEA,IAAI,QAAO,SAAS,WAAW,SAAS;YAItC,IAAI,WAAU,SAAS,SAAS;gBAG9B,UAAS;YACX;YAMA,OAAO,UAAS;QAClB;QAEA,IAAI,WAAU,SAAS,SAAS;YAC9B,MAAM,QAAO,SAAS,cAAc;YACpC,MAAK,MAAM;YACX,MAAK,OAAO,CAAC,CAAC,EAAE,WAAU,CAAC;YAC3B,MAAK,UAAU;gBACb,UAAS;YACX;YACA,MAAK,SAAS;gBAGZ,UAAS;YACX;YACA,SAAS,KAAK,YAAY;QAC5B,OAAO,IAAI,WAAU,SAAS,QAAQ;YACpC,MAAM,UAAS,SAAS,cAAc;YACtC,QAAO,MAAM,CAAC,CAAC,EAAE,WAAU,CAAC;YAI5B,QAAO,UAAU;gBACf,UAAS;YACX;YACA,SAAS,KAAK,YAAY;QAC5B,OAAO;YACL,MAAM,IAAI,MAAM,CAAC,oCAAoC,EAAE,WAAU,CAAC;QACpE;QAEA,OAAO,UAAS;IAClB;AACF,CAAA;AAEA,SAAS,MAAM,EAAE,KAAI,EAAE,IAAG,EAAE,IAAG,EAAyB;IACtD,QAAQ,CAAC,kBAAkB,EAAE,SAAS,OAAO,EAAE,IAAI,CAAC;IACpD,IAAI,KAAK,QAAQ,CAAC,uBAAuB,EAAE,IAAI,CAAC;IAChD,OAAO,KAAK;AACd"}}, - {"offset": {"line": 1026, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":"A"}}] + {"offset": {"line": 109, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/dev/runtime/base/runtime-base.ts"],"sourcesContent":["/**\n * This file contains runtime types and functions that are shared between all\n * Turbopack *development* ECMAScript runtimes.\n *\n * It will be appended to the runtime code of each runtime right after the\n * shared runtime utils.\n */\n\n/* eslint-disable @next/next/no-assign-module-variable */\n\n/// \n/// \n/// \n/// \n\n// This file must not use `import` and `export` statements. Otherwise, it\n// becomes impossible to augment interfaces declared in ``d files\n// (e.g. `Module`). Hence the need for `import()` here.\ntype RefreshRuntimeGlobals =\n import(\"@next/react-refresh-utils/dist/runtime\").RefreshRuntimeGlobals;\n\ndeclare var $RefreshHelpers$: RefreshRuntimeGlobals[\"$RefreshHelpers$\"];\ndeclare var $RefreshReg$: RefreshRuntimeGlobals[\"$RefreshReg$\"];\ndeclare var $RefreshSig$: RefreshRuntimeGlobals[\"$RefreshSig$\"];\ndeclare var $RefreshInterceptModuleExecution$:\n | RefreshRuntimeGlobals[\"$RefreshInterceptModuleExecution$\"];\n\ntype RefreshContext = {\n register: RefreshRuntimeGlobals[\"$RefreshReg$\"];\n signature: RefreshRuntimeGlobals[\"$RefreshSig$\"];\n};\n\n// @next/react-refresh-utils/internal/helpers\ntype RefreshHelpers = {\n registerExportsForReactRefresh(\n moduleExports: unknown,\n moduleID: string\n ): void;\n getRefreshBoundarySignature(moduleExports: unknown): Array;\n isReactRefreshBoundary(moduleExports: unknown): boolean;\n shouldInvalidateReactRefreshBoundary(\n prevExports: unknown,\n nextExports: unknown\n ): boolean;\n scheduleUpdate(): void;\n};\n\ninterface TurbopackDevBaseContext {\n e: Module[\"exports\"];\n r: CommonJsRequire;\n f: RequireContextFactory;\n i: EsmImport;\n s: EsmExport;\n j: typeof cjsExport;\n v: ExportValue;\n n: typeof exportNamespace;\n m: Module;\n c: ModuleCache;\n l: LoadChunk;\n g: typeof globalThis;\n k: RefreshContext;\n __dirname: string;\n}\n\ninterface TurbopackDevContext extends TurbopackDevBaseContext {}\n\n// string encoding of a module factory (used in hmr updates)\ntype ModuleFactoryString = string;\n\ntype ModuleFactory = (\n this: Module[\"exports\"],\n context: TurbopackDevContext\n) => undefined;\n\ntype DevRuntimeParams = {\n otherChunks: ChunkData[];\n runtimeModuleIds: ModuleId[];\n};\n\ntype ChunkRegistration = [\n chunkPath: ChunkPath,\n chunkModules: ModuleFactories,\n params: DevRuntimeParams | undefined\n];\ntype ChunkList = {\n path: ChunkPath;\n chunks: ChunkData[];\n source: \"entry\" | \"dynamic\";\n};\n\nenum SourceType {\n /**\n * The module was instantiated because it was included in an evaluated chunk's\n * runtime.\n */\n Runtime = 0,\n /**\n * The module was instantiated because a parent module imported it.\n */\n Parent = 1,\n /**\n * The module was instantiated because it was included in a chunk's hot module\n * update.\n */\n Update = 2,\n}\n\ntype SourceInfo =\n | {\n type: SourceType.Runtime;\n chunkPath: ChunkPath;\n }\n | {\n type: SourceType.Parent;\n parentId: ModuleId;\n }\n | {\n type: SourceType.Update;\n parents?: ModuleId[];\n };\n\ninterface RuntimeBackend {\n registerChunk: (chunkPath: ChunkPath, params?: DevRuntimeParams) => void;\n loadChunk: (chunkPath: ChunkPath, source: SourceInfo) => Promise;\n reloadChunk?: (chunkPath: ChunkPath) => Promise;\n unloadChunk?: (chunkPath: ChunkPath) => void;\n\n restart: () => void;\n}\n\nconst moduleFactories: ModuleFactories = Object.create(null);\nconst moduleCache: ModuleCache = Object.create(null);\n/**\n * Maps module IDs to persisted data between executions of their hot module\n * implementation (`hot.data`).\n */\nconst moduleHotData: Map = new Map();\n/**\n * Maps module instances to their hot module state.\n */\nconst moduleHotState: Map = new Map();\n/**\n * Module IDs that are instantiated as part of the runtime of a chunk.\n */\nconst runtimeModules: Set = new Set();\n/**\n * Map from module ID to the chunks that contain this module.\n *\n * In HMR, we need to keep track of which modules are contained in which so\n * chunks. This is so we don't eagerly dispose of a module when it is removed\n * from chunk A, but still exists in chunk B.\n */\nconst moduleChunksMap: Map> = new Map();\n/**\n * Map from chunk path to all modules it contains.\n */\nconst chunkModulesMap: Map> = new Map();\n/**\n * Chunk lists that contain a runtime. When these chunk lists receive an update\n * that can't be reconciled with the current state of the page, we need to\n * reload the runtime entirely.\n */\nconst runtimeChunkLists: Set = new Set();\n/**\n * Map from chunk list to the chunk paths it contains.\n */\nconst chunkListChunksMap: Map> = new Map();\n/**\n * Map from chunk path to the chunk lists it belongs to.\n */\nconst chunkChunkListsMap: Map> = new Map();\n\nconst availableModules: Map | true> = new Map();\n\nconst availableModuleChunks: Map | true> = new Map();\n\nasync function loadChunk(\n source: SourceInfo,\n chunkData: ChunkData\n): Promise {\n if (typeof chunkData === \"string\") {\n return loadChunkPath(source, chunkData);\n }\n\n const includedList = chunkData.included || [];\n const modulesPromises = includedList.map((included) => {\n if (moduleFactories[included]) return true;\n return availableModules.get(included);\n });\n if (modulesPromises.length > 0 && modulesPromises.every((p) => p)) {\n // When all included items are already loaded or loading, we can skip loading ourselves\n return Promise.all(modulesPromises);\n }\n\n const includedModuleChunksList = chunkData.moduleChunks || [];\n const moduleChunksPromises = includedModuleChunksList\n .map((included) => {\n // TODO(alexkirsz) Do we need this check?\n // if (moduleFactories[included]) return true;\n return availableModuleChunks.get(included);\n })\n .filter((p) => p);\n\n let promise;\n if (moduleChunksPromises.length > 0) {\n // Some module chunks are already loaded or loading.\n\n if (moduleChunksPromises.length == includedModuleChunksList.length) {\n // When all included module chunks are already loaded or loading, we can skip loading ourselves\n return Promise.all(moduleChunksPromises);\n }\n\n const moduleChunksToLoad: Set = new Set();\n for (const moduleChunk of includedModuleChunksList) {\n if (!availableModuleChunks.has(moduleChunk)) {\n moduleChunksToLoad.add(moduleChunk);\n }\n }\n\n for (const moduleChunkToLoad of moduleChunksToLoad) {\n const promise = loadChunkPath(source, moduleChunkToLoad);\n\n availableModuleChunks.set(moduleChunkToLoad, promise);\n\n moduleChunksPromises.push(promise);\n }\n\n promise = Promise.all(moduleChunksPromises);\n } else {\n promise = loadChunkPath(source, chunkData.path);\n\n // Mark all included module chunks as loading if they are not already loaded or loading.\n for (const includedModuleChunk of includedModuleChunksList) {\n if (!availableModuleChunks.has(includedModuleChunk)) {\n availableModuleChunks.set(includedModuleChunk, promise);\n }\n }\n }\n\n for (const included of includedList) {\n if (!availableModules.has(included)) {\n // It might be better to race old and new promises, but it's rare that the new promise will be faster than a request started earlier.\n // In production it's even more rare, because the chunk optimization tries to deduplicate modules anyway.\n availableModules.set(included, promise);\n }\n }\n\n return promise;\n}\n\nasync function loadChunkPath(\n source: SourceInfo,\n chunkPath: ChunkPath\n): Promise {\n try {\n await BACKEND.loadChunk(chunkPath, source);\n } catch (error) {\n let loadReason;\n switch (source.type) {\n case SourceType.Runtime:\n loadReason = `as a runtime dependency of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n loadReason = `from module ${source.parentId}`;\n break;\n case SourceType.Update:\n loadReason = \"from an HMR update\";\n break;\n }\n throw new Error(\n `Failed to load chunk ${chunkPath} ${loadReason}${\n error ? `: ${error}` : \"\"\n }`\n );\n }\n}\n\nfunction instantiateModule(id: ModuleId, source: SourceInfo): Module {\n const moduleFactory = moduleFactories[id];\n if (typeof moduleFactory !== \"function\") {\n // This can happen if modules incorrectly handle HMR disposes/updates,\n // e.g. when they keep a `setTimeout` around which still executes old code\n // and contains e.g. a `require(\"something\")` call.\n let instantiationReason;\n switch (source.type) {\n case SourceType.Runtime:\n instantiationReason = `as a runtime entry of chunk ${source.chunkPath}`;\n break;\n case SourceType.Parent:\n instantiationReason = `because it was required from module ${source.parentId}`;\n break;\n case SourceType.Update:\n instantiationReason = \"because of an HMR update\";\n break;\n }\n throw new Error(\n `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.`\n );\n }\n\n const hotData = moduleHotData.get(id)!;\n const { hot, hotState } = createModuleHot(hotData);\n\n let parents: ModuleId[];\n switch (source.type) {\n case SourceType.Runtime:\n runtimeModules.add(id);\n parents = [];\n break;\n case SourceType.Parent:\n // No need to add this module as a child of the parent module here, this\n // has already been taken care of in `getOrInstantiateModuleFromParent`.\n parents = [source.parentId];\n break;\n case SourceType.Update:\n parents = source.parents || [];\n break;\n }\n const module: Module = {\n exports: {},\n error: undefined,\n loaded: false,\n id,\n parents,\n children: [],\n namespaceObject: undefined,\n hot,\n };\n\n moduleCache[id] = module;\n moduleHotState.set(module, hotState);\n\n // NOTE(alexkirsz) This can fail when the module encounters a runtime error.\n try {\n runModuleExecutionHooks(module, (refresh) => {\n moduleFactory.call(\n module.exports,\n augmentContext({\n e: module.exports,\n r: commonJsRequire.bind(null, module),\n f: requireContext.bind(null, module),\n i: esmImport.bind(null, module),\n s: esmExport.bind(null, module),\n j: cjsExport.bind(null, module.exports),\n v: exportValue.bind(null, module),\n n: exportNamespace.bind(null, module),\n m: module,\n c: moduleCache,\n l: loadChunk.bind(null, { type: SourceType.Parent, parentId: id }),\n g: globalThis,\n k: refresh,\n __dirname: module.id.replace(/(^|\\/)[\\/]+$/, \"\"),\n })\n );\n });\n } catch (error) {\n module.error = error as any;\n throw error;\n }\n\n module.loaded = true;\n if (module.namespaceObject && module.exports !== module.namespaceObject) {\n // in case of a circular dependency: cjs1 -> esm2 -> cjs1\n interopEsm(module.exports, module.namespaceObject);\n }\n\n return module;\n}\n\n/**\n * NOTE(alexkirsz) Webpack has an \"module execution\" interception hook that\n * Next.js' React Refresh runtime hooks into to add module context to the\n * refresh registry.\n */\nfunction runModuleExecutionHooks(\n module: Module,\n executeModule: (ctx: RefreshContext) => void\n) {\n const cleanupReactRefreshIntercept =\n typeof globalThis.$RefreshInterceptModuleExecution$ === \"function\"\n ? globalThis.$RefreshInterceptModuleExecution$(module.id)\n : () => {};\n\n try {\n executeModule({\n register: globalThis.$RefreshReg$,\n signature: globalThis.$RefreshSig$,\n });\n\n if (\"$RefreshHelpers$\" in globalThis) {\n // This pattern can also be used to register the exports of\n // a module with the React Refresh runtime.\n registerExportsAndSetupBoundaryForReactRefresh(\n module,\n globalThis.$RefreshHelpers$\n );\n }\n } catch (e) {\n throw e;\n } finally {\n // Always cleanup the intercept, even if module execution failed.\n cleanupReactRefreshIntercept();\n }\n}\n\n/**\n * Retrieves a module from the cache, or instantiate it if it is not cached.\n */\nconst getOrInstantiateModuleFromParent: GetOrInstantiateModuleFromParent = (\n id,\n sourceModule\n) => {\n if (!sourceModule.hot.active) {\n console.warn(\n `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update`\n );\n }\n\n const module = moduleCache[id];\n\n if (sourceModule.children.indexOf(id) === -1) {\n sourceModule.children.push(id);\n }\n\n if (module) {\n if (module.parents.indexOf(sourceModule.id) === -1) {\n module.parents.push(sourceModule.id);\n }\n\n return module;\n }\n\n return instantiateModule(id, {\n type: SourceType.Parent,\n parentId: sourceModule.id,\n });\n};\n\n/**\n * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts\n */\nfunction registerExportsAndSetupBoundaryForReactRefresh(\n module: Module,\n helpers: RefreshHelpers\n) {\n const currentExports = module.exports;\n const prevExports = module.hot.data.prevExports ?? null;\n\n helpers.registerExportsForReactRefresh(currentExports, module.id);\n\n // A module can be accepted automatically based on its exports, e.g. when\n // it is a Refresh Boundary.\n if (helpers.isReactRefreshBoundary(currentExports)) {\n // Save the previous exports on update so we can compare the boundary\n // signatures.\n module.hot.dispose((data) => {\n data.prevExports = currentExports;\n });\n // Unconditionally accept an update to this module, we'll check if it's\n // still a Refresh Boundary later.\n module.hot.accept();\n\n // This field is set when the previous version of this module was a\n // Refresh Boundary, letting us know we need to check for invalidation or\n // enqueue an update.\n if (prevExports !== null) {\n // A boundary can become ineligible if its exports are incompatible\n // with the previous exports.\n //\n // For example, if you add/remove/change exports, we'll want to\n // re-execute the importing modules, and force those components to\n // re-render. Similarly, if you convert a class component to a\n // function, we want to invalidate the boundary.\n if (\n helpers.shouldInvalidateReactRefreshBoundary(\n prevExports,\n currentExports\n )\n ) {\n module.hot.invalidate();\n } else {\n helpers.scheduleUpdate();\n }\n }\n } else {\n // Since we just executed the code for the module, it's possible that the\n // new exports made it ineligible for being a boundary.\n // We only care about the case when we were _previously_ a boundary,\n // because we already accepted this update (accidental side effect).\n const isNoLongerABoundary = prevExports !== null;\n if (isNoLongerABoundary) {\n module.hot.invalidate();\n }\n }\n}\n\nfunction formatDependencyChain(dependencyChain: ModuleId[]): string {\n return `Dependency chain: ${dependencyChain.join(\" -> \")}`;\n}\n\nfunction computeOutdatedModules(\n added: Map,\n modified: Map\n): { outdatedModules: Set; newModuleFactories: Map } {\n const outdatedModules = new Set();\n const newModuleFactories = new Map();\n\n for (const [moduleId, entry] of added) {\n if (entry != null) {\n newModuleFactories.set(moduleId, _eval(entry));\n }\n }\n\n for (const [moduleId, entry] of modified) {\n const effect = getAffectedModuleEffects(moduleId);\n\n switch (effect.type) {\n case \"unaccepted\":\n throw new Error(\n `cannot apply update: unaccepted module. ${formatDependencyChain(\n effect.dependencyChain\n )}.`\n );\n case \"self-declined\":\n throw new Error(\n `cannot apply update: self-declined module. ${formatDependencyChain(\n effect.dependencyChain\n )}.`\n );\n case \"accepted\":\n newModuleFactories.set(moduleId, _eval(entry));\n for (const outdatedModuleId of effect.outdatedModules) {\n outdatedModules.add(outdatedModuleId);\n }\n break;\n // TODO(alexkirsz) Dependencies: handle dependencies effects.\n }\n }\n\n return { outdatedModules, newModuleFactories };\n}\n\nfunction computeOutdatedSelfAcceptedModules(\n outdatedModules: Iterable\n): { moduleId: ModuleId; errorHandler: true | Function }[] {\n const outdatedSelfAcceptedModules = [];\n for (const moduleId of outdatedModules) {\n const module = moduleCache[moduleId];\n const hotState = moduleHotState.get(module)!;\n if (module && hotState.selfAccepted && !hotState.selfInvalidated) {\n outdatedSelfAcceptedModules.push({\n moduleId,\n errorHandler: hotState.selfAccepted,\n });\n }\n }\n return outdatedSelfAcceptedModules;\n}\n\n/**\n * Adds, deletes, and moves modules between chunks. This must happen before the\n * dispose phase as it needs to know which modules were removed from all chunks,\n * which we can only compute *after* taking care of added and moved modules.\n */\nfunction updateChunksPhase(\n chunksAddedModules: Map>,\n chunksDeletedModules: Map>\n): { disposedModules: Set } {\n for (const [chunkPath, addedModuleIds] of chunksAddedModules) {\n for (const moduleId of addedModuleIds) {\n addModuleToChunk(moduleId, chunkPath);\n }\n }\n\n const disposedModules: Set = new Set();\n for (const [chunkPath, addedModuleIds] of chunksDeletedModules) {\n for (const moduleId of addedModuleIds) {\n if (removeModuleFromChunk(moduleId, chunkPath)) {\n disposedModules.add(moduleId);\n }\n }\n }\n\n return { disposedModules };\n}\n\nfunction disposePhase(\n outdatedModules: Iterable,\n disposedModules: Set\n): { outdatedModuleParents: Map> } {\n for (const moduleId of outdatedModules) {\n disposeModule(moduleId, \"replace\");\n }\n\n for (const moduleId of disposedModules) {\n disposeModule(moduleId, \"clear\");\n }\n\n // Removing modules from the module cache is a separate step.\n // We also want to keep track of previous parents of the outdated modules.\n const outdatedModuleParents = new Map();\n for (const moduleId of outdatedModules) {\n const oldModule = moduleCache[moduleId];\n outdatedModuleParents.set(moduleId, oldModule?.parents);\n delete moduleCache[moduleId];\n }\n\n // TODO(alexkirsz) Dependencies: remove outdated dependency from module\n // children.\n\n return { outdatedModuleParents };\n}\n\n/**\n * Disposes of an instance of a module.\n *\n * Returns the persistent hot data that should be kept for the next module\n * instance.\n *\n * NOTE: mode = \"replace\" will not remove modules from the moduleCache.\n * This must be done in a separate step afterwards.\n * This is important because all modules need to be diposed to update the\n * parent/child relationships before they are actually removed from the moduleCache.\n * If this would be done in this method, following disposeModulecalls won't find\n * the module from the module id in the cache.\n */\nfunction disposeModule(moduleId: ModuleId, mode: \"clear\" | \"replace\") {\n const module = moduleCache[moduleId];\n if (!module) {\n return;\n }\n\n const hotState = moduleHotState.get(module)!;\n const data = {};\n\n // Run the `hot.dispose` handler, if any, passing in the persistent\n // `hot.data` object.\n for (const disposeHandler of hotState.disposeHandlers) {\n disposeHandler(data);\n }\n\n // This used to warn in `getOrInstantiateModuleFromParent` when a disposed\n // module is still importing other modules.\n module.hot.active = false;\n\n moduleHotState.delete(module);\n\n // TODO(alexkirsz) Dependencies: delete the module from outdated deps.\n\n // Remove the disposed module from its children's parents list.\n // It will be added back once the module re-instantiates and imports its\n // children again.\n for (const childId of module.children) {\n const child = moduleCache[childId];\n if (!child) {\n continue;\n }\n\n const idx = child.parents.indexOf(module.id);\n if (idx >= 0) {\n child.parents.splice(idx, 1);\n }\n }\n\n switch (mode) {\n case \"clear\":\n delete moduleCache[module.id];\n moduleHotData.delete(module.id);\n break;\n case \"replace\":\n moduleHotData.set(module.id, data);\n break;\n default:\n invariant(mode, (mode) => `invalid mode: ${mode}`);\n }\n}\n\nfunction applyPhase(\n outdatedSelfAcceptedModules: {\n moduleId: ModuleId;\n errorHandler: true | Function;\n }[],\n newModuleFactories: Map,\n outdatedModuleParents: Map>\n) {\n // Update module factories.\n for (const [moduleId, factory] of newModuleFactories.entries()) {\n moduleFactories[moduleId] = factory;\n }\n\n // TODO(alexkirsz) Run new runtime entries here.\n\n // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps.\n\n // Re-instantiate all outdated self-accepted modules.\n for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) {\n try {\n instantiateModule(moduleId, {\n type: SourceType.Update,\n parents: outdatedModuleParents.get(moduleId),\n });\n } catch (err) {\n if (typeof errorHandler === \"function\") {\n try {\n errorHandler(err, { moduleId, module: moduleCache[moduleId] });\n } catch (_) {\n // Ignore error.\n }\n }\n }\n }\n}\n\n/**\n * Utility function to ensure all variants of an enum are handled.\n */\nfunction invariant(never: never, computeMessage: (arg: any) => string): never {\n throw new Error(`Invariant: ${computeMessage(never)}`);\n}\n\nfunction applyUpdate(chunkListPath: ChunkPath, update: PartialUpdate) {\n switch (update.type) {\n case \"ChunkListUpdate\":\n applyChunkListUpdate(chunkListPath, update);\n break;\n default:\n invariant(update, (update) => `Unknown update type: ${update.type}`);\n }\n}\n\nfunction applyChunkListUpdate(\n chunkListPath: ChunkPath,\n update: ChunkListUpdate\n) {\n if (update.merged != null) {\n for (const merged of update.merged) {\n switch (merged.type) {\n case \"EcmascriptMergedUpdate\":\n applyEcmascriptMergedUpdate(chunkListPath, merged);\n break;\n default:\n invariant(merged, (merged) => `Unknown merged type: ${merged.type}`);\n }\n }\n }\n\n if (update.chunks != null) {\n for (const [chunkPath, chunkUpdate] of Object.entries(update.chunks)) {\n switch (chunkUpdate.type) {\n case \"added\":\n BACKEND.loadChunk(chunkPath, { type: SourceType.Update });\n break;\n case \"total\":\n BACKEND.reloadChunk?.(chunkPath);\n break;\n case \"deleted\":\n BACKEND.unloadChunk?.(chunkPath);\n break;\n case \"partial\":\n invariant(\n chunkUpdate.instruction,\n (instruction) =>\n `Unknown partial instruction: ${JSON.stringify(instruction)}.`\n );\n default:\n invariant(\n chunkUpdate,\n (chunkUpdate) => `Unknown chunk update type: ${chunkUpdate.type}`\n );\n }\n }\n }\n}\n\nfunction applyEcmascriptMergedUpdate(\n chunkPath: ChunkPath,\n update: EcmascriptMergedUpdate\n) {\n const { entries = {}, chunks = {} } = update;\n const { added, modified, deleted, chunksAdded, chunksDeleted } =\n computeChangedModules(entries, chunks);\n const { outdatedModules, newModuleFactories } = computeOutdatedModules(\n added,\n modified\n );\n const outdatedSelfAcceptedModules =\n computeOutdatedSelfAcceptedModules(outdatedModules);\n const { disposedModules } = updateChunksPhase(chunksAdded, chunksDeleted);\n const { outdatedModuleParents } = disposePhase(\n outdatedModules,\n disposedModules\n );\n applyPhase(\n outdatedSelfAcceptedModules,\n newModuleFactories,\n outdatedModuleParents\n );\n}\n\nfunction computeChangedModules(\n entries: Record,\n updates: Record\n): {\n added: Map;\n modified: Map;\n deleted: Set;\n chunksAdded: Map>;\n chunksDeleted: Map>;\n} {\n const chunksAdded = new Map();\n const chunksDeleted = new Map();\n const added: Map = new Map();\n const modified = new Map();\n const deleted: Set = new Set();\n\n for (const [chunkPath, mergedChunkUpdate] of Object.entries(updates)) {\n switch (mergedChunkUpdate.type) {\n case \"added\": {\n const updateAdded = new Set(mergedChunkUpdate.modules);\n for (const moduleId of updateAdded) {\n added.set(moduleId, entries[moduleId]);\n }\n chunksAdded.set(chunkPath, updateAdded);\n break;\n }\n case \"deleted\": {\n // We could also use `mergedChunkUpdate.modules` here.\n const updateDeleted = new Set(chunkModulesMap.get(chunkPath));\n for (const moduleId of updateDeleted) {\n deleted.add(moduleId);\n }\n chunksDeleted.set(chunkPath, updateDeleted);\n break;\n }\n case \"partial\": {\n const updateAdded = new Set(mergedChunkUpdate.added);\n const updateDeleted = new Set(mergedChunkUpdate.deleted);\n for (const moduleId of updateAdded) {\n added.set(moduleId, entries[moduleId]);\n }\n for (const moduleId of updateDeleted) {\n deleted.add(moduleId);\n }\n chunksAdded.set(chunkPath, updateAdded);\n chunksDeleted.set(chunkPath, updateDeleted);\n break;\n }\n default:\n invariant(\n mergedChunkUpdate,\n (mergedChunkUpdate) =>\n `Unknown merged chunk update type: ${mergedChunkUpdate.type}`\n );\n }\n }\n\n // If a module was added from one chunk and deleted from another in the same update,\n // consider it to be modified, as it means the module was moved from one chunk to another\n // AND has new code in a single update.\n for (const moduleId of added.keys()) {\n if (deleted.has(moduleId)) {\n added.delete(moduleId);\n deleted.delete(moduleId);\n }\n }\n\n for (const [moduleId, entry] of Object.entries(entries)) {\n // Modules that haven't been added to any chunk but have new code are considered\n // to be modified.\n // This needs to be under the previous loop, as we need it to get rid of modules\n // that were added and deleted in the same update.\n if (!added.has(moduleId)) {\n modified.set(moduleId, entry);\n }\n }\n\n return { added, deleted, modified, chunksAdded, chunksDeleted };\n}\n\ntype ModuleEffect =\n | {\n type: \"unaccepted\";\n dependencyChain: ModuleId[];\n }\n | {\n type: \"self-declined\";\n dependencyChain: ModuleId[];\n moduleId: ModuleId;\n }\n | {\n type: \"accepted\";\n moduleId: ModuleId;\n outdatedModules: Set;\n };\n\nfunction getAffectedModuleEffects(moduleId: ModuleId): ModuleEffect {\n const outdatedModules: Set = new Set();\n\n type QueueItem = { moduleId?: ModuleId; dependencyChain: ModuleId[] };\n\n const queue: QueueItem[] = [\n {\n moduleId,\n dependencyChain: [],\n },\n ];\n\n let nextItem;\n while ((nextItem = queue.shift())) {\n const { moduleId, dependencyChain } = nextItem;\n\n if (moduleId != null) {\n outdatedModules.add(moduleId);\n }\n\n // We've arrived at the runtime of the chunk, which means that nothing\n // else above can accept this update.\n if (moduleId === undefined) {\n return {\n type: \"unaccepted\",\n dependencyChain,\n };\n }\n\n const module = moduleCache[moduleId];\n const hotState = moduleHotState.get(module)!;\n\n if (\n // The module is not in the cache. Since this is a \"modified\" update,\n // it means that the module was never instantiated before.\n !module || // The module accepted itself without invalidating globalThis.\n // TODO is that right?\n (hotState.selfAccepted && !hotState.selfInvalidated)\n ) {\n continue;\n }\n\n if (hotState.selfDeclined) {\n return {\n type: \"self-declined\",\n dependencyChain,\n moduleId,\n };\n }\n\n if (runtimeModules.has(moduleId)) {\n queue.push({\n moduleId: undefined,\n dependencyChain: [...dependencyChain, moduleId],\n });\n continue;\n }\n\n for (const parentId of module.parents) {\n const parent = moduleCache[parentId];\n\n if (!parent) {\n // TODO(alexkirsz) Is this even possible?\n continue;\n }\n\n // TODO(alexkirsz) Dependencies: check accepted and declined\n // dependencies here.\n\n queue.push({\n moduleId: parentId,\n dependencyChain: [...dependencyChain, moduleId],\n });\n }\n }\n\n return {\n type: \"accepted\",\n moduleId,\n outdatedModules,\n };\n}\n\nfunction handleApply(chunkListPath: ChunkPath, update: ServerMessage) {\n switch (update.type) {\n case \"partial\": {\n // This indicates that the update is can be applied to the current state of the application.\n applyUpdate(chunkListPath, update.instruction);\n break;\n }\n case \"restart\": {\n // This indicates that there is no way to apply the update to the\n // current state of the application, and that the application must be\n // restarted.\n BACKEND.restart();\n break;\n }\n case \"notFound\": {\n // This indicates that the chunk list no longer exists: either the dynamic import which created it was removed,\n // or the page itself was deleted.\n // If it is a dynamic import, we simply discard all modules that the chunk has exclusive access to.\n // If it is a runtime chunk list, we restart the application.\n if (runtimeChunkLists.has(chunkListPath)) {\n BACKEND.restart();\n } else {\n disposeChunkList(chunkListPath);\n }\n break;\n }\n default:\n throw new Error(`Unknown update type: ${update.type}`);\n }\n}\n\nfunction createModuleHot(hotData: HotData): { hot: Hot; hotState: HotState } {\n const hotState: HotState = {\n selfAccepted: false,\n selfDeclined: false,\n selfInvalidated: false,\n disposeHandlers: [],\n };\n\n const hot: Hot = {\n // TODO(alexkirsz) This is not defined in the HMR API. It was used to\n // decide whether to warn whenever an HMR-disposed module required other\n // modules. We might want to remove it.\n active: true,\n\n data: hotData ?? {},\n\n // TODO(alexkirsz) Support full (dep, callback, errorHandler) form.\n accept: (\n modules?: string | string[] | AcceptErrorHandler,\n _callback?: AcceptCallback,\n _errorHandler?: AcceptErrorHandler\n ) => {\n if (modules === undefined) {\n hotState.selfAccepted = true;\n } else if (typeof modules === \"function\") {\n hotState.selfAccepted = modules;\n } else {\n throw new Error(\"unsupported `accept` signature\");\n }\n },\n\n decline: (dep) => {\n if (dep === undefined) {\n hotState.selfDeclined = true;\n } else {\n throw new Error(\"unsupported `decline` signature\");\n }\n },\n\n dispose: (callback) => {\n hotState.disposeHandlers.push(callback);\n },\n\n addDisposeHandler: (callback) => {\n hotState.disposeHandlers.push(callback);\n },\n\n removeDisposeHandler: (callback) => {\n const idx = hotState.disposeHandlers.indexOf(callback);\n if (idx >= 0) {\n hotState.disposeHandlers.splice(idx, 1);\n }\n },\n\n invalidate: () => {\n hotState.selfInvalidated = true;\n // TODO(alexkirsz) The original HMR code had management-related code\n // here.\n },\n\n // NOTE(alexkirsz) This is part of the management API, which we don't\n // implement, but the Next.js React Refresh runtime uses this to decide\n // whether to schedule an update.\n status: () => \"idle\",\n\n // NOTE(alexkirsz) Since we always return \"idle\" for now, these are no-ops.\n addStatusHandler: (_handler) => {},\n removeStatusHandler: (_handler) => {},\n };\n\n return { hot, hotState };\n}\n\n/**\n * Adds a module to a chunk.\n */\nfunction addModuleToChunk(moduleId: ModuleId, chunkPath: ChunkPath) {\n let moduleChunks = moduleChunksMap.get(moduleId);\n if (!moduleChunks) {\n moduleChunks = new Set([chunkPath]);\n moduleChunksMap.set(moduleId, moduleChunks);\n } else {\n moduleChunks.add(chunkPath);\n }\n\n let chunkModules = chunkModulesMap.get(chunkPath);\n if (!chunkModules) {\n chunkModules = new Set([moduleId]);\n chunkModulesMap.set(chunkPath, chunkModules);\n } else {\n chunkModules.add(moduleId);\n }\n}\n\n/**\n * Returns the first chunk that included a module.\n * This is used by the Node.js backend, hence why it's marked as unused in this\n * file.\n */\nfunction getFirstModuleChunk(moduleId: ModuleId) {\n const moduleChunkPaths = moduleChunksMap.get(moduleId);\n if (moduleChunkPaths == null) {\n return null;\n }\n\n return moduleChunkPaths.values().next().value;\n}\n\n/**\n * Removes a module from a chunk. Returns true there are no remaining chunks\n * including this module.\n */\nfunction removeModuleFromChunk(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): boolean {\n const moduleChunks = moduleChunksMap.get(moduleId)!;\n moduleChunks.delete(chunkPath);\n\n const chunkModules = chunkModulesMap.get(chunkPath)!;\n chunkModules.delete(moduleId);\n\n const noRemainingModules = chunkModules.size === 0;\n if (noRemainingModules) {\n chunkModulesMap.delete(chunkPath);\n }\n\n const noRemainingChunks = moduleChunks.size === 0;\n if (noRemainingChunks) {\n moduleChunksMap.delete(moduleId);\n }\n\n return noRemainingChunks;\n}\n\n/**\n * Diposes of a chunk list and its corresponding exclusive chunks.\n */\nfunction disposeChunkList(chunkListPath: ChunkPath): boolean {\n const chunkPaths = chunkListChunksMap.get(chunkListPath);\n if (chunkPaths == null) {\n return false;\n }\n chunkListChunksMap.delete(chunkListPath);\n\n for (const chunkPath of chunkPaths) {\n const chunkChunkLists = chunkChunkListsMap.get(chunkPath)!;\n chunkChunkLists.delete(chunkListPath);\n\n if (chunkChunkLists.size === 0) {\n chunkChunkListsMap.delete(chunkPath);\n disposeChunk(chunkPath);\n }\n }\n\n // We must also dispose of the chunk list's chunk itself to ensure it may\n // be reloaded properly in the future.\n BACKEND.unloadChunk?.(chunkListPath);\n\n return true;\n}\n\n/**\n * Disposes of a chunk and its corresponding exclusive modules.\n *\n * @returns Whether the chunk was disposed of.\n */\nfunction disposeChunk(chunkPath: ChunkPath): boolean {\n // This should happen whether or not the chunk has any modules in it. For instance,\n // CSS chunks have no modules in them, but they still need to be unloaded.\n BACKEND.unloadChunk?.(chunkPath);\n\n const chunkModules = chunkModulesMap.get(chunkPath);\n if (chunkModules == null) {\n return false;\n }\n chunkModules.delete(chunkPath);\n\n for (const moduleId of chunkModules) {\n const moduleChunks = moduleChunksMap.get(moduleId)!;\n moduleChunks.delete(chunkPath);\n\n const noRemainingChunks = moduleChunks.size === 0;\n if (noRemainingChunks) {\n moduleChunksMap.delete(moduleId);\n disposeModule(moduleId, \"clear\");\n availableModules.delete(moduleId);\n }\n }\n\n return true;\n}\n\n/**\n * Instantiates a runtime module.\n */\nfunction instantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Gets or instantiates a runtime module.\n */\nfunction getOrInstantiateRuntimeModule(\n moduleId: ModuleId,\n chunkPath: ChunkPath\n): Module {\n const module = moduleCache[moduleId];\n if (module) {\n if (module.error) {\n throw module.error;\n }\n return module;\n }\n\n return instantiateModule(moduleId, { type: SourceType.Runtime, chunkPath });\n}\n\n/**\n * Subscribes to chunk list updates from the update server and applies them.\n */\nfunction registerChunkList(\n chunkUpdateProvider: ChunkUpdateProvider,\n chunkList: ChunkList\n) {\n chunkUpdateProvider.push([\n chunkList.path,\n handleApply.bind(null, chunkList.path),\n ]);\n\n // Adding chunks to chunk lists and vice versa.\n const chunks = new Set(chunkList.chunks.map(getChunkPath));\n chunkListChunksMap.set(chunkList.path, chunks);\n for (const chunkPath of chunks) {\n let chunkChunkLists = chunkChunkListsMap.get(chunkPath);\n if (!chunkChunkLists) {\n chunkChunkLists = new Set([chunkList.path]);\n chunkChunkListsMap.set(chunkPath, chunkChunkLists);\n } else {\n chunkChunkLists.add(chunkList.path);\n }\n }\n\n if (chunkList.source === \"entry\") {\n markChunkListAsRuntime(chunkList.path);\n }\n}\n\n/**\n * Marks a chunk list as a runtime chunk list. There can be more than one\n * runtime chunk list. For instance, integration tests can have multiple chunk\n * groups loaded at runtime, each with its own chunk list.\n */\nfunction markChunkListAsRuntime(chunkListPath: ChunkPath) {\n runtimeChunkLists.add(chunkListPath);\n}\n\nfunction registerChunk([\n chunkPath,\n chunkModules,\n runtimeParams,\n]: ChunkRegistration) {\n for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) {\n if (!moduleFactories[moduleId]) {\n moduleFactories[moduleId] = moduleFactory;\n }\n addModuleToChunk(moduleId, chunkPath);\n }\n\n return BACKEND.registerChunk(chunkPath, runtimeParams);\n}\n\nglobalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS ??= [];\n\nconst chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS;\nif (Array.isArray(chunkListsToRegister)) {\n for (const chunkList of chunkListsToRegister) {\n registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS, chunkList);\n }\n}\n\nglobalThis.TURBOPACK_CHUNK_LISTS = {\n push: (chunkList) => {\n registerChunkList(globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS!, chunkList);\n },\n} satisfies ChunkListProvider;\n"],"names":[],"mappings":";;;;;;IA0FA;UAAK,UAAU;IAAV,WAAA,WAKH,aAAU,KAAV;IALG,WAAA,WASH,YAAS,KAAT;IATG,WAAA,WAcH,YAAS,KAAT;GAdG,eAAA;;AAwCL,MAAM,kBAAmC,OAAO,OAAO;AACvD,MAAM,cAA2B,OAAO,OAAO;AAK/C,MAAM,gBAAwC,IAAI;AAIlD,MAAM,iBAAwC,IAAI;AAIlD,MAAM,iBAAgC,IAAI;AAQ1C,MAAM,kBAAiD,IAAI;AAI3D,MAAM,kBAAiD,IAAI;AAM3D,MAAM,oBAAoC,IAAI;AAI9C,MAAM,qBAAqD,IAAI;AAI/D,MAAM,qBAAqD,IAAI;AAE/D,MAAM,mBAAuD,IAAI;AAEjE,MAAM,wBAA6D,IAAI;AAEvE,eAAe,UACb,MAAkB,EAClB,SAAoB;IAEpB,IAAI,OAAO,cAAc,UAAU;QACjC,OAAO,cAAc,QAAQ;IAC/B;IAEA,MAAM,eAAe,UAAU,YAAY,EAAE;IAC7C,MAAM,kBAAkB,aAAa,IAAI,CAAC;QACxC,IAAI,eAAe,CAAC,SAAS,EAAE,OAAO;QACtC,OAAO,iBAAiB,IAAI;IAC9B;IACA,IAAI,gBAAgB,SAAS,KAAK,gBAAgB,MAAM,CAAC,IAAM,IAAI;QAEjE,OAAO,QAAQ,IAAI;IACrB;IAEA,MAAM,2BAA2B,UAAU,gBAAgB,EAAE;IAC7D,MAAM,uBAAuB,yBAC1B,IAAI,CAAC;QAGJ,OAAO,sBAAsB,IAAI;IACnC,GACC,OAAO,CAAC,IAAM;IAEjB,IAAI;IACJ,IAAI,qBAAqB,SAAS,GAAG;QAGnC,IAAI,qBAAqB,UAAU,yBAAyB,QAAQ;YAElE,OAAO,QAAQ,IAAI;QACrB;QAEA,MAAM,qBAAqC,IAAI;QAC/C,KAAK,MAAM,eAAe,yBAA0B;YAClD,IAAI,CAAC,sBAAsB,IAAI,cAAc;gBAC3C,mBAAmB,IAAI;YACzB;QACF;QAEA,KAAK,MAAM,qBAAqB,mBAAoB;YAClD,MAAM,UAAU,cAAc,QAAQ;YAEtC,sBAAsB,IAAI,mBAAmB;YAE7C,qBAAqB,KAAK;QAC5B;QAEA,UAAU,QAAQ,IAAI;IACxB,OAAO;QACL,UAAU,cAAc,QAAQ,UAAU;QAG1C,KAAK,MAAM,uBAAuB,yBAA0B;YAC1D,IAAI,CAAC,sBAAsB,IAAI,sBAAsB;gBACnD,sBAAsB,IAAI,qBAAqB;YACjD;QACF;IACF;IAEA,KAAK,MAAM,YAAY,aAAc;QACnC,IAAI,CAAC,iBAAiB,IAAI,WAAW;YAGnC,iBAAiB,IAAI,UAAU;QACjC;IACF;IAEA,OAAO;AACT;AAEA,eAAe,cACb,MAAkB,EAClB,SAAoB;IAEpB,IAAI;QACF,MAAM,QAAQ,UAAU,WAAW;IACrC,EAAE,OAAO,OAAO;QACd,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,aAAa,CAAC,iCAAiC,EAAE,OAAO,UAAU,CAAC;gBACnE;YACF,KAAK,WAAW;gBACd,aAAa,CAAC,YAAY,EAAE,OAAO,SAAS,CAAC;gBAC7C;YACF,KAAK,WAAW;gBACd,aAAa;gBACb;QACJ;QACA,MAAM,IAAI,MACR,CAAC,qBAAqB,EAAE,UAAU,CAAC,EAAE,WAAW,EAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,GACxB,CAAC;IAEN;AACF;AAEA,SAAS,kBAAkB,EAAY,EAAE,MAAkB;IACzD,MAAM,gBAAgB,eAAe,CAAC,GAAG;IACzC,IAAI,OAAO,kBAAkB,YAAY;QAIvC,IAAI;QACJ,OAAQ,OAAO;YACb,KAAK,WAAW;gBACd,sBAAsB,CAAC,4BAA4B,EAAE,OAAO,UAAU,CAAC;gBACvE;YACF,KAAK,WAAW;gBACd,sBAAsB,CAAC,oCAAoC,EAAE,OAAO,SAAS,CAAC;gBAC9E;YACF,KAAK,WAAW;gBACd,sBAAsB;gBACtB;QACJ;QACA,MAAM,IAAI,MACR,CAAC,OAAO,EAAE,GAAG,kBAAkB,EAAE,oBAAoB,uFAAuF,CAAC;IAEjJ;IAEA,MAAM,UAAU,cAAc,IAAI;IAClC,MAAM,EAAE,IAAG,EAAE,SAAQ,EAAE,GAAG,gBAAgB;IAE1C,IAAI;IACJ,OAAQ,OAAO;QACb,KAAK,WAAW;YACd,eAAe,IAAI;YACnB,UAAU,EAAE;YACZ;QACF,KAAK,WAAW;YAGd,UAAU;gBAAC,OAAO;aAAS;YAC3B;QACF,KAAK,WAAW;YACd,UAAU,OAAO,WAAW,EAAE;YAC9B;IACJ;IACA,MAAM,SAAiB;QACrB,SAAS,CAAC;QACV,OAAO;QACP,QAAQ;QACR;QACA;QACA,UAAU,EAAE;QACZ,iBAAiB;QACjB;IACF;IAEA,WAAW,CAAC,GAAG,GAAG;IAClB,eAAe,IAAI,QAAQ;IAG3B,IAAI;QACF,wBAAwB,QAAQ,CAAC;YAC/B,cAAc,KACZ,OAAO,SACP,eAAe;gBACb,GAAG,OAAO;gBACV,GAAG,gBAAgB,KAAK,MAAM;gBAC9B,GAAG,eAAe,KAAK,MAAM;gBAC7B,GAAG,UAAU,KAAK,MAAM;gBACxB,GAAG,UAAU,KAAK,MAAM;gBACxB,GAAG,UAAU,KAAK,MAAM,OAAO;gBAC/B,GAAG,YAAY,KAAK,MAAM;gBAC1B,GAAG,gBAAgB,KAAK,MAAM;gBAC9B,GAAG;gBACH,GAAG;gBACH,GAAG,UAAU,KAAK,MAAM;oBAAE,MAAM,WAAW;oBAAQ,UAAU;gBAAG;gBAChE,GAAG;gBACH,GAAG;gBACH,WAAW,OAAO,GAAG,QAAQ,gBAAgB;YAC/C;QAEJ;IACF,EAAE,OAAO,OAAO;QACd,OAAO,QAAQ;QACf,MAAM;IACR;IAEA,OAAO,SAAS;IAChB,IAAI,OAAO,mBAAmB,OAAO,YAAY,OAAO,iBAAiB;QAEvE,WAAW,OAAO,SAAS,OAAO;IACpC;IAEA,OAAO;AACT;AAOA,SAAS,wBACP,MAAc,EACd,aAA4C;IAE5C,MAAM,+BACJ,OAAO,WAAW,sCAAsC,aACpD,WAAW,kCAAkC,OAAO,MACpD,KAAO;IAEb,IAAI;QACF,cAAc;YACZ,UAAU,WAAW;YACrB,WAAW,WAAW;QACxB;QAEA,IAAI,sBAAsB,YAAY;YAGpC,+CACE,QACA,WAAW;QAEf;IACF,EAAE,OAAO,GAAG;QACV,MAAM;IACR,SAAU;QAER;IACF;AACF;AAKA,MAAM,mCAAqE,CACzE,IACA;IAEA,IAAI,CAAC,aAAa,IAAI,QAAQ;QAC5B,QAAQ,KACN,CAAC,4BAA4B,EAAE,GAAG,aAAa,EAAE,aAAa,GAAG,oCAAoC,CAAC;IAE1G;IAEA,MAAM,SAAS,WAAW,CAAC,GAAG;IAE9B,IAAI,aAAa,SAAS,QAAQ,QAAQ,CAAC,GAAG;QAC5C,aAAa,SAAS,KAAK;IAC7B;IAEA,IAAI,QAAQ;QACV,IAAI,OAAO,QAAQ,QAAQ,aAAa,QAAQ,CAAC,GAAG;YAClD,OAAO,QAAQ,KAAK,aAAa;QACnC;QAEA,OAAO;IACT;IAEA,OAAO,kBAAkB,IAAI;QAC3B,MAAM,WAAW;QACjB,UAAU,aAAa;IACzB;AACF;AAKA,SAAS,+CACP,MAAc,EACd,OAAuB;IAEvB,MAAM,iBAAiB,OAAO;IAC9B,MAAM,cAAc,OAAO,IAAI,KAAK,eAAe;IAEnD,QAAQ,+BAA+B,gBAAgB,OAAO;IAI9D,IAAI,QAAQ,uBAAuB,iBAAiB;QAGlD,OAAO,IAAI,QAAQ,CAAC;YAClB,KAAK,cAAc;QACrB;QAGA,OAAO,IAAI;QAKX,IAAI,gBAAgB,MAAM;YAQxB,IACE,QAAQ,qCACN,aACA,iBAEF;gBACA,OAAO,IAAI;YACb,OAAO;gBACL,QAAQ;YACV;QACF;IACF,OAAO;QAKL,MAAM,sBAAsB,gBAAgB;QAC5C,IAAI,qBAAqB;YACvB,OAAO,IAAI;QACb;IACF;AACF;AAEA,SAAS,sBAAsB,eAA2B;IACxD,OAAO,CAAC,kBAAkB,EAAE,gBAAgB,KAAK,QAAQ,CAAC;AAC5D;AAEA,SAAS,uBACP,KAAuD,EACvD,QAA8C;IAE9C,MAAM,kBAAkB,IAAI;IAC5B,MAAM,qBAAqB,IAAI;IAE/B,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,MAAO;QACrC,IAAI,SAAS,MAAM;YACjB,mBAAmB,IAAI,UAAU,MAAM;QACzC;IACF;IAEA,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,SAAU;QACxC,MAAM,SAAS,yBAAyB;QAExC,OAAQ,OAAO;YACb,KAAK;gBACH,MAAM,IAAI,MACR,CAAC,wCAAwC,EAAE,sBACzC,OAAO,iBACP,CAAC,CAAC;YAER,KAAK;gBACH,MAAM,IAAI,MACR,CAAC,2CAA2C,EAAE,sBAC5C,OAAO,iBACP,CAAC,CAAC;YAER,KAAK;gBACH,mBAAmB,IAAI,UAAU,MAAM;gBACvC,KAAK,MAAM,oBAAoB,OAAO,gBAAiB;oBACrD,gBAAgB,IAAI;gBACtB;gBACA;QAEJ;IACF;IAEA,OAAO;QAAE;QAAiB;IAAmB;AAC/C;AAEA,SAAS,mCACP,eAAmC;IAEnC,MAAM,8BAA8B,EAAE;IACtC,KAAK,MAAM,YAAY,gBAAiB;QACtC,MAAM,SAAS,WAAW,CAAC,SAAS;QACpC,MAAM,WAAW,eAAe,IAAI;QACpC,IAAI,UAAU,SAAS,gBAAgB,CAAC,SAAS,iBAAiB;YAChE,4BAA4B,KAAK;gBAC/B;gBACA,cAAc,SAAS;YACzB;QACF;IACF;IACA,OAAO;AACT;AAOA,SAAS,kBACP,kBAAiD,EACjD,oBAAmD;IAEnD,KAAK,MAAM,CAAC,WAAW,eAAe,IAAI,mBAAoB;QAC5D,KAAK,MAAM,YAAY,eAAgB;YACrC,iBAAiB,UAAU;QAC7B;IACF;IAEA,MAAM,kBAAiC,IAAI;IAC3C,KAAK,MAAM,CAAC,WAAW,eAAe,IAAI,qBAAsB;QAC9D,KAAK,MAAM,YAAY,eAAgB;YACrC,IAAI,sBAAsB,UAAU,YAAY;gBAC9C,gBAAgB,IAAI;YACtB;QACF;IACF;IAEA,OAAO;QAAE;IAAgB;AAC3B;AAEA,SAAS,aACP,eAAmC,EACnC,eAA8B;IAE9B,KAAK,MAAM,YAAY,gBAAiB;QACtC,cAAc,UAAU;IAC1B;IAEA,KAAK,MAAM,YAAY,gBAAiB;QACtC,cAAc,UAAU;IAC1B;IAIA,MAAM,wBAAwB,IAAI;IAClC,KAAK,MAAM,YAAY,gBAAiB;QACtC,MAAM,YAAY,WAAW,CAAC,SAAS;QACvC,sBAAsB,IAAI,UAAU,WAAW;QAC/C,OAAO,WAAW,CAAC,SAAS;IAC9B;IAKA,OAAO;QAAE;IAAsB;AACjC;AAeA,SAAS,cAAc,QAAkB,EAAE,IAAyB;IAClE,MAAM,SAAS,WAAW,CAAC,SAAS;IACpC,IAAI,CAAC,QAAQ;QACX;IACF;IAEA,MAAM,WAAW,eAAe,IAAI;IACpC,MAAM,OAAO,CAAC;IAId,KAAK,MAAM,kBAAkB,SAAS,gBAAiB;QACrD,eAAe;IACjB;IAIA,OAAO,IAAI,SAAS;IAEpB,eAAe,OAAO;IAOtB,KAAK,MAAM,WAAW,OAAO,SAAU;QACrC,MAAM,QAAQ,WAAW,CAAC,QAAQ;QAClC,IAAI,CAAC,OAAO;YACV;QACF;QAEA,MAAM,MAAM,MAAM,QAAQ,QAAQ,OAAO;QACzC,IAAI,OAAO,GAAG;YACZ,MAAM,QAAQ,OAAO,KAAK;QAC5B;IACF;IAEA,OAAQ;QACN,KAAK;YACH,OAAO,WAAW,CAAC,OAAO,GAAG;YAC7B,cAAc,OAAO,OAAO;YAC5B;QACF,KAAK;YACH,cAAc,IAAI,OAAO,IAAI;YAC7B;QACF;YACE,UAAU,MAAM,CAAC,OAAS,CAAC,cAAc,EAAE,KAAK,CAAC;IACrD;AACF;AAEA,SAAS,WACP,2BAGG,EACH,kBAAgD,EAChD,qBAAqD;IAGrD,KAAK,MAAM,CAAC,UAAU,QAAQ,IAAI,mBAAmB,UAAW;QAC9D,eAAe,CAAC,SAAS,GAAG;IAC9B;IAOA,KAAK,MAAM,EAAE,SAAQ,EAAE,aAAY,EAAE,IAAI,4BAA6B;QACpE,IAAI;YACF,kBAAkB,UAAU;gBAC1B,MAAM,WAAW;gBACjB,SAAS,sBAAsB,IAAI;YACrC;QACF,EAAE,OAAO,KAAK;YACZ,IAAI,OAAO,iBAAiB,YAAY;gBACtC,IAAI;oBACF,aAAa,KAAK;wBAAE;wBAAU,QAAQ,WAAW,CAAC,SAAS;oBAAC;gBAC9D,EAAE,OAAO,GAAG,CAEZ;YACF;QACF;IACF;AACF;AAKA,SAAS,UAAU,KAAY,EAAE,cAAoC;IACnE,MAAM,IAAI,MAAM,CAAC,WAAW,EAAE,eAAe,OAAO,CAAC;AACvD;AAEA,SAAS,YAAY,aAAwB,EAAE,MAAqB;IAClE,OAAQ,OAAO;QACb,KAAK;YACH,qBAAqB,eAAe;YACpC;QACF;YACE,UAAU,QAAQ,CAAC,SAAW,CAAC,qBAAqB,EAAE,OAAO,KAAK,CAAC;IACvE;AACF;AAEA,SAAS,qBACP,aAAwB,EACxB,MAAuB;IAEvB,IAAI,OAAO,UAAU,MAAM;QACzB,KAAK,MAAM,UAAU,OAAO,OAAQ;YAClC,OAAQ,OAAO;gBACb,KAAK;oBACH,4BAA4B,eAAe;oBAC3C;gBACF;oBACE,UAAU,QAAQ,CAAC,SAAW,CAAC,qBAAqB,EAAE,OAAO,KAAK,CAAC;YACvE;QACF;IACF;IAEA,IAAI,OAAO,UAAU,MAAM;QACzB,KAAK,MAAM,CAAC,WAAW,YAAY,IAAI,OAAO,QAAQ,OAAO,QAAS;YACpE,OAAQ,YAAY;gBAClB,KAAK;oBACH,QAAQ,UAAU,WAAW;wBAAE,MAAM,WAAW;oBAAO;oBACvD;gBACF,KAAK;oBACH,QAAQ,cAAc;oBACtB;gBACF,KAAK;oBACH,QAAQ,cAAc;oBACtB;gBACF,KAAK;oBACH,UACE,YAAY,aACZ,CAAC,cACC,CAAC,6BAA6B,EAAE,KAAK,UAAU,aAAa,CAAC,CAAC;gBAEpE;oBACE,UACE,aACA,CAAC,cAAgB,CAAC,2BAA2B,EAAE,YAAY,KAAK,CAAC;YAEvE;QACF;IACF;AACF;AAEA,SAAS,4BACP,SAAoB,EACpB,MAA8B;IAE9B,MAAM,EAAE,SAAU,CAAC,EAAC,EAAE,QAAS,CAAC,EAAC,EAAE,GAAG;IACtC,MAAM,EAAE,MAAK,EAAE,SAAQ,EAAE,QAAO,EAAE,YAAW,EAAE,cAAa,EAAE,GAC5D,sBAAsB,SAAS;IACjC,MAAM,EAAE,gBAAe,EAAE,mBAAkB,EAAE,GAAG,uBAC9C,OACA;IAEF,MAAM,8BACJ,mCAAmC;IACrC,MAAM,EAAE,gBAAe,EAAE,GAAG,kBAAkB,aAAa;IAC3D,MAAM,EAAE,sBAAqB,EAAE,GAAG,aAChC,iBACA;IAEF,WACE,6BACA,oBACA;AAEJ;AAEA,SAAS,sBACP,OAAgD,EAChD,OAAuD;IAQvD,MAAM,cAAc,IAAI;IACxB,MAAM,gBAAgB,IAAI;IAC1B,MAAM,QAA8C,IAAI;IACxD,MAAM,WAAW,IAAI;IACrB,MAAM,UAAyB,IAAI;IAEnC,KAAK,MAAM,CAAC,WAAW,kBAAkB,IAAI,OAAO,QAAQ,SAAU;QACpE,OAAQ,kBAAkB;YACxB,KAAK;gBAAS;oBACZ,MAAM,cAAc,IAAI,IAAI,kBAAkB;oBAC9C,KAAK,MAAM,YAAY,YAAa;wBAClC,MAAM,IAAI,UAAU,OAAO,CAAC,SAAS;oBACvC;oBACA,YAAY,IAAI,WAAW;oBAC3B;gBACF;YACA,KAAK;gBAAW;oBAEd,MAAM,gBAAgB,IAAI,IAAI,gBAAgB,IAAI;oBAClD,KAAK,MAAM,YAAY,cAAe;wBACpC,QAAQ,IAAI;oBACd;oBACA,cAAc,IAAI,WAAW;oBAC7B;gBACF;YACA,KAAK;gBAAW;oBACd,MAAM,cAAc,IAAI,IAAI,kBAAkB;oBAC9C,MAAM,gBAAgB,IAAI,IAAI,kBAAkB;oBAChD,KAAK,MAAM,YAAY,YAAa;wBAClC,MAAM,IAAI,UAAU,OAAO,CAAC,SAAS;oBACvC;oBACA,KAAK,MAAM,YAAY,cAAe;wBACpC,QAAQ,IAAI;oBACd;oBACA,YAAY,IAAI,WAAW;oBAC3B,cAAc,IAAI,WAAW;oBAC7B;gBACF;YACA;gBACE,UACE,mBACA,CAAC,oBACC,CAAC,kCAAkC,EAAE,kBAAkB,KAAK,CAAC;QAErE;IACF;IAKA,KAAK,MAAM,YAAY,MAAM,OAAQ;QACnC,IAAI,QAAQ,IAAI,WAAW;YACzB,MAAM,OAAO;YACb,QAAQ,OAAO;QACjB;IACF;IAEA,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,OAAO,QAAQ,SAAU;QAKvD,IAAI,CAAC,MAAM,IAAI,WAAW;YACxB,SAAS,IAAI,UAAU;QACzB;IACF;IAEA,OAAO;QAAE;QAAO;QAAS;QAAU;QAAa;IAAc;AAChE;AAkBA,SAAS,yBAAyB,QAAkB;IAClD,MAAM,kBAAiC,IAAI;IAI3C,MAAM,QAAqB;QACzB;YACE;YACA,iBAAiB,EAAE;QACrB;KACD;IAED,IAAI;IACJ,MAAQ,WAAW,MAAM,QAAU;QACjC,MAAM,EAAE,SAAQ,EAAE,gBAAe,EAAE,GAAG;QAEtC,IAAI,YAAY,MAAM;YACpB,gBAAgB,IAAI;QACtB;QAIA,IAAI,aAAa,WAAW;YAC1B,OAAO;gBACL,MAAM;gBACN;YACF;QACF;QAEA,MAAM,SAAS,WAAW,CAAC,SAAS;QACpC,MAAM,WAAW,eAAe,IAAI;QAEpC,IAGE,CAAC,UAEA,SAAS,gBAAgB,CAAC,SAAS,iBACpC;YACA;QACF;QAEA,IAAI,SAAS,cAAc;YACzB,OAAO;gBACL,MAAM;gBACN;gBACA;YACF;QACF;QAEA,IAAI,eAAe,IAAI,WAAW;YAChC,MAAM,KAAK;gBACT,UAAU;gBACV,iBAAiB;uBAAI;oBAAiB;iBAAS;YACjD;YACA;QACF;QAEA,KAAK,MAAM,YAAY,OAAO,QAAS;YACrC,MAAM,SAAS,WAAW,CAAC,SAAS;YAEpC,IAAI,CAAC,QAAQ;gBAEX;YACF;YAKA,MAAM,KAAK;gBACT,UAAU;gBACV,iBAAiB;uBAAI;oBAAiB;iBAAS;YACjD;QACF;IACF;IAEA,OAAO;QACL,MAAM;QACN;QACA;IACF;AACF;AAEA,SAAS,YAAY,aAAwB,EAAE,MAAqB;IAClE,OAAQ,OAAO;QACb,KAAK;YAAW;gBAEd,YAAY,eAAe,OAAO;gBAClC;YACF;QACA,KAAK;YAAW;gBAId,QAAQ;gBACR;YACF;QACA,KAAK;YAAY;gBAKf,IAAI,kBAAkB,IAAI,gBAAgB;oBACxC,QAAQ;gBACV,OAAO;oBACL,iBAAiB;gBACnB;gBACA;YACF;QACA;YACE,MAAM,IAAI,MAAM,CAAC,qBAAqB,EAAE,OAAO,KAAK,CAAC;IACzD;AACF;AAEA,SAAS,gBAAgB,OAAgB;IACvC,MAAM,WAAqB;QACzB,cAAc;QACd,cAAc;QACd,iBAAiB;QACjB,iBAAiB,EAAE;IACrB;IAEA,MAAM,MAAW;QAIf,QAAQ;QAER,MAAM,WAAW,CAAC;QAGlB,QAAQ,CACN,SACA,WACA;YAEA,IAAI,YAAY,WAAW;gBACzB,SAAS,eAAe;YAC1B,OAAO,IAAI,OAAO,YAAY,YAAY;gBACxC,SAAS,eAAe;YAC1B,OAAO;gBACL,MAAM,IAAI,MAAM;YAClB;QACF;QAEA,SAAS,CAAC;YACR,IAAI,QAAQ,WAAW;gBACrB,SAAS,eAAe;YAC1B,OAAO;gBACL,MAAM,IAAI,MAAM;YAClB;QACF;QAEA,SAAS,CAAC;YACR,SAAS,gBAAgB,KAAK;QAChC;QAEA,mBAAmB,CAAC;YAClB,SAAS,gBAAgB,KAAK;QAChC;QAEA,sBAAsB,CAAC;YACrB,MAAM,MAAM,SAAS,gBAAgB,QAAQ;YAC7C,IAAI,OAAO,GAAG;gBACZ,SAAS,gBAAgB,OAAO,KAAK;YACvC;QACF;QAEA,YAAY;YACV,SAAS,kBAAkB;QAG7B;QAKA,QAAQ,IAAM;QAGd,kBAAkB,CAAC,YAAc;QACjC,qBAAqB,CAAC,YAAc;IACtC;IAEA,OAAO;QAAE;QAAK;IAAS;AACzB;AAKA,SAAS,iBAAiB,QAAkB,EAAE,SAAoB;IAChE,IAAI,eAAe,gBAAgB,IAAI;IACvC,IAAI,CAAC,cAAc;QACjB,eAAe,IAAI,IAAI;YAAC;SAAU;QAClC,gBAAgB,IAAI,UAAU;IAChC,OAAO;QACL,aAAa,IAAI;IACnB;IAEA,IAAI,eAAe,gBAAgB,IAAI;IACvC,IAAI,CAAC,cAAc;QACjB,eAAe,IAAI,IAAI;YAAC;SAAS;QACjC,gBAAgB,IAAI,WAAW;IACjC,OAAO;QACL,aAAa,IAAI;IACnB;AACF;AAOA,SAAS,oBAAoB,QAAkB;IAC7C,MAAM,mBAAmB,gBAAgB,IAAI;IAC7C,IAAI,oBAAoB,MAAM;QAC5B,OAAO;IACT;IAEA,OAAO,iBAAiB,SAAS,OAAO;AAC1C;AAMA,SAAS,sBACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,eAAe,gBAAgB,IAAI;IACzC,aAAa,OAAO;IAEpB,MAAM,eAAe,gBAAgB,IAAI;IACzC,aAAa,OAAO;IAEpB,MAAM,qBAAqB,aAAa,SAAS;IACjD,IAAI,oBAAoB;QACtB,gBAAgB,OAAO;IACzB;IAEA,MAAM,oBAAoB,aAAa,SAAS;IAChD,IAAI,mBAAmB;QACrB,gBAAgB,OAAO;IACzB;IAEA,OAAO;AACT;AAKA,SAAS,iBAAiB,aAAwB;IAChD,MAAM,aAAa,mBAAmB,IAAI;IAC1C,IAAI,cAAc,MAAM;QACtB,OAAO;IACT;IACA,mBAAmB,OAAO;IAE1B,KAAK,MAAM,aAAa,WAAY;QAClC,MAAM,kBAAkB,mBAAmB,IAAI;QAC/C,gBAAgB,OAAO;QAEvB,IAAI,gBAAgB,SAAS,GAAG;YAC9B,mBAAmB,OAAO;YAC1B,aAAa;QACf;IACF;IAIA,QAAQ,cAAc;IAEtB,OAAO;AACT;AAOA,SAAS,aAAa,SAAoB;IAGxC,QAAQ,cAAc;IAEtB,MAAM,eAAe,gBAAgB,IAAI;IACzC,IAAI,gBAAgB,MAAM;QACxB,OAAO;IACT;IACA,aAAa,OAAO;IAEpB,KAAK,MAAM,YAAY,aAAc;QACnC,MAAM,eAAe,gBAAgB,IAAI;QACzC,aAAa,OAAO;QAEpB,MAAM,oBAAoB,aAAa,SAAS;QAChD,IAAI,mBAAmB;YACrB,gBAAgB,OAAO;YACvB,cAAc,UAAU;YACxB,iBAAiB,OAAO;QAC1B;IACF;IAEA,OAAO;AACT;AAKA,SAAS,yBACP,QAAkB,EAClB,SAAoB;IAEpB,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,8BACP,QAAkB,EAClB,SAAoB;IAEpB,MAAM,SAAS,WAAW,CAAC,SAAS;IACpC,IAAI,QAAQ;QACV,IAAI,OAAO,OAAO;YAChB,MAAM,OAAO;QACf;QACA,OAAO;IACT;IAEA,OAAO,kBAAkB,UAAU;QAAE,MAAM,WAAW;QAAS;IAAU;AAC3E;AAKA,SAAS,kBACP,mBAAwC,EACxC,SAAoB;IAEpB,oBAAoB,KAAK;QACvB,UAAU;QACV,YAAY,KAAK,MAAM,UAAU;KAClC;IAGD,MAAM,SAAS,IAAI,IAAI,UAAU,OAAO,IAAI;IAC5C,mBAAmB,IAAI,UAAU,MAAM;IACvC,KAAK,MAAM,aAAa,OAAQ;QAC9B,IAAI,kBAAkB,mBAAmB,IAAI;QAC7C,IAAI,CAAC,iBAAiB;YACpB,kBAAkB,IAAI,IAAI;gBAAC,UAAU;aAAK;YAC1C,mBAAmB,IAAI,WAAW;QACpC,OAAO;YACL,gBAAgB,IAAI,UAAU;QAChC;IACF;IAEA,IAAI,UAAU,WAAW,SAAS;QAChC,uBAAuB,UAAU;IACnC;AACF;AAOA,SAAS,uBAAuB,aAAwB;IACtD,kBAAkB,IAAI;AACxB;AAEA,SAAS,cAAc,CACrB,WACA,cACA,cACkB;IAClB,KAAK,MAAM,CAAC,UAAU,cAAc,IAAI,OAAO,QAAQ,cAAe;QACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9B,eAAe,CAAC,SAAS,GAAG;QAC9B;QACA,iBAAiB,UAAU;IAC7B;IAEA,OAAO,QAAQ,cAAc,WAAW;AAC1C;AAEA,WAAW,qCAAqC,EAAE;AAElD,MAAM,uBAAuB,WAAW;AACxC,IAAI,MAAM,QAAQ,uBAAuB;IACvC,KAAK,MAAM,aAAa,qBAAsB;QAC5C,kBAAkB,WAAW,kCAAkC;IACjE;AACF;AAEA,WAAW,wBAAwB;IACjC,MAAM,CAAC;QACL,kBAAkB,WAAW,kCAAmC;IAClE;AACF"}}, + {"offset": {"line": 871, "column": 0}, "map": {"version":3,"sources":["/turbopack/[turbopack]/dev/runtime/dom/runtime-backend-dom.ts"],"sourcesContent":["/**\n * This file contains the runtime code specific to the Turbopack development\n * ECMAScript DOM runtime.\n *\n * It will be appended to the base development runtime code.\n */\n\n/// \n\ntype ChunkResolver = {\n resolved: boolean;\n resolve: () => void;\n reject: (error?: Error) => void;\n promise: Promise;\n};\n\nlet BACKEND: RuntimeBackend;\n\nfunction augmentContext(context: TurbopackDevBaseContext): TurbopackDevContext {\n return context;\n}\n\nfunction commonJsRequireContext(\n entry: RequireContextEntry,\n sourceModule: Module\n): Exports {\n return commonJsRequire(sourceModule, entry.id());\n}\n\n(() => {\n BACKEND = {\n async registerChunk(chunkPath, params) {\n const resolver = getOrCreateResolver(chunkPath);\n resolver.resolve();\n\n if (params == null) {\n return;\n }\n\n for (const otherChunkData of params.otherChunks) {\n const otherChunkPath = getChunkPath(otherChunkData);\n // Chunk might have started loading, so we want to avoid triggering another load.\n getOrCreateResolver(otherChunkPath);\n }\n\n // This waits for chunks to be loaded, but also marks included items as available.\n await Promise.all(\n params.otherChunks.map((otherChunkData) =>\n loadChunk({ type: SourceType.Runtime, chunkPath }, otherChunkData)\n )\n );\n\n if (params.runtimeModuleIds.length > 0) {\n for (const moduleId of params.runtimeModuleIds) {\n getOrInstantiateRuntimeModule(moduleId, chunkPath);\n }\n }\n },\n\n loadChunk(chunkPath, source) {\n return doLoadChunk(chunkPath, source);\n },\n\n unloadChunk(chunkPath) {\n deleteResolver(chunkPath);\n\n if (chunkPath.endsWith(\".css\")) {\n const links = document.querySelectorAll(`link[href=\"/${chunkPath}\"]`);\n for (const link of Array.from(links)) {\n link.remove();\n }\n } else if (chunkPath.endsWith(\".js\")) {\n // Unloading a JS chunk would have no effect, as it lives in the JS\n // runtime once evaluated.\n // However, we still want to remove the script tag from the DOM to keep\n // the HTML somewhat consistent from the user's perspective.\n const scripts = document.querySelectorAll(\n `script[src=\"/${chunkPath}\"]`\n );\n for (const script of Array.from(scripts)) {\n script.remove();\n }\n } else {\n throw new Error(`can't infer type of chunk from path ${chunkPath}`);\n }\n },\n\n reloadChunk(chunkPath) {\n return new Promise((resolve, reject) => {\n if (!chunkPath.endsWith(\".css\")) {\n reject(new Error(\"The DOM backend can only reload CSS chunks\"));\n return;\n }\n\n const encodedChunkPath = chunkPath\n .split(\"/\")\n .map((p) => encodeURIComponent(p))\n .join(\"/\");\n\n const previousLink = document.querySelector(\n `link[rel=stylesheet][href^=\"/${encodedChunkPath}\"]`\n );\n\n if (previousLink == null) {\n reject(new Error(`No link element found for chunk ${chunkPath}`));\n return;\n }\n\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = `/${encodedChunkPath}`;\n link.onerror = () => {\n reject();\n };\n link.onload = () => {\n // First load the new CSS, then remove the old one. This prevents visible\n // flickering that would happen in-between removing the previous CSS and\n // loading the new one.\n previousLink.remove();\n\n // CSS chunks do not register themselves, and as such must be marked as\n // loaded instantly.\n resolve();\n };\n\n // Make sure to insert the new CSS right after the previous one, so that\n // its precedence is higher.\n previousLink.parentElement!.insertBefore(\n link,\n previousLink.nextSibling\n );\n });\n },\n\n restart: () => self.location.reload(),\n };\n\n /**\n * Maps chunk paths to the corresponding resolver.\n */\n const chunkResolvers: Map = new Map();\n\n function getOrCreateResolver(chunkPath: ChunkPath): ChunkResolver {\n let resolver = chunkResolvers.get(chunkPath);\n if (!resolver) {\n let resolve: () => void;\n let reject: (error?: Error) => void;\n const promise = new Promise((innerResolve, innerReject) => {\n resolve = innerResolve;\n reject = innerReject;\n });\n resolver = {\n resolved: false,\n promise,\n resolve: () => {\n resolver!.resolved = true;\n resolve();\n },\n reject: reject!,\n };\n chunkResolvers.set(chunkPath, resolver);\n }\n return resolver;\n }\n\n function deleteResolver(chunkPath: ChunkPath) {\n chunkResolvers.delete(chunkPath);\n }\n\n /**\n * Loads the given chunk, and returns a promise that resolves once the chunk\n * has been loaded.\n */\n async function doLoadChunk(chunkPath: ChunkPath, source: SourceInfo) {\n const resolver = getOrCreateResolver(chunkPath);\n if (resolver.resolved) {\n return resolver.promise;\n }\n\n if (source.type === SourceType.Runtime) {\n // We don't need to load chunks references from runtime code, as they're already\n // present in the DOM.\n\n if (chunkPath.endsWith(\".css\")) {\n // CSS chunks do not register themselves, and as such must be marked as\n // loaded instantly.\n resolver.resolve();\n }\n\n // We need to wait for JS chunks to register themselves within `registerChunk`\n // before we can start instantiating runtime modules, hence the absence of\n // `resolver.resolve()` in this branch.\n\n return resolver.promise;\n }\n\n if (chunkPath.endsWith(\".css\")) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = `/${chunkPath}`;\n link.onerror = () => {\n resolver.reject();\n };\n link.onload = () => {\n // CSS chunks do not register themselves, and as such must be marked as\n // loaded instantly.\n resolver.resolve();\n };\n document.body.appendChild(link);\n } else if (chunkPath.endsWith(\".js\")) {\n const script = document.createElement(\"script\");\n script.src = `/${chunkPath}`;\n // We'll only mark the chunk as loaded once the script has been executed,\n // which happens in `registerChunk`. Hence the absence of `resolve()` in\n // this branch.\n script.onerror = () => {\n resolver.reject();\n };\n document.body.appendChild(script);\n } else {\n throw new Error(`can't infer type of chunk from path ${chunkPath}`);\n }\n\n return resolver.promise;\n }\n})();\n\nfunction _eval({ code, url, map }: EcmascriptModuleEntry): ModuleFactory {\n code += `\\n\\n//# sourceURL=${location.origin}${url}`;\n if (map) code += `\\n//# sourceMappingURL=${map}`;\n return eval(code);\n}\n"],"names":[],"mappings":"AAgBA,IAAI;AAEJ,SAAS,eAAe,QAAgC;IACtD,OAAO;AACT;AAEA,SAAS,uBACP,MAA0B,EAC1B,aAAoB;IAEpB,OAAO,gBAAgB,eAAc,OAAM;AAC7C;AAEC,CAAA;IACC,UAAU;QACR,MAAM,eAAc,UAAS,EAAE,OAAM;YACnC,MAAM,YAAW,qBAAoB;YACrC,UAAS;YAET,IAAI,WAAU,MAAM;gBAClB;YACF;YAEA,KAAK,MAAM,mBAAkB,QAAO,YAAa;gBAC/C,MAAM,kBAAiB,aAAa;gBAEpC,qBAAoB;YACtB;YAGA,MAAM,QAAQ,IACZ,QAAO,YAAY,IAAI,CAAC,kBACtB,UAAU;oBAAE,MAAM,WAAW;oBAAS,WAAA;gBAAU,GAAG;YAIvD,IAAI,QAAO,iBAAiB,SAAS,GAAG;gBACtC,KAAK,MAAM,aAAY,QAAO,iBAAkB;oBAC9C,8BAA8B,WAAU;gBAC1C;YACF;QACF;QAEA,WAAU,UAAS,EAAE,OAAM;YACzB,OAAO,aAAY,YAAW;QAChC;QAEA,aAAY,UAAS;YACnB,gBAAe;YAEf,IAAI,WAAU,SAAS,SAAS;gBAC9B,MAAM,SAAQ,SAAS,iBAAiB,CAAC,YAAY,EAAE,WAAU,EAAE,CAAC;gBACpE,KAAK,MAAM,SAAQ,MAAM,KAAK,QAAQ;oBACpC,MAAK;gBACP;YACF,OAAO,IAAI,WAAU,SAAS,QAAQ;gBAKpC,MAAM,WAAU,SAAS,iBACvB,CAAC,aAAa,EAAE,WAAU,EAAE,CAAC;gBAE/B,KAAK,MAAM,WAAU,MAAM,KAAK,UAAU;oBACxC,QAAO;gBACT;YACF,OAAO;gBACL,MAAM,IAAI,MAAM,CAAC,oCAAoC,EAAE,WAAU,CAAC;YACpE;QACF;QAEA,aAAY,UAAS;YACnB,OAAO,IAAI,QAAc,CAAC,UAAS;gBACjC,IAAI,CAAC,WAAU,SAAS,SAAS;oBAC/B,QAAO,IAAI,MAAM;oBACjB;gBACF;gBAEA,MAAM,oBAAmB,WACtB,MAAM,KACN,IAAI,CAAC,KAAM,mBAAmB,KAC9B,KAAK;gBAER,MAAM,gBAAe,SAAS,cAC5B,CAAC,6BAA6B,EAAE,kBAAiB,EAAE,CAAC;gBAGtD,IAAI,iBAAgB,MAAM;oBACxB,QAAO,IAAI,MAAM,CAAC,gCAAgC,EAAE,WAAU,CAAC;oBAC/D;gBACF;gBAEA,MAAM,QAAO,SAAS,cAAc;gBACpC,MAAK,MAAM;gBACX,MAAK,OAAO,CAAC,CAAC,EAAE,kBAAiB,CAAC;gBAClC,MAAK,UAAU;oBACb;gBACF;gBACA,MAAK,SAAS;oBAIZ,cAAa;oBAIb;gBACF;gBAIA,cAAa,cAAe,aAC1B,OACA,cAAa;YAEjB;QACF;QAEA,SAAS,IAAM,KAAK,SAAS;IAC/B;IAKA,MAAM,kBAAgD,IAAI;IAE1D,SAAS,qBAAoB,UAAoB;QAC/C,IAAI,YAAW,gBAAe,IAAI;QAClC,IAAI,CAAC,WAAU;YACb,IAAI;YACJ,IAAI;YACJ,MAAM,WAAU,IAAI,QAAc,CAAC,eAAc;gBAC/C,WAAU;gBACV,UAAS;YACX;YACA,YAAW;gBACT,UAAU;gBACV,SAAA;gBACA,SAAS;oBACP,UAAU,WAAW;oBACrB;gBACF;gBACA,QAAQ;YACV;YACA,gBAAe,IAAI,YAAW;QAChC;QACA,OAAO;IACT;IAEA,SAAS,gBAAe,UAAoB;QAC1C,gBAAe,OAAO;IACxB;IAMA,eAAe,aAAY,UAAoB,EAAE,OAAkB;QACjE,MAAM,YAAW,qBAAoB;QACrC,IAAI,UAAS,UAAU;YACrB,OAAO,UAAS;QAClB;QAEA,IAAI,QAAO,SAAS,WAAW,SAAS;YAItC,IAAI,WAAU,SAAS,SAAS;gBAG9B,UAAS;YACX;YAMA,OAAO,UAAS;QAClB;QAEA,IAAI,WAAU,SAAS,SAAS;YAC9B,MAAM,QAAO,SAAS,cAAc;YACpC,MAAK,MAAM;YACX,MAAK,OAAO,CAAC,CAAC,EAAE,WAAU,CAAC;YAC3B,MAAK,UAAU;gBACb,UAAS;YACX;YACA,MAAK,SAAS;gBAGZ,UAAS;YACX;YACA,SAAS,KAAK,YAAY;QAC5B,OAAO,IAAI,WAAU,SAAS,QAAQ;YACpC,MAAM,UAAS,SAAS,cAAc;YACtC,QAAO,MAAM,CAAC,CAAC,EAAE,WAAU,CAAC;YAI5B,QAAO,UAAU;gBACf,UAAS;YACX;YACA,SAAS,KAAK,YAAY;QAC5B,OAAO;YACL,MAAM,IAAI,MAAM,CAAC,oCAAoC,EAAE,WAAU,CAAC;QACpE;QAEA,OAAO,UAAS;IAClB;AACF,CAAA;AAEA,SAAS,MAAM,EAAE,KAAI,EAAE,IAAG,EAAE,IAAG,EAAyB;IACtD,QAAQ,CAAC,kBAAkB,EAAE,SAAS,OAAO,EAAE,IAAI,CAAC;IACpD,IAAI,KAAK,QAAQ,CAAC,uBAAuB,EAAE,IAAI,CAAC;IAChD,OAAO,KAAK;AACd"}}, + {"offset": {"line": 1012, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":"A"}}] } \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/63a02_styled-components_index_a35c8c.js b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/63a02_styled-components_index_a35c8c.js index 935e60fd10625..04f63d6cd6558 100644 --- a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/63a02_styled-components_index_a35c8c.js +++ b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/63a02_styled-components_index_a35c8c.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_styled-components_index_a35c8c.js", { -"[project]/crates/turbopack-tests/tests/node_modules/styled-components/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/styled-components/index.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "styled-components/index.js"; diff --git a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js index 9bd06d096f897..976bc0577a43e 100644 --- a/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_styled_components_styled_components_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/styled_components/styled_components/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$styled$2d$components$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/styled-components/index.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/63a02_react_jsx-dev-runtime_7d1be7.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/63a02_react_jsx-dev-runtime_7d1be7.js index 4c68642ae350d..9cebb7f2b9d3e 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/63a02_react_jsx-dev-runtime_7d1be7.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/63a02_react_jsx-dev-runtime_7d1be7.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_react_jsx-dev-runtime_7d1be7.js", { -"[project]/crates/turbopack-tests/tests/node_modules/react/jsx-dev-runtime.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/react/jsx-dev-runtime.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "react/jsx-dev-runtime.js"; diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/7b7bf_third_party_component_index_8e9ad8.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/7b7bf_third_party_component_index_8e9ad8.js index 673755fcfe2a2..34adacd015dda 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/7b7bf_third_party_component_index_8e9ad8.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/7b7bf_third_party_component_index_8e9ad8.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/7b7bf_third_party_component_index_8e9ad8.js", { -"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/node_modules/third_party_component/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/node_modules/third_party_component/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>ThirdPartyComponent diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js index 546b0c3b083ba..5aa8aa1407136 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/8562f_snapshot_swc_transforms_mono_transforms_input_packages_component_index_b0e6f8.js", { -"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/component/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/component/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "default": ()=>MyApp diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js index 69a5d7d579820..f3f0168cbac4e 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_swc_transforms_mono_transforms_input_packages_app_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/app/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/app/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$swc_transforms$2f$mono_transforms$2f$input$2f$packages$2f$component$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/packages/component/index.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$swc_transforms$2f$mono_transforms$2f$input$2f$node_modules$2f$third_party_component$2f$index$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/mono_transforms/input/node_modules/third_party_component/index.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/63a02_@swc_helpers____class_call_check_f08d44.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/63a02_@swc_helpers____class_call_check_f08d44.js index 6ed895e115793..efecf6a0c6207 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/63a02_@swc_helpers____class_call_check_f08d44.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/63a02_@swc_helpers____class_call_check_f08d44.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_@swc_helpers____class_call_check_f08d44.js", { -"[project]/crates/turbopack-tests/tests/node_modules/@swc/helpers/_/_class_call_check.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { +"[project]/crates/turbopack-tests/tests/node_modules/@swc/helpers/_/_class_call_check.js (ecmascript)": (function({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__, m: module, e: exports }) { !function() { "purposefully empty stub"; "@swc/helpers/_/_class_call_check.js"; diff --git a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js index 98c23403d4c2e..7ecf66aa9fc84 100644 --- a/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_swc_transforms_preset_env_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f40$swc$2f$helpers$2f$_$2f$_class_call_check$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/@swc/helpers/_/_class_call_check.js (ecmascript)"); "__TURBOPACK__ecmascript__hoisting__location__"; diff --git a/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js index b8ba06d4cdb97..84fa9a707523a 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_typescript_jsconfig-baseurl_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/prop.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/prop.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/index.js (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$jsconfig$2d$baseurl$2f$input$2f$prop$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/prop.js (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$jsconfig$2d$baseurl$2f$input$2f$prop$2e$js__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/jsconfig-baseurl/input/prop.js (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js index 6a05aca5a54f3..a5580e124be8d 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-baseurl_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/index.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$baseurl$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$baseurl$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-baseurl/input/prop.ts (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js index ea50e6c09c340..15bd246b74b5d 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/63a02_tsconfig-mod_prop_ts_2aa573._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_tsconfig-mod_prop_ts_2aa573._.js", { -"[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js index 2403be0ae4c95..b827fe470bfd3 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/8562f_snapshot_typescript_tsconfig-extends-module-full-path_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module-full-path/input/index.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$tsconfig$2d$mod$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$tsconfig$2d$mod$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js index 12803026cf6a8..d6abd005efd0d 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/63a02_tsconfig-mod_prop_ts_ae3f0e._.js", { -"[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js index 8b062e3f6cfe6..8a11b3ce9ca86 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends-module_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-module/input/index.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$tsconfig$2d$mod$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$node_modules$2f$tsconfig$2d$mod$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/node_modules/tsconfig-mod/prop.ts (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js index b1a211e853b3d..34628ba8584cb 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends-relative-dir_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/index.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2d$relative$2d$dir$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2d$relative$2d$dir$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-relative-dir/input/prop.ts (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js index be6a10dea912b..32c364b61f481 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends-without-ext_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/index.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2d$without$2d$ext$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2d$without$2d$ext$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends-without-ext/input/prop.ts (ecmascript)"); diff --git a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js index b2c3b5f76600f..0f582581b3592 100644 --- a/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js +++ b/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js @@ -1,6 +1,6 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/a587c_tests_snapshot_typescript_tsconfig-extends_input_index_ts_b53fce._.js", { -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/prop.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { __turbopack_esm__({ "prop": ()=>prop @@ -8,7 +8,7 @@ __turbopack_esm__({ const prop = 1; })()), -"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/index.ts (ecmascript)": (({ r: __turbopack_require__, x: __turbopack_external_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { +"[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/index.ts (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, k: __turbopack_refresh__ }) => (() => { var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/prop.ts (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$crates$2f$turbopack$2d$tests$2f$tests$2f$snapshot$2f$typescript$2f$tsconfig$2d$extends$2f$input$2f$prop$2e$ts__$28$ecmascript$29$__ = __turbopack_import__("[project]/crates/turbopack-tests/tests/snapshot/typescript/tsconfig-extends/input/prop.ts (ecmascript)"); From 9b463a539a8f0b73517c70179c3eebc90ff945a4 Mon Sep 17 00:00:00 2001 From: Alex Kirszenberg Date: Thu, 25 May 2023 18:12:57 +0200 Subject: [PATCH 19/19] Update snapshots, fix externals test --- crates/turbopack-tests/tests/snapshot.rs | 43 ++++++++++++++----- ...neration for chunk item errored-2613b6.txt | 14 ------ .../node/node_protocol_external/options.json | 3 ++ ...de_protocol_external_input_index_b53fce.js | 12 ++++-- ...rotocol_external_input_index_b53fce.js.map | 4 +- 5 files changed, 47 insertions(+), 29 deletions(-) delete mode 100644 crates/turbopack-tests/tests/snapshot/node/node_protocol_external/issues/Code generation for chunk item errored-2613b6.txt create mode 100644 crates/turbopack-tests/tests/snapshot/node/node_protocol_external/options.json diff --git a/crates/turbopack-tests/tests/snapshot.rs b/crates/turbopack-tests/tests/snapshot.rs index 9f4b0524a0c79..eacbaa7934342 100644 --- a/crates/turbopack-tests/tests/snapshot.rs +++ b/crates/turbopack-tests/tests/snapshot.rs @@ -38,7 +38,10 @@ use turbopack_core::{ compile_time_defines, compile_time_info::CompileTimeInfo, context::{AssetContext, AssetContextVc}, - environment::{BrowserEnvironment, EnvironmentIntention, EnvironmentVc, ExecutionEnvironment}, + environment::{ + BrowserEnvironment, EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, + NodeJsEnvironment, + }, issue::IssueVc, reference::all_referenced_assets, reference_type::{EntryReferenceSubType, ReferenceType}, @@ -90,6 +93,8 @@ struct SnapshotOptions { runtime: Runtime, #[serde(default = "default_runtime_type")] runtime_type: RuntimeType, + #[serde(default)] + environment: Environment, } #[derive(Debug, Deserialize, Default)] @@ -99,6 +104,13 @@ enum Runtime { Build, } +#[derive(Debug, Deserialize, Default)] +enum Environment { + #[default] + Browser, + NodeJs, +} + impl Default for SnapshotOptions { fn default() -> Self { SnapshotOptions { @@ -106,6 +118,7 @@ impl Default for SnapshotOptions { entry: default_entry(), runtime: Default::default(), runtime_type: default_runtime_type(), + environment: Default::default(), } } } @@ -201,16 +214,26 @@ async fn run_test(resource: &str) -> Result { let entry_paths = vec![entry_asset]; let env = EnvironmentVc::new( - Value::new(ExecutionEnvironment::Browser( - // TODO: load more from options.json - BrowserEnvironment { - dom: true, - web_worker: false, - service_worker: false, - browserslist_query: options.browserslist.to_owned(), + Value::new(match options.environment { + Environment::Browser => { + ExecutionEnvironment::Browser( + // TODO: load more from options.json + BrowserEnvironment { + dom: true, + web_worker: false, + service_worker: false, + browserslist_query: options.browserslist.to_owned(), + } + .into(), + ) + } + Environment::NodeJs => { + ExecutionEnvironment::NodeJsBuildTime( + // TODO: load more from options.json + NodeJsEnvironment::default().into(), + ) } - .into(), - )), + }), Value::new(EnvironmentIntention::Client), ); let compile_time_info = CompileTimeInfo::builder(env) diff --git a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/issues/Code generation for chunk item errored-2613b6.txt b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/issues/Code generation for chunk item errored-2613b6.txt deleted file mode 100644 index cd84cfdf89290..0000000000000 --- a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/issues/Code generation for chunk item errored-2613b6.txt +++ /dev/null @@ -1,14 +0,0 @@ -PlainIssue { - severity: Error, - context: "[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js", - category: "code generation", - title: "Code generation for chunk item errored", - description: "An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)\n\nCaused by:\n- the chunking context does not support Node.js external modules\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)\n- Execution of EcmascriptChunkItemContentVc::module_factory failed\n- Execution of EcmascriptChunkItemContentVc::new failed\n- Execution of EcmascriptModuleContentVc::new failed\n- Execution of EsmAssetReference::code_generation failed\n- the chunking context does not support Node.js external modules", - detail: "", - documentation_link: "", - source: None, - sub_issues: [], - processing_path: Some( - [], - ), -} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/options.json b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/options.json new file mode 100644 index 0000000000000..d56676da5aa7f --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/options.json @@ -0,0 +1,3 @@ +{ + "environment": "NodeJs" +} \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js index c0959d7cf4daa..1ea4e85db427a 100644 --- a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js @@ -1,8 +1,12 @@ (globalThis.TURBOPACK = globalThis.TURBOPACK || []).push(["output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js", { -"[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)": (() => {{ +"[project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname, x: __turbopack_external_require__, k: __turbopack_refresh__ }) => (() => { -throw new Error("An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)\n\nCaused by:\n- the chunking context does not support Node.js external modules\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/input/index.js (ecmascript)\n- Execution of EcmascriptChunkItemContentVc::module_factory failed\n- Execution of EcmascriptChunkItemContentVc::new failed\n- Execution of EcmascriptModuleContentVc::new failed\n- Execution of EsmAssetReference::code_generation failed\n- the chunking context does not support Node.js external modules"); +var __TURBOPACK__external__node$3a$fs__ = __turbopack_external_require__("node:fs", true); +"__TURBOPACK__ecmascript__hoisting__location__"; +; -}}), -}]); \ No newline at end of file +})()), +}]); + +//# sourceMappingURL=79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map index a12b83d3337ca..e998c77728e14 100644 --- a/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map +++ b/crates/turbopack-tests/tests/snapshot/node/node_protocol_external/output/79fb1_turbopack-tests_tests_snapshot_node_node_protocol_external_input_index_b53fce.js.map @@ -1,4 +1,6 @@ { "version": 3, - "sections": [] + "sections": [ + {"offset": {"line": 4, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":""}}, + {"offset": {"line": 7, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":"A"}}] } \ No newline at end of file