diff --git a/doc/api/vm.md b/doc/api/vm.md index c4b7e3f9b381ed..ae4daec7166eb6 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -434,10 +434,10 @@ changes: in stack traces produced by this script. * `columnOffset` {number} Specifies the column number offset that is displayed in stack traces produced by this script. - * `cachedData` {Buffer} Provides an optional `Buffer` with V8's code cache - data for the supplied source. When supplied, the `cachedDataRejected` value - will be set to either `true` or `false` depending on acceptance of the data - by V8. + * `cachedData` {Buffer|TypedArray|DataView} Provides an optional `Buffer` or + `TypedArray`, or `DataView` with V8's code cache data for the supplied + source. When supplied, the `cachedDataRejected` value will be set to + either `true` or `false` depending on acceptance of the data by V8. * `produceCachedData` {boolean} When `true` and no `cachedData` is present, V8 will attempt to produce code cache data for `code`. Upon success, a `Buffer` with V8's code cache data will be produced and stored in the @@ -669,8 +669,9 @@ added: v10.10.0 in stack traces produced by this script. **Default:** `0`. * `columnOffset` {number} Specifies the column number offset that is displayed in stack traces produced by this script. **Default:** `0`. - * `cachedData` {Buffer} Provides an optional `Buffer` with V8's code cache - data for the supplied source. + * `cachedData` {Buffer|TypedArray|DataView} Provides an optional `Buffer` or + `TypedArray`, or `DataView` with V8's code cache data for the supplied + source. * `produceCachedData` {boolean} Specifies whether to produce new cache data. **Default:** `false`. * `parsingContext` {Object} The [contextified][] sandbox in which the said diff --git a/lib/vm.js b/lib/vm.js index 1bb948fa550531..6e735bca4a76d9 100644 --- a/lib/vm.js +++ b/lib/vm.js @@ -32,7 +32,7 @@ const { ERR_INVALID_ARG_TYPE, ERR_VM_MODULE_NOT_MODULE, } = require('internal/errors').codes; -const { isModuleNamespaceObject, isUint8Array } = require('util').types; +const { isModuleNamespaceObject, isArrayBufferView } = require('util').types; const { validateInt32, validateUint32 } = require('internal/validators'); const kParsingContext = Symbol('script parsing context'); @@ -64,9 +64,12 @@ class Script extends ContextifyScript { } validateInt32(lineOffset, 'options.lineOffset'); validateInt32(columnOffset, 'options.columnOffset'); - if (cachedData !== undefined && !isUint8Array(cachedData)) { - throw new ERR_INVALID_ARG_TYPE('options.cachedData', - ['Buffer', 'Uint8Array'], cachedData); + if (cachedData !== undefined && !isArrayBufferView(cachedData)) { + throw new ERR_INVALID_ARG_TYPE( + 'options.cachedData', + ['Buffer', 'TypedArray', 'DataView'], + cachedData + ); } if (typeof produceCachedData !== 'boolean') { throw new ERR_INVALID_ARG_TYPE('options.produceCachedData', 'boolean', @@ -346,10 +349,10 @@ function compileFunction(code, params, options = {}) { } validateUint32(columnOffset, 'options.columnOffset'); validateUint32(lineOffset, 'options.lineOffset'); - if (cachedData !== undefined && !isUint8Array(cachedData)) { + if (cachedData !== undefined && !isArrayBufferView(cachedData)) { throw new ERR_INVALID_ARG_TYPE( 'options.cachedData', - 'Uint8Array', + ['Buffer', 'TypedArray', 'DataView'], cachedData ); } diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 3fbc616fda0284..79943f1ad6a7a4 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -33,6 +33,7 @@ namespace contextify { using v8::Array; using v8::ArrayBuffer; +using v8::ArrayBufferView; using v8::Boolean; using v8::Context; using v8::EscapableHandleScope; @@ -64,7 +65,6 @@ using v8::String; using v8::Symbol; using v8::TryCatch; using v8::Uint32; -using v8::Uint8Array; using v8::UnboundScript; using v8::Value; using v8::WeakCallbackInfo; @@ -629,7 +629,7 @@ void ContextifyScript::New(const FunctionCallbackInfo& args) { Local line_offset; Local column_offset; - Local cached_data_buf; + Local cached_data_buf; bool produce_cached_data = false; Local parsing_context = context; @@ -642,8 +642,8 @@ void ContextifyScript::New(const FunctionCallbackInfo& args) { CHECK(args[3]->IsNumber()); column_offset = args[3].As(); if (!args[4]->IsUndefined()) { - CHECK(args[4]->IsUint8Array()); - cached_data_buf = args[4].As(); + CHECK(args[4]->IsArrayBufferView()); + cached_data_buf = args[4].As(); } CHECK(args[5]->IsBoolean()); produce_cached_data = args[5]->IsTrue(); @@ -994,10 +994,10 @@ void ContextifyContext::CompileFunction( Local column_offset = args[3].As(); // Argument 5: cached data (optional) - Local cached_data_buf; + Local cached_data_buf; if (!args[4]->IsUndefined()) { - CHECK(args[4]->IsUint8Array()); - cached_data_buf = args[4].As(); + CHECK(args[4]->IsArrayBufferView()); + cached_data_buf = args[4].As(); } // Argument 6: produce cache data diff --git a/test/parallel/test-vm-basic.js b/test/parallel/test-vm-basic.js index 54b7c45ff8043a..df0c7df1062c14 100644 --- a/test/parallel/test-vm-basic.js +++ b/test/parallel/test-vm-basic.js @@ -178,18 +178,20 @@ const vm = require('vm'); 'filename': 'string', 'columnOffset': 'number', 'lineOffset': 'number', - 'cachedData': 'Uint8Array', + 'cachedData': 'Buffer, TypedArray, or DataView', 'produceCachedData': 'boolean', }; for (const option in optionTypes) { + const typeErrorMessage = `The "options.${option}" property must be ` + + `${option === 'cachedData' ? 'one of' : 'of'} type`; common.expectsError(() => { vm.compileFunction('', undefined, { [option]: null }); }, { type: TypeError, code: 'ERR_INVALID_ARG_TYPE', - message: `The "options.${option}" property must be of type ` + - `${optionTypes[option]}. Received type object` + message: typeErrorMessage + + ` ${optionTypes[option]}. Received type object` }); } diff --git a/test/parallel/test-vm-cached-data.js b/test/parallel/test-vm-cached-data.js index e3947d1ae6c166..1b14999cdbc2f7 100644 --- a/test/parallel/test-vm-cached-data.js +++ b/test/parallel/test-vm-cached-data.js @@ -41,12 +41,14 @@ function testProduceConsume() { const data = produce(source); - // It should consume code cache - const script = new vm.Script(source, { - cachedData: data - }); - assert(!script.cachedDataRejected); - assert.strictEqual(script.runInThisContext()(), 'original'); + for (const cachedData of common.getArrayBufferViews(data)) { + // It should consume code cache + const script = new vm.Script(source, { + cachedData + }); + assert(!script.cachedDataRejected); + assert.strictEqual(script.runInThisContext()(), 'original'); + } } testProduceConsume(); @@ -91,5 +93,5 @@ common.expectsError(() => { }, { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: /must be one of type Buffer or Uint8Array/ + message: /must be one of type Buffer, TypedArray, or DataView/ });