Skip to content

Commit

Permalink
vm: add Script.createCodeCache()
Browse files Browse the repository at this point in the history
PR-URL: #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>
  • Loading branch information
devsnek authored and targos committed Jun 28, 2018
1 parent 9f2bf3c commit 4fc05ac
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 2 deletions.
9 changes: 9 additions & 0 deletions doc/api/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,14 @@ because it also made sense to interpret the value as the number of bytes
read by the engine, but is inconsistent with other streams in Node.js that
expose values under these names.
<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
[`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size
[`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array
Expand Down Expand Up @@ -1039,6 +1047,7 @@ expose values under these names.
[`process.env`]: process.html#process_process_env
[`punycode`]: punycode.html
[`require.extensions`]: modules.html#modules_require_extensions
[`script.createCachedData()`]: vm.html#vm_script_create_cached_data
[`setInterval()`]: timers.html#timers_setinterval_callback_delay_args
[`setTimeout()`]: timers.html#timers_settimeout_callback_delay_args
[`tls.CryptoStream`]: tls.html#tls_class_cryptostream
Expand Down
32 changes: 32 additions & 0 deletions doc/api/vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,10 @@ changes:
pr-url: https://github.com/nodejs/node/pull/4777
description: The `cachedData` and `produceCachedData` options are
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.
Expand All @@ -431,11 +435,39 @@ changes:
`cachedData` property of the returned `vm.Script` instance.
The `cachedDataProduced` value will be set to either `true` or `false`
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
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.

### 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])
<!-- YAML
added: v0.3.1
Expand Down
26 changes: 24 additions & 2 deletions src/node_contextify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "base_object-inl.h"
#include "node_contextify.h"
#include "node_context_data.h"
#include "node_errors.h"

namespace node {
namespace contextify {
Expand Down Expand Up @@ -595,6 +596,7 @@ class ContextifyScript : public BaseObject {
Local<FunctionTemplate> script_tmpl = env->NewFunctionTemplate(New);
script_tmpl->InstanceTemplate()->SetInternalFieldCount(1);
script_tmpl->SetClassName(class_name);
env->SetProtoMethod(script_tmpl, "createCachedData", CreateCachedData);
env->SetProtoMethod(script_tmpl, "runInContext", RunInContext);
env->SetProtoMethod(script_tmpl, "runInThisContext", RunInThisContext);

Expand Down Expand Up @@ -636,7 +638,7 @@ class ContextifyScript : public BaseObject {
Local<Context> parsing_context = context;

if (argc > 2) {
// new ContextifyScript(code, filename, lineOffset, columnOffset
// new ContextifyScript(code, filename, lineOffset, columnOffset,
// cachedData, produceCachedData, parsingContext)
CHECK_EQ(argc, 7);
CHECK(args[2]->IsNumber());
Expand Down Expand Up @@ -718,7 +720,7 @@ class ContextifyScript : public BaseObject {
Boolean::New(isolate, source.GetCachedData()->rejected));
} else if (produce_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;
if (cached_data_produced) {
MaybeLocal<Object> buf = Buffer::Copy(
Expand All @@ -744,6 +746,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) {
Environment* env = Environment::GetCurrent(args);

Expand Down
22 changes: 22 additions & 0 deletions test/parallel/test-vm-createcacheddata.js
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 4fc05ac

Please sign in to comment.