Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JSC] ReferenceError when multiple modules are simultaneously importing a module containing a top-level await #24122

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

shvaikalesh
Copy link
Member

@shvaikalesh shvaikalesh commented Feb 9, 2024

544b0f0

[JSC] ReferenceError when multiple modules are simultaneously importing a module containing a top-level await
https://bugs.webkit.org/show_bug.cgi?id=242740
<rdar://problem/97370038>

Reviewed by NOBODY (OOPS!).

This change completely re-implements module loader to precisely follow the spec steps [1],
resolving multiple issues revolving around importing modules with top-level `await`.

Infinite retry of module fetching & parsing is removed as it's not part of the spec,
nor other browsers behave in the same way.

This patch also rewires the way module loader is hooked into workers / worklets, which became
necessary due to functions like evaluateModule() became always `async`. Along with this,
errors occuring in modules with top-level `await` are now properly reported to the console,
resolving another developers' pain point.

[1]: https://tc39.es/ecma262/#sec-cyclic-module-records

* JSTests/test262/expectations.yaml:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/cors-crossorigin-requests-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/repeated-imports.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/repeated-imports.any.sharedworker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/repeated-imports.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror-module-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.sharedworker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/crossorigin-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.sharedworker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-fetch-error.sub-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/event-handler-processing-algorithm-error/worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/dedicated-worker-import-blob-url.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/dedicated-worker-import-blob-url.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/dedicated-worker-import-failure-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/dedicated-worker-parse-error-failure-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/shared-worker-import-blob-url.window-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/shared-worker-parse-error-failure-expected.txt:
* Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj:
* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/builtins/ModuleLoader.js:
(visibility.PrivateRecursive.ensureModuleMapEntry):
(visibility.PrivateRecursive.hostFetchAndLoadImportedModule):
(visibility.PrivateRecursive.hostLoadImportedModule):
(visibility.PrivateRecursive.fetchDescendantsOfAndLink):
(visibility.PrivateRecursive.innerModuleLoading):
(visibility.PrivateRecursive.moduleLinking):
(visibility.PrivateRecursive.innerModuleLinking):
(visibility.PrivateRecursive.moduleEvaluation):
(visibility.PrivateRecursive.innerModuleEvaluation):
(visibility.PrivateRecursive.async executeAsyncModule):
(linkTimeConstant.gatherAvailableAncestors):
(visibility.PrivateRecursive.asyncModuleExecutionFulfilled):
(linkTimeConstant.asyncModuleExecutionRejected):
(visibility.PrivateRecursive.fetchModule):
(visibility.PrivateRecursive.fetchModuleAndEvaluate):
(visibility.PrivateRecursive.evaluateModule):
(visibility.PrivateRecursive.loadModule):
(visibility.PrivateRecursive.loadModuleAndEvaluate):
(visibility.PrivateRecursive.requestImportModule):
(visibility.PrivateRecursive.dependencyKeysIfEvaluated):
(linkTimeConstant.setStateToMax): Deleted.
(linkTimeConstant.newRegistryEntry): Deleted.
(visibility.PrivateRecursive.ensureRegistered): Deleted.
(linkTimeConstant.forceFulfillPromise): Deleted.
(linkTimeConstant.fulfillFetch): Deleted.
(visibility.PrivateRecursive.requestFetch): Deleted.
(linkTimeConstant.cacheSatisfy): Deleted.
(async linkTimeConstant.cacheSatisfyAndReturn): Deleted.
(visibility.PrivateRecursive.requestSatisfy): Deleted.
(visibility.PrivateRecursive.requestSatisfyUtil): Deleted.
(visibility.PrivateRecursive.link): Deleted.
(visibility.PrivateRecursive.async asyncModuleEvaluation): Deleted.
(visibility.PrivateRecursive.provideFetch): Deleted.
(visibility.PrivateRecursive.async loadModule): Deleted.
(visibility.PrivateRecursive.linkAndEvaluateModule): Deleted.
(visibility.PrivateRecursive.async loadAndEvaluateModule): Deleted.
(visibility.PrivateRecursive.async requestImportModule): Deleted.
* Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp:
(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
* Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h:
* Source/JavaScriptCore/jsc.cpp:
(dumpException):
(runWithOptions):
* Source/JavaScriptCore/parser/Parser.cpp:
(JSC::Parser<LexerType>::parseInner):
* Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp:
(JSC::AbstractModuleRecord::hostResolveImportedModule):
(JSC::AbstractModuleRecord::link):
* Source/JavaScriptCore/runtime/ArrayPrototype.cpp:
(JSC::ArrayPrototype::finishCreation):
* Source/JavaScriptCore/runtime/Completion.cpp:
(JSC::createSymbolForEntryPointModule): Deleted.
(JSC::rejectPromise): Deleted.
(JSC::loadAndEvaluateModule): Deleted.
(JSC::loadModule): Deleted.
(JSC::linkAndEvaluateModule): Deleted.
* Source/JavaScriptCore/runtime/Completion.h:
* Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::finishCreation):
(JSC::createSymbolForEntryPointModule):
(JSC::JSModuleLoader::loadModule):
(JSC::JSModuleLoader::loadModuleAndEvaluate):
(JSC::JSModuleLoader::fetchModule):
(JSC::JSModuleLoader::fetchModuleAndEvaluate):
(JSC::JSModuleLoader::evaluateModule):
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSModuleLoader::provideFetch): Deleted.
(JSC::JSModuleLoader::loadAndEvaluateModule): Deleted.
(JSC::JSModuleLoader::linkAndEvaluateModule): Deleted.
* Source/JavaScriptCore/runtime/JSModuleLoader.h:
* Source/JavaScriptCore/runtime/SyntheticModuleRecord.cpp:
(JSC::SyntheticModuleRecord::link):
* Source/JavaScriptCore/runtime/SyntheticModuleRecord.h:
* Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
* Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h:
* Source/WebCore/bindings/js/JSExecState.h:
(WebCore::JSExecState::loadModule):
(WebCore::JSExecState::loadModuleAndEvaluate):
(WebCore::JSExecState::fetchModule):
(WebCore::JSExecState::fetchModuleAndEvaluate):
(WebCore::JSExecState::evaluateModule):
(WebCore::JSExecState::linkAndEvaluateModule): Deleted.
* Source/WebCore/bindings/js/ScheduledAction.cpp:
(WebCore::ScheduledAction::execute):
* Source/WebCore/bindings/js/ScriptController.cpp:
(WebCore::ScriptController::loadModuleScriptInWorld):
(WebCore::ScriptController::evaluateModuleScriptInWorld):
(WebCore::ScriptController::evaluateModuleScript):
(WebCore::ScriptController::linkAndEvaluateModuleScriptInWorld): Deleted.
(WebCore::ScriptController::linkAndEvaluateModuleScript): Deleted.
* Source/WebCore/bindings/js/ScriptController.h:
* Source/WebCore/bindings/js/WorkerScriptFetcher.h:
* Source/WebCore/dom/ScriptElement.cpp:
(WebCore::ScriptElement::executeModuleScript):
* Source/WebCore/workers/DedicatedWorkerThread.h:
(WebCore::DedicatedWorkerThread::workerObjectProxy const):
(WebCore::DedicatedWorkerThread::start): Deleted.
* Source/WebCore/workers/WorkerOrWorkletScriptController.cpp:
(WebCore::WorkerOrWorkletScriptController::evaluateAndReportException):
(WebCore::WorkerOrWorkletScriptController::evaluate):
(WebCore::WorkerOrWorkletScriptController::loadModuleAndEvaluate):
(WebCore::WorkerOrWorkletScriptController::fetchWorkletModuleAndEvaluate):
(WebCore::jsValueToModuleKey): Deleted.
(WebCore::WorkerOrWorkletScriptController::loadModuleSynchronously): Deleted.
(WebCore::WorkerOrWorkletScriptController::linkAndEvaluateModule): Deleted.
(WebCore::WorkerOrWorkletScriptController::loadAndEvaluateModule): Deleted.
* Source/WebCore/workers/WorkerOrWorkletScriptController.h:
* Source/WebCore/workers/WorkerOrWorkletThread.cpp:
(WebCore::WorkerOrWorkletThread::workerOrWorkletThread):
* Source/WebCore/workers/WorkerOrWorkletThread.h:
(WebCore::WorkerOrWorkletThread::evaluateScriptIfNecessary):
* Source/WebCore/workers/WorkerThread.cpp:
(WebCore::WorkerThread::evaluateScriptIfNecessary):
* Source/WebCore/workers/WorkerThread.h:
* Source/WebCore/workers/shared/context/SharedWorkerContextManager.cpp:
(WebCore::SharedWorkerContextManager::registerSharedWorkerThread):
* Source/WebCore/worklets/WorkletGlobalScope.cpp:
(WebCore::WorkletGlobalScope::evaluate):
(WebCore::WorkletGlobalScope::fetchAndInvokeScript):

