From 739de2c9cd19736b6d088a9f127b52709e72909b Mon Sep 17 00:00:00 2001 From: Derrick Farris Date: Mon, 13 Feb 2023 05:07:18 -0600 Subject: feat(napi): add `napi_get_value_bigint_words` (#2061) * feat(napi): add `napi_get_value_bigint_words` * fix(napi): handle `napi_get_value_bigint_words` arr too small --- src/bun.js/bindings/napi.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ src/napi/napi.zig | 1 + src/symbols.txt | 1 + 3 files changed, 44 insertions(+) diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 574224939..ecae69427 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -1568,6 +1568,48 @@ extern "C" napi_status napi_typeof(napi_env env, napi_value val, return napi_generic_failure; } +extern "C" napi_status napi_get_value_bigint_words(napi_env env, + napi_value value, + int* sign_bit, + size_t* word_count, + uint64_t* words) +{ + Zig::GlobalObject* globalObject = toJS(env); + + JSC::JSValue jsValue = toJS(value); + if (UNLIKELY(!jsValue.isBigInt())) + return napi_invalid_arg; + + JSC::JSBigInt* bigInt = jsValue.asHeapBigInt(); + if (UNLIKELY(!bigInt)) + return napi_invalid_arg; + + if (UNLIKELY(word_count == nullptr)) + return napi_invalid_arg; + + size_t available_words = *word_count; + *word_count = bigInt->length(); + + // If both sign_bit and words are nullptr, we're just querying the word count + // Return ok in this case + if (sign_bit == nullptr) { + // However, if one of them is nullptr, we have an invalid argument + if (UNLIKELY(words != nullptr)) + return napi_invalid_arg; + + return napi_ok; + } else if (UNLIKELY(words == nullptr)) + return napi_invalid_arg; // If sign_bit is not nullptr, words must not be nullptr + + *sign_bit = (int)bigInt->sign(); + + size_t len = *word_count; + for (size_t i = 0; i < available_words && i < len; i++) + words[i] = bigInt->digit(i); + + return napi_ok; +} + extern "C" napi_status napi_get_value_external(napi_env env, napi_value value, void** result) { diff --git a/src/napi/napi.zig b/src/napi/napi.zig index 73a633025..ba5040ca8 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -1504,6 +1504,7 @@ pub fn fixDeadCodeElimination() void { std.mem.doNotOptimizeAway(&napi_create_bigint_uint64); std.mem.doNotOptimizeAway(&napi_get_value_bigint_int64); std.mem.doNotOptimizeAway(&napi_get_value_bigint_uint64); + std.mem.doNotOptimizeAway(&napi_get_value_bigint_words); std.mem.doNotOptimizeAway(&napi_fatal_error); std.mem.doNotOptimizeAway(&napi_fatal_exception); std.mem.doNotOptimizeAway(&napi_create_buffer); diff --git a/src/symbols.txt b/src/symbols.txt index 72f24291d..16125adb3 100644 --- a/src/symbols.txt +++ b/src/symbols.txt @@ -81,6 +81,7 @@ _napi_get_undefined _napi_get_uv_event_loop _napi_get_value_bigint_int64 _napi_get_value_bigint_uint64 +_napi_get_value_bigint_words _napi_get_value_bool _napi_get_value_double _napi_get_value_external -- cgit v1.2.3