Skip to content

Commit b4ece1b

Browse files
committed
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: #4947 Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 137f53c commit b4ece1b

File tree

2 files changed

+51
-22
lines changed

2 files changed

+51
-22
lines changed

‎src/node_contextify.cc‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -518,10 +518,11 @@ class ContextifyScript : public BaseObject{
518518

519519
ScriptCompiler::CachedData* cached_data = nullptr;
520520
if (!cached_data_buf.IsEmpty()){
521-
ArrayBuffer::Contents contents =
522-
cached_data_buf.ToLocalChecked()->Buffer()->GetContents();
521+
Local<Uint8Array> ui8 = cached_data_buf.ToLocalChecked();
522+
ArrayBuffer::Contents contents = ui8->Buffer()->GetContents();
523523
cached_data = newScriptCompiler::CachedData(
524-
static_cast<uint8_t*>(contents.Data()), contents.ByteLength());
524+
static_cast<uint8_t*>(contents.Data()) + ui8->ByteOffset(),
525+
ui8->ByteLength());
525526
}
526527

527528
ScriptOrigin origin(filename, lineOffset, columnOffset);

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

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,58 @@ const assert = require('assert');
44
constvm=require('vm');
55
constBuffer=require('buffer').Buffer;
66

7-
constoriginalSource='(function bcd(){return \'original\'})';
7+
functiongetSource(tag){
8+
return`(function ${tag}(){return \'${tag}\'})`;
9+
}
810

9-
// It should produce code cache
10-
constoriginal=newvm.Script(originalSource,{
11-
produceCachedData: true
12-
});
13-
assert(original.cachedDatainstanceofBuffer);
11+
functionproduce(source){
12+
constscript=newvm.Script(source,{
13+
produceCachedData: true
14+
});
15+
assert(script.cachedDatainstanceofBuffer);
1416

15-
assert.equal(original.runInThisContext()(),'original');
17+
returnscript.cachedData;
18+
}
1619

17-
// It should consume code cache
18-
constsuccess=newvm.Script(originalSource,{
19-
cachedData: original.cachedData
20-
});
21-
assert(!success.cachedDataRejected);
20+
functiontestProduceConsume(){
21+
constsource=getSource('original');
2222

23-
assert.equal(success.runInThisContext()(),'original');
23+
constdata=produce(source);
2424

25-
// It should reject invalid code cache
26-
constreject=newvm.Script('(function abc(){return \'invalid\'})',{
27-
cachedData: original.cachedData
28-
});
29-
assert(reject.cachedDataRejected);
30-
assert.equal(reject.runInThisContext()(),'invalid');
25+
// It should consume code cache
26+
constscript=newvm.Script(source,{
27+
cachedData: data
28+
});
29+
assert(!script.cachedDataRejected);
30+
assert.equal(script.runInThisContext()(),'original');
31+
}
32+
testProduceConsume();
33+
34+
functiontestRejectInvalid(){
35+
constsource=getSource('invalid');
36+
37+
constdata=produce(source);
38+
39+
// It should reject invalid code cache
40+
constscript=newvm.Script(getSource('invalid_1'),{
41+
cachedData: data
42+
});
43+
assert(script.cachedDataRejected);
44+
assert.equal(script.runInThisContext()(),'invalid_1');
45+
}
46+
testRejectInvalid();
47+
48+
functiontestRejectSlice(){
49+
constsource=getSource('slice');
50+
51+
constdata=produce(source).slice(4);
52+
53+
constscript=newvm.Script(source,{
54+
cachedData: data
55+
});
56+
assert(script.cachedDataRejected);
57+
}
58+
testRejectSlice();
3159

3260
// It should throw on non-Buffer cachedData
3361
assert.throws(()=>{

0 commit comments

Comments
(0)