544b0f0

Misc iOS, tvOS & watchOS macOS Linux Windows
βœ… πŸ§ͺ style βœ… πŸ›  ios βœ… πŸ›  mac βœ… πŸ›  wpe βœ… πŸ›  wincairo
βœ… πŸ§ͺ bindings βœ… πŸ›  ios-sim βœ… πŸ›  mac-AS-debug βœ… πŸ§ͺ wpe-wk2 βœ… πŸ§ͺ wincairo-tests
βœ… πŸ§ͺ webkitperl βœ… πŸ§ͺ ios-wk2 βœ… πŸ§ͺ api-mac βœ… πŸ§ͺ api-wpe
βœ… πŸ§ͺ ios-wk2-wpt βœ… πŸ§ͺ mac-wk1 βœ… πŸ›  wpe-cairo
βœ… πŸ›  πŸ§ͺ jsc βœ… πŸ§ͺ api-ios βœ… πŸ§ͺ mac-wk2 βœ… πŸ›  gtk
βœ… πŸ›  πŸ§ͺ jsc-arm64 βœ… πŸ›  tv βœ… πŸ§ͺ mac-AS-debug-wk2 βœ… πŸ§ͺ gtk-wk2
βœ… πŸ›  tv-sim βœ… πŸ§ͺ mac-wk2-stress ❌ πŸ§ͺ api-gtk
βœ… πŸ›  watch βœ… πŸ›  jsc-armv7
βœ… πŸ›  watch-sim βœ… πŸ§ͺ jsc-armv7-tests

