aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-09-05 23:05:22 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-09-05 23:05:22 -0700
commit11aa17a57cc679d34e8e6f6f7aa665f565cb7305 (patch)
treeccb9a605cb4bcc42c6b2665ddbf8d04af72d94c7 /src/bun.js/bindings
parentd2397b60e79e4386c6a7b7a9783a6f8e379a5ae0 (diff)
downloadbun-11aa17a57cc679d34e8e6f6f7aa665f565cb7305.tar.gz
bun-11aa17a57cc679d34e8e6f6f7aa665f565cb7305.tar.zst
bun-11aa17a57cc679d34e8e6f6f7aa665f565cb7305.zip
Support async `onLoad` callbacks in `Bun.plugin`
Diffstat (limited to 'src/bun.js/bindings')
-rw-r--r--src/bun.js/bindings/BunPlugin.cpp6
-rw-r--r--src/bun.js/bindings/ModuleLoader.cpp520
-rw-r--r--src/bun.js/bindings/ModuleLoader.h94
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp252
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.h21
-rw-r--r--src/bun.js/bindings/bindings.cpp30
-rw-r--r--src/bun.js/bindings/headers-handwritten.h39
-rw-r--r--src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h1
-rw-r--r--src/bun.js/bindings/webcore/DOMIsoSubspaces.h1
9 files changed, 738 insertions, 226 deletions
diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp
index 0941d2722..ba1d40a0b 100644
--- a/src/bun.js/bindings/BunPlugin.cpp
+++ b/src/bun.js/bindings/BunPlugin.cpp
@@ -303,8 +303,7 @@ extern "C" EncodedJSValue jsFunctionBunPlugin(JSC::JSGlobalObject* globalObject,
RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
if (auto* promise = JSC::jsDynamicCast<JSC::JSPromise*>(result)) {
- JSC::throwTypeError(globalObject, throwScope, "setup() does not support promises yet"_s);
- return JSValue::encode(jsUndefined());
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(promise));
}
RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined()));
@@ -384,8 +383,7 @@ EncodedJSValue BunPlugin::OnLoad::run(JSC::JSGlobalObject* globalObject, ZigStri
if (auto* promise = JSC::jsDynamicCast<JSPromise*>(result)) {
switch (promise->status(vm)) {
case JSPromise::Status::Pending: {
- JSC::throwTypeError(globalObject, throwScope, "onLoad() doesn't support pending promises yet"_s);
- return JSValue::encode({});
+ return JSValue::encode(promise);
}
case JSPromise::Status::Rejected: {
promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(static_cast<unsigned>(JSC::JSPromise::Status::Fulfilled)));
diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp
new file mode 100644
index 000000000..dd5ea01ad
--- /dev/null
+++ b/src/bun.js/bindings/ModuleLoader.cpp
@@ -0,0 +1,520 @@
+#include "root.h"
+#include "headers-handwritten.h"
+
+#include "ModuleLoader.h"
+
+#include "ZigGlobalObject.h"
+#include "JavaScriptCore/JSCInlines.h"
+#include "JavaScriptCore/JSNativeStdFunction.h"
+#include "JavaScriptCore/JSCJSValueInlines.h"
+#include "JavaScriptCore/JSInternalPromise.h"
+#include "JavaScriptCore/JSInternalFieldObjectImpl.h"
+
+#include "ZigSourceProvider.h"
+
+#include "JavaScriptCore/JSSourceCode.h"
+#include "JavaScriptCore/JSString.h"
+#include "JavaScriptCore/JSValueInternal.h"
+#include "JavaScriptCore/JSVirtualMachineInternal.h"
+#include "JavaScriptCore/ObjectConstructor.h"
+#include "JavaScriptCore/OptionsList.h"
+#include "JavaScriptCore/ParserError.h"
+#include "JavaScriptCore/ScriptExecutable.h"
+#include "JavaScriptCore/SourceOrigin.h"
+#include "JavaScriptCore/StackFrame.h"
+#include "JavaScriptCore/StackVisitor.h"
+
+#include "EventEmitter.h"
+#include "JSEventEmitter.h"
+
+#include "../modules/BufferModule.h"
+#include "../modules/EventsModule.h"
+#include "../modules/ProcessModule.h"
+#include "../modules/StringDecoderModule.h"
+#include "../modules/ObjectModule.h"
+#include "../modules/NodeModuleModule.h"
+
+namespace Bun {
+using namespace Zig;
+using namespace WebCore;
+
+static JSC::JSInternalPromise* rejectedInternalPromise(JSC::JSGlobalObject* globalObject, JSC::JSValue value)
+{
+ JSC::VM& vm = globalObject->vm();
+ JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
+ promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, value);
+ promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32AsAnyInt() | JSC::JSPromise::isFirstResolvingFunctionCalledFlag | static_cast<unsigned>(JSC::JSPromise::Status::Rejected)));
+ return promise;
+}
+
+static JSC::JSInternalPromise* resolvedInternalPromise(JSC::JSGlobalObject* globalObject, JSC::JSValue value)
+{
+ JSC::VM& vm = globalObject->vm();
+
+ JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
+ promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, value);
+ promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32AsAnyInt() | JSC::JSPromise::isFirstResolvingFunctionCalledFlag | static_cast<unsigned>(JSC::JSPromise::Status::Fulfilled)));
+ return promise;
+}
+
+using namespace JSC;
+
+static OnLoadResult handleOnLoadObjectResult(Zig::GlobalObject* globalObject, JSC::JSObject* object)
+{
+ OnLoadResult result {};
+ result.type = OnLoadResultTypeObject;
+ JSC::VM& vm = globalObject->vm();
+ if (JSC::JSValue exportsValue = object->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "exports"_s))) {
+ if (exportsValue.isObject()) {
+ result.value.object = exportsValue;
+ return result;
+ }
+ }
+
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ scope.throwException(globalObject, createTypeError(globalObject, "\"object\" loader must return an \"exports\" object"_s));
+ result.type = OnLoadResultTypeError;
+ result.value.error = scope.exception();
+ scope.clearException();
+ scope.release();
+ return result;
+}
+
+JSC::JSInternalPromise* PendingVirtualModuleResult::internalPromise()
+{
+ return jsCast<JSC::JSInternalPromise*>(internalField(2).get());
+}
+
+const ClassInfo PendingVirtualModuleResult::s_info = { "PendingVirtualModule"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(PendingVirtualModuleResult) };
+
+PendingVirtualModuleResult* PendingVirtualModuleResult::create(VM& vm, Structure* structure)
+{
+ PendingVirtualModuleResult* mod = new (NotNull, allocateCell<PendingVirtualModuleResult>(vm)) PendingVirtualModuleResult(vm, structure);
+ return mod;
+}
+Structure* PendingVirtualModuleResult::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+ return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+}
+
+PendingVirtualModuleResult::PendingVirtualModuleResult(VM& vm, Structure* structure)
+ : Base(vm, structure)
+{
+}
+
+void PendingVirtualModuleResult::finishCreation(VM& vm, const WTF::String& specifier, const WTF::String& referrer)
+{
+ Base::finishCreation(vm);
+ Base::internalField(0).set(vm, this, JSC::jsString(vm, specifier));
+ Base::internalField(1).set(vm, this, JSC::jsString(vm, referrer));
+ Base::internalField(2).set(vm, this, JSC::JSInternalPromise::create(vm, globalObject()->internalPromiseStructure()));
+}
+
+template<typename Visitor>
+void PendingVirtualModuleResult::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ auto* thisObject = jsCast<PendingVirtualModuleResult*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+}
+
+DEFINE_VISIT_CHILDREN(PendingVirtualModuleResult);
+
+PendingVirtualModuleResult* PendingVirtualModuleResult::create(JSC::JSGlobalObject* globalObject, const WTF::String& specifier, const WTF::String& referrer)
+{
+ auto* virtualModule = create(globalObject->vm(), reinterpret_cast<Zig::GlobalObject*>(globalObject)->pendingVirtualModuleResultStructure());
+ virtualModule->finishCreation(globalObject->vm(), specifier, referrer);
+ return virtualModule;
+}
+
+OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC::JSValue objectValue)
+{
+ OnLoadResult result = {};
+ result.type = OnLoadResultTypeError;
+ JSC::VM& vm = globalObject->vm();
+ result.value.error = JSC::jsUndefined();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ BunLoaderType loader = BunLoaderTypeNone;
+
+ JSC::JSObject* object = objectValue.getObject();
+ if (UNLIKELY(!object)) {
+ scope.throwException(globalObject, JSC::createError(globalObject, "Expected onLoad callback to return an object"_s));
+ result.value.error = scope.exception();
+ scope.clearException();
+ scope.release();
+ return result;
+ }
+
+ if (JSC::JSValue loaderValue = object->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "loader"_s))) {
+ if (loaderValue.isString()) {
+ if (JSC::JSString* loaderJSString = loaderValue.toStringOrNull(globalObject)) {
+ WTF::String loaderString = loaderJSString->value(globalObject);
+ if (loaderString == "js"_s) {
+ loader = BunLoaderTypeJS;
+ } else if (loaderString == "object"_s) {
+ return handleOnLoadObjectResult(globalObject, object);
+ } else if (loaderString == "jsx"_s) {
+ loader = BunLoaderTypeJSX;
+ } else if (loaderString == "ts"_s) {
+ loader = BunLoaderTypeTS;
+ } else if (loaderString == "tsx"_s) {
+ loader = BunLoaderTypeTSX;
+ } else if (loaderString == "json"_s) {
+ loader = BunLoaderTypeJSON;
+ } else if (loaderString == "toml"_s) {
+ loader = BunLoaderTypeTOML;
+ }
+ }
+ }
+ }
+
+ if (UNLIKELY(loader == BunLoaderTypeNone)) {
+ throwException(globalObject, scope, createError(globalObject, "Expected loader to be one of \"js\", \"jsx\", \"object\", \"ts\", \"tsx\", \"toml\", or \"json\""_s));
+ result.value.error = scope.exception();
+ scope.clearException();
+ scope.release();
+ return result;
+ }
+
+ result.value.sourceText.loader = loader;
+ result.value.sourceText.value = JSValue {};
+ result.value.sourceText.string = {};
+
+ if (JSC::JSValue contentsValue = object->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "contents"_s))) {
+ if (contentsValue.isString()) {
+ if (JSC::JSString* contentsJSString = contentsValue.toStringOrNull(globalObject)) {
+ result.value.sourceText.string = Zig::toZigString(contentsJSString, globalObject);
+ result.value.sourceText.value = contentsValue;
+ }
+ } else if (JSC::JSArrayBufferView* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(contentsValue)) {
+ result.value.sourceText.string = ZigString { reinterpret_cast<const unsigned char*>(view->vector()), view->byteLength() };
+ result.value.sourceText.value = contentsValue;
+ }
+ }
+
+ if (UNLIKELY(result.value.sourceText.value.isEmpty())) {
+ throwException(globalObject, scope, createError(globalObject, "Expected \"contents\" to be a string or an ArrayBufferView"_s));
+ result.value.error = scope.exception();
+ scope.clearException();
+ scope.release();
+ return result;
+ }
+
+ result.type = OnLoadResultTypeCode;
+ return result;
+}
+
+static OnLoadResult handleOnLoadResult(Zig::GlobalObject* globalObject, JSC::JSValue objectValue)
+{
+ if (JSC::JSPromise* promise = JSC::jsDynamicCast<JSC::JSPromise*>(objectValue)) {
+ OnLoadResult result = {};
+ result.type = OnLoadResultTypePromise;
+ result.value.promise = objectValue;
+ return result;
+ }
+
+ return handleOnLoadResultNotPromise(globalObject, objectValue);
+}
+
+template<bool allowPromise>
+static JSValue handleVirtualModuleResult(
+ Zig::GlobalObject* globalObject,
+ JSValue virtualModuleResult,
+ ErrorableResolvedSource* res,
+ ZigString* specifier,
+ ZigString* referrer)
+{
+ auto onLoadResult = handleOnLoadResult(globalObject, virtualModuleResult);
+ JSC::VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto reject = [&](JSC::JSValue exception) -> JSValue {
+ if constexpr (allowPromise) {
+ return rejectedInternalPromise(globalObject, exception);
+ } else {
+ throwException(globalObject, scope, exception);
+ return exception;
+ }
+ };
+
+ auto resolve = [&](JSValue code) -> JSValue {
+ res->success = true;
+ if constexpr (allowPromise) {
+ return resolvedInternalPromise(globalObject, code);
+ } else {
+ return code;
+ }
+ };
+
+ auto rejectOrResolve = [&](JSValue code) -> JSValue {
+ if (auto* exception = scope.exception()) {
+ if constexpr (allowPromise) {
+ scope.clearException();
+ return rejectedInternalPromise(globalObject, exception);
+ } else {
+ return exception;
+ }
+ }
+
+ res->success = true;
+
+ if constexpr (allowPromise) {
+ return resolvedInternalPromise(globalObject, code);
+ } else {
+ return code;
+ }
+ };
+
+ switch (onLoadResult.type) {
+ case OnLoadResultTypeCode: {
+ Bun__transpileVirtualModule(globalObject, specifier, referrer, &onLoadResult.value.sourceText.string, onLoadResult.value.sourceText.loader, res);
+ if (!res->success) {
+ return reject(JSValue::decode(reinterpret_cast<EncodedJSValue>(res->result.err.ptr)));
+ }
+
+ auto provider = Zig::SourceProvider::create(res->result.value);
+ return resolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider)));
+ }
+ case OnLoadResultTypeError: {
+ return reject(onLoadResult.value.error);
+ }
+
+ case OnLoadResultTypeObject: {
+ JSC::JSObject* object = onLoadResult.value.object.getObject();
+ JSC::ensureStillAliveHere(object);
+ auto function = generateObjectModuleSourceCode(
+ globalObject,
+ object);
+ auto source = JSC::SourceCode(
+ JSC::SyntheticSourceProvider::create(WTFMove(function),
+ JSC::SourceOrigin(), Zig::toString(*specifier)));
+ JSC::ensureStillAliveHere(object);
+ return rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source)));
+ }
+
+ case OnLoadResultTypePromise: {
+ JSC::JSPromise* promise = jsCast<JSC::JSPromise*>(onLoadResult.value.promise);
+ JSFunction* performPromiseThenFunction = globalObject->performPromiseThenFunction();
+ auto callData = JSC::getCallData(performPromiseThenFunction);
+ ASSERT(callData.type != CallData::Type::None);
+ auto specifierString = Zig::toString(*specifier);
+ auto referrerString = Zig::toString(*referrer);
+ PendingVirtualModuleResult* pendingModule = PendingVirtualModuleResult::create(globalObject, specifierString, referrerString);
+ JSC::JSInternalPromise* internalPromise = pendingModule->internalPromise();
+ MarkedArgumentBuffer arguments;
+ arguments.append(promise);
+ arguments.append(globalObject->thenable(jsFunctionOnLoadObjectResultResolve));
+ arguments.append(globalObject->thenable(jsFunctionOnLoadObjectResultReject));
+ arguments.append(jsUndefined());
+ arguments.append(pendingModule);
+ ASSERT(!arguments.hasOverflowed());
+ JSC::call(globalObject, performPromiseThenFunction, callData, jsUndefined(), arguments);
+ return internalPromise;
+ }
+ default: {
+ __builtin_unreachable();
+ }
+ }
+}
+
+template<bool allowPromise>
+static JSValue fetchSourceCode(
+ Zig::GlobalObject* globalObject,
+ ErrorableResolvedSource* res,
+ ZigString* specifier,
+ ZigString* referrer)
+{
+ void* bunVM = globalObject->bunVM();
+ auto& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto reject = [&](JSC::JSValue exception) -> JSValue {
+ if constexpr (allowPromise) {
+ return rejectedInternalPromise(globalObject, exception);
+ } else {
+ throwException(globalObject, scope, exception);
+ return JSC::jsUndefined();
+ }
+ };
+
+ auto resolve = [&](JSValue code) -> JSValue {
+ if constexpr (allowPromise) {
+ return resolvedInternalPromise(globalObject, code);
+ } else {
+ return code;
+ }
+ };
+
+ auto rejectOrResolve = [&](JSValue code) -> JSValue {
+ if (auto* exception = scope.exception()) {
+ scope.clearException();
+ return rejectedInternalPromise(globalObject, exception);
+ }
+
+ if constexpr (allowPromise) {
+ return resolvedInternalPromise(globalObject, code);
+ } else {
+ return code;
+ }
+ };
+
+ if (Bun__fetchBuiltinModule(bunVM, globalObject, specifier, referrer, res)) {
+ if (!res->success) {
+ throwException(scope, res->result.err, globalObject);
+ auto* exception = scope.exception();
+ scope.clearException();
+ return reject(exception);
+ }
+
+ auto moduleKey = Zig::toString(*specifier);
+
+ switch (res->result.value.tag) {
+ case SyntheticModuleType::Module: {
+ auto source = JSC::SourceCode(
+ JSC::SyntheticSourceProvider::create(generateNodeModuleModule,
+ JSC::SourceOrigin(), WTFMove(moduleKey)));
+
+ return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
+ }
+
+ case SyntheticModuleType::Buffer: {
+ auto source = JSC::SourceCode(
+ JSC::SyntheticSourceProvider::create(generateBufferSourceCode,
+ JSC::SourceOrigin(), WTFMove(moduleKey)));
+
+ auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
+
+ return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
+ }
+ case SyntheticModuleType::Process: {
+ auto source = JSC::SourceCode(
+ JSC::SyntheticSourceProvider::create(generateProcessSourceCode,
+ JSC::SourceOrigin(), WTFMove(moduleKey)));
+
+ return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
+ }
+ case SyntheticModuleType::Events: {
+ auto source = JSC::SourceCode(
+ JSC::SyntheticSourceProvider::create(generateEventsSourceCode,
+ JSC::SourceOrigin(), WTFMove(moduleKey)));
+
+ return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
+ }
+ case SyntheticModuleType::StringDecoder: {
+ auto source = JSC::SourceCode(
+ JSC::SyntheticSourceProvider::create(generateStringDecoderSourceCode,
+ JSC::SourceOrigin(), WTFMove(moduleKey)));
+
+ return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)));
+ }
+ default: {
+ auto provider = Zig::SourceProvider::create(res->result.value);
+ return rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider)));
+ }
+ }
+ }
+
+ if (JSC::JSValue virtualModuleResult = JSValue::decode(Bun__runVirtualModule(globalObject, specifier))) {
+ return handleVirtualModuleResult<allowPromise>(globalObject, virtualModuleResult, res, specifier, referrer);
+ }
+
+ Bun__transpileFile(bunVM, globalObject, specifier, referrer, res);
+ if (!res->success) {
+ throwException(scope, res->result.err, globalObject);
+ auto* exception = scope.exception();
+ scope.clearException();
+ return reject(exception);
+ }
+
+ auto provider = Zig::SourceProvider::create(res->result.value);
+ return rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider)));
+}
+
+extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
+{
+ JSC::VM& vm = globalObject->vm();
+ ErrorableResolvedSource res = {};
+ res.success = false;
+ JSC::JSValue objectResult = callFrame->argument(0);
+ PendingVirtualModuleResult* pendingModule = JSC::jsCast<PendingVirtualModuleResult*>(callFrame->argument(1));
+ JSC::JSValue specifierString = pendingModule->internalField(0).get();
+ JSC::JSValue referrerString = pendingModule->internalField(1).get();
+ pendingModule->internalField(0).set(vm, pendingModule, JSC::jsUndefined());
+ pendingModule->internalField(1).set(vm, pendingModule, JSC::jsUndefined());
+ JSC::JSInternalPromise* promise = pendingModule->internalPromise();
+
+ ZigString specifier = Zig::toZigString(specifierString, globalObject);
+ ZigString referrer = Zig::toZigString(referrerString, globalObject);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ JSC::JSValue result = handleVirtualModuleResult<false>(reinterpret_cast<Zig::GlobalObject*>(globalObject), objectResult, &res, &specifier, &referrer);
+ if (res.success) {
+ if (scope.exception()) {
+ auto retValue = JSValue::encode(promise->rejectWithCaughtException(globalObject, scope));
+ pendingModule->internalField(2).set(vm, pendingModule, JSC::jsUndefined());
+ return retValue;
+ }
+ scope.release();
+ promise->resolve(globalObject, result);
+ pendingModule->internalField(2).set(vm, pendingModule, JSC::jsUndefined());
+ } else {
+ throwException(globalObject, scope, result);
+ auto retValue = JSValue::encode(promise->rejectWithCaughtException(globalObject, scope));
+ pendingModule->internalField(2).set(vm, pendingModule, JSC::jsUndefined());
+ return retValue;
+ }
+ return JSValue::encode(jsUndefined());
+}
+
+extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
+{
+ JSC::VM& vm = globalObject->vm();
+ ErrorableResolvedSource res = {};
+ JSC::JSValue reason = callFrame->argument(0);
+ PendingVirtualModuleResult* pendingModule = JSC::jsCast<PendingVirtualModuleResult*>(callFrame->argument(1));
+ JSC::JSValue specifierString = pendingModule->internalField(0).get();
+ JSC::JSValue referrerString = pendingModule->internalField(1).get();
+ pendingModule->internalField(0).set(vm, pendingModule, JSC::jsUndefined());
+ pendingModule->internalField(1).set(vm, pendingModule, JSC::jsUndefined());
+ JSC::JSInternalPromise* promise = pendingModule->internalPromise();
+
+ ZigString specifier = Zig::toZigString(specifierString, globalObject);
+ ZigString referrer = Zig::toZigString(referrerString, globalObject);
+ pendingModule->internalField(2).set(vm, pendingModule, JSC::jsUndefined());
+ promise->reject(globalObject, reason);
+
+ return JSValue::encode(reason);
+}
+
+JSValue fetchSourceCodeSync(
+ Zig::GlobalObject* globalObject,
+ ErrorableResolvedSource* res,
+ ZigString* specifier,
+ ZigString* referrer)
+{
+ return fetchSourceCode<false>(globalObject, res, specifier, referrer);
+}
+
+JSValue fetchSourceCodeAsync(
+ Zig::GlobalObject* globalObject,
+ ErrorableResolvedSource* res,
+ ZigString* specifier,
+ ZigString* referrer)
+{
+ return fetchSourceCode<true>(globalObject, res, specifier, referrer);
+}
+}
+namespace JSC {
+
+template<unsigned passedNumberOfInternalFields>
+template<typename Visitor>
+void JSInternalFieldObjectImpl<passedNumberOfInternalFields>::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ auto* thisObject = jsCast<JSInternalFieldObjectImpl*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+ visitor.appendValues(thisObject->m_internalFields, numberOfInternalFields);
+}
+
+DEFINE_VISIT_CHILDREN_WITH_MODIFIER(template<unsigned passedNumberOfInternalFields>, JSInternalFieldObjectImpl<passedNumberOfInternalFields>);
+
+} // namespace JSC
diff --git a/src/bun.js/bindings/ModuleLoader.h b/src/bun.js/bindings/ModuleLoader.h
new file mode 100644
index 000000000..98f8b7dbb
--- /dev/null
+++ b/src/bun.js/bindings/ModuleLoader.h
@@ -0,0 +1,94 @@
+#include "root.h"
+#include "headers-handwritten.h"
+
+#include "JavaScriptCore/JSCInlines.h"
+#include "BunClientData.h"
+
+namespace Zig {
+class GlobalObject;
+}
+
+namespace JSC {
+class JSInternalPromise;
+}
+
+namespace Bun {
+using namespace JSC;
+
+typedef uint8_t OnLoadResultType;
+const OnLoadResultType OnLoadResultTypeError = 0;
+const OnLoadResultType OnLoadResultTypeCode = 1;
+const OnLoadResultType OnLoadResultTypeObject = 2;
+const OnLoadResultType OnLoadResultTypePromise = 3;
+
+struct CodeString {
+ ZigString string;
+ JSC::JSValue value;
+ BunLoaderType loader;
+};
+
+union OnLoadResultValue {
+ CodeString sourceText;
+ JSC::JSValue object;
+ JSC::JSValue promise;
+ JSC::JSValue error;
+};
+
+struct OnLoadResult {
+ OnLoadResultValue value;
+ OnLoadResultType type;
+};
+
+class PendingVirtualModuleResult : public JSC::JSInternalFieldObjectImpl<3> {
+public:
+ using Base = JSC::JSInternalFieldObjectImpl<3>;
+
+ template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<PendingVirtualModuleResult, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForPendingVirtualModuleResult.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForPendingVirtualModuleResult = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForPendingVirtualModuleResult.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForPendingVirtualModuleResult = WTFMove(space); });
+ }
+
+ JS_EXPORT_PRIVATE static PendingVirtualModuleResult* create(VM&, Structure*);
+ static PendingVirtualModuleResult* create(JSC::JSGlobalObject* globalObject, const WTF::String& specifier, const WTF::String& referrer);
+ static PendingVirtualModuleResult* createWithInitialValues(VM&, Structure*);
+ static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+ JSC::JSInternalPromise* internalPromise();
+
+ static std::array<JSValue, numberOfInternalFields> initialValues()
+ {
+ return { {
+ jsUndefined(),
+ jsUndefined(),
+ jsUndefined(),
+ } };
+ }
+
+ DECLARE_EXPORT_INFO;
+ DECLARE_VISIT_CHILDREN;
+
+ PendingVirtualModuleResult(JSC::VM&, JSC::Structure*);
+ void finishCreation(JSC::VM&, const WTF::String& specifier, const WTF::String& referrer);
+};
+
+OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC::JSValue objectValue);
+JSValue fetchSourceCodeSync(
+ Zig::GlobalObject* globalObject,
+ ErrorableResolvedSource* res,
+ ZigString* specifier,
+ ZigString* referrer);
+
+JSValue fetchSourceCodeAsync(
+ Zig::GlobalObject* globalObject,
+ ErrorableResolvedSource* res,
+ ZigString* specifier,
+ ZigString* referrer);
+
+} // namespace Bun \ No newline at end of file
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index 888bf8f6b..2753707e8 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -103,6 +103,7 @@
#include "JSSQLStatement.h"
#include "ReadableStreamBuiltins.h"
#include "BunJSCModule.h"
+#include "ModuleLoader.h"
#include "ZigGeneratedClasses.h"
@@ -160,13 +161,6 @@ using JSBuffer = WebCore::JSBuffer;
#include "DOMJITHelpers.h"
#include <JavaScriptCore/DFGAbstractHeap.h>
-#include "../modules/BufferModule.h"
-#include "../modules/EventsModule.h"
-#include "../modules/ProcessModule.h"
-#include "../modules/StringDecoderModule.h"
-#include "../modules/ObjectModule.h"
-#include "../modules/NodeModuleModule.h"
-
// #include <iostream>
static bool has_loaded_jsc = false;
@@ -1022,6 +1016,7 @@ JSC:
static NeverDestroyed<const String> bunJSCString(MAKE_STATIC_STRING_IMPL("bun:jsc"));
static NeverDestroyed<const String> bunStreamString(MAKE_STATIC_STRING_IMPL("bun:stream"));
static NeverDestroyed<const String> noopString(MAKE_STATIC_STRING_IMPL("noop"));
+ static NeverDestroyed<const String> createImportMeta(MAKE_STATIC_STRING_IMPL("createImportMeta"));
JSC::JSValue moduleName = callFrame->argument(0);
if (moduleName.isNumber()) {
@@ -1081,6 +1076,11 @@ JSC:
return JSValue::encode(obj);
}
+ if (string == createImportMeta) {
+ Zig::ImportMetaObject* obj = Zig::ImportMetaObject::create(globalObject, callFrame->argument(1));
+ return JSValue::encode(obj);
+ }
+
if (UNLIKELY(string == noopString)) {
auto* obj = constructEmptyObject(globalObject);
obj->putDirectCustomAccessor(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "getterSetter"_s)), JSC::CustomGetterSetter::create(vm, noop_getter, noop_setter), 0);
@@ -1884,6 +1884,11 @@ void GlobalObject::finishCreation(VM& vm)
init.set(JSModuleNamespaceObject::createStructure(init.vm, init.owner, init.owner->objectPrototype()));
});
+ this->m_pendingVirtualModuleResultStructure.initLater(
+ [](const Initializer<Structure>& init) {
+ init.set(Bun::PendingVirtualModuleResult::createStructure(init.vm, init.owner, init.owner->objectPrototype()));
+ });
+
this->initGeneratedLazyClasses();
m_NapiClassStructure.initLater(
@@ -2655,87 +2660,27 @@ static JSC_DEFINE_HOST_FUNCTION(functionFulfillModuleSync,
res.result.err.code = 0;
res.result.err.ptr = nullptr;
- Zig__GlobalObject__fetch(&res, globalObject, &specifier, &specifier);
+ JSValue result = Bun::fetchSourceCodeSync(
+ reinterpret_cast<Zig::GlobalObject*>(globalObject),
+ &res,
+ &specifier,
+ &specifier);
- if (!res.success) {
- throwException(scope, res.result.err, globalObject);
- return JSValue::encode(JSC::jsUndefined());
+ if (result.isUndefined() || !result) {
+ return JSValue::encode(result);
}
- switch (res.result.value.tag) {
- case SyntheticModuleType::Buffer: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(
- generateBufferSourceCode,
- JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath("node:buffer"_s)), WTFMove(moduleKey)));
-
- globalObject->moduleLoader()->provideFetch(globalObject, key, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
- RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined()));
- }
- case SyntheticModuleType::ObjectModule: {
- JSC::EncodedJSValue encodedValue = reinterpret_cast<JSC::EncodedJSValue>(
- bitwise_cast<int64_t>(reinterpret_cast<size_t>(res.result.value.source_code.ptr)));
- JSC::JSObject* object = JSC::JSValue::decode(encodedValue).getObject();
- auto function = generateObjectModuleSourceCode(
- globalObject,
- object);
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(WTFMove(function),
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
- globalObject->moduleLoader()->provideFetch(globalObject, key, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
- RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined()));
- }
- case SyntheticModuleType::Process: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(
- generateProcessSourceCode,
- JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath("node:process"_s)), WTFMove(moduleKey)));
-
- globalObject->moduleLoader()->provideFetch(globalObject, key, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
- RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined()));
- }
- case SyntheticModuleType::Events: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(
- generateEventsSourceCode,
- JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath("node:events"_s)), WTFMove(moduleKey)));
-
- globalObject->moduleLoader()->provideFetch(globalObject, key, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
- RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined()));
- }
- case SyntheticModuleType::Module: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(
- generateNodeModuleModule,
- JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath("node:module"_s)), WTFMove(moduleKey)));
-
- globalObject->moduleLoader()->provideFetch(globalObject, key, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
- RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined()));
- }
- case SyntheticModuleType::StringDecoder: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(
- generateStringDecoderSourceCode,
- JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath("node:string_decoder"_s)), WTFMove(moduleKey)));
-
- globalObject->moduleLoader()->provideFetch(globalObject, key, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
- RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined()));
- }
- default: {
- auto provider = Zig::SourceProvider::create(res.result.value);
- globalObject->moduleLoader()->provideFetch(globalObject, key, JSC::SourceCode(provider));
- RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined()));
- RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined()));
- }
- }
+ globalObject->moduleLoader()->provideFetch(globalObject, key, jsCast<JSC::JSSourceCode*>(result)->sourceCode());
+ RELEASE_AND_RETURN(scope, JSValue::encode(JSC::jsUndefined()));
+}
+
+static JSC::JSInternalPromise* rejectedInternalPromise(JSC::JSGlobalObject* globalObject, JSC::JSValue value)
+{
+ JSC::VM& vm = globalObject->vm();
+ JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
+ promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, value);
+ promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32AsAnyInt() | JSC::JSPromise::isFirstResolvingFunctionCalledFlag | static_cast<unsigned>(JSC::JSPromise::Status::Rejected)));
+ return promise;
}
JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject,
@@ -2743,20 +2688,15 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalOb
JSValue value1, JSValue value2)
{
JSC::VM& vm = globalObject->vm();
- JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
auto scope = DECLARE_THROW_SCOPE(vm);
- auto rejectWithError = [&](JSC::JSValue error) {
- promise->reject(globalObject, error);
- return promise;
- };
-
auto moduleKey = key.toWTFString(globalObject);
- RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
+ if (UNLIKELY(scope.exception()))
+ return rejectedInternalPromise(globalObject, scope.exception()->value());
if (moduleKey.endsWith(".node"_s)) {
- return rejectWithError(createTypeError(globalObject, "To load Node-API modules, use require() or process.dlopen instead of import."_s));
+ return rejectedInternalPromise(globalObject, createTypeError(globalObject, "To load Node-API modules, use require() or process.dlopen instead of import."_s));
}
auto moduleKeyZig = toZigString(moduleKey);
@@ -2766,123 +2706,19 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalOb
res.result.err.code = 0;
res.result.err.ptr = nullptr;
- Zig__GlobalObject__fetch(&res, globalObject, &moduleKeyZig, &source);
-
- if (!res.success) {
- throwException(scope, res.result.err, globalObject);
- RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
- }
-
- switch (res.result.value.tag) {
- case 1: {
- auto buffer = Vector<uint8_t>(res.result.value.source_code.ptr, res.result.value.source_code.len);
- auto source = JSC::SourceCode(
- JSC::WebAssemblySourceProvider::create(WTFMove(buffer),
- JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(Zig::toString(res.result.value.source_url))),
- WTFMove(moduleKey)));
-
- auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
-
- promise->resolve(globalObject, sourceCode);
- scope.release();
-
- globalObject->vm().drainMicrotasks();
- return promise;
- }
- case SyntheticModuleType::ObjectModule: {
- JSC::EncodedJSValue encodedValue = reinterpret_cast<JSC::EncodedJSValue>(
- bitwise_cast<int64_t>(reinterpret_cast<size_t>(res.result.value.source_code.ptr)));
- JSC::JSObject* object = JSC::JSValue::decode(encodedValue).getObject();
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateObjectModuleSourceCode(
- globalObject,
- object),
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
+ JSValue result = Bun::fetchSourceCodeAsync(
+ reinterpret_cast<Zig::GlobalObject*>(globalObject),
+ &res,
+ &moduleKeyZig,
+ &source);
- promise->resolve(globalObject, sourceCode);
- scope.release();
- return promise;
- }
- case SyntheticModuleType::Module: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateNodeModuleModule,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
-
- promise->resolve(globalObject, sourceCode);
- scope.release();
- return promise;
- }
-
- case SyntheticModuleType::Buffer: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateBufferSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
-
- promise->resolve(globalObject, sourceCode);
- scope.release();
- return promise;
- }
- case SyntheticModuleType::Process: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateProcessSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
-
- promise->resolve(globalObject, sourceCode);
- scope.release();
- return promise;
- }
- case SyntheticModuleType::Events: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateEventsSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
-
- promise->resolve(globalObject, sourceCode);
- scope.release();
- return promise;
- }
- case SyntheticModuleType::StringDecoder: {
- auto source = JSC::SourceCode(
- JSC::SyntheticSourceProvider::create(generateStringDecoderSourceCode,
- JSC::SourceOrigin(), WTFMove(moduleKey)));
-
- auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
- RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
-
- promise->resolve(globalObject, sourceCode);
- scope.release();
- return promise;
- }
- default: {
- auto provider = Zig::SourceProvider::create(res.result.value);
- auto jsSourceCode = JSC::JSSourceCode::create(vm, JSC::SourceCode(provider));
- promise->resolve(globalObject, jsSourceCode);
- }
+ if (auto* internalPromise = JSC::jsDynamicCast<JSC::JSInternalPromise*>(result)) {
+ return internalPromise;
+ } else if (auto* promise = JSC::jsDynamicCast<JSC::JSPromise*>(result)) {
+ return jsCast<JSC::JSInternalPromise*>(promise);
+ } else {
+ return rejectedInternalPromise(globalObject, result);
}
-
- // if (provider.ptr()->isBytecodeCacheEnabled()) {
- // provider.ptr()->readOrGenerateByteCodeCache(vm, jsSourceCode->sourceCode());
- // }
-
- scope.release();
-
- globalObject->vm().drainMicrotasks();
- return promise;
}
JSC::JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject,
diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h
index 6c5c23b3a..160aef714 100644
--- a/src/bun.js/bindings/ZigGlobalObject.h
+++ b/src/bun.js/bindings/ZigGlobalObject.h
@@ -35,7 +35,9 @@ class EventLoopTask;
#include "BunPlugin.h"
extern "C" void Bun__reportError(JSC__JSGlobalObject*, JSC__JSValue);
-
+// defined in ModuleLoader.cpp
+extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame);
+extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame);
// #include "EventTarget.h"
// namespace WebCore {
@@ -239,7 +241,10 @@ public:
Bun__HTTPRequestContextDebugTLS__onResolve,
Bun__HTTPRequestContextDebugTLS__onResolveStream,
+ jsFunctionOnLoadObjectResultResolve,
+ jsFunctionOnLoadObjectResultReject,
};
+ static constexpr size_t promiseFunctionsSize = 18;
static PromiseFunctions promiseHandlerID(EncodedJSValue (*handler)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1))
{
@@ -275,6 +280,14 @@ public:
return PromiseFunctions::Bun__HTTPRequestContextDebugTLS__onResolve;
} else if (handler == Bun__HTTPRequestContextDebugTLS__onResolveStream) {
return PromiseFunctions::Bun__HTTPRequestContextDebugTLS__onResolveStream;
+ } else if (handler == Bun__HTTPRequestContextDebugTLS__onResolveStream) {
+ return PromiseFunctions::Bun__HTTPRequestContextDebugTLS__onResolveStream;
+ } else if (handler == Bun__HTTPRequestContextDebugTLS__onResolveStream) {
+ return PromiseFunctions::Bun__HTTPRequestContextDebugTLS__onResolveStream;
+ } else if (handler == jsFunctionOnLoadObjectResultResolve) {
+ return PromiseFunctions::jsFunctionOnLoadObjectResultResolve;
+ } else if (handler == jsFunctionOnLoadObjectResultReject) {
+ return PromiseFunctions::jsFunctionOnLoadObjectResultReject;
} else {
RELEASE_ASSERT_NOT_REACHED();
}
@@ -300,7 +313,7 @@ public:
mutable WriteBarrier<JSFunction> m_readableStreamToJSON;
mutable WriteBarrier<JSFunction> m_readableStreamToArrayBuffer;
mutable WriteBarrier<JSFunction> m_assignToStream;
- mutable WriteBarrier<JSFunction> m_thenables[16];
+ mutable WriteBarrier<JSFunction> m_thenables[promiseFunctionsSize + 1];
void trackFFIFunction(JSC::JSFunction* function)
{
@@ -311,6 +324,8 @@ public:
BunPlugin::OnResolve onResolvePlugins[BunPluginTargetMax + 1] {};
BunPluginTarget defaultBunPluginTarget = BunPluginTargetBun;
+ JSC::Structure* pendingVirtualModuleResultStructure() { return m_pendingVirtualModuleResultStructure.get(this); }
+
// When a napi module initializes on dlopen, we need to know what the value is
JSValue pendingNapiModule = JSValue {};
@@ -344,6 +359,8 @@ private:
LazyProperty<JSGlobalObject, JSMap> m_requireMap;
LazyProperty<JSGlobalObject, JSObject> m_performanceObject;
+ LazyProperty<JSGlobalObject, JSC::Structure> m_pendingVirtualModuleResultStructure;
+
LazyProperty<JSGlobalObject, JSObject> m_encodeIntoObjectPrototype;
// LazyProperty<JSGlobalObject, WebCore::JSEventTarget> m_eventTarget;
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp
index 81e9c602b..bb0718ea9 100644
--- a/src/bun.js/bindings/bindings.cpp
+++ b/src/bun.js/bindings/bindings.cpp
@@ -873,27 +873,33 @@ bool JSC__JSModuleLoader__checkSyntax(JSC__JSGlobalObject* arg0, const JSC__Sour
return result;
}
-JSC__JSValue JSC__JSModuleLoader__evaluate(JSC__JSGlobalObject* arg0, const unsigned char* arg1,
+JSC__JSValue JSC__JSModuleLoader__evaluate(JSC__JSGlobalObject* globalObject, const unsigned char* arg1,
size_t arg2, const unsigned char* arg3, size_t arg4,
JSC__JSValue JSValue5, JSC__JSValue* arg6)
{
- WTF::String src = WTF::String(WTF::StringImpl::createWithoutCopying(arg1, arg2));
- WTF::URL origin = WTF::URL::fileURLWithFileSystemPath(WTF::StringView(arg3, arg4));
+ WTF::String src = WTF::String::fromUTF8(arg1, arg2).isolatedCopy();
+ WTF::URL origin = WTF::URL::fileURLWithFileSystemPath(WTF::String(WTF::StringImpl::createWithoutCopying(arg3, arg4))).isolatedCopy();
- JSC::VM& vm = arg0->vm();
- JSC::JSLockHolder locker(vm);
+ JSC::VM& vm = globalObject->vm();
JSC::SourceCode sourceCode = JSC::makeSource(
- src, JSC::SourceOrigin { origin }, origin.lastPathComponent().toStringWithoutCopying(),
+ src, JSC::SourceOrigin { origin }, origin.fileSystemPath(),
WTF::TextPosition(), JSC::SourceProviderSourceType::Module);
- WTF::NakedPtr<JSC::Exception> exception;
- auto val = JSC::evaluate(arg0, sourceCode, JSC::JSValue(), exception);
- if (exception.get()) {
- *arg6 = JSC::JSValue::encode(JSC::JSValue(exception.get()));
+ globalObject->moduleLoader()->provideFetch(globalObject, jsString(vm, origin.fileSystemPath()), WTFMove(sourceCode));
+ auto* promise = JSC::importModule(globalObject, JSC::Identifier::fromString(vm, origin.fileSystemPath()), JSValue(), JSValue());
+
+ if (promise->status(vm) == JSC::JSPromise::Status::Pending) {
+ vm.drainMicrotasks();
}
- vm.drainMicrotasks();
- return JSC::JSValue::encode(val);
+ if (promise->status(vm) == JSC::JSPromise::Status::Fulfilled) {
+ return JSC::JSValue::encode(promise->result(vm));
+ } else if (promise->status(vm) == JSC::JSPromise::Status::Rejected) {
+ *arg6 = JSC::JSValue::encode(promise->result(vm));
+ return JSC::JSValue::encode(JSC::jsUndefined());
+ } else {
+ return JSC::JSValue::encode(promise);
+ }
}
JSC__JSInternalPromise* JSC__JSModuleLoader__importModule(JSC__JSGlobalObject* arg0,
const JSC__Identifier* arg1)
diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h
index 45d4752e0..36678e22e 100644
--- a/src/bun.js/bindings/headers-handwritten.h
+++ b/src/bun.js/bindings/headers-handwritten.h
@@ -116,6 +116,19 @@ const JSErrorCode JSErrorCodeOutOfMemoryError = 8;
const JSErrorCode JSErrorCodeStackOverflow = 253;
const JSErrorCode JSErrorCodeUserErrorCode = 254;
+typedef uint8_t BunLoaderType;
+const BunLoaderType BunLoaderTypeNone = 0;
+const BunLoaderType BunLoaderTypeJSX = 1;
+const BunLoaderType BunLoaderTypeJS = 2;
+const BunLoaderType BunLoaderTypeTS = 3;
+const BunLoaderType BunLoaderTypeTSX = 4;
+const BunLoaderType BunLoaderTypeCSS = 5;
+const BunLoaderType BunLoaderTypeFILE = 6;
+const BunLoaderType BunLoaderTypeJSON = 7;
+const BunLoaderType BunLoaderTypeTOML = 8;
+const BunLoaderType BunLoaderTypeWASM = 9;
+const BunLoaderType BunLoaderTypeNAPI = 10;
+
#pragma mark - Stream
typedef uint8_t Encoding;
@@ -199,6 +212,32 @@ extern "C" void ZigString__free(const unsigned char* ptr, size_t len, void* allo
extern "C" void Microtask__run(void* ptr, void* global);
extern "C" void Microtask__run_default(void* ptr, void* global);
+extern "C" bool Bun__transpileVirtualModule(
+ JSC::JSGlobalObject* global,
+ ZigString* specifier,
+ ZigString* referrer,
+ ZigString* sourceCode,
+ BunLoaderType loader,
+ ErrorableResolvedSource* result);
+
+extern "C" JSC::EncodedJSValue Bun__runVirtualModule(
+ JSC::JSGlobalObject* global,
+ ZigString* specifier);
+
+extern "C" bool Bun__transpileFile(
+ void* bunVM,
+ JSC::JSGlobalObject* global,
+ ZigString* specifier,
+ ZigString* referrer,
+ ErrorableResolvedSource* result);
+
+extern "C" bool Bun__fetchBuiltinModule(
+ void* bunVM,
+ JSC::JSGlobalObject* global,
+ ZigString* specifier,
+ ZigString* referrer,
+ ErrorableResolvedSource* result);
+
// Used in process.version
extern "C" const char* Bun__version;
diff --git a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
index 75b7995f0..456ef6aa4 100644
--- a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
+++ b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
@@ -28,6 +28,7 @@ public:
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSSink;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForStringDecoder;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForStringDecoderConstructor;
+ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForPendingVirtualModuleResult;
#include "ZigGeneratedClasses+DOMClientIsoSubspaces.h"
/* --- bun --- */
diff --git a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h
index 42fb1d88b..c5e01c902 100644
--- a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h
+++ b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h
@@ -28,6 +28,7 @@ public:
std::unique_ptr<IsoSubspace> m_subspaceForJSSink;
std::unique_ptr<IsoSubspace> m_subspaceForStringDecoder;
std::unique_ptr<IsoSubspace> m_subspaceForStringDecoderConstructor;
+ std::unique_ptr<IsoSubspace> m_subspaceForPendingVirtualModuleResult;
#include "ZigGeneratedClasses+DOMIsoSubspaces.h"
/*-- BUN --*/