Browse Source

contextify: use offset/length from Uint8Array

Do not blindly take data from underlying `ArrayBuffer`, use
`ByteOffset`/`ByteLength` of `Uint8Array` itself.

Additionally, fix tests that weren't actually properly running because
of V8's internal code cache. The code should be different, otherwise the
cached data won't be used at all.

Fix: #4939
PR-URL: https://github.com/nodejs/node/pull/4947
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
v5.x
Fedor Indutny 9 years ago
committed by Rod Vagg
parent
commit
c397ba8fa3
  1. 7
      src/node_contextify.cc
  2. 66
      test/parallel/test-vm-cached-data.js

7
src/node_contextify.cc

@ -507,10 +507,11 @@ class ContextifyScript : public BaseObject {
ScriptCompiler::CachedData* cached_data = nullptr; ScriptCompiler::CachedData* cached_data = nullptr;
if (!cached_data_buf.IsEmpty()) { if (!cached_data_buf.IsEmpty()) {
ArrayBuffer::Contents contents = Local<Uint8Array> ui8 = cached_data_buf.ToLocalChecked();
cached_data_buf.ToLocalChecked()->Buffer()->GetContents(); ArrayBuffer::Contents contents = ui8->Buffer()->GetContents();
cached_data = new ScriptCompiler::CachedData( cached_data = new ScriptCompiler::CachedData(
static_cast<uint8_t*>(contents.Data()), contents.ByteLength()); static_cast<uint8_t*>(contents.Data()) + ui8->ByteOffset(),
ui8->ByteLength());
} }
ScriptOrigin origin(filename, lineOffset, columnOffset); ScriptOrigin origin(filename, lineOffset, columnOffset);

66
test/parallel/test-vm-cached-data.js

@ -4,30 +4,58 @@ const assert = require('assert');
const vm = require('vm'); const vm = require('vm');
const Buffer = require('buffer').Buffer; const Buffer = require('buffer').Buffer;
const originalSource = '(function bcd() { return \'original\'; })'; function getSource(tag) {
return `(function ${tag}() { return \'${tag}\'; })`;
}
// It should produce code cache function produce(source) {
const original = new vm.Script(originalSource, { const script = new vm.Script(source, {
produceCachedData: true produceCachedData: true
}); });
assert(original.cachedData instanceof Buffer); assert(script.cachedData instanceof Buffer);
assert.equal(original.runInThisContext()(), 'original'); return script.cachedData;
}
// It should consume code cache function testProduceConsume() {
const success = new vm.Script(originalSource, { const source = getSource('original');
cachedData: original.cachedData
});
assert(!success.cachedDataRejected);
assert.equal(success.runInThisContext()(), 'original'); const data = produce(source);
// It should reject invalid code cache // It should consume code cache
const reject = new vm.Script('(function abc() { return \'invalid\'; })', { const script = new vm.Script(source, {
cachedData: original.cachedData cachedData: data
}); });
assert(reject.cachedDataRejected); assert(!script.cachedDataRejected);
assert.equal(reject.runInThisContext()(), 'invalid'); assert.equal(script.runInThisContext()(), 'original');
}
testProduceConsume();
function testRejectInvalid() {
const source = getSource('invalid');
const data = produce(source);
// It should reject invalid code cache
const script = new vm.Script(getSource('invalid_1'), {
cachedData: data
});
assert(script.cachedDataRejected);
assert.equal(script.runInThisContext()(), 'invalid_1');
}
testRejectInvalid();
function testRejectSlice() {
const source = getSource('slice');
const data = produce(source).slice(4);
const script = new vm.Script(source, {
cachedData: data
});
assert(script.cachedDataRejected);
}
testRejectSlice();
// It should throw on non-Buffer cachedData // It should throw on non-Buffer cachedData
assert.throws(() => { assert.throws(() => {

Loading…
Cancel
Save