@shvaikalesh shvaikalesh requested a review from a team as a code owner February 9, 2024 03:26
@shvaikalesh shvaikalesh self-assigned this Feb 9, 2024
@shvaikalesh shvaikalesh added the JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues. label Feb 9, 2024
@shvaikalesh shvaikalesh marked this pull request as draft February 9, 2024 03:42
@MrHBS
Copy link

MrHBS commented Feb 10, 2024

This is a horrible bug.

@biozal
Copy link

biozal commented Feb 13, 2024

Is there a work around for this until this is fixed? This is causing a lot of issues for a product I'm working on and supporting Safari.

@shvaikalesh
Copy link
Member Author

Is there a work around for this until this is fixed?

The fix proposed in this PR breaks the case of module importing itself. I don't see any other way except for re-implementing the module loader to adhere to the spec (https://tc39.es/ecma262/#cyclic-module-record), which will take some time.

@biozal
Copy link

biozal commented Feb 14, 2024

Is there a work around for this until this is fixed?

The fix proposed in this PR breaks the case of module importing itself. I don't see any other way except for re-implementing the module loader to adhere to the spec (https://tc39.es/ecma262/#cyclic-module-record), which will take some time.

So what do we do then until this is fixed, tell people not to use Safari? I mean this is a pretty big problem for any modern web application.

@mb21
Copy link

mb21 commented Mar 21, 2024

I don't see any other way except for re-implementing the module loader to adhere to the spec, which will take some time.

Would be great if this could be prioritized. A lot of people using modern frameworks like SvelteKit or Astro (that use native ESM modules) are running into this, and it's often very hard to debug, so they don't realize it's this bug.

@shvaikalesh
Copy link
Member Author

Would be great if this could be prioritized. A lot of people using modern frameworks like sveltejs/kit#11601 or withastro/astro#10055 (that use native ESM modules) are running into this, and it's often very hard to debug, so they don't realize it's this bug.

Thank you for linking the issues, it's super important for our internal bookkeeping. Good news is that this issue being worked on, we are rewriting module loader to adhere to the spec, ETA is only a few weeks.

@GauteHaugen
Copy link

