From f00e2be548da21b9feaef178bb0ac22230801d6f Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sat, 1 Jul 2023 17:37:44 -0700 Subject: Use `BunString` in `SystemError` (#3485) * Use `BunString` in SystemError * Use Bun::toStringRef when we will de-ref strings * Move `napi_create_error` to C++ to support `code` being a Symbol potentially * Update blob.zig * Make this test less flaky --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> --- src/bun.js/bindings/napi.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'src/bun.js/bindings/napi.cpp') diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index a859e3ac5..bb62cb2a0 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -554,7 +554,6 @@ extern "C" napi_status napi_wrap(napi_env env, auto* globalObject = toJS(env); auto& vm = globalObject->vm(); - auto* val = jsDynamicCast(value); @@ -572,7 +571,7 @@ extern "C" napi_status napi_wrap(napi_env env, auto clientData = WebCore::clientData(vm); auto* ref = new NapiRef(globalObject, 1); - ref->strongRef.set(globalObject->vm(), value.getObject()); + ref->strongRef.set(globalObject->vm(), value.getObject()); if (finalize_cb) { ref->finalizer.finalize_cb = finalize_cb; @@ -816,7 +815,7 @@ extern "C" napi_status napi_create_reference(napi_env env, napi_value value, } } - if(object) { + if (object) { object->napiRef = ref; } @@ -1029,7 +1028,26 @@ extern "C" napi_status napi_create_type_error(napi_env env, napi_value code, auto error = JSC::createTypeError(globalObject, messageValue.toWTFString(globalObject)); if (codeValue) { - error->putDirect(vm, Identifier::fromString(vm, "code"_s), codeValue, 0); + error->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), codeValue, 0); + } + + *result = reinterpret_cast(JSC::JSValue::encode(error)); + return napi_ok; +} + +extern "C" napi_status napi_create_error(napi_env env, napi_value code, + napi_value msg, + napi_value* result) +{ + Zig::GlobalObject* globalObject = toJS(env); + JSC::VM& vm = globalObject->vm(); + + JSC::JSValue codeValue = JSC::JSValue::decode(reinterpret_cast(code)); + JSC::JSValue messageValue = JSC::JSValue::decode(reinterpret_cast(msg)); + + auto error = JSC::createError(globalObject, messageValue.toWTFString(globalObject)); + if (codeValue) { + error->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), codeValue, 0); } *result = reinterpret_cast(JSC::JSValue::encode(error)); @@ -1474,7 +1492,8 @@ extern "C" napi_status napi_get_property_names(napi_env env, napi_value object, return napi_ok; } -extern "C" napi_status napi_create_object(napi_env env, napi_value* result){ +extern "C" napi_status napi_create_object(napi_env env, napi_value* result) +{ if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; -- cgit v1.2.3 From 424717a9737321a3f37f7596f62067d72cd97e25 Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Mon, 3 Jul 2023 13:47:37 -0700 Subject: Fixes #3317 --- src/bun.js/bindings/napi.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src/bun.js/bindings/napi.cpp') diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index bb62cb2a0..5d7204285 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -1539,8 +1539,10 @@ extern "C" napi_status napi_typeof(napi_env env, napi_value val, JSC::JSValue value = toJS(val); - if (UNLIKELY(value.isEmpty())) { - return napi_invalid_arg; + if (value.isEmpty()) { + // This can happen + *result = napi_undefined; + return napi_ok; } if (value.isCell()) { @@ -1579,17 +1581,18 @@ extern "C" napi_status napi_typeof(napi_env env, napi_value val, *result = napi_object; return napi_ok; - default: - if (cell->isObject()) { - *result = napi_object; + default: { + if (cell->isCallable() || cell->isConstructor()) { + *result = napi_function; return napi_ok; } - if (cell->isCallable() || cell->isConstructor()) { - *result = napi_function; + if (cell->isObject()) { + *result = napi_object; return napi_ok; } } + } } if (value.isNumber()) { -- cgit v1.2.3 From 33bc507f7453beecd831295b576941b2d5fa6cfd Mon Sep 17 00:00:00 2001 From: Jarred SUmner Date: Tue, 4 Jul 2023 01:04:18 -0700 Subject: Fix napi --- src/bun.js/bindings/napi.cpp | 84 +++++++++++++++++++++++++++++++++++++++++--- src/napi/napi.zig | 63 ++------------------------------- 2 files changed, 82 insertions(+), 65 deletions(-) (limited to 'src/bun.js/bindings/napi.cpp') diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 5d7204285..8fffcc05f 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -14,7 +14,7 @@ #include "wtf/text/StringView.h" #include "wtf/text/StringBuilder.h" #include "wtf/text/WTFString.h" - +#include "BufferEncodingType.h" #include "JavaScriptCore/AggregateError.h" #include "JavaScriptCore/BytecodeIndex.h" #include "JavaScriptCore/CallFrame.h" @@ -1188,9 +1188,7 @@ 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_DEFINE_HOST_FUNCTION(NapiClass_ConstructorFunction, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { JSC::VM& vm = globalObject->vm(); @@ -1280,7 +1278,6 @@ NapiClass* NapiClass::create(VM& vm, Zig::GlobalObject* globalObject, const char { WTF::String name = WTF::String::fromUTF8(utf8name, length).isolatedCopy(); NativeExecutable* executable = vm.getHostFunction(NapiClass_ConstructorFunction, ImplementationVisibility::Public, NapiClass_ConstructorFunction, name); - Structure* structure = globalObject->NapiClassStructure(); NapiClass* napiClass = new (NotNull, allocateCell(vm)) NapiClass(vm, executable, globalObject, structure); napiClass->finishCreation(vm, executable, length, name, constructor, data, property_count, properties); @@ -1492,6 +1489,83 @@ extern "C" napi_status napi_get_property_names(napi_env env, napi_value object, return napi_ok; } +extern "C" napi_status napi_get_value_string_utf8(napi_env env, + napi_value napiValue, char* buf, + size_t bufsize, + size_t* writtenPtr) +{ + JSGlobalObject* globalObject = toJS(env); + JSC::VM& vm = globalObject->vm(); + + JSValue jsValue = toJS(napiValue); + if (!jsValue || !jsValue.isString()) { + return napi_string_expected; + } + + JSString* jsString = jsValue.toStringOrNull(globalObject); + if (UNLIKELY(!jsString)) { + return napi_generic_failure; + } + + size_t length = jsString->length(); + auto viewWithUnderlyingString = jsString->viewWithUnderlyingString(globalObject); + auto view = viewWithUnderlyingString.view; + + if (buf == nullptr) { + if (writtenPtr != nullptr) { + if (view.is8Bit()) { + *writtenPtr = Bun__encoding__byteLengthLatin1(view.characters8(), length, static_cast(WebCore::BufferEncodingType::utf8)); + } else { + *writtenPtr = Bun__encoding__byteLengthUTF16(view.characters16(), length, static_cast(WebCore::BufferEncodingType::utf8)); + } + } + + return napi_ok; + } + + if (bufsize == NAPI_AUTO_LENGTH) { + bufsize = strlen(buf); + } + + size_t written; + if (view.is8Bit()) { + written = Bun__encoding__writeLatin1(view.characters8(), view.length(), reinterpret_cast(buf), bufsize, static_cast(WebCore::BufferEncodingType::utf8)); + } else { + written = Bun__encoding__writeUTF16(view.characters16(), view.length(), reinterpret_cast(buf), bufsize, static_cast(WebCore::BufferEncodingType::utf8)); + } + + if (writtenPtr != nullptr) { + *writtenPtr = written; + } + + if (written < bufsize) { + buf[written] = '\0'; + } + + return napi_ok; +} + +extern "C" napi_status napi_get_element(napi_env env, napi_value objectValue, + uint32_t index, napi_value* result) +{ + JSValue jsValue = toJS(objectValue); + if (!jsValue || !jsValue.isObject()) { + return napi_invalid_arg; + } + + JSObject* object = jsValue.getObject(); + + auto scope = DECLARE_THROW_SCOPE(object->vm()); + JSValue element = object->getIndex(toJS(env), index); + RETURN_IF_EXCEPTION(scope, napi_generic_failure); + + if (result) { + *result = toNapi(element); + } + + return napi_ok; +} + extern "C" napi_status napi_create_object(napi_env env, napi_value* result) { diff --git a/src/napi/napi.zig b/src/napi/napi.zig index dc2cb602e..92b03aef0 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -291,7 +291,6 @@ pub export fn napi_create_string_utf8(env: napi_env, str: [*]const u8, length: u var string = bun.String.create(slice); defer string.deref(); - setNapiValue(result, string.toJS(env)); return .ok; } @@ -392,56 +391,8 @@ pub export fn napi_get_value_string_latin1(env: napi_env, value: napi_value, buf /// If buf is NULL, this method returns the length of the string (in bytes) /// via the result parameter. /// The result argument is optional unless buf is NULL. -pub export fn napi_get_value_string_utf8(env: napi_env, value: napi_value, buf_ptr: [*c]u8, bufsize: usize, result_ptr: ?*usize) napi_status { - defer value.ensureStillAlive(); - - if (!value.isString()) { - return .string_expected; - } - - const str = value.toBunString(env); - - if (str.isEmpty()) { - if (result_ptr) |result| { - result.* = 0; - } - return .ok; - } - - var buf = buf_ptr orelse { - if (result_ptr) |result| { - result.* = str.utf8ByteLength(); - } - - return .ok; - }; - - var buf_ = buf[0..bufsize]; - - if (bufsize == 0) { - buf_ = bun.sliceTo(buf_ptr, 0); - if (buf_.len == 0) { - if (result_ptr) |result| { - result.* = 0; - } - return .ok; - } - } - - const written = str.encodeInto(buf_, .utf8) catch unreachable; - const max_buf_len = if (bufsize == 0) buf_.len else bufsize; - - if (result_ptr) |result| { - result.* = written; - } else if (written < max_buf_len) { - buf[written] = 0; - } - - log("napi_get_value_string_utf8: {s}", .{buf[0..written]}); - - return .ok; -} -pub export fn napi_get_value_string_utf16(env: napi_env, value: napi_value, buf_ptr: [*c]char16_t, bufsize: usize, result_ptr: ?*usize) napi_status { +pub extern fn napi_get_value_string_utf8(env: napi_env, value: napi_value, buf_ptr: [*c]u8, bufsize: usize, result_ptr: ?*usize) napi_status ; +pub export fn napi_get_value_string_utf16(env: napi_env, value: napi_value, buf_ptr: ?[*]char16_t, bufsize: usize, result_ptr: ?*usize) napi_status { log("napi_get_value_string_utf16", .{}); defer value.ensureStillAlive(); const str = value.toBunString(env); @@ -539,15 +490,7 @@ pub export fn napi_has_element(env: napi_env, object: napi_value, index: c_uint, result.* = object.getLength(env) > index; return .ok; } -pub export fn napi_get_element(env: napi_env, object: napi_value, index: u32, result: *napi_value) napi_status { - log("napi_get_element", .{}); - if (!object.jsType().isIndexable()) { - return .array_expected; - } - - result.* = JSC.JSObject.getIndex(object, env, index); - return .ok; -} +pub extern fn napi_get_element(env: napi_env, object: napi_value, index: u32, result: *napi_value) napi_status; pub extern fn napi_define_properties(env: napi_env, object: napi_value, property_count: usize, properties: [*c]const napi_property_descriptor) napi_status; pub export fn napi_is_array(_: napi_env, value: napi_value, result: *bool) napi_status { log("napi_is_array", .{}); -- cgit v1.2.3