diff options
Diffstat (limited to 'src/bun.js/bindings/ImportMetaObject.cpp')
-rw-r--r-- | src/bun.js/bindings/ImportMetaObject.cpp | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp new file mode 100644 index 000000000..dc4290c91 --- /dev/null +++ b/src/bun.js/bindings/ImportMetaObject.cpp @@ -0,0 +1,249 @@ +#include "root.h" +#include "ImportMetaObject.h" +#include "ZigGlobalObject.h" +#include "ActiveDOMObject.h" +#include "ExtendedDOMClientIsoSubspaces.h" +#include "ExtendedDOMIsoSubspaces.h" +#include "IDLTypes.h" +// #include "JSBlob.h" +#include "JSDOMAttribute.h" +#include "JSDOMBinding.h" +#include "JSDOMConstructor.h" +#include "JSDOMConvertBase.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObject.h" +#include "JSDOMGlobalObjectInlines.h" +#include "JSDOMOperation.h" +#include "JSDOMWrapperCache.h" +#include "ScriptExecutionContext.h" +#include "WebCoreJSClientData.h" +#include "JavaScriptCore/FunctionPrototype.h" +#include "JavaScriptCore/HeapAnalyzer.h" + +#include "JavaScriptCore/JSDestructibleObjectHeapCellType.h" +#include "JavaScriptCore/SlotVisitorMacros.h" +#include "JavaScriptCore/SubspaceInlines.h" +#include "wtf/GetPtr.h" +#include "wtf/PointerPreparations.h" +#include "wtf/URL.h" +#include "JavaScriptCore/BuiltinNames.h" + +#include "JSBufferEncodingType.h" +#include "JSBufferPrototypeBuiltins.h" +#include "JSBufferConstructorBuiltins.h" +#include "JavaScriptCore/JSBase.h" + +namespace Zig { +using namespace JSC; +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 JSC_DECLARE_HOST_FUNCTION(functionImportMeta__resolveSync); + +static JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolveSync, + (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + 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.resolveSync 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, "import.meta.resolveSync expects a string"_s); + scope.release(); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + JSC__JSValue from; + + 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); + } + } + } + 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())); + } + + 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; + } + } +} + +static JSC_DECLARE_HOST_FUNCTION(functionImportMeta__resolve); + +static JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve, + (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + 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); + + if (moduleName.isUndefinedOrNull()) { + 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__JSValue from; + + if (callFrame->argumentCount() > 1) { + from = JSC::JSValue::encode(callFrame->argument(1)); + } 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 clientData = WebCore::clientData(vm); + + from = JSC::JSValue::encode(thisObject->get(globalObject, clientData->builtinNames().pathPublicName())); + } + + return Bun__resolve(globalObject, JSC::JSValue::encode(moduleName), from); + } + } +} + +class ImportMetaObjectPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + + static ImportMetaObjectPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + ImportMetaObjectPrototype* ptr = new (NotNull, JSC::allocateCell<ImportMetaObjectPrototype>(vm)) ImportMetaObjectPrototype(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + 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) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + ImportMetaObjectPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ImportMetaObjectPrototype, ImportMetaObjectPrototype::Base); + +JSObject* ImportMetaObject::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return ImportMetaObjectPrototype::create(vm, &globalObject, ImportMetaObjectPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); +} + +void ImportMetaObjectPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject_) +{ + Base::finishCreation(vm); + auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject_); + auto clientData = WebCore::clientData(vm); + + this->putDirect(vm, clientData->builtinNames().filePublicName(), jsEmptyString(vm), 0); + this->putDirect(vm, clientData->builtinNames().dirPublicName(), jsEmptyString(vm), 0); + 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); + this->putDirectBuiltinFunction(vm, globalObject, + clientData->builtinNames().loadModulePublicName(), importMetaObjectLoadModuleCodeGenerator(vm), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | 0); + this->putDirectBuiltinFunction(vm, globalObject, + clientData->builtinNames().requireModulePublicName(), importMetaObjectRequireModuleCodeGenerator(vm), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | 0); + + this->putDirectNativeFunction(vm, globalObject, clientData->builtinNames().resolvePublicName(), 1, + functionImportMeta__resolve, + NoIntrinsic, + JSC::PropertyAttribute::Function | 0); + this->putDirectNativeFunction( + vm, globalObject, clientData->builtinNames().resolveSyncPublicName(), + 1, + functionImportMeta__resolveSync, + NoIntrinsic, + JSC::PropertyAttribute::Function | 0); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +void ImportMetaObject::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); +} + +void ImportMetaObject::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<ImportMetaObject*>(cell); + // if (void* wrapped = thisObject->wrapped()) { + // if (thisObject->scriptExecutionContext()) + // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + // } + 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) }; + +} |