@shvaikalesh, Is there an update on this? Also, when this gets merged, what is the usual process/timeline for getting this fix out to end users?

@shvaikalesh shvaikalesh force-pushed the eng/JSC-ReferenceError-when-multiple-modules-are-simultaneously-importing-a-module-containing-a-top-level-await branch from 7aabdfe to aee0d36 Compare May 13, 2024 14:25
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label May 13, 2024
@shvaikalesh shvaikalesh removed the merging-blocked Applied to prevent a change from being merged label May 13, 2024
@shvaikalesh shvaikalesh force-pushed the eng/JSC-ReferenceError-when-multiple-modules-are-simultaneously-importing-a-module-containing-a-top-level-await branch from aee0d36 to a0c5449 Compare May 13, 2024 23:51
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label May 14, 2024
@shvaikalesh shvaikalesh removed the merging-blocked Applied to prevent a change from being merged label May 14, 2024
@shvaikalesh shvaikalesh force-pushed the eng/JSC-ReferenceError-when-multiple-modules-are-simultaneously-importing-a-module-containing-a-top-level-await branch from a0c5449 to 8c637db Compare May 14, 2024 20:33
@shvaikalesh shvaikalesh marked this pull request as ready for review May 14, 2024 20:44
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label May 14, 2024
@shvaikalesh shvaikalesh removed the merging-blocked Applied to prevent a change from being merged label May 14, 2024
@shvaikalesh shvaikalesh force-pushed the eng/JSC-ReferenceError-when-multiple-modules-are-simultaneously-importing-a-module-containing-a-top-level-await branch from 8c637db to 3aacdb9 Compare May 14, 2024 21:33
@shvaikalesh shvaikalesh force-pushed the eng/JSC-ReferenceError-when-multiple-modules-are-simultaneously-importing-a-module-containing-a-top-level-await branch from 3aacdb9 to 7f9c271 Compare May 14, 2024 21:51
@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for 8f80a0b. Live statuses available at the PR page, #24122

@shvaikalesh shvaikalesh force-pushed the eng/JSC-ReferenceError-when-multiple-modules-are-simultaneously-importing-a-module-containing-a-top-level-await branch from 8f80a0b to 008d151 Compare June 4, 2024 19:56
@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for 008d151. Live statuses available at the PR page, #24122

@shvaikalesh shvaikalesh force-pushed the eng/JSC-ReferenceError-when-multiple-modules-are-simultaneously-importing-a-module-containing-a-top-level-await branch from 008d151 to b6abb4b Compare June 4, 2024 23:24
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Jun 4, 2024
@shvaikalesh shvaikalesh removed the merging-blocked Applied to prevent a change from being merged label Jun 4, 2024
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Jun 4, 2024
@shvaikalesh shvaikalesh force-pushed the eng/JSC-ReferenceError-when-multiple-modules-are-simultaneously-importing-a-module-containing-a-top-level-await branch from b6abb4b to ef165bf Compare June 4, 2024 23:39
@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for b6abb4b. Live statuses available at the PR page, #24122

@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for ef165bf. Live statuses available at the PR page, #24122

@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for ef165bf. Live statuses available at the PR page, #24122

2 similar comments
@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for ef165bf. Live statuses available at the PR page, #24122

@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for ef165bf. Live statuses available at the PR page, #24122

…ng a module containing a top-level await

https://bugs.webkit.org/show_bug.cgi?id=242740
<rdar://problem/97370038>

Reviewed by NOBODY (OOPS!).

This change completely re-implements module loader to precisely follow the spec steps [1],
resolving multiple issues revolving around importing modules with top-level `await`.

Infinite retry of module fetching & parsing is removed as it's not part of the spec,
nor other browsers behave in the same way.

This patch also rewires the way module loader is hooked into workers / worklets, which became
necessary due to functions like evaluateModule() became always `async`. Along with this,
errors occuring in modules with top-level `await` are now properly reported to the console,
resolving another developers' pain point.

[1]: https://tc39.es/ecma262/#sec-cyclic-module-records

