aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/javascript/jsc/bindings/napi.cpp209
-rw-r--r--src/javascript/jsc/bindings/napi.h55
-rw-r--r--src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h1
-rw-r--r--src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h1
-rw-r--r--src/napi/napi.zig45
5 files changed, 220 insertions, 91 deletions
diff --git a/src/javascript/jsc/bindings/napi.cpp b/src/javascript/jsc/bindings/napi.cpp
index b7e2c8403..5ec8bb6b2 100644
--- a/src/javascript/jsc/bindings/napi.cpp
+++ b/src/javascript/jsc/bindings/napi.cpp
@@ -49,6 +49,9 @@
using namespace JSC;
using namespace Zig;
+// #include <csignal>
+#define NAPI_OBJECT_EXPECTED napi_object_expected
+
class NapiRefWeakHandleOwner final : public JSC::WeakHandleOwner {
public:
void finalize(JSC::Handle<JSC::Unknown>, void* context) final
@@ -140,7 +143,7 @@ static uint32_t getPropertyAttributes(napi_property_attributes attributes)
}
if (!(attributes & napi_key_writable)) {
- result |= JSC::PropertyAttribute::ReadOnly;
+ // result |= JSC::PropertyAttribute::ReadOnly;
}
return result;
@@ -150,9 +153,9 @@ static uint32_t getPropertyAttributes(napi_property_descriptor prop)
{
uint32_t result = getPropertyAttributes(prop.attributes);
- if (!(prop.getter && !prop.setter)) {
- result |= JSC::PropertyAttribute::ReadOnly;
- }
+ // if (!(prop.getter && !prop.setter)) {
+ // result |= JSC::PropertyAttribute::ReadOnly;
+ // }
if (prop.method) {
result |= JSC::PropertyAttribute::Function;
@@ -161,13 +164,13 @@ static uint32_t getPropertyAttributes(napi_property_descriptor prop)
return result;
}
-const ClassInfo NapiClass::s_info = { "Function"_s, &NapiClass::Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(NapiClass) };
-
-static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* to, napi_property_descriptor property)
+static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* to, void* inheritedDataPtr, napi_property_descriptor property, bool isInstance)
{
JSC::VM& vm = globalObject->vm();
void* dataPtr = property.data;
- auto is_static = !!(property.attributes & napi_static);
+ if (!dataPtr) {
+ dataPtr = inheritedDataPtr;
+ }
WTF::String nameStr;
if (property.utf8name != nullptr) {
nameStr = WTF::String::fromUTF8(property.utf8name);
@@ -182,30 +185,39 @@ static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* t
function->dataPtr = dataPtr;
JSC::JSValue value = JSC::JSValue(function);
- to->putDirect(vm, Identifier::fromString(vm, nameStr), value, getPropertyAttributes(property));
+ to->putDirect(vm, propertyName, value, getPropertyAttributes(property));
return;
}
if (property.getter != nullptr || property.setter != nullptr) {
- JSC::JSValue getter = {};
- JSC::JSValue setter = {};
+ JSC::JSObject* getter = nullptr;
+ JSC::JSObject* setter = nullptr;
if (property.getter) {
auto callGetter = property.getter;
auto function = Zig::JSFFIFunction::create(vm, globalObject, 0, nameStr, reinterpret_cast<Zig::FFIFunction>(property.getter));
function->dataPtr = dataPtr;
- getter = JSC::JSValue(function);
+
+ // if (isInstance) {
+ // getter = JSBoundFunction::create(vm, globalObject, to, function, nullptr, 0, nullptr);
+ // } else {
+ getter = function;
+ // }
}
if (property.setter) {
auto callGetter = property.setter;
auto function = Zig::JSFFIFunction::create(vm, globalObject, 1, nameStr, reinterpret_cast<Zig::FFIFunction>(property.setter));
function->dataPtr = dataPtr;
- getter = JSC::JSValue(function);
+ // if (isInstance) {
+ // setter = JSBoundFunction::create(vm, globalObject, to, function, nullptr, 1, nullptr);
+ // } else {
+ setter = function;
+ // }
}
auto getterSetter = JSC::GetterSetter::create(vm, globalObject, getter, setter);
- to->putDirect(vm, propertyName, getterSetter, getPropertyAttributes(property) | JSC::PropertyAttribute::Accessor);
+ to->putDirect(vm, propertyName, getterSetter, getPropertyAttributes(property));
} else {
// TODO: is dataPtr allowed when given a value?
@@ -268,27 +280,29 @@ extern "C" napi_status napi_wrap(napi_env env,
napi_ref* result)
{
if (!toJS(js_object).isObject()) {
- return napi_object_expected;
+ return napi_arraybuffer_expected;
}
auto* globalObject = toJS(env);
auto& vm = globalObject->vm();
- auto* val = toJS(js_object).getObject();
+ auto* val = jsDynamicCast<NapiPrototype*>(toJS(js_object));
auto clientData = WebCore::clientData(vm);
+ auto* ref = new NapiRef(globalObject, 0);
+ ref->weakValueRef.setObject(val, weakValueHandleOwner(), ref);
+
+ if (finalize_cb) {
+ ref->finalizer.finalize_cb = finalize_cb;
+ ref->finalizer.finalize_hint = finalize_hint;
+ }
+
if (native_object) {
- uintptr_t ref_ptr = reinterpret_cast<uintptr_t>(native_object);
- double ref_double = bitwise_cast<double>(ref_ptr);
- val->putDirect(vm, clientData->builtinNames().passwordPrivateName(), JSC::jsNumber(ref_double), JSC::PropertyAttribute::DontEnum | 0);
+ ref->data = native_object;
}
+ val->napiRef = ref;
+
if (result) {
- auto* ref = new NapiRef(globalObject, 0);
- auto clientData = WebCore::clientData(vm);
- if (finalize_cb) {
- ref->finalizer.finalize_cb = finalize_cb;
- ref->finalizer.finalize_hint = finalize_hint;
- }
*result = reinterpret_cast<napi_ref>(ref);
}
@@ -298,22 +312,16 @@ extern "C" napi_status napi_wrap(napi_env env,
extern "C" napi_status napi_unwrap(napi_env env, napi_value js_object,
void** result)
{
- if (!toJS(js_object).isObject()) {
- return napi_object_expected;
- }
+ // if (!toJS(js_object).isObject()) {
+ // return NAPI_OBJECT_EXPECTED;
+ // }
auto* globalObject = toJS(env);
auto& vm = globalObject->vm();
- auto* object = toJS(js_object).getObject();
+ auto* object = JSC::jsDynamicCast<NapiPrototype*>(toJS(js_object));
auto clientData = WebCore::clientData(vm);
- if (result) {
- JSC::JSValue priv = object->getDirect(vm, clientData->builtinNames().passwordPrivateName());
- if (priv.isNumber()) {
- uintptr_t ref_ptr = bitwise_cast<uintptr_t>(priv.asNumber());
- *result = reinterpret_cast<void*>(ref_ptr);
- } else {
- *result = nullptr;
- }
+ if (object) {
+ *result = object->napiRef ? object->napiRef->data : nullptr;
}
return napi_ok;
@@ -323,7 +331,7 @@ extern "C" napi_status napi_create_function(napi_env env, const char* utf8name,
size_t length, napi_callback cb,
void* data, napi_value* result)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto name = WTF::String::fromUTF8(utf8name, length);
// std::cout << "napi_create_function: " << utf8name << std::endl;
@@ -343,7 +351,7 @@ extern "C" napi_status napi_get_cb_info(
napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
void** data)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto inputArgsCount = argc == nullptr ? 0 : *argc;
JSC::CallFrame* callFrame = reinterpret_cast<JSC::CallFrame*>(cbinfo);
@@ -364,15 +372,18 @@ extern "C" napi_status napi_get_cb_info(
}
}
+ JSC::JSValue thisValue = callFrame->thisValue();
+
if (this_arg != nullptr) {
- JSC::JSValue thisValue = callFrame->thisValue();
- *this_arg = reinterpret_cast<napi_value>(JSC::JSValue::encode(thisValue));
+ *this_arg = toNapi(thisValue);
}
if (data != nullptr) {
JSC::JSValue callee = JSC::JSValue(callFrame->jsCallee());
if (Zig::JSFFIFunction* ffiFunction = JSC::jsDynamicCast<Zig::JSFFIFunction*>(callee)) {
*data = reinterpret_cast<void*>(ffiFunction->dataPtr);
+ } else if (NapiPrototype* proto = JSC::jsDynamicCast<NapiPrototype*>(callee)) {
+ *data = proto->napiRef ? proto->napiRef->data : nullptr;
} else {
*data = nullptr;
}
@@ -385,17 +396,23 @@ extern "C" napi_status
napi_define_properties(napi_env env, napi_value object, size_t property_count,
const napi_property_descriptor* properties)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
- JSC::JSValue objectValue = JSC::JSValue(reinterpret_cast<JSC::EncodedJSValue>(object));
+ JSC::JSValue objectValue = toJS(object);
JSC::JSObject* objectObject = objectValue.getObject();
+
if (!objectObject) {
- return napi_object_expected;
+ return NAPI_OBJECT_EXPECTED;
+ }
+
+ void* inheritedDataPtr = nullptr;
+ if (NapiPrototype* proto = jsDynamicCast<NapiPrototype*>(objectValue)) {
+ inheritedDataPtr = proto->napiRef ? proto->napiRef->data : nullptr;
}
for (size_t i = 0; i < property_count; i++) {
- defineNapiProperty(globalObject, objectObject, properties[i]);
+ defineNapiProperty(globalObject, objectObject, inheritedDataPtr, properties[i], true);
}
return napi_ok;
@@ -405,7 +422,7 @@ extern "C" napi_status napi_throw_error(napi_env env,
const char* code,
const char* msg)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
@@ -424,10 +441,11 @@ extern "C" napi_status napi_create_reference(napi_env env, napi_value value,
JSC::JSValue val = toJS(value);
if (!val.isObject()) {
+
return napi_object_expected;
}
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto* ref = new NapiRef(toJS(env), initial_refcount);
@@ -446,10 +464,12 @@ extern "C" napi_status napi_create_reference(napi_env env, napi_value value,
}
}
- uintptr_t ref_ptr = reinterpret_cast<uintptr_t>(ref);
- double ref_double = bitwise_cast<double>(ref_ptr);
- val.getObject()->putDirect(vm, clientData->builtinNames().passwordPrivateName(), JSC::jsNumber(ref_double), JSC::PropertyAttribute::DontEnum | 0);
+ NapiPrototype* object = jsDynamicCast<NapiPrototype*>(val);
+ if (!object) {
+ return napi_invalid_arg;
+ }
+ object->napiRef = ref;
*result = toNapi(ref);
return napi_ok;
@@ -495,7 +515,7 @@ extern "C" napi_status napi_is_detached_arraybuffer(napi_env env,
napi_value arraybuffer,
bool* result)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
JSC::EncodedJSValue encodedValue = reinterpret_cast<JSC::EncodedJSValue>(arraybuffer);
@@ -518,7 +538,7 @@ extern "C" napi_status napi_is_detached_arraybuffer(napi_env env,
extern "C" napi_status napi_detach_arraybuffer(napi_env env,
napi_value arraybuffer)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
JSC::EncodedJSValue encodedValue = reinterpret_cast<JSC::EncodedJSValue>(arraybuffer);
@@ -545,7 +565,7 @@ extern "C" napi_status napi_detach_arraybuffer(napi_env env,
extern "C" napi_status napi_throw(napi_env env, napi_value error)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
@@ -557,7 +577,7 @@ extern "C" napi_status napi_throw(napi_env env, napi_value error)
extern "C" napi_status napi_throw_type_error(napi_env env, const char* code,
const char* msg)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
@@ -572,7 +592,7 @@ extern "C" napi_status napi_create_type_error(napi_env env, napi_value code,
napi_value msg,
napi_value* result)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
JSC::JSValue codeValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(code));
@@ -589,7 +609,7 @@ extern "C" napi_status napi_create_type_error(napi_env env, napi_value code,
extern "C" napi_status napi_throw_range_error(napi_env env, const char* code,
const char* msg)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
@@ -603,14 +623,14 @@ extern "C" napi_status napi_throw_range_error(napi_env env, const char* code,
extern "C" napi_status napi_object_freeze(napi_env env, napi_value object_value)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
JSC::EncodedJSValue encodedValue = reinterpret_cast<JSC::EncodedJSValue>(object_value);
JSC::JSValue value = JSC::JSValue::decode(encodedValue);
if (!value.isObject()) {
- return napi_object_expected;
+ return NAPI_OBJECT_EXPECTED;
}
JSC::JSObject* object = JSC::jsCast<JSC::JSObject*>(value);
@@ -622,7 +642,7 @@ extern "C" napi_status napi_object_freeze(napi_env env, napi_value object_value)
}
extern "C" napi_status napi_object_seal(napi_env env, napi_value object_value)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
@@ -630,7 +650,7 @@ extern "C" napi_status napi_object_seal(napi_env env, napi_value object_value)
JSC::JSValue value = JSC::JSValue::decode(encodedValue);
if (UNLIKELY(!value.isObject())) {
- return napi_object_expected;
+ return NAPI_OBJECT_EXPECTED;
}
JSC::JSObject* object = JSC::jsCast<JSC::JSObject*>(value);
@@ -643,7 +663,7 @@ extern "C" napi_status napi_object_seal(napi_env env, napi_value object_value)
extern "C" napi_status napi_get_global(napi_env env, napi_value* result)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
*result = reinterpret_cast<napi_value>(globalObject->globalThis());
return napi_ok;
@@ -653,7 +673,7 @@ extern "C" napi_status napi_create_range_error(napi_env env, napi_value code,
napi_value msg,
napi_value* result)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
JSC::EncodedJSValue encodedCode = reinterpret_cast<JSC::EncodedJSValue>(code);
@@ -671,7 +691,7 @@ extern "C" napi_status napi_get_new_target(napi_env env,
napi_callback_info cbinfo,
napi_value* result)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
// handle:
// - if they call this function when it was originally a getter/setter call
@@ -680,14 +700,6 @@ extern "C" napi_status napi_get_new_target(napi_env env,
return napi_invalid_arg;
}
- if (reinterpret_cast<size_t>(cbinfo) & (static_cast<size_t>(1) << StackAllocatedCallFramePointerTag)) {
- // This is a stack allocated call frame, so we can't get the new target.
- // We'll just return undefined.
- // TODO: verify this is what napi does too
- *result = reinterpret_cast<napi_value>(JSC::JSValue::encode(JSC::jsUndefined()));
- return napi_ok;
- }
-
CallFrame* callFrame = reinterpret_cast<JSC::CallFrame*>(cbinfo);
JSC::JSValue newTarget = callFrame->newTarget();
*result = reinterpret_cast<napi_value>(JSC::JSValue::encode(newTarget));
@@ -699,7 +711,7 @@ extern "C" napi_status napi_create_dataview(napi_env env, size_t length,
size_t byte_offset,
napi_value* result)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
@@ -729,6 +741,33 @@ void NapiClass::visitChildrenImpl(JSCell* cell, Visitor& visitor)
DEFINE_VISIT_CHILDREN(NapiClass);
+static JSC_DECLARE_HOST_FUNCTION(NapiClass_ConstructorFunction);
+
+static JSC_DEFINE_HOST_FUNCTION(NapiClass_ConstructorFunction,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
+{
+ JSC::VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ JSObject* newTarget = asObject(callFrame->newTarget());
+
+ NapiClass* napi = jsDynamicCast<NapiClass*>(newTarget);
+ if (UNLIKELY(!napi)) {
+ JSC::throwVMError(globalObject, scope, JSC::createTypeError(globalObject, "NapiClass constructor called on an object that is not a NapiClass"_s));
+ return JSC::JSValue::encode(JSC::jsUndefined());
+ }
+
+ NapiPrototype* prototype = JSC::jsDynamicCast<NapiPrototype*>(napi->getDirect(vm, vm.propertyNames->prototype));
+
+ RETURN_IF_EXCEPTION(scope, {});
+
+ callFrame->setThisValue(prototype->subclass(newTarget));
+ napi->constructor()(globalObject, callFrame);
+ RETURN_IF_EXCEPTION(scope, {});
+
+ RELEASE_AND_RETURN(scope, JSValue::encode(callFrame->thisValue()));
+}
+
NapiClass* NapiClass::create(VM& vm, Zig::GlobalObject* globalObject, const char* utf8name,
size_t length,
napi_callback constructor,
@@ -737,7 +776,7 @@ NapiClass* NapiClass::create(VM& vm, Zig::GlobalObject* globalObject, const char
const napi_property_descriptor* properties)
{
WTF::String name = WTF::String::fromUTF8(utf8name, length);
- NativeExecutable* executable = vm.getHostFunction(reinterpret_cast<FFIFunction>(constructor), JSC::NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
+ NativeExecutable* executable = vm.getHostFunction(NapiClass_ConstructorFunction, NapiClass_ConstructorFunction, name);
Structure* structure = globalObject->NapiClassStructure();
NapiClass* napiClass = new (NotNull, allocateCell<NapiClass>(vm)) NapiClass(vm, executable, globalObject, structure);
@@ -783,24 +822,26 @@ void NapiClass::finishCreation(VM& vm, NativeExecutable* executable, unsigned le
prototypePropertyCount += property.attributes & napi_static ? 0 : 1;
}
- JSC::JSObject* prototype = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), prototypePropertyCount);
+ NapiPrototype* prototype = NapiPrototype::create(vm, globalObject);
for (size_t i = 0; i < property_count; i++) {
const napi_property_descriptor& property = properties[i];
if (property.attributes & napi_static) {
- defineNapiProperty(globalObject, this, property);
+ defineNapiProperty(globalObject, this, nullptr, property, true);
} else {
- defineNapiProperty(globalObject, prototype, property);
+ defineNapiProperty(globalObject, prototype, nullptr, property, false);
}
}
this->putDirect(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::DontEnum | 0);
prototype->putDirect(vm, vm.propertyNames->constructor, this, JSC::PropertyAttribute::DontEnum | 0);
- prototype->putDirect(vm, clientData->builtinNames().passwordPrivateName(), JSC::jsNumber(0), JSC::PropertyAttribute::DontEnum | 0);
}
}
+const ClassInfo NapiClass::s_info = { "Function"_s, &NapiClass::Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(NapiClass) };
+const ClassInfo NapiPrototype::s_info = { "Object"_s, &NapiPrototype::Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(NapiPrototype) };
+
extern "C" napi_status napi_get_all_property_names(
napi_env env, napi_value objectNapi, napi_key_collection_mode key_mode,
napi_key_filter key_filter, napi_key_conversion key_conversion,
@@ -814,13 +855,13 @@ extern "C" napi_status napi_get_all_property_names(
jsc_property_mode = PropertyNameMode::Symbols;
}
- auto globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ auto globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
- auto objectValue = JSC::JSValue::decode(reinterpret_cast<EncodedJSValue>(objectNapi));
+ auto objectValue = toJS(objectNapi);
auto* object = objectValue.getObject();
if (!object) {
- return napi_object_expected;
+ return NAPI_OBJECT_EXPECTED;
}
JSC::JSArray* exportKeys = ownPropertyKeys(globalObject, object, jsc_property_mode, jsc_key_mode, std::nullopt);
@@ -838,7 +879,7 @@ extern "C" napi_status napi_define_class(napi_env env,
const napi_property_descriptor* properties,
napi_value* result)
{
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
NapiClass* napiClass = NapiClass::create(vm, globalObject, utf8name, length, constructor, data, property_count, properties);
@@ -847,7 +888,7 @@ extern "C" napi_status napi_define_class(napi_env env,
napiClass->dataPtr = data;
}
- *result = reinterpret_cast<napi_value>(JSC::JSValue::encode(value));
+ *result = toNapi(value);
return napi_ok;
}
@@ -858,7 +899,7 @@ extern "C" napi_status napi_coerce_to_string(napi_env env, napi_value value,
return napi_invalid_arg;
}
- Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(env);
+ Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_CATCH_SCOPE(vm);
@@ -866,7 +907,7 @@ extern "C" napi_status napi_coerce_to_string(napi_env env, napi_value value,
// .toString() can throw
JSC::JSValue resultValue = JSC::JSValue(jsValue.toString(globalObject));
- *result = reinterpret_cast<napi_value>(JSC::JSValue::encode(resultValue));
+ *result = toNapi(resultValue);
if (UNLIKELY(scope.exception())) {
*result = reinterpret_cast<napi_value>(JSC::JSValue::encode(JSC::jsUndefined()));
diff --git a/src/javascript/jsc/bindings/napi.h b/src/javascript/jsc/bindings/napi.h
index 7e7ba123d..5bc11e9a5 100644
--- a/src/javascript/jsc/bindings/napi.h
+++ b/src/javascript/jsc/bindings/napi.h
@@ -106,6 +106,7 @@ public:
JSC::JSWeakValue weakValueRef;
JSC::Strong<JSC::Unknown> strongRef;
NapiFinalizer finalizer;
+ void* data = nullptr;
uint32_t refCount = 0;
};
@@ -175,6 +176,60 @@ private:
DECLARE_VISIT_CHILDREN;
};
+class NapiPrototype : public JSC::JSDestructibleObject {
+public:
+ using Base = JSC::JSDestructibleObject;
+
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
+ static constexpr bool needsDestruction = true;
+
+ template<typename CellType, SubspaceAccess>
+ static CompleteSubspace* subspaceFor(VM& vm)
+ {
+ return &vm.destructibleObjectSpace();
+ }
+
+ DECLARE_INFO;
+
+ static NapiPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
+ {
+ NapiPrototype* footprint = new (NotNull, allocateCell<NapiPrototype>(vm)) NapiPrototype(vm, structure);
+ footprint->finishCreation(vm);
+ return footprint;
+ }
+
+ static NapiPrototype* create(VM& vm, JSGlobalObject* globalObject)
+ {
+ Structure* structure = createStructure(vm, globalObject, globalObject->objectPrototype());
+ return create(vm, globalObject, structure);
+ }
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ ASSERT(globalObject);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+ }
+
+ NapiPrototype* subclass(JSC::JSObject* newTarget)
+ {
+ auto& vm = this->vm();
+ auto* structure = InternalFunction::createSubclassStructure(globalObject(),
+ newTarget,
+ this->structure());
+ NapiPrototype* footprint = new (NotNull, allocateCell<NapiPrototype>(vm)) NapiPrototype(vm, structure);
+ footprint->finishCreation(vm);
+ return footprint;
+ }
+
+ NapiRef* napiRef = nullptr;
+
+private:
+ NapiPrototype(VM& vm, Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+};
+
static inline NapiRef* toJS(napi_ref val)
{
return reinterpret_cast<NapiRef*>(val);
diff --git a/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h b/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h
index 3dbb03d00..3db96a489 100644
--- a/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h
+++ b/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h
@@ -19,6 +19,7 @@ public:
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBuffer;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForFFIFunction;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNapiClass;
+ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNapiPrototype;
/* --- bun --- */
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForGlobalObject;
diff --git a/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h b/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h
index d7391f49b..0c0632221 100644
--- a/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h
+++ b/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h
@@ -19,6 +19,7 @@ public:
std::unique_ptr<IsoSubspace> m_subspaceForBuffer;
std::unique_ptr<IsoSubspace> m_subspaceForFFIFunction;
std::unique_ptr<IsoSubspace> m_subspaceForNapiClass;
+ std::unique_ptr<IsoSubspace> m_subspaceForNapiPrototype;
/*-- BUN --*/
// std::unique_ptr<IsoSubspace> m_subspaceForTouch;
diff --git a/src/napi/napi.zig b/src/napi/napi.zig
index 3ec0bac2b..2616b2374 100644
--- a/src/napi/napi.zig
+++ b/src/napi/napi.zig
@@ -383,26 +383,46 @@ pub export fn napi_get_value_bool(_: napi_env, value: napi_value, result: *bool)
}
pub export fn napi_get_value_string_latin1(env: napi_env, value: napi_value, buf: [*]u8, bufsize: usize, result: *usize) napi_status {
const zig_str = value.getZigString(env);
+ if (@ptrToInt(buf) == 0) {
+ result.* = zig_str.len;
+ return .ok;
+ }
+
+ var buf_ = buf[0..bufsize];
+ if (bufsize == 0) {
+ buf_ = std.mem.span(std.meta.assumeSentinel(buf, 0));
+ }
+
if (zig_str.is16Bit()) {
const utf16 = zig_str.utf16SliceAligned();
- const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, @minimum(utf16.len, bufsize), .latin1);
+ const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, @minimum(utf16.len, buf_.len), .latin1);
if (wrote < 0) {
return .generic_failure;
}
result.* = @intCast(usize, wrote);
return .ok;
}
-
- const to_copy = @minimum(zig_str.len, bufsize);
+ const to_copy = @minimum(zig_str.len, buf_.len);
@memcpy(buf, zig_str.slice().ptr, to_copy);
result.* = to_copy;
return .ok;
}
pub export fn napi_get_value_string_utf8(env: napi_env, value: napi_value, buf: [*]u8, bufsize: usize, result: *usize) napi_status {
const zig_str = value.getZigString(env);
+ if (@ptrToInt(buf) == 0) {
+ result.* = zig_str.len;
+ return .ok;
+ }
+
+ var buf_ = buf[0..bufsize];
+
+ if (bufsize == 0) {
+ buf_ = std.mem.span(std.meta.assumeSentinel(buf, 0));
+ }
+
if (zig_str.is16Bit()) {
const utf16 = zig_str.utf16SliceAligned();
- const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, @minimum(utf16.len, bufsize), .utf8);
+ const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, @minimum(utf16.len, buf_.len), .utf8);
if (wrote < 0) {
return .generic_failure;
}
@@ -410,21 +430,32 @@ pub export fn napi_get_value_string_utf8(env: napi_env, value: napi_value, buf:
return .ok;
}
- const to_copy = @minimum(zig_str.len, bufsize);
+ const to_copy = @minimum(zig_str.len, buf_.len);
@memcpy(buf, zig_str.slice().ptr, to_copy);
result.* = to_copy;
return .ok;
}
pub export fn napi_get_value_string_utf16(env: napi_env, value: napi_value, buf: [*]char16_t, bufsize: usize, result: *usize) napi_status {
const zig_str = value.getZigString(env);
+ if (@ptrToInt(buf) == 0) {
+ result.* = zig_str.len;
+ return .ok;
+ }
+
+ var buf_ = buf[0..bufsize];
+
+ if (bufsize == 0) {
+ buf_ = std.mem.span(std.meta.assumeSentinel(buf, 0));
+ }
+
if (!zig_str.is16Bit()) {
const slice = zig_str.slice();
- const encode_into_result = strings.copyLatin1IntoUTF16([]char16_t, buf[0..bufsize], []const u8, slice);
+ const encode_into_result = strings.copyLatin1IntoUTF16([]char16_t, buf_, []const u8, slice);
result.* = encode_into_result.written;
return .ok;
}
- const to_copy = @minimum(zig_str.len, bufsize);
+ const to_copy = @minimum(zig_str.len, buf_.len);
@memcpy(std.mem.sliceAsBytes(buf[0..bufsize]).ptr, std.mem.sliceAsBytes(zig_str.utf16SliceAligned()).ptr, to_copy * 2);
result.* = to_copy;
return .ok;