Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Source/JavaScriptCore/runtime/JSMicrotask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,7 @@ static void moduleLoadTopSettled(JSGlobalObject* globalObject, VM& vm, ThrowScop
}
#if USE(BUN_JSC_ADDITIONS)
}
context->setEntry(vm, context->loader()->getRegisteredMayBeNull(specifier, type));
Comment thread
dylan-conway marked this conversation as resolved.
Outdated
#endif

JSPromise* statePromise = JSPromise::create(vm, globalObject->promiseStructure());
Expand Down Expand Up @@ -1262,6 +1263,16 @@ static void moduleLoadTopSettled(JSGlobalObject* globalObject, VM& vm, ThrowScop
}
}

#if USE(BUN_JSC_ADDITIONS)
// A load that failed before it had an entry has not lost one to removeEntry() or clearAll().
static ModuleRegistryEntry* entryOfLoad(ModuleLoadingContext* context, const Identifier& specifier, ScriptFetchParameters::Type type)
{
if (ModuleRegistryEntry* entry = context->entry())
return entry;
return context->loader()->getRegisteredMayBeNull(specifier, type);
}
#endif

static void moduleLoadTopRejected(JSGlobalObject* globalObject, VM& vm, std::span<const JSValue, maxMicrotaskArguments> arguments, uint8_t payload)
{
// loadModule first overload: onLoadRejected
Expand All @@ -1278,7 +1289,11 @@ static void moduleLoadTopRejected(JSGlobalObject* globalObject, VM& vm, std::spa
auto type = context->moduleRequest().type();
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script step 13.1
// Only set an error if the entry already exists.
#if USE(BUN_JSC_ADDITIONS)
if (ModuleRegistryEntry* entry = entryOfLoad(context, specifier, type))
#else
if (ModuleRegistryEntry* entry = context->loader()->getRegisteredMayBeNull(specifier, type))
#endif
entry->setEvaluationError(globalObject, arguments[1]);
resultPromise->reject(vm, arguments[1]);
}
Expand Down Expand Up @@ -1433,7 +1448,11 @@ static void moduleLoadStoreError(JSGlobalObject* globalObject, std::span<const J
auto type = context->moduleRequest().type();
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script step 13.1
// Only set an error if the entry already exists.
#if USE(BUN_JSC_ADDITIONS)
ModuleRegistryEntry* entry = entryOfLoad(context, specifier, type);
#else
ModuleRegistryEntry* entry = context->loader()->getRegisteredMayBeNull(specifier, type);
#endif
if (!entry)
return;
if (auto* error = dynamicDowncast<ErrorInstance>(errorValue)) {
Expand Down
13 changes: 13 additions & 0 deletions Source/JavaScriptCore/runtime/JSModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,9 @@ JSPromise* JSModuleLoader::loadModule(JSGlobalObject* globalObject, const Module
RETURN_IF_EXCEPTION(scope, nullptr);

auto* context = ModuleLoadingContext::create(vm, this, moduleRequest, WTF::move(scriptFetcher), flags);
#if USE(BUN_JSC_ADDITIONS)
context->setEntry(vm, getRegisteredMayBeNull(moduleRequest.m_specifier, moduleRequest.type()));
#endif
JSPromise* resultPromise = JSPromise::create(vm, globalObject->promiseStructure());
resultPromise->markAsHandled();

Expand Down Expand Up @@ -1060,7 +1063,17 @@ void JSModuleLoader::finishLoadingImportedModule(JSGlobalObject* globalObject, c
auto scope = DECLARE_THROW_SCOPE(vm);

// 1. If result is a normal completion, then
#if USE(BUN_JSC_ADDITIONS)
// hostLoadImportedModule() reads the realm's [[LoadedModules]] as a cache of the registry, and removeEntry() and
// clearAll() purge the two together. A load that was in flight then ends here with a record the registry let go of.
auto isRegistered = [&](AbstractModuleRecord* record) {
ModuleRegistryEntry* entry = getRegisteredMayBeNull(record->moduleKey(), moduleRequest.type());
return entry && entry->record() == record;
};
if (auto* resultRecord = std::get_if<AbstractModuleRecord*>(&result); resultRecord && (referrer.getModule() || isRegistered(*resultRecord))) {
#else
if (auto* resultRecord = std::get_if<AbstractModuleRecord*>(&result)) {
#endif
JSCell* owner = nullptr;

auto& loadedModules = [&] -> ModuleMap<AbstractModuleRecord::LoadedModuleRequest> & {
Expand Down
5 changes: 5 additions & 0 deletions Source/JavaScriptCore/runtime/ModuleLoadingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ class ModuleLoadingContext final : public JSCell {
const AbstractModuleRecord::ModuleRequest& moduleRequest() const { return m_moduleRequest; }
JSCell* payload() const { return m_payload.get(); }
ModuleRegistryEntry* entry() const { return m_entry.get(); }
#if USE(BUN_JSC_ADDITIONS)
// A loadModule() context has none until the load has one. What the load then stores, it stores there: removeEntry()
// and clearAll() can leave another load's entry, or none, under the key while this one is in flight.
void setEntry(VM& vm, ModuleRegistryEntry* entry) { m_entry.setMayBeNull(vm, this, entry); }
#endif
ScriptFetcher* scriptFetcher() const { return m_scriptFetcher.get(); }
AbstractModuleRecord* module() const { return m_module.get(); }
void module(VM& vm, AbstractModuleRecord* mod) { m_module.set(vm, this, mod); }
Expand Down
Loading