* JSTests/test262/expectations.yaml:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/cors-crossorigin-requests-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/repeated-imports.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/repeated-imports.any.sharedworker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/json-module/repeated-imports.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror-module-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.sharedworker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/crossorigin-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.sharedworker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-fetch-error.sub-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/event-handler-processing-algorithm-error/worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/dedicated-worker-import-blob-url.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/dedicated-worker-import-blob-url.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/dedicated-worker-import-failure-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/dedicated-worker-parse-error-failure-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/shared-worker-import-blob-url.window-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/workers/modules/shared-worker-parse-error-failure-expected.txt:
* Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj:
* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/builtins/ModuleLoader.js:
(visibility.PrivateRecursive.ensureModuleMapEntry):
(visibility.PrivateRecursive.hostFetchAndLoadImportedModule):
(visibility.PrivateRecursive.hostLoadImportedModule):
(visibility.PrivateRecursive.fetchDescendantsOfAndLink):
(visibility.PrivateRecursive.innerModuleLoading):
(visibility.PrivateRecursive.moduleLinking):
(visibility.PrivateRecursive.innerModuleLinking):
(visibility.PrivateRecursive.moduleEvaluation):
(visibility.PrivateRecursive.innerModuleEvaluation):
(visibility.PrivateRecursive.async executeAsyncModule):
(linkTimeConstant.gatherAvailableAncestors):
(visibility.PrivateRecursive.asyncModuleExecutionFulfilled):
(linkTimeConstant.asyncModuleExecutionRejected):
(visibility.PrivateRecursive.fetchModule):
(visibility.PrivateRecursive.fetchModuleAndEvaluate):
(visibility.PrivateRecursive.evaluateModule):
(visibility.PrivateRecursive.loadModule):
(visibility.PrivateRecursive.loadModuleAndEvaluate):
(visibility.PrivateRecursive.requestImportModule):
(visibility.PrivateRecursive.dependencyKeysIfEvaluated):
(linkTimeConstant.setStateToMax): Deleted.
(linkTimeConstant.newRegistryEntry): Deleted.
(visibility.PrivateRecursive.ensureRegistered): Deleted.
(linkTimeConstant.forceFulfillPromise): Deleted.
(linkTimeConstant.fulfillFetch): Deleted.
(visibility.PrivateRecursive.requestFetch): Deleted.
(linkTimeConstant.cacheSatisfy): Deleted.
(async linkTimeConstant.cacheSatisfyAndReturn): Deleted.
(visibility.PrivateRecursive.requestSatisfy): Deleted.
(visibility.PrivateRecursive.requestSatisfyUtil): Deleted.
(visibility.PrivateRecursive.link): Deleted.
(visibility.PrivateRecursive.async asyncModuleEvaluation): Deleted.
(visibility.PrivateRecursive.provideFetch): Deleted.
(visibility.PrivateRecursive.async loadModule): Deleted.
(visibility.PrivateRecursive.linkAndEvaluateModule): Deleted.
(visibility.PrivateRecursive.async loadAndEvaluateModule): Deleted.
(visibility.PrivateRecursive.async requestImportModule): Deleted.
* Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp:
(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
* Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h:
* Source/JavaScriptCore/jsc.cpp:
(dumpException):
(runWithOptions):
* Source/JavaScriptCore/parser/Parser.cpp:
(JSC::Parser<LexerType>::parseInner):
* Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp:
(JSC::AbstractModuleRecord::hostResolveImportedModule):
(JSC::AbstractModuleRecord::link):
* Source/JavaScriptCore/runtime/ArrayPrototype.cpp:
(JSC::ArrayPrototype::finishCreation):
* Source/JavaScriptCore/runtime/Completion.cpp:
(JSC::createSymbolForEntryPointModule): Deleted.
(JSC::rejectPromise): Deleted.
(JSC::loadAndEvaluateModule): Deleted.
(JSC::loadModule): Deleted.
(JSC::linkAndEvaluateModule): Deleted.
* Source/JavaScriptCore/runtime/Completion.h:
* Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::finishCreation):
(JSC::createSymbolForEntryPointModule):
(JSC::JSModuleLoader::loadModule):
(JSC::JSModuleLoader::loadModuleAndEvaluate):
(JSC::JSModuleLoader::fetchModule):
(JSC::JSModuleLoader::fetchModuleAndEvaluate):
(JSC::JSModuleLoader::evaluateModule):
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSModuleLoader::provideFetch): Deleted.
(JSC::JSModuleLoader::loadAndEvaluateModule): Deleted.
(JSC::JSModuleLoader::linkAndEvaluateModule): Deleted.
* Source/JavaScriptCore/runtime/JSModuleLoader.h:
* Source/JavaScriptCore/runtime/SyntheticModuleRecord.cpp:
(JSC::SyntheticModuleRecord::link):
* Source/JavaScriptCore/runtime/SyntheticModuleRecord.h:
* Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
* Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h:
* Source/WebCore/bindings/js/JSExecState.h:
(WebCore::JSExecState::loadModule):
(WebCore::JSExecState::loadModuleAndEvaluate):
(WebCore::JSExecState::fetchModule):
(WebCore::JSExecState::fetchModuleAndEvaluate):
(WebCore::JSExecState::evaluateModule):
(WebCore::JSExecState::linkAndEvaluateModule): Deleted.
* Source/WebCore/bindings/js/ScheduledAction.cpp:
(WebCore::ScheduledAction::execute):
* Source/WebCore/bindings/js/ScriptController.cpp:
(WebCore::ScriptController::loadModuleScriptInWorld):
(WebCore::ScriptController::evaluateModuleScriptInWorld):
(WebCore::ScriptController::evaluateModuleScript):
(WebCore::ScriptController::linkAndEvaluateModuleScriptInWorld): Deleted.
(WebCore::ScriptController::linkAndEvaluateModuleScript): Deleted.
* Source/WebCore/bindings/js/ScriptController.h:
* Source/WebCore/bindings/js/WorkerScriptFetcher.h:
* Source/WebCore/dom/ScriptElement.cpp:
(WebCore::ScriptElement::executeModuleScript):
* Source/WebCore/workers/DedicatedWorkerThread.h:
(WebCore::DedicatedWorkerThread::workerObjectProxy const):
(WebCore::DedicatedWorkerThread::start): Deleted.
* Source/WebCore/workers/WorkerOrWorkletScriptController.cpp:
(WebCore::WorkerOrWorkletScriptController::evaluateAndReportException):
(WebCore::WorkerOrWorkletScriptController::evaluate):
(WebCore::WorkerOrWorkletScriptController::loadModuleAndEvaluate):
(WebCore::WorkerOrWorkletScriptController::fetchWorkletModuleAndEvaluate):
(WebCore::jsValueToModuleKey): Deleted.
(WebCore::WorkerOrWorkletScriptController::loadModuleSynchronously): Deleted.
(WebCore::WorkerOrWorkletScriptController::linkAndEvaluateModule): Deleted.
(WebCore::WorkerOrWorkletScriptController::loadAndEvaluateModule): Deleted.
* Source/WebCore/workers/WorkerOrWorkletScriptController.h:
* Source/WebCore/workers/WorkerOrWorkletThread.cpp:
(WebCore::WorkerOrWorkletThread::workerOrWorkletThread):
* Source/WebCore/workers/WorkerOrWorkletThread.h:
(WebCore::WorkerOrWorkletThread::evaluateScriptIfNecessary):
* Source/WebCore/workers/WorkerThread.cpp:
(WebCore::WorkerThread::evaluateScriptIfNecessary):
* Source/WebCore/workers/WorkerThread.h:
* Source/WebCore/workers/shared/context/SharedWorkerContextManager.cpp:
(WebCore::SharedWorkerContextManager::registerSharedWorkerThread):
* Source/WebCore/worklets/WorkletGlobalScope.cpp:
(WebCore::WorkletGlobalScope::evaluate):
(WebCore::WorkletGlobalScope::fetchAndInvokeScript):
@shvaikalesh shvaikalesh removed the merging-blocked Applied to prevent a change from being merged label Jun 6, 2024
@shvaikalesh shvaikalesh force-pushed the eng/JSC-ReferenceError-when-multiple-modules-are-simultaneously-importing-a-module-containing-a-top-level-await branch from ef165bf to 544b0f0 Compare June 6, 2024 14:57
@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for 544b0f0. Live statuses available at the PR page, #24122

