aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/ImportMetaObject.cpp
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-07-11 19:14:34 -0700
committerGravatar GitHub <noreply@github.com> 2023-07-11 19:14:34 -0700
commitcbb88672f217a90db1aa1eb29cd92d5d9035b22b (patch)
tree43a00501f3cde495967e116f0b660777051551f8 /src/bun.js/bindings/ImportMetaObject.cpp
parent1f900cff453700b19bca2acadfe26da4468c1282 (diff)
parent34b0e7a2bbd8bf8097341cdb0075d0908283e834 (diff)
downloadbun-jarred/esm-conditions.tar.gz
bun-jarred/esm-conditions.tar.zst
bun-jarred/esm-conditions.zip
Merge branch 'main' into jarred/esm-conditionsjarred/esm-conditions
Diffstat (limited to 'src/bun.js/bindings/ImportMetaObject.cpp')
-rw-r--r--src/bun.js/bindings/ImportMetaObject.cpp597
1 files changed, 402 insertions, 195 deletions
diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp
index a53712823..037305c81 100644
--- a/src/bun.js/bindings/ImportMetaObject.cpp
+++ b/src/bun.js/bindings/ImportMetaObject.cpp
@@ -38,6 +38,9 @@
#include "JSDOMURL.h"
#include "JavaScriptCore/JSNativeStdFunction.h"
#include "JavaScriptCore/GetterSetter.h"
+#include <JavaScriptCore/LazyProperty.h>
+#include <JavaScriptCore/LazyPropertyInlines.h>
+#include <JavaScriptCore/VMTrapsInlines.h>
namespace Zig {
using namespace JSC;
@@ -56,6 +59,7 @@ static EncodedJSValue functionRequireResolve(JSC::JSGlobalObject* globalObject,
return JSC::JSValue::encode(JSC::JSValue {});
}
default: {
+ JSValue thisValue = callFrame->thisValue();
JSC::JSValue moduleName = callFrame->argument(0);
auto doIt = [&](const WTF::String& fromStr) -> JSC::EncodedJSValue {
@@ -83,10 +87,12 @@ static EncodedJSValue functionRequireResolve(JSC::JSGlobalObject* globalObject,
// require.resolve also supports a paths array
// we only support a single path
if (!fromValue.isUndefinedOrNull() && fromValue.isObject()) {
- if (JSValue pathsValue = fromValue.getObject()->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "paths"_s))) {
- if (JSC::JSArray* array = JSC::jsDynamicCast<JSC::JSArray*>(pathsValue)) {
- if (array->length() > 0) {
- fromValue = array->getIndex(globalObject, 0);
+ 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 {}));
}
}
}
@@ -123,216 +129,265 @@ Zig::ImportMetaObject* Zig::ImportMetaObject::create(JSC::JSGlobalObject* global
}
JSC_DECLARE_HOST_FUNCTION(jsFunctionRequireResolve);
+JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireResolve, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
+{
+ JSValue thisValue = callFrame->thisValue();
+ WTF::String fromStr;
-class JSRequireResolveFunctionPrototype final : public JSC::InternalFunction {
-public:
- using Base = JSC::InternalFunction;
-
- static JSRequireResolveFunctionPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
- {
- auto* structure = createStructure(vm, globalObject, globalObject->functionPrototype());
- JSRequireResolveFunctionPrototype* function = new (NotNull, JSC::allocateCell<JSRequireResolveFunctionPrototype>(vm)) JSRequireResolveFunctionPrototype(vm, structure);
- function->finishCreation(vm);
- return function;
+ if (thisValue.isString()) {
+ fromStr = thisValue.toWTFString(globalObject);
}
- static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
- {
- return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info());
- }
+ return functionRequireResolve(globalObject, callFrame, fromStr);
+}
- DECLARE_INFO;
+JSC_DEFINE_CUSTOM_GETTER(jsRequireCacheGetter, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
+{
+ Zig::GlobalObject* thisObject = jsCast<Zig::GlobalObject*>(globalObject);
+ return JSValue::encode(thisObject->lazyRequireCacheObject());
+}
+
+JSC_DEFINE_CUSTOM_SETTER(jsRequireCacheSetter,
+ (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName propertyName))
+{
+ JSObject* thisObject = jsDynamicCast<JSObject*>(JSValue::decode(thisValue));
+ if (!thisObject)
+ return false;
+
+ thisObject->putDirect(globalObject->vm(), propertyName, JSValue::decode(value), 0);
+ return true;
+}
- static JSC::EncodedJSValue pathsFunction(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
+JSC_DEFINE_HOST_FUNCTION(requireResolvePathsFunction, (JSGlobalObject * globalObject, CallFrame* callframe))
+{
+ return JSValue::encode(JSC::constructEmptyArray(globalObject, nullptr, 0));
+}
+
+static const HashTableValue RequireResolveFunctionPrototypeValues[] = {
+ { "paths"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, requireResolvePathsFunction, 1 } },
+};
+
+class RequireResolveFunctionPrototype final : public JSC::JSNonFinalObject {
+public:
+ using Base = JSC::JSNonFinalObject;
+ static RequireResolveFunctionPrototype* create(
+ JSC::JSGlobalObject* globalObject)
{
- return JSValue::encode(JSC::constructEmptyArray(globalObject, nullptr));
+ auto& vm = globalObject->vm();
+
+ auto* structure = RequireResolveFunctionPrototype::createStructure(vm, globalObject, globalObject->functionPrototype());
+ RequireResolveFunctionPrototype* prototype = new (NotNull, JSC::allocateCell<RequireResolveFunctionPrototype>(vm)) RequireResolveFunctionPrototype(vm, structure);
+ prototype->finishCreation(vm);
+ return prototype;
}
-private:
- JSRequireResolveFunctionPrototype(JSC::VM& vm, JSC::Structure* structure)
- : JSC::InternalFunction(vm, structure, jsFunctionRequireResolve, jsFunctionRequireResolve)
+ DECLARE_INFO;
+ RequireResolveFunctionPrototype(
+ JSC::VM& vm,
+ JSC::Structure* structure)
+ : Base(vm, structure)
{
}
- void finishCreation(JSC::VM& vm)
+ template<typename CellType, JSC::SubspaceAccess>
+ static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
- this->putDirectNativeFunction(vm, globalObject(), Identifier::fromString(vm, "paths"_s), 0, pathsFunction, ImplementationVisibility::Public, NoIntrinsic, 0);
- Base::finishCreation(vm, 2, "resolve"_s, PropertyAdditionMode::WithoutStructureTransition);
+ return &vm.plainObjectSpace();
}
};
-const JSC::ClassInfo JSRequireResolveFunctionPrototype::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSRequireResolveFunctionPrototype) };
+class ResolveFunction final : public JSC::InternalFunction {
-class JSRequireResolveFunction final : public JSC::InternalFunction {
public:
using Base = JSC::InternalFunction;
-
- static JSRequireResolveFunction* create(JSC::VM& vm, JSC::Structure* structure, const WTF::String& from)
- {
- JSRequireResolveFunction* function = new (NotNull, JSC::allocateCell<JSRequireResolveFunction>(vm)) JSRequireResolveFunction(vm, structure, from);
- function->finishCreation(vm);
- return function;
- }
-
- static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ static ResolveFunction* create(JSGlobalObject* globalObject)
{
- return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info());
+ JSObject* resolvePrototype = RequireResolveFunctionPrototype::create(globalObject);
+ Structure* structure = Structure::create(
+ globalObject->vm(),
+ globalObject,
+ resolvePrototype,
+ JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags),
+ ResolveFunction::info());
+ auto* resolveFunction = new (NotNull, JSC::allocateCell<ResolveFunction>(globalObject->vm())) ResolveFunction(globalObject->vm(), structure);
+ resolveFunction->finishCreation(globalObject->vm());
+ return resolveFunction;
}
DECLARE_INFO;
- WTF::String from;
-
- template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
- {
- if constexpr (mode == JSC::SubspaceAccess::Concurrently)
- return nullptr;
-
- return WebCore::subspaceForImpl<JSRequireResolveFunction, UseCustomHeapCellType::No>(
- vm,
- [](auto& spaces) { return spaces.m_clientSubspaceForRequireResolveFunction.get(); },
- [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForRequireResolveFunction = std::forward<decltype(space)>(space); },
- [](auto& spaces) { return spaces.m_subspaceForRequireResolveFunction.get(); },
- [](auto& spaces, auto&& space) { spaces.m_subspaceForRequireResolveFunction = std::forward<decltype(space)>(space); });
- }
-
-private:
- JSRequireResolveFunction(JSC::VM& vm, JSC::Structure* structure, const WTF::String& from_)
- : JSC::InternalFunction(vm, structure, jsFunctionRequireResolve, jsFunctionRequireResolve)
- , from(from_)
+ template<typename CellType, JSC::SubspaceAccess>
+ static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
+ return &vm.internalFunctionSpace();
}
- void finishCreation(JSC::VM& vm)
+ ResolveFunction(
+ JSC::VM& vm,
+ JSC::Structure* structure)
+ : InternalFunction(vm, structure, jsFunctionRequireResolve, nullptr)
{
- Base::finishCreation(vm);
}
};
-const JSC::ClassInfo JSRequireResolveFunction::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSRequireResolveFunction) };
-
-JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireResolve, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
+JSObject* Zig::ImportMetaObject::createRequireResolveFunctionUnbound(VM& vm, JSGlobalObject* globalObject)
{
- JSRequireResolveFunction* thisObject = JSC::jsCast<JSRequireResolveFunction*>(callFrame->jsCallee());
- return functionRequireResolve(globalObject, callFrame, thisObject->from);
+ return ResolveFunction::create(globalObject);
}
-JSValue Zig::ImportMetaObject::createResolveFunctionPrototype(JSC::VM& vm, Zig::GlobalObject* globalObject)
+JSObject* Zig::ImportMetaObject::createRequireFunctionUnbound(VM& vm, JSGlobalObject* globalObject)
{
- return JSRequireResolveFunctionPrototype::create(vm, globalObject);
-}
+ auto& builtinNames = WebCore::builtinNames(vm);
-JSC::Structure* Zig::ImportMetaObject::createResolveFunctionStructure(JSC::VM& vm, Zig::GlobalObject* globalObject)
-{
- JSValue prototype = globalObject->requireResolveFunctionPrototype();
- return JSRequireResolveFunction::createStructure(vm, globalObject, prototype);
-}
+ JSC::JSFunction* requireDotMainFunction = JSFunction::create(
+ vm,
+ moduleMainCodeGenerator(vm),
+ globalObject->globalScope());
-JSC_DEFINE_CUSTOM_GETTER(jsRequireCacheGetter, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
-{
- Zig::GlobalObject* thisObject = jsCast<Zig::GlobalObject*>(globalObject);
- return JSValue::encode(thisObject->lazyRequireCacheObject());
+ auto* prototype = JSC::constructEmptyObject(globalObject, globalObject->functionPrototype());
+ prototype->putDirect(
+ vm,
+ JSC::Identifier::fromString(vm, "main"_s),
+ JSC::GetterSetter::create(vm, globalObject, requireDotMainFunction, JSValue()),
+ PropertyAttribute::Builtin | PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | 0);
+ prototype->putDirect(vm, JSC::Identifier::fromString(vm, "extensions"_s), constructEmptyObject(globalObject), 0);
+ prototype->putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "cache"_s), JSC::CustomGetterSetter::create(vm, Zig::jsRequireCacheGetter, Zig::jsRequireCacheSetter), 0);
+ return JSFunction::create(vm, importMetaObjectRequireCodeGenerator(vm), globalObject, JSFunction::createStructure(vm, globalObject, prototype));
}
-JSC_DEFINE_CUSTOM_SETTER(jsRequireCacheSetter,
- (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
- JSC::EncodedJSValue value, JSC::PropertyName propertyName))
+JSObject* Zig::ImportMetaObject::createRequireFunction(VM& vm, JSGlobalObject* lexicalGlobalObject, const WTF::String& pathString)
{
- JSObject* thisObject = jsDynamicCast<JSObject*>(JSValue::decode(thisValue));
- if (!thisObject)
- return false;
+ auto* globalObject = jsCast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto& builtinNames = WebCore::builtinNames(vm);
- thisObject->putDirect(globalObject->vm(), propertyName, JSValue::decode(value), 0);
- return true;
-}
+ JSFunction* resolveFunctionUnbound = jsCast<JSFunction*>(globalObject->importMetaRequireResolveFunctionUnbound());
+ JSFunction* requireFunctionUnbound = jsCast<JSFunction*>(globalObject->importMetaRequireFunctionUnbound());
+ auto str = jsString(vm, pathString);
+
+ JSFunction* requireFunction = JSC::JSBoundFunction::create(vm,
+ globalObject, requireFunctionUnbound,
+ str, ArgList(), 1, jsString(vm, String("require"_s)));
+
+ JSFunction* resolveFunction = JSC::JSBoundFunction::create(vm,
+ globalObject, resolveFunctionUnbound,
+ str, ArgList(), 2, jsString(vm, String("resolve"_s)));
+
+ requireFunction->putDirect(vm, builtinNames.resolvePublicName(), resolveFunction, PropertyAttribute::Function | 0);
-JSObject* Zig::ImportMetaObject::createRequireFunction(VM& vm, JSGlobalObject* lexicalGlobalObject, const WTF::String& pathString)
-{
- Zig::GlobalObject* globalObject = static_cast<Zig::GlobalObject*>(lexicalGlobalObject);
- JSFunction* requireFunction = JSFunction::create(vm, importMetaObjectRequireCodeGenerator(vm), globalObject);
- auto* resolveFunction = JSRequireResolveFunction::create(vm, globalObject->requireResolveFunctionStructure(), pathString);
- auto clientData = WebCore::clientData(vm);
- requireFunction->putDirect(vm, clientData->builtinNames().pathPublicName(), jsString(vm, pathString), PropertyAttribute::DontEnum | 0);
- requireFunction->putDirect(vm, clientData->builtinNames().resolvePublicName(), resolveFunction, PropertyAttribute::Function | PropertyAttribute::DontDelete | 0);
- requireFunction->putDirectCustomAccessor(vm, Identifier::fromString(vm, "cache"_s), JSC::CustomGetterSetter::create(vm, jsRequireCacheGetter, jsRequireCacheSetter), 0);
return requireFunction;
}
+const JSC::ClassInfo RequireResolveFunctionPrototype::s_info = { "resolve"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(RequireResolveFunctionPrototype) };
+const JSC::ClassInfo ResolveFunction::s_info = { "resolve"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ResolveFunction) };
+
extern "C" EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
{
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
- switch (callFrame->argumentCount()) {
- case 0: {
+ JSValue thisValue = callFrame->thisValue();
+ JSC::JSValue moduleName = callFrame->argument(0);
+ JSC::JSValue fromValue = callFrame->argument(1);
- // not "requires" because "require" could be confusing
- JSC::throwTypeError(globalObject, scope, "import.meta.resolveSync needs 1 argument (a string)"_s);
+ if (moduleName.isUndefinedOrNull()) {
+ JSC::throwTypeError(globalObject, scope, "expects a string"_s);
scope.release();
return JSC::JSValue::encode(JSC::JSValue {});
}
- default: {
- JSC::JSValue moduleName = callFrame->argument(0);
- if (moduleName.isUndefinedOrNull()) {
- JSC::throwTypeError(globalObject, scope, "import.meta.resolveSync expects a string"_s);
- scope.release();
- return JSC::JSValue::encode(JSC::JSValue {});
- }
+ JSC__JSValue from;
+ bool isESM = true;
- JSC__JSValue from;
- bool isESM = true;
+ if (callFrame->argumentCount() > 1) {
- if (callFrame->argumentCount() > 1) {
- JSC::JSValue fromValue = callFrame->argument(1);
+ if (callFrame->argumentCount() > 2) {
+ JSC::JSValue isESMValue = callFrame->argument(2);
+ if (isESMValue.isBoolean()) {
+ isESM = isESMValue.toBoolean(globalObject);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {}));
+ }
+ }
- // 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);
- }
- }
+ if (!fromValue.isUndefinedOrNull() && fromValue.isObject()) {
- if (callFrame->argumentCount() > 2) {
- JSC::JSValue isESMValue = callFrame->argument(2);
- if (isESMValue.isBoolean()) {
- isESM = isESMValue.toBoolean(globalObject);
+ 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 {}));
}
}
- } else if (fromValue.isBoolean()) {
- isESM = fromValue.toBoolean(globalObject);
- RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {}));
- }
- from = JSC::JSValue::encode(fromValue);
-
- } 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.resolveSync must be bound to an import.meta object"_s);
- return JSC::JSValue::encode(JSC::JSValue {});
}
- auto clientData = WebCore::clientData(vm);
-
- from = JSC::JSValue::encode(thisObject->get(globalObject, clientData->builtinNames().pathPublicName()));
+ } else if (fromValue.isBoolean()) {
+ isESM = fromValue.toBoolean(globalObject);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {}));
+ fromValue = JSC::jsUndefined();
}
- auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from, isESM);
+ if (fromValue.isString()) {
+ from = JSC::JSValue::encode(fromValue);
+ } else if (thisValue.isString()) {
+ from = JSC::JSValue::encode(thisValue);
+ }
- if (!JSC::JSValue::decode(result).isString()) {
- JSC::throwException(globalObject, scope, JSC::JSValue::decode(result));
+ } else if (thisValue.isString()) {
+ from = JSC::JSValue::encode(thisValue);
+ } else {
+ JSC::JSObject* thisObject = JSC::jsDynamicCast<JSC::JSObject*>(thisValue);
+ if (UNLIKELY(!thisObject)) {
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ JSC::throwTypeError(globalObject, scope, "import.meta.resolveSync must be bound to an import.meta object"_s);
return JSC::JSValue::encode(JSC::JSValue {});
}
+ auto clientData = WebCore::clientData(vm);
+ JSValue pathProperty = thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().pathPublicName());
+
+ if (pathProperty && pathProperty.isString())
+ from = JSC::JSValue::encode(pathProperty);
+ }
+
+ auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), from, isESM);
+
+ if (!JSC::JSValue::decode(result).isString()) {
+ JSC::throwException(globalObject, scope, JSC::JSValue::decode(result));
+ return JSC::JSValue::encode(JSC::JSValue {});
+ }
+
+ scope.release();
+ return result;
+}
+
+extern "C" EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
+{
+ JSC::VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+
+ JSC::JSValue moduleName = callFrame->argument(0);
+ JSValue from = callFrame->argument(1);
+ bool isESM = callFrame->argument(2).asBoolean();
+
+ if (moduleName.isUndefinedOrNull()) {
+ JSC::throwTypeError(globalObject, scope, "expected module name as a string"_s);
scope.release();
- return result;
+ return JSC::JSValue::encode(JSC::JSValue {});
}
+
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {}));
+
+ auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), JSValue::encode(from), isESM);
+
+ 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_DECLARE_HOST_FUNCTION(functionImportMeta__resolve);
@@ -362,7 +417,7 @@ JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve,
JSC__JSValue from;
- if (callFrame->argumentCount() > 1) {
+ if (callFrame->argumentCount() > 1 && callFrame->argument(1).isString()) {
from = JSC::JSValue::encode(callFrame->argument(1));
} else {
JSC::JSObject* thisObject = JSC::jsDynamicCast<JSC::JSObject*>(callFrame->thisValue());
@@ -374,7 +429,7 @@ JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve,
auto clientData = WebCore::clientData(vm);
- from = JSC::JSValue::encode(thisObject->get(globalObject, clientData->builtinNames().pathPublicName()));
+ from = JSC::JSValue::encode(thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().pathPublicName()));
}
return Bun__resolve(globalObject, JSC::JSValue::encode(moduleName), from, true);
@@ -382,89 +437,244 @@ JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve,
}
}
+enum class ImportMetaPropertyOffset : uint32_t {
+ url,
+ dir,
+ file,
+ path,
+ require,
+
+};
+static constexpr uint32_t numberOfImportMetaProperties = 5;
+
+Zig::ImportMetaObject* ImportMetaObject::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, const WTF::String& url)
+{
+ ImportMetaObject* ptr = new (NotNull, JSC::allocateCell<ImportMetaObject>(vm)) ImportMetaObject(vm, structure, url);
+ ptr->finishCreation(vm);
+ return ptr;
+}
+Zig::ImportMetaObject* ImportMetaObject::create(JSC::JSGlobalObject* jslobalObject, JSC::JSString* keyString)
+{
+ auto* globalObject = jsCast<Zig::GlobalObject*>(jslobalObject);
+ auto& vm = globalObject->vm();
+ auto view = keyString->value(globalObject);
+ JSC::Structure* structure = globalObject->ImportMetaObjectStructure();
+ return Zig::ImportMetaObject::create(vm, globalObject, structure, view);
+}
+
+JSC_DEFINE_CUSTOM_GETTER(jsImportMetaObjectGetter_url, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName propertyName))
+{
+ ImportMetaObject* thisObject = jsDynamicCast<ImportMetaObject*>(JSValue::decode(thisValue));
+ if (UNLIKELY(!thisObject))
+ return JSValue::encode(jsUndefined());
+
+ return JSValue::encode(thisObject->urlProperty.getInitializedOnMainThread(thisObject));
+}
+JSC_DEFINE_CUSTOM_GETTER(jsImportMetaObjectGetter_dir, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName propertyName))
+{
+ ImportMetaObject* thisObject = jsDynamicCast<ImportMetaObject*>(JSValue::decode(thisValue));
+ if (UNLIKELY(!thisObject))
+ return JSValue::encode(jsUndefined());
+
+ return JSValue::encode(thisObject->dirProperty.getInitializedOnMainThread(thisObject));
+}
+JSC_DEFINE_CUSTOM_GETTER(jsImportMetaObjectGetter_file, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName propertyName))
+{
+ ImportMetaObject* thisObject = jsDynamicCast<ImportMetaObject*>(JSValue::decode(thisValue));
+ if (UNLIKELY(!thisObject))
+ return JSValue::encode(jsUndefined());
+
+ return JSValue::encode(thisObject->fileProperty.getInitializedOnMainThread(thisObject));
+}
+JSC_DEFINE_CUSTOM_GETTER(jsImportMetaObjectGetter_path, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName propertyName))
+{
+ ImportMetaObject* thisObject = jsDynamicCast<ImportMetaObject*>(JSValue::decode(thisValue));
+ if (UNLIKELY(!thisObject))
+ return JSValue::encode(jsUndefined());
+
+ return JSValue::encode(thisObject->pathProperty.getInitializedOnMainThread(thisObject));
+}
+JSC_DEFINE_CUSTOM_GETTER(jsImportMetaObjectGetter_require, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName propertyName))
+{
+ ImportMetaObject* thisObject = jsDynamicCast<ImportMetaObject*>(JSValue::decode(thisValue));
+ if (UNLIKELY(!thisObject))
+ return JSValue::encode(jsUndefined());
+
+ return JSValue::encode(thisObject->requireProperty.getInitializedOnMainThread(thisObject));
+}
+
+static const HashTableValue ImportMetaObjectPrototypeValues[] = {
+ { "resolve"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, functionImportMeta__resolve, 0 } },
+ { "resolveSync"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, functionImportMeta__resolveSync, 0 } },
+ { "url"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, jsImportMetaObjectGetter_url, 0 } },
+ { "dir"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, jsImportMetaObjectGetter_dir, 0 } },
+ { "file"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, jsImportMetaObjectGetter_file, 0 } },
+ { "path"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, jsImportMetaObjectGetter_path, 0 } },
+ { "require"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, jsImportMetaObjectGetter_require, 0 } },
+};
+
class ImportMetaObjectPrototype final : public JSC::JSNonFinalObject {
public:
+ DECLARE_INFO;
using Base = JSC::JSNonFinalObject;
- static ImportMetaObjectPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure)
+ static Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
{
- ImportMetaObjectPrototype* ptr = new (NotNull, JSC::allocateCell<ImportMetaObjectPrototype>(vm)) ImportMetaObjectPrototype(vm, globalObject, structure);
- ptr->finishCreation(vm, globalObject);
- return ptr;
+ return Structure::create(vm, globalObject, globalObject->objectPrototype(), TypeInfo(ObjectType, StructureFlags), info());
+ }
+
+ static ImportMetaObjectPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
+ {
+ ImportMetaObjectPrototype* prototype = new (NotNull, JSC::allocateCell<ImportMetaObjectPrototype>(vm)) ImportMetaObjectPrototype(vm, structure);
+ prototype->finishCreation(vm, globalObject);
+ return prototype;
}
- DECLARE_INFO;
template<typename CellType, JSC::SubspaceAccess>
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
return &vm.plainObjectSpace();
}
- static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+
+ void finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
{
- return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ Base::finishCreation(vm);
+
+ auto* clientData = WebCore::clientData(vm);
+ auto& builtinNames = clientData->builtinNames();
+
+ reifyStaticProperties(vm, ImportMetaObject::info(), ImportMetaObjectPrototypeValues, *this);
+ JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+
+ this->putDirect(
+ vm,
+ builtinNames.mainPublicName(),
+ GetterSetter::create(vm, globalObject, JSFunction::create(vm, importMetaObjectMainCodeGenerator(vm), globalObject), nullptr),
+ JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin | 0);
}
-private:
- ImportMetaObjectPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
+ ImportMetaObjectPrototype(JSC::VM& vm, JSC::Structure* structure)
: Base(vm, structure)
{
}
+};
+
+const ClassInfo ImportMetaObjectPrototype::s_info = {
+ "ImportMeta"_s,
- void finishCreation(JSC::VM&, JSC::JSGlobalObject*);
+ Base::info(), nullptr, nullptr, CREATE_METHOD_TABLE(ImportMetaObjectPrototype)
};
-STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ImportMetaObjectPrototype, ImportMetaObjectPrototype::Base);
-JSObject* ImportMetaObject::createPrototype(VM& vm, JSDOMGlobalObject& globalObject)
+JSC::Structure* ImportMetaObject::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
{
- return ImportMetaObjectPrototype::create(vm, &globalObject, ImportMetaObjectPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype()));
-}
+ ImportMetaObjectPrototype* prototype = ImportMetaObjectPrototype::create(vm,
+ globalObject,
+ ImportMetaObjectPrototype::createStructure(vm, globalObject));
-void ImportMetaObjectPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject_)
-{
- Base::finishCreation(vm);
- auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject_);
auto clientData = WebCore::clientData(vm);
-
auto& builtinNames = clientData->builtinNames();
- this->putDirect(vm, builtinNames.filePublicName(), jsEmptyString(vm), 0);
- this->putDirect(vm, builtinNames.dirPublicName(), jsEmptyString(vm), 0);
- this->putDirect(vm, builtinNames.pathPublicName(), jsEmptyString(vm), 0);
- this->putDirect(vm, builtinNames.urlPublicName(), jsEmptyString(vm), 0);
-
- this->putDirect(
- vm,
- builtinNames.mainPublicName(),
- GetterSetter::create(vm, globalObject, JSFunction::create(vm, importMetaObjectMainCodeGenerator(vm), globalObject), nullptr),
- JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin | 0);
-
- this->putDirect(vm, Identifier::fromString(vm, "primordials"_s), jsUndefined(), JSC::PropertyAttribute::DontEnum | 0);
-
- String requireString = "[[require]]"_s;
- this->putDirect(vm, builtinNames.requirePublicName(), Zig::ImportMetaObject::createRequireFunction(vm, globalObject, requireString), PropertyAttribute::Builtin | PropertyAttribute::Function | 0);
-
- this->putDirectNativeFunction(vm, globalObject, builtinNames.resolvePublicName(), 1,
- functionImportMeta__resolve,
- ImplementationVisibility::Public,
- NoIntrinsic,
- JSC::PropertyAttribute::Function | 0);
- this->putDirectNativeFunction(
- vm, globalObject, builtinNames.resolveSyncPublicName(),
- 1,
- functionImportMeta__resolveSync,
- ImplementationVisibility::Public,
- NoIntrinsic,
- JSC::PropertyAttribute::Function | 0);
-
- JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), ImportMetaObject::info());
}
void ImportMetaObject::finishCreation(VM& vm)
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
+
+ this->requireProperty.initLater([](const JSC::LazyProperty<JSC::JSObject, JSC::JSFunction>::Initializer& init) {
+ ImportMetaObject* meta = jsCast<ImportMetaObject*>(init.owner);
+
+ WTF::URL url = meta->url.startsWith('/') ? WTF::URL::fileURLWithFileSystemPath(meta->url) : WTF::URL(meta->url);
+ WTF::StringView path;
+ if (url.protocolIs("file"_s)) {
+ path = url.fileSystemPath();
+ } else {
+ path = url.path();
+ }
+
+ JSFunction* value = jsCast<JSFunction*>(ImportMetaObject::createRequireFunction(init.vm, meta->globalObject(), path.toString()));
+ init.set(value);
+ });
+ this->urlProperty.initLater([](const JSC::LazyProperty<JSC::JSObject, JSC::JSString>::Initializer& init) {
+ ImportMetaObject* meta = jsCast<ImportMetaObject*>(init.owner);
+ WTF::URL url = meta->url.startsWith('/') ? WTF::URL::fileURLWithFileSystemPath(meta->url) : WTF::URL(meta->url);
+
+ init.set(jsString(init.vm, url.string()));
+ });
+ this->dirProperty.initLater([](const JSC::LazyProperty<JSC::JSObject, JSC::JSString>::Initializer& init) {
+ ImportMetaObject* meta = jsCast<ImportMetaObject*>(init.owner);
+
+ WTF::URL url = meta->url.startsWith('/') ? WTF::URL::fileURLWithFileSystemPath(meta->url) : WTF::URL(meta->url);
+ WTF::StringView dirname;
+
+ if (url.protocolIs("file"_s)) {
+ dirname = url.fileSystemPath();
+ } else {
+ dirname = url.path();
+ }
+
+ if (dirname.endsWith("/"_s)) {
+ dirname = dirname.substring(0, dirname.length() - 1);
+ } else if (dirname.contains('/')) {
+ dirname = dirname.substring(0, dirname.reverseFind('/'));
+ }
+
+ init.set(jsString(init.vm, dirname.toString()));
+ });
+ this->fileProperty.initLater([](const JSC::LazyProperty<JSC::JSObject, JSC::JSString>::Initializer& init) {
+ ImportMetaObject* meta = jsCast<ImportMetaObject*>(init.owner);
+
+ WTF::URL url = meta->url.startsWith('/') ? WTF::URL::fileURLWithFileSystemPath(meta->url) : WTF::URL(meta->url);
+ WTF::StringView path;
+ if (url.protocolIs("file"_s)) {
+ path = url.fileSystemPath();
+ } else {
+ path = url.path();
+ }
+
+ WTF::StringView filename;
+
+ if (path.endsWith("/"_s)) {
+ filename = path.substring(path.reverseFind('/', path.length() - 2) + 1);
+ } else {
+ filename = path.substring(path.reverseFind('/') + 1);
+ }
+
+ init.set(jsString(init.vm, filename.toString()));
+ });
+ this->pathProperty.initLater([](const JSC::LazyProperty<JSC::JSObject, JSC::JSString>::Initializer& init) {
+ ImportMetaObject* meta = jsCast<ImportMetaObject*>(init.owner);
+
+ WTF::URL url = meta->url.startsWith('/') ? WTF::URL::fileURLWithFileSystemPath(meta->url) : WTF::URL(meta->url);
+ WTF::StringView path;
+
+ if (url.protocolIs("file"_s)) {
+ path = url.fileSystemPath();
+ } else {
+ path = url.path();
+ }
+
+ init.set(jsString(init.vm, path.toString()));
+ });
+}
+
+template<typename Visitor>
+void ImportMetaObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ ImportMetaObject* fn = jsCast<ImportMetaObject*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(fn, info());
+ Base::visitChildren(fn, visitor);
+
+ fn->requireProperty.visit(visitor);
+ fn->urlProperty.visit(visitor);
+ fn->dirProperty.visit(visitor);
+ fn->fileProperty.visit(visitor);
+ fn->pathProperty.visit(visitor);
}
+DEFINE_VISIT_CHILDREN(ImportMetaObject);
+
void ImportMetaObject::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
{
auto* thisObject = jsCast<ImportMetaObject*>(cell);
@@ -475,9 +685,6 @@ void ImportMetaObject::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
Base::analyzeHeap(cell, analyzer);
}
-const JSC::ClassInfo ImportMetaObjectPrototype::s_info = { "ImportMeta"_s, &Base::s_info, nullptr, nullptr,
- CREATE_METHOD_TABLE(ImportMetaObjectPrototype) };
-
const JSC::ClassInfo ImportMetaObject::s_info = { "ImportMeta"_s, &Base::s_info, nullptr, nullptr,
CREATE_METHOD_TABLE(ImportMetaObject) };
}