mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 19:08:50 +00:00
Recursive module evaluation support (sync-only for now) + namespace object fixes
This commit is contained in:
@@ -88,6 +88,28 @@ NodeVMModule* NodeVMModule::create(JSC::VM& vm, JSC::JSGlobalObject* globalObjec
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSModuleNamespaceObject* NodeVMModule::namespaceObject(JSC::JSGlobalObject* globalObject)
|
||||
{
|
||||
JSModuleNamespaceObject* object = m_namespaceObject.get();
|
||||
if (object) {
|
||||
return object;
|
||||
}
|
||||
|
||||
if (auto* thisObject = jsDynamicCast<NodeVMSourceTextModule*>(this)) {
|
||||
VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
object = thisObject->moduleRecord(globalObject)->getModuleNamespace(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (object) {
|
||||
namespaceObject(vm, object);
|
||||
}
|
||||
} else {
|
||||
RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("NodeVMModule::namespaceObject called on an unsupported module type (%s)", info()->className.characters());
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
JSC_DECLARE_CUSTOM_GETTER(jsNodeVmModuleGetterIdentifier);
|
||||
JSC_DECLARE_HOST_FUNCTION(jsNodeVmModuleGetStatusCode);
|
||||
JSC_DECLARE_HOST_FUNCTION(jsNodeVmModuleGetStatus);
|
||||
@@ -179,7 +201,7 @@ JSC_DEFINE_HOST_FUNCTION(jsNodeVmModuleGetStatus, (JSC::JSGlobalObject * globalO
|
||||
JSC_DEFINE_HOST_FUNCTION(jsNodeVmModuleGetNamespace, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
auto* thisObject = jsCast<NodeVMSourceTextModule*>(callFrame->thisValue());
|
||||
return JSValue::encode(thisObject->namespace_());
|
||||
return JSValue::encode(thisObject->namespaceObject(globalObject));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsNodeVmModuleGetError, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
|
||||
@@ -292,7 +314,7 @@ void NodeVMModule::visitChildrenImpl(JSCell* cell, Visitor& visitor)
|
||||
ASSERT_GC_OBJECT_INHERITS(vmModule, info());
|
||||
Base::visitChildren(vmModule, visitor);
|
||||
|
||||
visitor.append(vmModule->m_namespace);
|
||||
visitor.append(vmModule->m_namespaceObject);
|
||||
visitor.append(vmModule->m_context);
|
||||
|
||||
auto moduleNatives = vmModule->m_resolveCache.values();
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
#include "NodeVM.h"
|
||||
|
||||
#include "JavaScriptCore/AbstractModuleRecord.h"
|
||||
#include "AbstractModuleRecord.h"
|
||||
#include "JSModuleNamespaceObject.h"
|
||||
|
||||
namespace Bun {
|
||||
|
||||
@@ -49,8 +50,8 @@ public:
|
||||
Status status() const { return m_status; }
|
||||
void status(Status value) { m_status = value; }
|
||||
|
||||
JSObject* namespace_() const { return m_namespace.get(); }
|
||||
void namespace_(VM& vm, JSObject* value) { m_namespace.set(vm, this, value); }
|
||||
JSModuleNamespaceObject* namespaceObject(JSC::JSGlobalObject* globalObject);
|
||||
void namespaceObject(JSC::VM& vm, JSModuleNamespaceObject* value) { m_namespaceObject.set(vm, this, value); }
|
||||
|
||||
const WTF::Vector<NodeVMModuleRequest>& moduleRequests() const { return m_moduleRequests; }
|
||||
void addModuleRequest(NodeVMModuleRequest request) { m_moduleRequests.append(WTFMove(request)); }
|
||||
@@ -67,7 +68,7 @@ public:
|
||||
protected:
|
||||
WTF::String m_identifier;
|
||||
Status m_status = Status::Unlinked;
|
||||
mutable WriteBarrier<JSObject> m_namespace;
|
||||
mutable WriteBarrier<JSModuleNamespaceObject> m_namespaceObject;
|
||||
mutable WriteBarrier<JSObject> m_context;
|
||||
WTF::Vector<NodeVMModuleRequest> m_moduleRequests;
|
||||
mutable WTF::HashMap<WTF::String, WriteBarrier<JSObject>> m_resolveCache;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#include "ErrorCode.h"
|
||||
#include "JSDOMExceptionHandling.h"
|
||||
#include "JSModuleLoader.h"
|
||||
#include "JSModuleRecord.h"
|
||||
#include "JSPromise.h"
|
||||
#include "JSSourceCode.h"
|
||||
#include "ModuleAnalyzer.h"
|
||||
#include "Parser.h"
|
||||
@@ -228,7 +228,7 @@ JSValue NodeVMSourceTextModule::link(JSGlobalObject* globalObject, JSArray* spec
|
||||
|
||||
WTF::String specifier = specifierValue.toWTFString(globalObject);
|
||||
JSObject* moduleNative = moduleNativeValue.getObject();
|
||||
auto* resolvedRecord = jsCast<NodeVMModule*>(moduleNative)->moduleRecord(globalObject);
|
||||
AbstractModuleRecord* resolvedRecord = jsCast<NodeVMModule*>(moduleNative)->moduleRecord(globalObject);
|
||||
|
||||
record->setImportedModule(globalObject, Identifier::fromString(vm, specifier), resolvedRecord);
|
||||
m_resolveCache.set(WTFMove(specifier), WriteBarrier<JSObject> { vm, this, moduleNative });
|
||||
@@ -244,11 +244,9 @@ JSValue NodeVMSourceTextModule::link(JSGlobalObject* globalObject, JSArray* spec
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
if (sync == Synchronousness::Async) {
|
||||
ASSERT_NOT_REACHED_WITH_MESSAGE("TODO(@heimskr): async module linking");
|
||||
RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("TODO(@heimskr): async module linking");
|
||||
}
|
||||
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
status(Status::Linked);
|
||||
return JSC::jsUndefined();
|
||||
}
|
||||
@@ -273,7 +271,19 @@ JSValue NodeVMSourceTextModule::evaluate(JSGlobalObject* globalObject, uint32_t
|
||||
}
|
||||
|
||||
auto run = [&] {
|
||||
// TODO(@heimskr): top-level await support
|
||||
status(Status::Evaluating);
|
||||
|
||||
for (const auto& request : record->requestedModules()) {
|
||||
if (auto iter = m_resolveCache.find(WTF::String(*request.m_specifier)); iter != m_resolveCache.end()) {
|
||||
if (auto* dependency = jsDynamicCast<NodeVMSourceTextModule*>(iter->value.get())) {
|
||||
if (dependency->status() == Status::Linked) {
|
||||
JSValue dependencyResult = dependency->evaluate(globalObject, timeout, breakOnSigint);
|
||||
RELEASE_ASSERT_WITH_MESSAGE(jsDynamicCast<JSC::JSPromise*>(dependencyResult) == nullptr, "TODO(@heimskr): implement async support for node:vm SourceTextModule dependencies");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = record->evaluate(globalObject, jsUndefined(), jsNumber(static_cast<int32_t>(JSGenerator::ResumeMode::NormalMode)));
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ const {
|
||||
validateInt32,
|
||||
validateBuffer,
|
||||
validateFunction,
|
||||
validateInternalField,
|
||||
} = require("internal/validators");
|
||||
const util = require("node:util");
|
||||
|
||||
@@ -190,7 +189,6 @@ class Module {
|
||||
}
|
||||
|
||||
[util.inspect.custom](depth, options) {
|
||||
validateInternalField(this, kNative, "Module");
|
||||
if (typeof depth === "number" && depth < 0) return this;
|
||||
|
||||
const constructor = getConstructorOf(this) || Module;
|
||||
@@ -301,7 +299,6 @@ class SourceTextModule extends Module {
|
||||
const moduleNatives = await SafePromiseAllReturnArrayLike(modulePromises);
|
||||
this[kNative].link(specifiers, moduleNatives, 0);
|
||||
} catch (e) {
|
||||
console.error("linking error:", e);
|
||||
this.#error = e;
|
||||
throw e;
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user