@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for 544b0f0. Live statuses available at the PR page, #24122

2 similar comments
@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for 544b0f0. Live statuses available at the PR page, #24122

@webkit-early-warning-system
Copy link
Collaborator

Starting EWS tests for 544b0f0. Live statuses available at the PR page, #24122

@nicolo-ribaudo
Copy link
Contributor

nicolo-ribaudo commented Jun 12, 2024

Hey, I recently added a WPT test for top level await that only JSC was failing: web-platform-tests/wpt#42944. I'm curious is this PR fixes it. βœ”οΈ

Infinite retry of module fetching & parsing is removed

Related: whatwg/html#10327


Side comment: as the person who recently rewrote most of the modules loading spec algorithms, I'm happy to see that following step-by-step them is actually a doable implementation strategy :)

if (entry)
return entry;

entry = @newRegistryEntry(key);
this.registry.@set(key, entry);
entry = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the https://tc39.es/ecma262/#cyclic-module-record link here?

entry.fetch = @undefined;
return this.requestFetch(entry, parameters, fetcher);
});
if (entry.errorToRethrow) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this since all fetchDescendantsOfAndLink uses are guarded by the error check?

isLoading: true,
pendingModulesCount: 1,
visited: new @Set,
parseError: null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this? Or just use entry.errorToRethrow is fine?

