vm: add Script.createCodeCache()
PR-URL: https://github.com/nodejs/node/pull/20300 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: John-David Dalton <john.david.dalton@gmail.com> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Yang Guo <yangguo@chromium.org>
This commit is contained in:
parent
a9d9d7689d
commit
4f67c6f667
@ -1005,6 +1005,14 @@ accepted by the legacy `url.parse()` API. The mentioned APIs now use the WHATWG
|
|||||||
URL parser that requires strictly valid URLs. Passing an invalid URL is
|
URL parser that requires strictly valid URLs. Passing an invalid URL is
|
||||||
deprecated and support will be removed in the future.
|
deprecated and support will be removed in the future.
|
||||||
|
|
||||||
|
<a id="DEP00XX"></a>
|
||||||
|
### DEP00XX: vm.Script cached data
|
||||||
|
|
||||||
|
Type: Documentation-only
|
||||||
|
|
||||||
|
The option `produceCachedData` has been deprecated. Use
|
||||||
|
[`script.createCachedData()`][] instead.
|
||||||
|
|
||||||
[`--pending-deprecation`]: cli.html#cli_pending_deprecation
|
[`--pending-deprecation`]: cli.html#cli_pending_deprecation
|
||||||
[`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size
|
[`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size
|
||||||
[`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array
|
[`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array
|
||||||
@ -1055,6 +1063,7 @@ deprecated and support will be removed in the future.
|
|||||||
[`process.env`]: process.html#process_process_env
|
[`process.env`]: process.html#process_process_env
|
||||||
[`punycode`]: punycode.html
|
[`punycode`]: punycode.html
|
||||||
[`require.extensions`]: modules.html#modules_require_extensions
|
[`require.extensions`]: modules.html#modules_require_extensions
|
||||||
|
[`script.createCachedData()`]: vm.html#vm_script_create_cached_data
|
||||||
[`setInterval()`]: timers.html#timers_setinterval_callback_delay_args
|
[`setInterval()`]: timers.html#timers_setinterval_callback_delay_args
|
||||||
[`setTimeout()`]: timers.html#timers_settimeout_callback_delay_args
|
[`setTimeout()`]: timers.html#timers_settimeout_callback_delay_args
|
||||||
[`tls.CryptoStream`]: tls.html#tls_class_cryptostream
|
[`tls.CryptoStream`]: tls.html#tls_class_cryptostream
|
||||||
|
@ -411,6 +411,10 @@ changes:
|
|||||||
pr-url: https://github.com/nodejs/node/pull/4777
|
pr-url: https://github.com/nodejs/node/pull/4777
|
||||||
description: The `cachedData` and `produceCachedData` options are
|
description: The `cachedData` and `produceCachedData` options are
|
||||||
supported now.
|
supported now.
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/20300
|
||||||
|
description: The `produceCachedData` is deprecated in favour of
|
||||||
|
`script.createCachedData()`
|
||||||
-->
|
-->
|
||||||
|
|
||||||
* `code` {string} The JavaScript code to compile.
|
* `code` {string} The JavaScript code to compile.
|
||||||
@ -431,11 +435,39 @@ changes:
|
|||||||
`cachedData` property of the returned `vm.Script` instance.
|
`cachedData` property of the returned `vm.Script` instance.
|
||||||
The `cachedDataProduced` value will be set to either `true` or `false`
|
The `cachedDataProduced` value will be set to either `true` or `false`
|
||||||
depending on whether code cache data is produced successfully.
|
depending on whether code cache data is produced successfully.
|
||||||
|
This option is deprecated in favor of `script.createCachedData`.
|
||||||
|
|
||||||
Creating a new `vm.Script` object compiles `code` but does not run it. The
|
Creating a new `vm.Script` object compiles `code` but does not run it. The
|
||||||
compiled `vm.Script` can be run later multiple times. The `code` is not bound to
|
compiled `vm.Script` can be run later multiple times. The `code` is not bound to
|
||||||
any global object; rather, it is bound before each run, just for that run.
|
any global object; rather, it is bound before each run, just for that run.
|
||||||
|
|
||||||
|
### script.createCachedData()
|
||||||
|
<!-- YAML
|
||||||
|
added: REPLACEME
|
||||||
|
-->
|
||||||
|
|
||||||
|
* Returns: {Buffer}
|
||||||
|
|
||||||
|
Creates a code cache that can be used with the Script constructor's
|
||||||
|
`cachedData` option. Returns a Buffer. This method may be called at any
|
||||||
|
time and any number of times.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const script = new vm.Script(`
|
||||||
|
function add(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
const x = add(1, 2);
|
||||||
|
`);
|
||||||
|
|
||||||
|
const cacheWithoutX = script.createCachedData();
|
||||||
|
|
||||||
|
script.runInThisContext();
|
||||||
|
|
||||||
|
const cacheWithX = script.createCachedData();
|
||||||
|
```
|
||||||
|
|
||||||
### script.runInContext(contextifiedSandbox[, options])
|
### script.runInContext(contextifiedSandbox[, options])
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.3.1
|
added: v0.3.1
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "base_object-inl.h"
|
#include "base_object-inl.h"
|
||||||
#include "node_contextify.h"
|
#include "node_contextify.h"
|
||||||
#include "node_context_data.h"
|
#include "node_context_data.h"
|
||||||
|
#include "node_errors.h"
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
namespace contextify {
|
namespace contextify {
|
||||||
@ -596,6 +597,7 @@ class ContextifyScript : public BaseObject {
|
|||||||
Local<FunctionTemplate> script_tmpl = env->NewFunctionTemplate(New);
|
Local<FunctionTemplate> script_tmpl = env->NewFunctionTemplate(New);
|
||||||
script_tmpl->InstanceTemplate()->SetInternalFieldCount(1);
|
script_tmpl->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
script_tmpl->SetClassName(class_name);
|
script_tmpl->SetClassName(class_name);
|
||||||
|
env->SetProtoMethod(script_tmpl, "createCachedData", CreateCachedData);
|
||||||
env->SetProtoMethod(script_tmpl, "runInContext", RunInContext);
|
env->SetProtoMethod(script_tmpl, "runInContext", RunInContext);
|
||||||
env->SetProtoMethod(script_tmpl, "runInThisContext", RunInThisContext);
|
env->SetProtoMethod(script_tmpl, "runInThisContext", RunInThisContext);
|
||||||
|
|
||||||
@ -637,7 +639,7 @@ class ContextifyScript : public BaseObject {
|
|||||||
Local<Context> parsing_context = context;
|
Local<Context> parsing_context = context;
|
||||||
|
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
// new ContextifyScript(code, filename, lineOffset, columnOffset
|
// new ContextifyScript(code, filename, lineOffset, columnOffset,
|
||||||
// cachedData, produceCachedData, parsingContext)
|
// cachedData, produceCachedData, parsingContext)
|
||||||
CHECK_EQ(argc, 7);
|
CHECK_EQ(argc, 7);
|
||||||
CHECK(args[2]->IsNumber());
|
CHECK(args[2]->IsNumber());
|
||||||
@ -719,7 +721,7 @@ class ContextifyScript : public BaseObject {
|
|||||||
Boolean::New(isolate, source.GetCachedData()->rejected));
|
Boolean::New(isolate, source.GetCachedData()->rejected));
|
||||||
} else if (produce_cached_data) {
|
} else if (produce_cached_data) {
|
||||||
const ScriptCompiler::CachedData* cached_data =
|
const ScriptCompiler::CachedData* cached_data =
|
||||||
ScriptCompiler::CreateCodeCache(v8_script.ToLocalChecked(), code);
|
ScriptCompiler::CreateCodeCache(v8_script.ToLocalChecked());
|
||||||
bool cached_data_produced = cached_data != nullptr;
|
bool cached_data_produced = cached_data != nullptr;
|
||||||
if (cached_data_produced) {
|
if (cached_data_produced) {
|
||||||
MaybeLocal<Object> buf = Buffer::Copy(
|
MaybeLocal<Object> buf = Buffer::Copy(
|
||||||
@ -745,6 +747,26 @@ class ContextifyScript : public BaseObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void CreateCachedData(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
ContextifyScript* wrapped_script;
|
||||||
|
ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder());
|
||||||
|
Local<UnboundScript> unbound_script =
|
||||||
|
PersistentToLocal(env->isolate(), wrapped_script->script_);
|
||||||
|
std::unique_ptr<ScriptCompiler::CachedData> cached_data(
|
||||||
|
ScriptCompiler::CreateCodeCache(unbound_script));
|
||||||
|
if (!cached_data) {
|
||||||
|
args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked());
|
||||||
|
} else {
|
||||||
|
MaybeLocal<Object> buf = Buffer::Copy(
|
||||||
|
env,
|
||||||
|
reinterpret_cast<const char*>(cached_data->data),
|
||||||
|
cached_data->length);
|
||||||
|
args.GetReturnValue().Set(buf.ToLocalChecked());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void RunInThisContext(const FunctionCallbackInfo<Value>& args) {
|
static void RunInThisContext(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
|
||||||
|
22
test/parallel/test-vm-createcacheddata.js
Normal file
22
test/parallel/test-vm-createcacheddata.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('../common');
|
||||||
|
|
||||||
|
const { Script } = require('vm');
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const source = 'function x() {} const y = x();';
|
||||||
|
|
||||||
|
const script = new Script(source);
|
||||||
|
let cachedData = script.createCachedData();
|
||||||
|
assert(cachedData instanceof Buffer);
|
||||||
|
|
||||||
|
assert(!new Script(source, { cachedData }).cachedDataRejected);
|
||||||
|
|
||||||
|
script.runInNewContext();
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i += 1) {
|
||||||
|
cachedData = script.createCachedData();
|
||||||
|
|
||||||
|
assert(!new Script(source, { cachedData }).cachedDataRejected);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user