aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/api/bun.zig21
-rw-r--r--src/bun.js/bindings/BunString.cpp2
-rw-r--r--src/bun.js/bindings/ImportMetaObject.cpp96
-rw-r--r--src/bun.js/bindings/ImportMetaObject.h1
-rw-r--r--src/bun.js/bindings/JSBuffer.lut.h4
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 } },