From 6c8378b15bd9ca378df6e14d5b0d7032caefd774 Mon Sep 17 00:00:00 2001 From: Jiho Choi Date: Sat, 20 Feb 2016 20:44:06 -0600 Subject: [PATCH] vm: fix `produceCachedData` Fix segmentation faults when compiling the same code with `produceCachedData` option. V8 ignores the option when the code is in its compilation cache and does not return cached data. Added `cachedDataProduced` property to `v8.Script` to denote whether the cached data is produced successfully. PR-URL: https://github.com/nodejs/node/pull/5343 Reviewed-By: Fedor Indutny --- doc/api/vm.markdown | 9 ++++++--- src/env.h | 1 + src/node_contextify.cc | 16 +++++++++++----- test/parallel/test-vm-cached-data.js | 11 ++++++++++- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/doc/api/vm.markdown b/doc/api/vm.markdown index a8ca746cc6..674c76d6a1 100644 --- a/doc/api/vm.markdown +++ b/doc/api/vm.markdown @@ -41,9 +41,12 @@ The options when creating a script are: - `cachedData`: an optional `Buffer` with V8's code cache data for the supplied source. When supplied `cachedDataRejected` value will be set to either `true` or `false` depending on acceptance of the data by V8. -- `produceCachedData`: if `true` and no `cachedData` is present - a `Buffer` - with V8's code cache data will be produced and stored in `cachedData` property - of the returned `vm.Script` instance. +- `produceCachedData`: if `true` and no `cachedData` is present - V8 tries to + produce code cache data for `code`. Upon success, a `Buffer` with V8's code + cache data will be produced and stored in `cachedData` property of the + returned `vm.Script` instance. `cachedDataProduced` value will be set to + either `true` or `false` depending on whether code cache data is produced + successfully. ### script.runInContext(contextifiedSandbox[, options]) diff --git a/src/env.h b/src/env.h index dadaa377da..9e5b50302b 100644 --- a/src/env.h +++ b/src/env.h @@ -62,6 +62,7 @@ namespace node { V(bytes_string, "bytes") \ V(bytes_parsed_string, "bytesParsed") \ V(cached_data_string, "cachedData") \ + V(cached_data_produced_string, "cachedDataProduced") \ V(cached_data_rejected_string, "cachedDataRejected") \ V(callback_string, "callback") \ V(change_string, "change") \ diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 35b95b8a5e..1db064a7a7 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -544,11 +544,17 @@ class ContextifyScript : public BaseObject { Boolean::New(env->isolate(), source.GetCachedData()->rejected)); } else if (compile_options == ScriptCompiler::kProduceCodeCache) { const ScriptCompiler::CachedData* cached_data = source.GetCachedData(); - MaybeLocal buf = Buffer::Copy( - env, - reinterpret_cast(cached_data->data), - cached_data->length); - args.This()->Set(env->cached_data_string(), buf.ToLocalChecked()); + bool cached_data_produced = cached_data != nullptr; + if (cached_data_produced) { + MaybeLocal buf = Buffer::Copy( + env, + reinterpret_cast(cached_data->data), + cached_data->length); + args.This()->Set(env->cached_data_string(), buf.ToLocalChecked()); + } + args.This()->Set( + env->cached_data_produced_string(), + Boolean::New(env->isolate(), cached_data_produced)); } } diff --git a/test/parallel/test-vm-cached-data.js b/test/parallel/test-vm-cached-data.js index 549eeecf26..924f082684 100644 --- a/test/parallel/test-vm-cached-data.js +++ b/test/parallel/test-vm-cached-data.js @@ -12,7 +12,7 @@ function produce(source) { const script = new vm.Script(source, { produceCachedData: true }); - assert(script.cachedData instanceof Buffer); + assert(!script.cachedDataProduced || script.cachedData instanceof Buffer); return script.cachedData; } @@ -31,6 +31,15 @@ function testProduceConsume() { } testProduceConsume(); +function testProduceMultiple() { + const source = getSource('original'); + + produce(source); + produce(source); + produce(source); +} +testProduceMultiple(); + function testRejectInvalid() { const source = getSource('invalid');