v8/test/inspector/debugger/side-effect-free-debug-evaluate.js
Aleksei Koziatinskii 43c775f24b inspector: debug-evaluate: allow setters on temporary Date object
Eager evaluation in DevTools console relies on the builtins side
effect attribution.

Setters on Date object should be marked as no side effects if called
on the temporary object.

This bug was uncovered after considering screenshot from a tweet [1].

[1] https://twitter.com/shuding_/status/1362132984376160256

Change-Id: Iedc0e29e2bdab719304e2f0a0435845f24eaaadc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2703459
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72835}
2021-02-18 08:21:18 +00:00

56 lines
2.5 KiB
JavaScript

// 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 someGlobalDate = new Date();
function testFunction()
{
var o = 0;
function f() { return 1; }
function g() { o = 2; return o; }
f,g;
debugger;
}
//# sourceURL=foo.js`);
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 testDate() {
const check = async (expression) => {
const {result:{exceptionDetails}} = await Protocol.Runtime.evaluate({expression, throwOnSideEffect: true});
InspectorTest.log(expression + ' : ' + (exceptionDetails ? 'throws' : 'ok'));
};
// 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()');
}
]);