diff options
author | Gabriel Schulhof <gabriel.schulhof@intel.com> | 2017-09-06 13:00:43 +0300 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2018-04-16 17:46:05 -0400 |
commit | 3b4708b025c4a4ad4e99d980a64a7c49a84cc9bf (patch) | |
tree | 64dcc4b693f15805eb764c6e2c64d75cfc28686a | |
parent | ac5b9048083156c8dba338e4973ff04f82dfa712 (diff) | |
download | node-new-3b4708b025c4a4ad4e99d980a64a7c49a84cc9bf.tar.gz |
n-api: implement napi_run_script
Fixes: https://github.com/nodejs/abi-stable-node/issues/51
Backport-PR-URL: https://github.com/nodejs/node/pull/19447
PR-URL: https://github.com/nodejs/node/pull/15216
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com
Reviewed-By: James M Snell <jasnell.gmail.com>
Reviewed-By: Michael Dawson <mhdawson@ca.ibm.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
-rw-r--r-- | doc/api/n-api.md | 21 | ||||
-rw-r--r-- | src/node_api.cc | 27 | ||||
-rw-r--r-- | src/node_api.h | 5 | ||||
-rw-r--r-- | test/addons-napi/test_general/testNapiRun.js | 12 | ||||
-rw-r--r-- | test/addons-napi/test_general/test_general.c | 13 |
5 files changed, 78 insertions, 0 deletions
diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 9c56e50e83..80d8361250 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -43,6 +43,7 @@ The documentation for N-API is structured as follows: * [Object Wrap][] * [Asynchronous Operations][] * [Promises][] +* [Script Execution][] The N-API is a C API that ensures ABI stability across Node.js versions and different compiler levels. However, we also understand that a C++ @@ -3556,6 +3557,25 @@ NAPI_EXTERN napi_status napi_is_promise(napi_env env, - `[out] is_promise`: Flag indicating whether `promise` is a native promise object - that is, a promise object created by the underlying engine. +## Script execution + +N-API provides an API for executing a string containing JavaScript using the +underlying JavaScript engine. + +### napi_run_script +<!-- YAML +added: REPLACEME +--> +```C +NAPI_EXTERN napi_status napi_run_script(napi_env env, + napi_value script, + napi_value* result); +``` + +- `[in] env`: The environment that the API is invoked under. +- `[in] script`: A JavaScript string containing the script to execute. +- `[out] result`: The value resulting from having executed the script. + [Promises]: #n_api_promises [Asynchronous Operations]: #n_api_asynchronous_operations [Basic N-API Data Types]: #n_api_basic_n_api_data_types @@ -3565,6 +3585,7 @@ object - that is, a promise object created by the underlying engine. [Native Abstractions for Node.js]: https://github.com/nodejs/nan [Object Lifetime Management]: #n_api_object_lifetime_management [Object Wrap]: #n_api_object_wrap +[Script Execution]: #n_api_script_execution [Section 9.1.6]: https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc [Section 12.5.5]: https://tc39.github.io/ecma262/#sec-typeof-operator [Section 24.3]: https://tc39.github.io/ecma262/#sec-dataview-objects diff --git a/src/node_api.cc b/src/node_api.cc index a2322295fc..9c8e0edec9 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -3426,3 +3426,30 @@ NAPI_EXTERN napi_status napi_is_promise(napi_env env, return napi_clear_last_error(env); } + +NAPI_EXTERN napi_status napi_run_script(napi_env env, + napi_value script, + napi_value* result) { + NAPI_PREAMBLE(env); + CHECK_ARG(env, script); + CHECK_ARG(env, result); + + v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script); + + if (!v8_script->IsString()) { + return napi_set_last_error(env, napi_string_expected); + } + + v8::Local<v8::Context> context = env->isolate->GetCurrentContext(); + + auto maybe_script = v8::Script::Compile(context, + v8::Local<v8::String>::Cast(v8_script)); + CHECK_MAYBE_EMPTY(env, maybe_script, napi_generic_failure); + + auto script_result = + maybe_script.ToLocalChecked()->Run(context); + CHECK_MAYBE_EMPTY(env, script_result, napi_generic_failure); + + *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked()); + return GET_RETURN_STATUS(env); +} diff --git a/src/node_api.h b/src/node_api.h index 702ddf2d9e..807595777d 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -562,6 +562,11 @@ NAPI_EXTERN napi_status napi_adjust_external_memory(napi_env env, int64_t change_in_bytes, int64_t* adjusted_value); +// Runnig a script +NAPI_EXTERN napi_status napi_run_script(napi_env env, + napi_value script, + napi_value* result); + EXTERN_C_END #endif // SRC_NODE_API_H_ diff --git a/test/addons-napi/test_general/testNapiRun.js b/test/addons-napi/test_general/testNapiRun.js new file mode 100644 index 0000000000..d7534ecf9c --- /dev/null +++ b/test/addons-napi/test_general/testNapiRun.js @@ -0,0 +1,12 @@ +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); + +// addon is referenced through the eval expression in testFile +// eslint-disable-next-line no-unused-vars +const addon = require(`./build/${common.buildType}/test_general`); + +assert.strictEqual(addon.testNapiRun('(41.92 + 0.08);'), 42, + 'napi_run_script() works correctly'); +assert.throws(() => addon.testNapiRun({ abc: 'def' }), /string was expected/); diff --git a/test/addons-napi/test_general/test_general.c b/test/addons-napi/test_general/test_general.c index ea1f2ece0a..287c1d7cb8 100644 --- a/test/addons-napi/test_general/test_general.c +++ b/test/addons-napi/test_general/test_general.c @@ -1,4 +1,5 @@ #include <node_api.h> +#include <stdlib.h> #include "../common.h" napi_value testStrictEquals(napi_env env, napi_callback_info info) { @@ -215,12 +216,24 @@ napi_value testAdjustExternalMemory(napi_env env, napi_callback_info info) { return result; } +napi_value testNapiRun(napi_env env, napi_callback_info info) { + napi_value script, result; + size_t argc = 1; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &script, NULL, NULL)); + + NAPI_CALL(env, napi_run_script(env, script, &result)); + + return result; +} + void Init(napi_env env, napi_value exports, napi_value module, void* priv) { napi_property_descriptor descriptors[] = { DECLARE_NAPI_PROPERTY("testStrictEquals", testStrictEquals), DECLARE_NAPI_PROPERTY("testGetPrototype", testGetPrototype), DECLARE_NAPI_PROPERTY("testGetVersion", testGetVersion), DECLARE_NAPI_PROPERTY("testGetNodeVersion", testGetNodeVersion), + DECLARE_NAPI_PROPERTY("testNapiRun", testNapiRun), DECLARE_NAPI_PROPERTY("doInstanceOf", doInstanceOf), DECLARE_NAPI_PROPERTY("getUndefined", getUndefined), DECLARE_NAPI_PROPERTY("getNull", getNull), |