From 3bd2bf40b1838ff816bfbc9959ccdfaaffb6f694 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Tue, 31 Jan 2023 20:36:59 +0800 Subject: [PATCH] fix(napi): run_script return type (#1467) --- crates/napi/src/bindgen_runtime/iterator.rs | 6 +++--- crates/napi/src/env.rs | 11 +++++++++-- examples/napi/__test__/typegen.spec.ts.md | 1 + examples/napi/__test__/typegen.spec.ts.snap | Bin 3746 -> 3764 bytes examples/napi/__test__/values.spec.ts | 6 ++++++ examples/napi/index.d.ts | 1 + examples/napi/src/lib.rs | 7 +++++++ 7 files changed, 27 insertions(+), 5 deletions(-) diff --git a/crates/napi/src/bindgen_runtime/iterator.rs b/crates/napi/src/bindgen_runtime/iterator.rs index 7d4a8dbe..3f71291d 100644 --- a/crates/napi/src/bindgen_runtime/iterator.rs +++ b/crates/napi/src/bindgen_runtime/iterator.rs @@ -16,19 +16,19 @@ pub trait Generator { type Return: FromNapiValue; /// Handle the `Generator.next()` - /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next + /// fn next(&mut self, value: Option) -> Option; #[allow(unused_variables)] /// Implement complete to handle the `Generator.return()` - /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return + /// fn complete(&mut self, value: Option) -> Option { None } #[allow(unused_variables)] /// Implement catch to handle the `Generator.throw()` - /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw + /// fn catch(&mut self, env: Env, value: Unknown) -> Result, Unknown> { Err(value) } diff --git a/crates/napi/src/env.rs b/crates/napi/src/env.rs index f11b75bf..95eae3f5 100644 --- a/crates/napi/src/env.rs +++ b/crates/napi/src/env.rs @@ -7,6 +7,7 @@ use std::mem; use std::os::raw::{c_char, c_void}; use std::ptr; +use crate::bindgen_runtime::FromNapiValue; #[cfg(all(feature = "napi4"))] use crate::bindgen_runtime::ToNapiValue; use crate::{ @@ -1078,13 +1079,19 @@ impl Env { result } - pub fn run_script>(&self, script: S) -> Result { + /// Node-API provides an API for executing a string containing JavaScript using the underlying JavaScript engine. + /// This function executes a string of JavaScript code and returns its result with the following caveats: + /// - Unlike `eval`, this function does not allow the script to access the current lexical scope, and therefore also does not allow to access the [module scope](https://nodejs.org/api/modules.html#the-module-scope), meaning that pseudo-globals such as require will not be available. + /// - The script can access the [global scope](https://nodejs.org/api/globals.html). Function and `var` declarations in the script will be added to the [global](https://nodejs.org/api/globals.html#global) object. Variable declarations made using `let` and `const` will be visible globally, but will not be added to the global object. + /// - The value of this is [global](https://nodejs.org/api/globals.html) within the script. + pub fn run_script, V: FromNapiValue>(&self, script: S) -> Result { let s = self.create_string(script.as_ref())?; let mut raw_value = ptr::null_mut(); check_status!(unsafe { sys::napi_run_script(self.0, s.raw(), &mut raw_value) })?; - Ok(unsafe { JsObject::from_raw_unchecked(self.0, raw_value) }) + unsafe { V::from_napi_value(self.0, raw_value) } } + /// `process.versions.napi` pub fn get_napi_version(&self) -> Result { let global = self.get_global()?; let process: JsObject = global.get_named_property("process")?; diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index e94183a7..4177d83b 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -218,6 +218,7 @@ Generated by [AVA](https://avajs.dev). export function bufferPassThrough(buf: Buffer): Promise␊ export function arrayBufferPassThrough(buf: Uint8Array): Promise␊ export function asyncReduceBuffer(buf: Buffer): Promise␊ + export function runScript(script: string): unknown␊ /**␊ * \`constructor\` option for \`struct\` requires all fields to be public,␊ * otherwise tag impl fn as constructor␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 4689623009c11a76cf1646ee5f5a4b0a10122246..84057f2f5a5c7bd33816270cd1a4ede464bdd357 100644 GIT binary patch literal 3764 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 literal 3746 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 { @@ -630,6 +631,11 @@ test('external', (t) => { ) }) +test('should be able to run script', async (t) => { + t.is(runScript(`1 + 1`), 2) + t.is(await runScript(`Promise.resolve(1)`), 1) +}) + const AbortSignalTest = typeof AbortController !== 'undefined' ? test : test.skip diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index 88078283..29ec410c 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -208,6 +208,7 @@ export function derefUint8Array(a: Uint8Array, b: Uint8ClampedArray): number export function bufferPassThrough(buf: Buffer): Promise export function arrayBufferPassThrough(buf: Uint8Array): Promise export function asyncReduceBuffer(buf: Buffer): Promise +export function runScript(script: string): unknown /** * `constructor` option for `struct` requires all fields to be public, * otherwise tag impl fn as constructor diff --git a/examples/napi/src/lib.rs b/examples/napi/src/lib.rs index fdd3e4fe..69d03eec 100644 --- a/examples/napi/src/lib.rs +++ b/examples/napi/src/lib.rs @@ -3,6 +3,8 @@ #![allow(clippy::disallowed_names)] #![allow(clippy::uninlined_format_args)] +use napi::{Env, JsUnknown}; + #[macro_use] extern crate napi_derive; #[macro_use] @@ -46,3 +48,8 @@ mod symbol; mod task; mod threadsafe_function; mod typed_array; + +#[napi] +pub fn run_script(env: Env, script: String) -> napi::Result { + env.run_script(&script) +}