forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtest-vm-context-dont-contextify.js
More file actions
185 lines (164 loc) · 7.32 KB
/
test-vm-context-dont-contextify.js
File metadata and controls
185 lines (164 loc) · 7.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
'use strict';
// Check vm.constants.DONT_CONTEXTIFY works.
const common = require('../common');
const assert = require('assert');
const vm = require('vm');
const fixtures = require('../common/fixtures');
{
// Check identity of the returned object.
const context = vm.createContext(vm.constants.DONT_CONTEXTIFY);
// The globalThis in the new context should be reference equal to the returned object.
assert.strictEqual(vm.runInContext('globalThis', context), context);
assert(vm.isContext(context));
assert.strictEqual(typeof context.Array, 'function'); // Can access builtins directly.
assert.deepStrictEqual(Object.keys(context), []); // Properties on the global proxy are not enumerable
}
{
// Check that vm.createContext can return the original context if re-passed.
const context = vm.createContext(vm.constants.DONT_CONTEXTIFY);
const context2 = new vm.createContext(context);
assert.strictEqual(context, context2);
}
{
// Check that the context is vanilla and that Script.runInContext works.
const context = vm.createContext(vm.constants.DONT_CONTEXTIFY);
const result =
new vm.Script('globalThis.hey = 1; Object.freeze(globalThis); globalThis.process')
.runInContext(context);
assert.strictEqual(globalThis.hey, undefined); // Should not leak into current context.
assert.strictEqual(result, undefined); // Vanilla context has no Node.js globals
}
{
// Check Script.runInNewContext works.
const result =
new vm.Script('globalThis.hey = 1; Object.freeze(globalThis); globalThis.process')
.runInNewContext(vm.constants.DONT_CONTEXTIFY);
assert.strictEqual(globalThis.hey, undefined); // Should not leak into current context.
assert.strictEqual(result, undefined); // Vanilla context has no Node.js globals
}
{
// Check that vm.runInNewContext() works
const result = vm.runInNewContext(
'globalThis.hey = 1; Object.freeze(globalThis); globalThis.process',
vm.constants.DONT_CONTEXTIFY);
assert.strictEqual(globalThis.hey, undefined); // Should not leak into current context.
assert.strictEqual(result, undefined); // Vanilla context has no Node.js globals
}
{
// Check that the global object of vanilla contexts work as expected.
const context = vm.createContext(vm.constants.DONT_CONTEXTIFY);
// Check mutation via globalThis.
vm.runInContext('globalThis.foo = 1;', context);
assert.strictEqual(globalThis.foo, undefined); // Should not pollute the current context.
assert.strictEqual(context.foo, 1);
assert.strictEqual(vm.runInContext('globalThis.foo', context), 1);
assert.strictEqual(vm.runInContext('foo', context), 1);
// Check mutation from outside.
context.foo = 2;
assert.strictEqual(context.foo, 2);
assert.strictEqual(vm.runInContext('globalThis.foo', context), 2);
assert.strictEqual(vm.runInContext('foo', context), 2);
// Check contextual mutation.
vm.runInContext('bar = 1;', context);
assert.strictEqual(globalThis.bar, undefined); // Should not pollute the current context.
assert.strictEqual(context.bar, 1);
assert.strictEqual(vm.runInContext('globalThis.bar', context), 1);
assert.strictEqual(vm.runInContext('bar', context), 1);
// Check adding new property from outside.
context.baz = 1;
assert.strictEqual(context.baz, 1);
assert.strictEqual(vm.runInContext('globalThis.baz', context), 1);
assert.strictEqual(vm.runInContext('baz', context), 1);
// Check mutation via Object.defineProperty().
vm.runInContext('Object.defineProperty(globalThis, "qux", {' +
'enumerable: false, configurable: false, get() { return 1; } })', context);
assert.strictEqual(globalThis.qux, undefined); // Should not pollute the current context.
assert.strictEqual(context.qux, 1);
assert.strictEqual(vm.runInContext('qux', context), 1);
const desc = Object.getOwnPropertyDescriptor(context, 'qux');
assert.strictEqual(desc.enumerable, false);
assert.strictEqual(desc.configurable, false);
assert.strictEqual(typeof desc.get, 'function');
assert.throws(() => { context.qux = 1; }, { name: 'TypeError' });
assert.throws(() => { Object.defineProperty(context, 'qux', { value: 1 }); }, { name: 'TypeError' });
// Setting a value without a setter fails silently.
assert.strictEqual(vm.runInContext('qux = 2; qux', context), 1);
assert.throws(() => {
vm.runInContext('Object.defineProperty(globalThis, "qux", { value: 1 });');
}, { name: 'TypeError' });
}
function checkFrozen(context) {
// Check mutation via globalThis.
vm.runInContext('globalThis.foo = 1', context); // Invoking setters on freezed object fails silently.
assert.strictEqual(context.foo, undefined);
assert.strictEqual(vm.runInContext('globalThis.foo', context), undefined);
assert.throws(() => {
vm.runInContext('foo', context); // It should not be looked up contextually.
}, {
name: 'ReferenceError'
});
// Check mutation from outside.
assert.throws(() => {
context.foo = 2;
}, { name: 'TypeError' });
assert.strictEqual(context.foo, undefined);
assert.strictEqual(vm.runInContext('globalThis.foo', context), undefined);
assert.throws(() => {
vm.runInContext('foo', context); // It should not be looked up contextually.
}, {
name: 'ReferenceError'
});
// Check contextual mutation.
vm.runInContext('bar = 1', context); // Invoking setters on freezed object fails silently.
assert.strictEqual(context.bar, undefined);
assert.strictEqual(vm.runInContext('globalThis.bar', context), undefined);
assert.throws(() => {
vm.runInContext('bar', context); // It should not be looked up contextually.
}, {
name: 'ReferenceError'
});
// Check mutation via Object.defineProperty().
assert.throws(() => {
vm.runInContext('Object.defineProperty(globalThis, "qux", {' +
'enumerable: false, configurable: false, get() { return 1; } })', context);
}, {
name: 'TypeError'
});
assert.strictEqual(context.qux, undefined);
assert.strictEqual(vm.runInContext('globalThis.qux', context), undefined);
assert.strictEqual(Object.getOwnPropertyDescriptor(context, 'qux'), undefined);
assert.throws(() => { Object.defineProperty(context, 'qux', { value: 1 }); }, { name: 'TypeError' });
assert.throws(() => {
vm.runInContext('qux', context);
}, {
name: 'ReferenceError'
});
}
{
// Check freezing the vanilla context's global object from within the context.
const context = vm.createContext(vm.constants.DONT_CONTEXTIFY);
// Only vanilla contexts' globals can be freezed. Contextified global objects cannot be freezed
// due to the presence of interceptors.
vm.runInContext('Object.freeze(globalThis)', context);
checkFrozen(context);
}
{
// Check freezing the vanilla context's global object from outside the context.
const context = vm.createContext(vm.constants.DONT_CONTEXTIFY);
Object.freeze(context);
checkFrozen(context);
}
// Check importModuleDynamically works.
(async function() {
{
const moduleUrl = fixtures.fileURL('es-modules', 'message.mjs');
const namespace = await import(moduleUrl.href);
// Check dynamic import works
const context = vm.createContext(vm.constants.DONT_CONTEXTIFY);
const script = new vm.Script(`import(${JSON.stringify(moduleUrl)})`, {
importModuleDynamically: vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER,
});
const promise = script.runInContext(context);
assert.strictEqual(await promise, namespace);
}
})().catch(common.mustNotCall());