summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schulhof <gabriel.schulhof@intel.com>2017-09-06 13:00:43 +0300
committerMyles Borins <mylesborins@google.com>2018-04-16 17:46:05 -0400
commit3b4708b025c4a4ad4e99d980a64a7c49a84cc9bf (patch)
tree64dcc4b693f15805eb764c6e2c64d75cfc28686a
parentac5b9048083156c8dba338e4973ff04f82dfa712 (diff)
downloadnode-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.md21
-rw-r--r--src/node_api.cc27
-rw-r--r--src/node_api.h5
-rw-r--r--test/addons-napi/test_general/testNapiRun.js12
-rw-r--r--test/addons-napi/test_general/test_general.c13
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),