var loadedEntry = entry.loadedModules.@get(specifier);
if (loadedEntry) {
if (loadedEntry.errorToRethrow) {
state.parseError = loadedEntry.errorToRethrow;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we throw an error here?


for (var i = 0, { length } = entry.requestedModules; i < length; i++) {
var specifier = entry.requestedModules[i];
var loadedEntry = entry.loadedModules.@get(specifier); // This implements step 2 of GetImportedModule
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throw entry.errorToRethrow;
return entry;
})
.then(() => this.fetchDescendantsOfAndLink(entry, fetcher));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use .then((entry) => this.fetchDescendantsOfAndLink(entry, fetcher)); is better?

Source/JavaScriptCore/jsc.cpp Show resolved Hide resolved
Satisfy,
Link,
Ready,
enum class Status : uint8_t {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add See [[Status]] in https://tc39.es/ecma262/#cyclic-module-record here?

Comment on lines +129 to +131
putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().everyPrivateName(), getDirect(vm, vm.propertyNames->builtinNames().everyPublicName()), static_cast<unsigned>(PropertyAttribute::ReadOnly));
putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().filterPrivateName(), getDirect(vm, vm.propertyNames->builtinNames().filterPublicName()), static_cast<unsigned>(PropertyAttribute::ReadOnly));
putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().findPrivateName(), getDirect(vm, vm.propertyNames->builtinNames().findPublicName()), static_cast<unsigned>(PropertyAttribute::ReadOnly));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use them in builtin code. Use normal iteration.


entry.hasTLA = this.linkModuleRecord(entry.moduleRecord, fetcher);

@assert(stack.@filter(e => e === entry).length === 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use filter.

return this.asyncModuleEvaluation(entry, fetcher, dependencies);
this.evaluate(entry.key, entry.moduleRecord, fetcher);

@assert(stack.@filter(e => e === entry).length === 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

Comment on lines +508 to +510
@assert(execList.@every(e => e.asyncEvaluation));
@assert(execList.@every(e => e.pendingAsyncDependencies === 0));
@assert(execList.@every(e => e.evaluationError === null));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use them.

};
return moduleType === @ModuleTypeJavaScript
? this.moduleMap.@get(key)
: this.nonJSModuleArray.@find(entry => entry.key === key && entry.moduleType === moduleType);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use find.

try {
this.innerModuleLinking(entry, stack, 0, fetcher);
} catch (error) {
for (var i = 0, { length } = stack; i < length; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

state.pendingModulesCount--;
if (state.pendingModulesCount === 0) {
state.isLoading = false;
state.visited.@forEach(loadedEntry => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

state.visited.@add(entry);
state.pendingModulesCount += entry.requestedModules.length;

var { fetcher } = state;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

state.pendingModulesCount += entry.requestedModules.length;

var { fetcher } = state;
for (var i = 0, { length } = entry.requestedModules; i < length; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

var moduleType = parameters === @undefined ? @ModuleTypeJavaScript : this.getModuleType(parameters);
var entry = this.ensureModuleMapEntry(key, moduleType);

entry.fetchAndParsePromise ??= this.fetch(key, parameters, fetcher).then(sourceCode => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto. do not use ??=.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues.
Projects
None yet