// Copyright 2017 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. let {session, contextGroup, Protocol} = InspectorTest.start('Tests side-effect-free evaluation'); contextGroup.addScript(` var someGlobalArray = [1, 2]; var someGlobalArrayIterator = someGlobalArray[Symbol.iterator](); var someGlobalDate = new Date(); var someGlobalMap = new Map([[1, 2], [3, 4]]); var someGlobalMapKeysIterator = someGlobalMap.keys(); var someGlobalMapValuesIterator = someGlobalMap.values(); var someGlobalSet = new Set([1, 2]) var someGlobalSetIterator = someGlobalSet.values(); function testFunction() { var o = 0; function f() { return 1; } function g() { o = 2; return o; } f,g; debugger; } async function testAsyncFunction(action) { switch (action) { case "resolve": return 1; case "reject": throw new Error(); } } `, 0, 0, 'foo.js'); const check = async (expression) => { const {result:{exceptionDetails}} = await Protocol.Runtime.evaluate({expression, throwOnSideEffect: true}); InspectorTest.log(expression + ' : ' + (exceptionDetails ? 'throws' : 'ok')); }; InspectorTest.runAsyncTestSuite([ async function basicTest() { Protocol.Debugger.enable(); Protocol.Runtime.evaluate({ 'expression': 'setTimeout(testFunction, 0)' }); const {params:{callFrames:[{callFrameId: topFrameId}]}} = await Protocol.Debugger.oncePaused(); InspectorTest.log('Paused on "debugger;"'); const {result:{result:{value: fResult}}} = await Protocol.Debugger.evaluateOnCallFrame({ callFrameId: topFrameId, expression: 'f()' }); InspectorTest.log('f() returns ' + fResult); const {result:{result:{value: gResult}}} = await Protocol.Debugger.evaluateOnCallFrame({ callFrameId: topFrameId, expression: 'g()' }); InspectorTest.log('g() returns ' + gResult); const {result:{result:{value: fResultSideEffect}}} = await Protocol.Debugger.evaluateOnCallFrame({ callFrameId: topFrameId, expression: 'f()', throwOnSideEffect: true}); InspectorTest.log('f() returns ' + fResultSideEffect); const {result:{result:{className}}} = await Protocol.Debugger.evaluateOnCallFrame({ callFrameId: topFrameId, expression: 'g()', throwOnSideEffect: true}); InspectorTest.log('g() throws ' + className); }, async function testAsyncFunctions() { await check('testAsyncFunction("resolve")'); await check('testAsyncFunction("reject")'); }, async function testDate() { // setters are only ok on temporary objects await check('someGlobalDate.setDate(10)'); await check('new Date().setDate(10)'); await check('someGlobalDate.setFullYear(1991)'); await check('new Date().setFullYear(1991)'); await check('someGlobalDate.setHours(0)'); await check('new Date().setHours(0)'); // getters are ok on any Date await check('someGlobalDate.getDate()'); await check('new Date().getDate()'); await check('someGlobalDate.getFullYear()'); await check('new Date().getFullYear()'); await check('someGlobalDate.getHours()'); await check('new Date().getHours()'); }, async function testPromiseReject() { await check('Promise.reject()'); }, async function testSpread() { await check('[...someGlobalArray]'); await check('[...someGlobalArray.values()]'); await check('[...someGlobalArrayIterator]'); await check('[...someGlobalMap]'); await check('[...someGlobalMap.keys()]'); await check('[...someGlobalMap.values()]'); await check('[...someGlobalMapKeysIterator]'); await check('[...someGlobalMapValuesIterator]'); await check('[...someGlobalSet]'); await check('[...someGlobalSet.values()]'); await check('[...someGlobalSetIterator]'); } ]);