1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23// Flags: --expose-gc 24 25const common = require('../common'); 26const assert = require('assert'); 27const vm = require('vm'); 28 29if (typeof global.gc !== 'function') 30 assert.fail('Run this test with --expose-gc'); 31 32// Run a string 33const result = vm.runInNewContext('\'passed\';'); 34assert.strictEqual(result, 'passed'); 35 36// Thrown error 37assert.throws(() => { 38 vm.runInNewContext('throw new Error(\'test\');'); 39}, /^Error: test$/); 40 41global.hello = 5; 42vm.runInNewContext('hello = 2'); 43assert.strictEqual(global.hello, 5); 44 45 46// Pass values in and out 47global.code = 'foo = 1;' + 48 'bar = 2;' + 49 'if (baz !== 3) throw new Error(\'test fail\');'; 50global.foo = 2; 51global.obj = { foo: 0, baz: 3 }; 52/* eslint-disable no-unused-vars */ 53const baz = vm.runInNewContext(global.code, global.obj); 54/* eslint-enable no-unused-vars */ 55assert.strictEqual(global.obj.foo, 1); 56assert.strictEqual(global.obj.bar, 2); 57assert.strictEqual(global.foo, 2); 58 59// Call a function by reference 60function changeFoo() { global.foo = 100; } 61vm.runInNewContext('f()', { f: changeFoo }); 62assert.strictEqual(global.foo, 100); 63 64// Modify an object by reference 65const f = { a: 1 }; 66vm.runInNewContext('f.a = 2', { f }); 67assert.strictEqual(f.a, 2); 68 69// Use function in context without referencing context 70const fn = vm.runInNewContext('(function() { obj.p = {}; })', { obj: {} }); 71global.gc(); 72fn(); 73// Should not crash 74 75const filename = 'test_file.vm'; 76for (const arg of [filename, { filename }]) { 77 // Verify that providing a custom filename works. 78 const code = 'throw new Error("foo");'; 79 80 assert.throws(() => { 81 vm.runInNewContext(code, {}, arg); 82 }, (err) => { 83 const lines = err.stack.split('\n'); 84 85 assert.strictEqual(lines[0].trim(), `${filename}:1`); 86 assert.strictEqual(lines[1].trim(), code); 87 // Skip lines[2] and lines[3]. They're just a ^ and blank line. 88 assert.strictEqual(lines[4].trim(), 'Error: foo'); 89 assert.strictEqual(lines[5].trim(), `at ${filename}:1:7`); 90 // The rest of the stack is uninteresting. 91 return true; 92 }); 93} 94 95common.allowGlobals( 96 global.hello, 97 global.code, 98 global.foo, 99 global.obj 100); 101