aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-08-09 01:33:12 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-08-09 01:41:13 -0700
commitb36b7fee16a5239cfb50cfde94ed871d60032b3c (patch)
tree1456e78bd1434ed92c9e0720cdc1bf07d3a6d63c /src/bun.js/bindings
parent01847cabd20d82733874a4b78eb8ee570f08c943 (diff)
downloadbun-b36b7fee16a5239cfb50cfde94ed871d60032b3c.tar.gz
bun-b36b7fee16a5239cfb50cfde94ed871d60032b3c.tar.zst
bun-b36b7fee16a5239cfb50cfde94ed871d60032b3c.zip
[node compat] Implement `require.resolve`
Diffstat (limited to 'src/bun.js/bindings')
-rw-r--r--src/bun.js/bindings/ImportMetaObject.cpp108
-rw-r--r--src/bun.js/bindings/ImportMetaObject.h2
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp20
3 files changed, 121 insertions, 9 deletions
diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp
index dc4290c91..8c0f573f3 100644
--- a/src/bun.js/bindings/ImportMetaObject.cpp
+++ b/src/bun.js/bindings/ImportMetaObject.cpp
@@ -35,6 +35,8 @@
#include "JSBufferConstructorBuiltins.h"
#include "JavaScriptCore/JSBase.h"
+#include "JavaScriptCore/JSNativeStdFunction.h"
+
namespace Zig {
using namespace JSC;
using namespace WebCore;
@@ -42,6 +44,104 @@ using namespace WebCore;
extern "C" JSC__JSValue Bun__resolve(JSC::JSGlobalObject* global, JSC__JSValue specifier, JSC__JSValue from);
extern "C" JSC__JSValue Bun__resolveSync(JSC::JSGlobalObject* global, JSC__JSValue specifier, JSC__JSValue from);
+static EncodedJSValue functionRequireResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame, JSC::EncodedJSValue from)
+{
+ 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, "require.resolve needs 1 argument (a string)"_s);
+ scope.release();
+ return JSC::JSValue::encode(JSC::JSValue {});
+ }
+ default: {
+ JSC::JSValue moduleName = callFrame->argument(0);
+
+ if (moduleName.isUndefinedOrNull()) {
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ JSC::throwTypeError(globalObject, scope, "require.resolve expects a string"_s);
+ scope.release();
+ return JSC::JSValue::encode(JSC::JSValue {});
+ }
+
+ if (callFrame->argumentCount() > 1) {
+ JSC::JSValue fromValue = callFrame->argument(1);
+
+ // require.resolve also supports a paths array
+ // we only support a single path
+ if (!fromValue.isUndefinedOrNull() && fromValue.isObject()) {
+ if (JSC::JSArray* array = JSC::jsDynamicCast<JSC::JSArray*>(fromValue.getObject()->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "paths"_s)))) {
+ if (array->length() > 0) {
+ fromValue = array->getIndex(globalObject, 0);
+ }
+ }
+ }
+ }
+
+ auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from);
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+
+ if (!JSC::JSValue::decode(result).isString()) {
+ JSC::throwException(globalObject, scope, JSC::JSValue::decode(result));
+ return JSC::JSValue::encode(JSC::JSValue {});
+ }
+
+ scope.release();
+ return result;
+ }
+ }
+}
+
+JSC_DEFINE_CUSTOM_SETTER(functionRequireResolveLazySetter,
+ (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName))
+{
+ Zig::GlobalObject* global = static_cast<Zig::GlobalObject*>(JSC::jsCast<JSC::JSObject*>(JSC::JSValue::decode(thisValue)));
+ JSC::VM& vm = globalObject->vm();
+ JSC::JSFunction* require = JSC::jsCast<JSC::JSFunction*>(JSC::JSValue::decode(thisValue));
+ auto clientData = WebCore::clientData(vm);
+ return require->putDirect(vm, PropertyName(clientData->builtinNames().resolvePrivateName()), JSValue::decode(value), 0);
+}
+
+JSC_DEFINE_CUSTOM_GETTER(functionRequireResolveLazyGetter,
+ (JSC::JSGlobalObject * _globalObject, JSC::EncodedJSValue thisValue,
+ JSC::PropertyName))
+{
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(_globalObject);
+
+ JSC::VM& vm = globalObject->vm();
+ auto clientData = WebCore::clientData(vm);
+ auto& builtinNames = clientData->builtinNames();
+
+ JSC::JSFunction* require = JSC::jsCast<JSC::JSFunction*>(JSC::JSValue::decode(thisValue));
+
+ if (JSC::JSValue resolveFunctionValue = require->getIfPropertyExists(globalObject, PropertyName(builtinNames.resolvePrivateName()))) {
+ return JSValue::encode(resolveFunctionValue);
+ }
+
+ JSValue pathStringValue = require->get(globalObject, PropertyName(builtinNames.pathPrivateName()));
+ JSC::Strong<JSC::JSString> pathString = JSC::Strong<JSC::JSString>(vm, pathStringValue.toStringOrNull(globalObject));
+
+ JSC::JSFunction* resolverFunction
+ = JSC::JSNativeStdFunction::create(
+ globalObject->vm(), globalObject, 1, "resolve"_s, [pathString_ = WTFMove(pathString)](JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -> const JSC::EncodedJSValue {
+ return functionRequireResolve(globalObject, callFrame, JSValue::encode(pathString_.get()));
+ });
+ require->putDirect(vm, builtinNames.resolvePrivateName(), resolverFunction, 0);
+ return JSValue::encode(JSValue(resolverFunction));
+}
+
+JSObject* Zig::ImportMetaObject::createRequireFunction(VM& vm, JSGlobalObject* globalObject, WTF::String& pathString)
+{
+ JSFunction* requireFunction = JSFunction::create(vm, importMetaObjectRequireCodeGenerator(vm), globalObject);
+ auto clientData = WebCore::clientData(vm);
+ requireFunction->putDirectCustomAccessor(vm, clientData->builtinNames().resolvePublicName(), JSC::CustomGetterSetter::create(vm, functionRequireResolveLazyGetter, functionRequireResolveLazySetter), 0);
+ requireFunction->putDirect(vm, clientData->builtinNames().pathPrivateName(), jsOwnedString(vm, pathString), JSC::PropertyAttribute::DontEnum | 0);
+ return requireFunction;
+}
+
static JSC_DECLARE_HOST_FUNCTION(functionImportMeta__resolveSync);
static JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolveSync,
@@ -204,8 +304,10 @@ void ImportMetaObjectPrototype::finishCreation(VM& vm, JSGlobalObject* globalObj
this->putDirect(vm, clientData->builtinNames().pathPublicName(), jsEmptyString(vm), 0);
this->putDirect(vm, clientData->builtinNames().urlPublicName(), jsEmptyString(vm), 0);
this->putDirect(vm, clientData->builtinNames().mainPublicName(), jsBoolean(false), 0);
- this->putDirectBuiltinFunction(vm, globalObject,
- clientData->builtinNames().requirePublicName(), importMetaObjectRequireCodeGenerator(vm), 0);
+
+ String requireString = "[[require]]"_s;
+ this->putDirect(vm, clientData->builtinNames().requirePublicName(), Zig::ImportMetaObject::createRequireFunction(vm, globalObject, requireString), PropertyAttribute::Builtin | PropertyAttribute::Function | 0);
+
this->putDirectBuiltinFunction(vm, globalObject,
clientData->builtinNames().loadModulePublicName(), importMetaObjectLoadModuleCodeGenerator(vm), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | 0);
this->putDirectBuiltinFunction(vm, globalObject,
@@ -221,6 +323,7 @@ void ImportMetaObjectPrototype::finishCreation(VM& vm, JSGlobalObject* globalObj
functionImportMeta__resolveSync,
NoIntrinsic,
JSC::PropertyAttribute::Function | 0);
+
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
}
@@ -245,5 +348,4 @@ const JSC::ClassInfo ImportMetaObjectPrototype::s_info = { "ImportMeta"_s, &Base
const JSC::ClassInfo ImportMetaObject::s_info = { "ImportMeta"_s, &Base::s_info, nullptr, nullptr,
CREATE_METHOD_TABLE(ImportMetaObject) };
-
}
diff --git a/src/bun.js/bindings/ImportMetaObject.h b/src/bun.js/bindings/ImportMetaObject.h
index 69348f1f6..7527dcb51 100644
--- a/src/bun.js/bindings/ImportMetaObject.h
+++ b/src/bun.js/bindings/ImportMetaObject.h
@@ -40,6 +40,8 @@ public:
static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject);
static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&);
+ static JSObject* createRequireFunction(VM& vm, JSGlobalObject* globalObject, WTF::String& pathString);
+
private:
ImportMetaObject(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
: Base(vm, structure)
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index daf6d3f14..bfc8e2ad4 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -2466,23 +2466,31 @@ JSC::JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObje
}
RETURN_IF_EXCEPTION(scope, nullptr);
+ auto& builtinNames = clientData->builtinNames();
+
auto view = keyString->value(globalObject);
auto index = view.reverseFind('/', view.length());
if (index != WTF::notFound) {
- metaProperties->putDirect(vm, clientData->builtinNames().dirPublicName(),
+ metaProperties->putDirect(vm, builtinNames.dirPublicName(),
JSC::jsSubstring(globalObject, keyString, 0, index));
metaProperties->putDirect(
- vm, clientData->builtinNames().filePublicName(),
+ vm, builtinNames.filePublicName(),
JSC::jsSubstring(globalObject, keyString, index + 1, keyString->length() - index - 1));
} else {
- metaProperties->putDirect(vm, clientData->builtinNames().filePublicName(), keyString);
+ metaProperties->putDirect(vm, builtinNames.filePublicName(), keyString);
}
- metaProperties->putDirect(vm, clientData->builtinNames().pathPublicName(), keyString);
+ metaProperties->putDirect(vm, builtinNames.pathPublicName(), keyString);
+ metaProperties->putDirect(
+ vm,
+ builtinNames.requirePublicName(),
+ Zig::ImportMetaObject::createRequireFunction(vm, globalObject, view),
+ PropertyAttribute::Builtin | PropertyAttribute::Function | 0);
+
if (view.startsWith('/')) {
- metaProperties->putDirect(vm, clientData->builtinNames().urlPublicName(), JSC::JSValue(JSC::jsString(vm, WTF::URL::fileURLWithFileSystemPath(view).string())));
+ metaProperties->putDirect(vm, builtinNames.urlPublicName(), JSC::JSValue(JSC::jsString(vm, WTF::URL::fileURLWithFileSystemPath(view).string())));
} else {
- metaProperties->putDirect(vm, clientData->builtinNames().urlPublicName(), keyString);
+ metaProperties->putDirect(vm, builtinNames.urlPublicName(), keyString);
}
RELEASE_AND_RETURN(scope, metaProperties);