| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| Debug = debug.Debug; |
| |
| // StaCurrentContextSlot |
| success(10, `(function(){ |
| const x = 10; |
| function f1() {return x;} |
| return x; |
| })()`); |
| |
| // StaNamedProperty |
| var a = {name: 'foo'}; |
| function set_name(a) { |
| a.name = 'bar'; |
| return a.name; |
| } |
| |
| fail(`set_name(a)`); |
| success('bar', `set_name({name: 'foo'})`); |
| |
| // StaNamedOwnProperty |
| var name_value = 'value'; |
| function create_object_literal() { |
| var obj = {name: name_value}; |
| return obj.name; |
| }; |
| |
| success('value', `create_object_literal()`); |
| |
| // StaKeyedProperty |
| var arrayValue = 1; |
| function create_array_literal() { |
| return [arrayValue]; |
| } |
| var b = { 1: 2 }; |
| |
| success([arrayValue], `create_array_literal()`) |
| fail(`b[1] ^= 2`); |
| |
| // StaInArrayLiteral |
| function return_array_use_spread(a) { |
| return [...a]; |
| } |
| |
| success([1], `return_array_use_spread([1])`); |
| |
| // CallAccessorSetter |
| var array = [1,2,3]; |
| fail(`array.length = 2`); |
| success(2, `[1,2,3].length = 2`); |
| |
| // StaDataPropertyInLiteral |
| function return_literal_with_data_property(a) { |
| return {[a] : 1}; |
| } |
| |
| success({foo: 1}, `return_literal_with_data_property('foo')`); |
| |
| // Set builtins with temporary objects |
| var set = new Set([1,2]); |
| fail(`set.add(3).size`); |
| success(1, `new Set().add(1).size`); |
| |
| success(0, `(() => { const s = new Set([1]); s.delete(1); return s.size; })()`); |
| fail(`set.delete(1)`); |
| |
| success(0, `(() => { const s = new Set([1]); s.clear(); return s.size; })()`); |
| fail(`set.clear()`); |
| |
| // new set |
| success(3, `(() => { |
| let s = 0; |
| for (const a of new Set([1,2])) |
| s += a; |
| return s; |
| })()`); |
| // existing set |
| success(3, `(() => { |
| let s = 0; |
| for (const a of set) |
| s += a; |
| return s; |
| })()`); |
| // existing iterator |
| var setIterator = set.entries(); |
| fail(`(() => { |
| let s = 0; |
| for (const a of setIterator) |
| s += a; |
| return s; |
| })()`); |
| |
| // Array builtins with temporary objects |
| success([1,1,1], '[1,2,3].fill(1)'); |
| fail(`array.fill(1)`); |
| |
| success([1], `(() => { const a = []; a.push(1); return a; })()`); |
| fail(`array.push(1)`); |
| |
| success([1], `(() => { const a = [1,2]; a.pop(); return a; })()`); |
| fail(`array.pop()`); |
| |
| success([3,2,1], `[1,2,3].reverse()`); |
| fail(`array.reverse()`); |
| |
| success([1,2,3], `[2,1,3].sort()`); |
| fail(`array.sort()`); |
| |
| success([2,3], `[1,2,3].splice(1,2)`); |
| fail(`array.splice(1,2)`); |
| |
| success([1,2], `(() => { const a = [2]; a.unshift(1); return a; })()`); |
| fail(`array.unshift(1)`); |
| success(1, `[1,2].shift()`); |
| fail(`array.shift()`); |
| |
| // new array |
| success(6, `(() => { |
| let s = 0; |
| for (const a of [1,2,3]) |
| s += a; |
| return s; |
| })()`); |
| // existing array |
| success(6, `(() => { |
| let s = 0; |
| for (const a of array) |
| s += a; |
| return s; |
| })()`); |
| // existing iterator |
| var arrayIterator = array.entries(); |
| fail(`(() => { |
| let s = 0; |
| for (const a of arrayIterator) |
| s += a; |
| return s; |
| })()`); |
| |
| success(6, `array.reduce((a,b) => a + b, 0)`); |
| |
| // Map builtins with temporary objects |
| var map = new Map([[1,2]]); |
| fail(`map.set(3, 4).size`); |
| success(1, `new Map().set(1, 2).size`); |
| |
| success(0, `(() => { |
| const m = new Map([[1, 2]]); |
| m.delete(1); |
| return m.size; |
| })()`); |
| fail(`map.delete(1)`); |
| |
| success(0, `(() => { |
| const m = new Map([[1, 2]]); |
| m.clear(); |
| return m.size; |
| })()`); |
| fail(`map.clear()`); |
| |
| // new set |
| success(2, `(() => { |
| let s = 0; |
| for (const [a, b] of new Map([[1,2]])) |
| s += b; |
| return s; |
| })()`); |
| // existing set |
| success(2, `(() => { |
| let s = 0; |
| for (const [a,b] of map) |
| s += b; |
| return s; |
| })()`); |
| // existing iterator |
| var mapIterator = map.entries(); |
| fail(`(() => { |
| let s = 0; |
| for (const [a,b] of mapIterator) |
| s += a; |
| return s; |
| })()`); |
| |
| // Regexps |
| var regExp = /a/; |
| success(true, `/a/.test('a')`); |
| fail(`/a/.test({toString: () => {map.clear(); return 'a';}})`) |
| fail(`regExp.test('a')`); |
| |
| function success(expectation, source) { |
| const result = Debug.evaluateGlobal(source, true).value(); |
| if (expectation !== undefined) assertEquals(expectation, result); |
| } |
| |
| function fail(source) { |
| assertThrows(() => Debug.evaluateGlobal(source, true), |
| EvalError); |
| } |