Repository navigation
Expose v8::String::NewExternalOneByte and v8::String::NewExternalTwoByte to Node-API #48198
Description
Activity
- addedfeature requestIssues requesting new Node.js features.Issues requesting new Node.js features.
on May 27, 2023 - addednode-apiIssues and PRs related to Node-API.Issues and PRs related to Node-API.
on May 27, 2023 Cross-engine portability is one of the n-api design goals and I don't think other engines have functionality that is similar enough. For instance, I'm fairly sure quickjs doesn't have a concept of non-owned strings.
I suppose n-api targeting other engines could copy the string to the JS heap but having APis with wildly different performance across engines isn't great.
Other engines could add such APIs if at some day node is seen as relevant user.
Not exposing any optimized APIs results in keeping NAPI slower than actually needed. It's quite a pain if one knows that moving from v8 to napi results in significant added overhead.
I'm not saying here that this added overhead is the standard case/relevant all the time.For something comparable, the current Chrome implementation of webassembly stringref proposal implements
string.from_code_pointfor similar performance reasons.It would probably make sense to at least have
napi_create_string_code_pointif WASM does adopt this as presumably all engines would have a faster path for the creation of such strings (which is expected as no decoding would be neccessary for such an instruction).We've had problems with Electron not supporting external Buffers: nodejs/node-addon-api#1257. I'm not opposed to this proposal though. I think it's fine to fall back to regular string creation.
BTW, is there an example of usage somewhere? Who manages the life cycle of the ExternalOneByteStringResource?
is there an example of usage somewhere?
I think the most common usage scenario is create JavaScript String from static string, like: denoland/deno#18051. There are also use cases in NAPI-RS:
We've had problems with Electron not supporting external Buffers
Yes, I handled it in NAPI-RS, too. I don't think it's a problem if we have a fallback strategy: https://github.com/napi-rs/napi-rs/blob/main/crates/napi/src/bindgen_runtime/js_values/buffer.rs#L245
let core_str = v8::String::new_external_onebyte_static(scope, b"core").unwrap();
It looks like the rust bindings for V8 have some mechanism for creating a static v8::ExternalStringResource to wrap the string literal. I don't think we can do that in Node-API without exposing v8::ExternalStringResource itself.
I think the only way to go is to heap-allocate v8::ExternalStringResource and tie it via a weak reference to the resulting string, to be freed when the string is garbage-collected. This would likely make it slower, not faster, and more memory intensive too, unless the string is sizable.
We decided at the 2023-06-02 Node-API meeting that we will implement this as a best-effort optimization.
- The function signatures will be exactly the same as
napi_create_string_* - We will create a v8::ExternalStringResource for each string on the heap, and delete it using a weak reference to the resulting string.
- We will fall back to
napi_create_string_*if we cannot use external pointers (such as when pointercage is on). - We will document that optimized performance is not guaranteed, and because of that, modifying the string on the native side may or may not be reflected on the JS side.
- The function signatures will be exactly the same as
- linked a pull request that will close this issue48198 node api external strings #48339
on Jun 8, 2023 - added a commit that references this issue
on Jul 3, 2023 - added 2 commits that reference this issue
on Aug 14, 2023 - added 2 commits that reference this issue
on Sep 8, 2023 - added a commit that references this issue
on Feb 18, 2024
What is the problem this feature will solve?
Provide a faster way to create JavaScript string from static str
What is the feature you are proposing to solve the problem?
v8::String::NewExternalOneByteandv8::String::NewExternalTwoByteWhat alternatives have you considered?
No response