1'use strict';
2require('../common');
3const assert = require('assert');
4const vm = require('vm');
5
6// These assertions check that we can set new keys to the global context,
7// get them back and also list them via getOwnProperty* or in.
8//
9// Related to:
10// - https://github.com/nodejs/node/issues/45983
11
12const global = vm.runInContext('this', vm.createContext());
13
14function runAssertions(data, property, viaDefine, value1, value2, value3) {
15  // Define the property for the first time
16  setPropertyAndAssert(data, property, viaDefine, value1);
17  // Update the property
18  setPropertyAndAssert(data, property, viaDefine, value2);
19  // Delete the property
20  deletePropertyAndAssert(data, property);
21  // Re-define the property
22  setPropertyAndAssert(data, property, viaDefine, value3);
23  // Delete the property again
24  deletePropertyAndAssert(data, property);
25}
26
27const fun1 = () => 1;
28const fun2 = () => 2;
29const fun3 = () => 3;
30
31function runAssertionsOnSandbox(builder) {
32  const sandboxContext = vm.createContext({ runAssertions, fun1, fun2, fun3 });
33  vm.runInContext(builder('this'), sandboxContext);
34  vm.runInContext(builder('{}'), sandboxContext);
35}
36
37// Assertions on: define property
38runAssertions(global, 'toto', true, 1, 2, 3);
39runAssertions(global, Symbol.for('toto'), true, 1, 2, 3);
40runAssertions(global, 'tutu', true, fun1, fun2, fun3);
41runAssertions(global, Symbol.for('tutu'), true, fun1, fun2, fun3);
42runAssertions(global, 'tyty', true, fun1, 2, 3);
43runAssertions(global, Symbol.for('tyty'), true, fun1, 2, 3);
44
45// Assertions on: direct assignment
46runAssertions(global, 'titi', false, 1, 2, 3);
47runAssertions(global, Symbol.for('titi'), false, 1, 2, 3);
48runAssertions(global, 'tata', false, fun1, fun2, fun3);
49runAssertions(global, Symbol.for('tata'), false, fun1, fun2, fun3);
50runAssertions(global, 'tztz', false, fun1, 2, 3);
51runAssertions(global, Symbol.for('tztz'), false, fun1, 2, 3);
52
53// Assertions on: define property from sandbox
54runAssertionsOnSandbox(
55  (variable) => `
56    runAssertions(${variable}, 'toto', true, 1, 2, 3);
57    runAssertions(${variable}, Symbol.for('toto'), true, 1, 2, 3);
58    runAssertions(${variable}, 'tutu', true, fun1, fun2, fun3);
59    runAssertions(${variable}, Symbol.for('tutu'), true, fun1, fun2, fun3);
60    runAssertions(${variable}, 'tyty', true, fun1, 2, 3);
61    runAssertions(${variable}, Symbol.for('tyty'), true, fun1, 2, 3);`
62);
63
64// Assertions on: direct assignment from sandbox
65runAssertionsOnSandbox(
66  (variable) => `
67    runAssertions(${variable}, 'titi', false, 1, 2, 3);
68    runAssertions(${variable}, Symbol.for('titi'), false, 1, 2, 3);
69    runAssertions(${variable}, 'tata', false, fun1, fun2, fun3);
70    runAssertions(${variable}, Symbol.for('tata'), false, fun1, fun2, fun3);
71    runAssertions(${variable}, 'tztz', false, fun1, 2, 3);
72    runAssertions(${variable}, Symbol.for('tztz'), false, fun1, 2, 3);`
73);
74
75// Helpers
76
77// Set the property on data and assert it worked
78function setPropertyAndAssert(data, property, viaDefine, value) {
79  if (viaDefine) {
80    Object.defineProperty(data, property, {
81      enumerable: true,
82      writable: true,
83      value: value,
84      configurable: true,
85    });
86  } else {
87    data[property] = value;
88  }
89  assert.strictEqual(data[property], value);
90  assert.ok(property in data);
91  if (typeof property === 'string') {
92    assert.ok(Object.getOwnPropertyNames(data).includes(property));
93  } else {
94    assert.ok(Object.getOwnPropertySymbols(data).includes(property));
95  }
96}
97
98// Delete the property from data and assert it worked
99function deletePropertyAndAssert(data, property) {
100  delete data[property];
101  assert.strictEqual(data[property], undefined);
102  assert.ok(!(property in data));
103  assert.ok(!Object.getOwnPropertyNames(data).includes(property));
104  assert.ok(!Object.getOwnPropertySymbols(data).includes(property));
105}
106