diff options
author | 2023-09-22 01:09:55 -0400 | |
---|---|---|
committer | 2023-09-21 22:09:55 -0700 | |
commit | 25e69c71e70ac8a0a88f9cf15b4057bd7b2a633a (patch) | |
tree | adf1d5e53f27a2f4ca7b2074fbd54e2c67764a74 /src/bun.js | |
parent | 9d5459221ff663b6c0058440167e098886d97cc2 (diff) | |
download | bun-25e69c71e70ac8a0a88f9cf15b4057bd7b2a633a.tar.gz bun-25e69c71e70ac8a0a88f9cf15b4057bd7b2a633a.tar.zst bun-25e69c71e70ac8a0a88f9cf15b4057bd7b2a633a.zip |
Implement module.parent (#5889)bun-v1.0.3
* Make module.parent work
* yay
* oops
* yay
Diffstat (limited to 'src/bun.js')
-rw-r--r-- | src/bun.js/bindings/CommonJSModuleRecord.cpp | 77 | ||||
-rw-r--r-- | src/bun.js/bindings/CommonJSModuleRecord.h | 12 | ||||
-rw-r--r-- | src/bun.js/bindings/ModuleLoader.cpp | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 8 | ||||
-rw-r--r-- | src/bun.js/bindings/headers.h | 2 | ||||
-rw-r--r-- | src/bun.js/javascript.zig | 4 |
6 files changed, 74 insertions, 30 deletions
diff --git a/src/bun.js/bindings/CommonJSModuleRecord.cpp b/src/bun.js/bindings/CommonJSModuleRecord.cpp index e4fb1939c..eea3b2a6f 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.cpp +++ b/src/bun.js/bindings/CommonJSModuleRecord.cpp @@ -71,6 +71,8 @@ #include <JavaScriptCore/JSSourceCode.h> #include <JavaScriptCore/LazyPropertyInlines.h> +extern "C" bool Bun__isBunMain(JSC::JSGlobalObject* global, const char* input_ptr, uint64_t input_len); + namespace Bun { using namespace JSC; @@ -267,6 +269,31 @@ JSC_DEFINE_CUSTOM_GETTER(getterPath, (JSC::JSGlobalObject * globalObject, JSC::E return JSValue::encode(thisObject->m_id.get()); } +JSC_DEFINE_CUSTOM_GETTER(getterParent, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) +{ + JSCommonJSModule* thisObject = jsDynamicCast<JSCommonJSModule*>(JSValue::decode(thisValue)); + if (UNLIKELY(!thisObject)) { + return JSValue::encode(jsUndefined()); + } + auto v = thisObject->m_parent.get(); + if (v) + return JSValue::encode(thisObject->m_parent.get()); + + // initialize parent by checking if it is the main module. we do this lazily because most people + // dont need `module.parent` and creating commonjs module records is done a ton. + auto idValue = thisObject->m_id.get(); + if (idValue) { + auto id = idValue->value(globalObject).utf8(); + if (Bun__isBunMain(globalObject, id.data(), id.length())) { + thisObject->m_parent.set(globalObject->vm(), thisObject, jsNull()); + return JSValue::encode(jsNull()); + } + } + + thisObject->m_parent.set(globalObject->vm(), thisObject, jsUndefined()); + return JSValue::encode(jsUndefined()); +} + JSC_DEFINE_CUSTOM_SETTER(setterPath, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, JSC::PropertyName propertyName)) @@ -331,16 +358,24 @@ JSC_DEFINE_CUSTOM_SETTER(setterId, thisObject->m_id.set(globalObject->vm(), thisObject, JSValue::decode(value).toString(globalObject)); return true; } +JSC_DEFINE_CUSTOM_SETTER(setterParent, + (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, + JSC::EncodedJSValue value, JSC::PropertyName propertyName)) +{ + JSCommonJSModule* thisObject = jsDynamicCast<JSCommonJSModule*>(JSValue::decode(thisValue)); + if (!thisObject) + return false; + + thisObject->m_parent.set(globalObject->vm(), thisObject, JSValue::decode(value)); + + return true; +} static JSValue createLoaded(VM& vm, JSObject* object) { JSCommonJSModule* cjs = jsCast<JSCommonJSModule*>(object); return jsBoolean(cjs->hasEvaluated); } -static JSValue createParent(VM& vm, JSObject* object) -{ - return jsUndefined(); -} static JSValue createChildren(VM& vm, JSObject* object) { return constructEmptyArray(object->globalObject(), nullptr, 0); @@ -404,14 +439,14 @@ JSC_DEFINE_HOST_FUNCTION(functionCommonJSModuleRecord_compile, (JSGlobalObject * } static const struct HashTableValue JSCommonJSModulePrototypeTableValues[] = { - { "children"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback | PropertyAttribute::DontEnum | 0), NoIntrinsic, { HashTableValue::LazyPropertyType, createChildren } }, + { "_compile"_s, static_cast<unsigned>(PropertyAttribute::Function | PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::NativeFunctionType, functionCommonJSModuleRecord_compile, 2 } }, + { "children"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, createChildren } }, { "filename"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterFilename, setterFilename } }, { "id"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterId, setterId } }, - { "loaded"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback | PropertyAttribute::DontEnum | 0), NoIntrinsic, { HashTableValue::LazyPropertyType, createLoaded } }, - { "parent"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback | PropertyAttribute::DontEnum | 0), NoIntrinsic, { HashTableValue::LazyPropertyType, createParent } }, + { "loaded"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, createLoaded } }, + { "parent"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor | PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, getterParent, setterParent } }, { "path"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterPath, setterPath } }, { "paths"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterPaths, setterPaths } }, - { "_compile"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionCommonJSModuleRecord_compile, 2 } }, }; class JSCommonJSModulePrototype final : public JSC::JSNonFinalObject { @@ -499,23 +534,23 @@ JSCommonJSModule* JSCommonJSModule::create( JSC_DEFINE_HOST_FUNCTION(jsFunctionCreateCommonJSModule, (JSGlobalObject * globalObject, CallFrame* callframe)) { auto& vm = globalObject->vm(); + RELEASE_ASSERT(callframe->argumentCount() == 4); - auto id = callframe->argument(0).toWTFString(globalObject); + auto id = callframe->uncheckedArgument(0).toWTFString(globalObject); + JSValue object = callframe->uncheckedArgument(1); + JSValue hasEvaluated = callframe->uncheckedArgument(2); + ASSERT(hasEvaluated.isBoolean()); + JSValue parent = callframe->uncheckedArgument(3); - JSValue object = callframe->argument(1); - - return JSValue::encode( - JSCommonJSModule::create( - jsCast<Zig::GlobalObject*>(globalObject), - id, - object, callframe->argument(2).isBoolean() && callframe->argument(2).asBoolean())); + return JSValue::encode(JSCommonJSModule::create(jsCast<Zig::GlobalObject*>(globalObject), id, object, hasEvaluated.isTrue(), parent)); } JSCommonJSModule* JSCommonJSModule::create( Zig::GlobalObject* globalObject, const WTF::String& key, JSValue exportsObject, - bool hasEvaluated) + bool hasEvaluated, + JSValue parent) { auto& vm = globalObject->vm(); JSString* requireMapKey = JSC::jsStringWithCache(vm, key); @@ -530,8 +565,14 @@ JSCommonJSModule* JSCommonJSModule::create( globalObject->CommonJSModuleObjectStructure(), requireMapKey, requireMapKey, dirname, nullptr); - out->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), exportsObject, exportsObject.isCell() && exportsObject.isCallable() ? JSC::PropertyAttribute::Function | 0 : 0); + out->putDirect( + vm, + WebCore::clientData(vm)->builtinNames().exportsPublicName(), + exportsObject, + exportsObject.isCallable() ? JSC::PropertyAttribute::Function | 0 : 0); out->hasEvaluated = hasEvaluated; + out->m_parent.set(vm, out, parent); + return out; } diff --git a/src/bun.js/bindings/CommonJSModuleRecord.h b/src/bun.js/bindings/CommonJSModuleRecord.h index e38d2e083..14d045478 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.h +++ b/src/bun.js/bindings/CommonJSModuleRecord.h @@ -22,11 +22,12 @@ public: using Base = JSC::JSDestructibleObject; static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::OverridesPut; - mutable JSC::WriteBarrier<JSC::JSString> m_id; - mutable JSC::WriteBarrier<JSC::Unknown> m_filename; - mutable JSC::WriteBarrier<JSC::JSString> m_dirname; + mutable JSC::WriteBarrier<JSString> m_id; + mutable JSC::WriteBarrier<Unknown> m_filename; + mutable JSC::WriteBarrier<JSString> m_dirname; mutable JSC::WriteBarrier<Unknown> m_paths; - mutable JSC::WriteBarrier<JSC::JSSourceCode> sourceCode; + mutable JSC::WriteBarrier<Unknown> m_parent; + mutable JSC::WriteBarrier<JSSourceCode> sourceCode; bool ignoreESModuleAnnotation { false }; static void destroy(JSC::JSCell*); @@ -54,8 +55,7 @@ public: static JSCommonJSModule* create( Zig::GlobalObject* globalObject, const WTF::String& key, - JSValue exportsObject, - bool hasEvaluated = false); + JSValue exportsObject, bool hasEvaluated, JSValue parent); static JSCommonJSModule* create( Zig::GlobalObject* globalObject, diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index 252c446b1..acda70e0a 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -27,7 +27,6 @@ #include "EventEmitter.h" #include "JSEventEmitter.h" -#include "CommonJSModuleRecord.h" #include <JavaScriptCore/JSModuleLoader.h> #include <JavaScriptCore/Completion.h> #include <JavaScriptCore/JSModuleNamespaceObject.h> diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index f3abd0f2d..54fb58776 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -1331,7 +1331,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBTOA, static_cast<uint8_t>(WebCore::BufferEncodingType::base64))); } -static JSC_DEFINE_HOST_FUNCTION(functionATOB, +JSC_DEFINE_HOST_FUNCTION(functionATOB, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { JSC::VM& vm = globalObject->vm(); @@ -1354,7 +1354,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionATOB, RELEASE_AND_RETURN(throwScope, JSValue::encode(jsString(vm, result.releaseReturnValue()))); } -static JSC_DEFINE_HOST_FUNCTION(functionReportError, +JSC_DEFINE_HOST_FUNCTION(functionReportError, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { switch (callFrame->argumentCount()) { @@ -1636,7 +1636,7 @@ JSC_DEFINE_HOST_FUNCTION(jsReceiveMessageOnPort, (JSGlobalObject * lexicalGlobal // we're trying out a new way to do this lazy loading // this is $lazy() in js code -static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, +JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { @@ -3353,7 +3353,7 @@ JSC_DEFINE_CUSTOM_GETTER(BunCommonJSModule_getter, (JSGlobalObject * globalObjec // This implementation works the same as setTimeout(myFunction, 0) // TODO: make it more efficient // https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate -static JSC_DEFINE_HOST_FUNCTION(functionSetImmediate, +JSC_DEFINE_HOST_FUNCTION(functionSetImmediate, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { JSC::VM& vm = globalObject->vm(); diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index cffb9f0c9..e4fb9d624 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -298,7 +298,7 @@ CPP_DECL void JSC__JSMap__set(JSC__JSMap* arg0, JSC__JSGlobalObject* arg1, JSC__ #pragma mark - JSC::JSValue -CPP_DECL void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2, JSC__JSValue(* ArgFn3)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1), JSC__JSValue(* ArgFn4)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)) __attribute__((nonnull (3, 4))); +CPP_DECL void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2, JSC__JSValue(* ArgFn3)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1), JSC__JSValue(* ArgFn4)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)); CPP_DECL bool JSC__JSValue__asArrayBuffer_(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, Bun__ArrayBuffer* arg2); CPP_DECL unsigned char JSC__JSValue__asBigIntCompare(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2); CPP_DECL JSC__JSCell* JSC__JSValue__asCell(JSC__JSValue JSValue0); diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index c0b22a6ec..caa7d3cd8 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -308,6 +308,10 @@ pub export fn Bun__Process__send( } } +pub export fn Bun__isBunMain(globalObject: *JSGlobalObject, input_ptr: [*]const u8, input_len: usize) bool { + return strings.eql(globalObject.bunVM().main, input_ptr[0..input_len]); +} + pub export fn Bun__Process__disconnect( globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame, |