diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bun.js/api/bun.zig | 21 | ||||
-rw-r--r-- | src/bun.js/bindings/BunString.cpp | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/ImportMetaObject.cpp | 96 | ||||
-rw-r--r-- | src/bun.js/bindings/ImportMetaObject.h | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/JSBuffer.lut.h | 4 |
5 files changed, 87 insertions, 37 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig index 966c82d38..a1446831f 100644 --- a/src/bun.js/api/bun.zig +++ b/src/bun.js/api/bun.zig @@ -876,6 +876,19 @@ export fn Bun__resolveSync( }; } +export fn Bun__resolveSyncWithStrings( + global: *JSGlobalObject, + specifier: *bun.String, + source: *bun.String, + is_esm: bool, +) JSC.JSValue { + var exception_ = [1]JSC.JSValueRef{null}; + var exception = &exception_; + return doResolveWithArgs(global, specifier.*, source.*, exception, is_esm, true) orelse { + return JSC.JSValue.fromRef(exception[0]); + }; +} + export fn Bun__resolveSyncWithSource( global: *JSGlobalObject, specifier: JSValue, @@ -889,14 +902,6 @@ export fn Bun__resolveSyncWithSource( }; } -comptime { - if (!is_bindgen) { - _ = Bun__resolve; - _ = Bun__resolveSync; - _ = Bun__resolveSyncWithSource; - } -} - pub fn getPublicPathJS(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { const arguments = callframe.arguments(1).slice(); if (arguments.len < 1) { diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index 416d5d334..21dc52eb8 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -381,7 +381,7 @@ extern "C" BunString URL__getHref(BunString* input) return Bun::toStringRef(url.string()); } -extern "C" BunString URL__getHrefJoin(BunString* baseStr, BunString *relativeStr) +extern "C" BunString URL__getHrefJoin(BunString* baseStr, BunString* relativeStr) { auto base = Bun::toWTFString(*baseStr); auto relative = Bun::toWTFString(*relativeStr); diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp index 4160102a5..097992777 100644 --- a/src/bun.js/bindings/ImportMetaObject.cpp +++ b/src/bun.js/bindings/ImportMetaObject.cpp @@ -269,44 +269,88 @@ JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve, { JSC::VM& vm = globalObject->vm(); - switch (callFrame->argumentCount()) { - case 0: { - auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - // not "requires" because "require" could be confusing - JSC::throwTypeError(globalObject, scope, "import.meta.resolve needs 1 argument (a string)"_s); - scope.release(); - return JSC::JSValue::encode(JSC::JSValue {}); - } - default: { - JSC::JSValue moduleName = callFrame->argument(0); + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - if (moduleName.isUndefinedOrNull()) { + auto thisValue = callFrame->thisValue(); + auto specifierValue = callFrame->argument(0); + // 1. Set specifier to ? ToString(specifier). + auto specifier = specifierValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {})); + + // Node.js allows a second argument for parent + JSValue from; + if (callFrame->argumentCount() >= 2) { + auto fromValue = callFrame->uncheckedArgument(1); + + if (!fromValue.isUndefinedOrNull() && fromValue.isObject()) { + if (auto pathsObject = fromValue.getObject()->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "paths"_s))) { + if (pathsObject.isCell() && pathsObject.asCell()->type() == JSC::JSType::ArrayType) { + auto pathsArray = JSC::jsCast<JSC::JSArray*>(pathsObject); + if (pathsArray->length() > 0) { + fromValue = pathsArray->getIndex(globalObject, 0); + RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {})); + } + } + } + } + + if (fromValue.isString()) { + from = fromValue; + } else + goto use_default_from; + } else { + use_default_from: + JSC::JSObject* thisObject = JSC::jsDynamicCast<JSC::JSObject*>(thisValue); + if (UNLIKELY(!thisObject)) { auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - JSC::throwTypeError(globalObject, scope, "import.meta.resolve expects a string"_s); - scope.release(); - return JSC::JSValue::encode(JSC::JSValue {}); + JSC::throwTypeError(globalObject, scope, "import.meta.resolve must be bound to an import.meta object"_s); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::JSValue {})); } - JSC__JSValue from; + auto clientData = WebCore::clientData(vm); + JSValue pathProperty = thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().pathPublicName()); - if (callFrame->argumentCount() > 1 && callFrame->argument(1).isString()) { - from = JSC::JSValue::encode(callFrame->argument(1)); + if (LIKELY(pathProperty && pathProperty.isString())) { + from = pathProperty; } else { - JSC::JSObject* thisObject = JSC::jsDynamicCast<JSC::JSObject*>(callFrame->thisValue()); - if (UNLIKELY(!thisObject)) { - auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - JSC::throwTypeError(globalObject, scope, "import.meta.resolve must be bound to an import.meta object"_s); - return JSC::JSValue::encode(JSC::JSValue {}); - } + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + JSC::throwTypeError(globalObject, scope, "import.meta.resolve must be bound to an import.meta object"_s); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::JSValue {})); + } + } - auto clientData = WebCore::clientData(vm); + // from.toWTFString() *should* always be the fast case, since above we check that it's a string. + auto fromWTFString = from.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {})); - from = JSC::JSValue::encode(thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().pathPublicName())); + // Try to resolve it to a relative file path. This path is not meant to throw module resolution errors. + if (specifier.startsWith("./"_s) || specifier.startsWith("../"_s) || specifier.startsWith("/"_s) || specifier.startsWith("file://"_s)) { + auto fromURL = fromWTFString.startsWith("file://"_s) ? WTF::URL(fromWTFString) : WTF::URL::fileURLWithFileSystemPath(fromWTFString); + if (!fromURL.isValid()) { + JSC::throwTypeError(globalObject, scope, "`parent` is not a valid Filepath / URL"_s); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::JSValue {})); } - return Bun__resolve(globalObject, JSC::JSValue::encode(moduleName), from, true); + WTF::URL url(fromURL, specifier); + RELEASE_AND_RETURN(scope, JSValue::encode(jsString(vm, url.string()))); } + + // In Node.js, `node:doesnotexist` resolves to `node:doesnotexist` + if (UNLIKELY(specifier.startsWith("node:")) || UNLIKELY(specifier.startsWith("bun:"))) { + return JSValue::encode(jsString(vm, specifier)); } + + // Run it through the module resolver, errors at this point are actual errors. + auto a = Bun::toString(specifier); + auto b = Bun::toString(fromWTFString); + auto result = JSValue::decode(Bun__resolveSyncWithStrings(globalObject, &a, &b, true)); + if (!result.isString()) { + JSC::throwException(globalObject, scope, result); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + // Stringified URL to a file, going off assumption that all modules would be file URLs + RELEASE_AND_RETURN(scope, JSValue::encode(jsString(vm, makeString("file://"_s, result.toWTFString(globalObject))))); } enum class ImportMetaPropertyOffset : uint32_t { diff --git a/src/bun.js/bindings/ImportMetaObject.h b/src/bun.js/bindings/ImportMetaObject.h index 02b911af0..638277d4b 100644 --- a/src/bun.js/bindings/ImportMetaObject.h +++ b/src/bun.js/bindings/ImportMetaObject.h @@ -13,6 +13,7 @@ extern "C" JSC_DECLARE_HOST_FUNCTION(functionImportMeta__resolveSyncPrivate); extern "C" JSC::EncodedJSValue Bun__resolve(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from, bool is_esm); extern "C" JSC::EncodedJSValue Bun__resolveSync(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, JSC::EncodedJSValue from, bool is_esm); extern "C" JSC::EncodedJSValue Bun__resolveSyncWithSource(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, BunString* from, bool is_esm); +extern "C" JSC::EncodedJSValue Bun__resolveSyncWithStrings(JSC::JSGlobalObject* global, BunString* specifier, BunString* from, bool is_esm); namespace Zig { diff --git a/src/bun.js/bindings/JSBuffer.lut.h b/src/bun.js/bindings/JSBuffer.lut.h index 47e8cb984..35a3acea9 100644 --- a/src/bun.js/bindings/JSBuffer.lut.h +++ b/src/bun.js/bindings/JSBuffer.lut.h @@ -37,8 +37,8 @@ static const struct CompactHashIndex jsBufferConstructorTableIndex[33] = { static const struct HashTableValue jsBufferConstructorTableValues[10] = { { "alloc"_s, static_cast<unsigned>(PropertyAttribute::Constructable|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_alloc, 1 } }, - { "allocUnsafe"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_allocUnsafe, 1 } }, - { "allocUnsafeSlow"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_allocUnsafeSlow, 1 } }, + { "allocUnsafe"_s, static_cast<unsigned>(PropertyAttribute::Constructable|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_allocUnsafe, 1 } }, + { "allocUnsafeSlow"_s, static_cast<unsigned>(PropertyAttribute::Constructable|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_allocUnsafeSlow, 1 } }, { "byteLength"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_byteLength, 2 } }, { "compare"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_compare, 2 } }, { "concat"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_concat, 2 } }, |