From 54245bd6b28dc0f1b50bf196e9453bbe948612df Mon Sep 17 00:00:00 2001 From: kozyatinskiy Date: Tue, 31 May 2016 15:04:53 -0700 Subject: [PATCH] Debugger: fix crash in DebugEvaluate If scripts is paused in class constructor before super() call then any attempt to evaluate something like this.* on top frame will produce crash. BUG=chromium:614019 R=yangguo@chromium.org Review-Url: https://codereview.chromium.org/2013223003 Cr-Commit-Position: refs/heads/master@{#36625} --- src/debug/debug-evaluate.cc | 3 +- .../debug-evaluate-receiver-before-super.js | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/mjsunit/es6/debug-evaluate-receiver-before-super.js diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc index 263b41be68..d5ebaa560b 100644 --- a/src/debug/debug-evaluate.cc +++ b/src/debug/debug-evaluate.cc @@ -249,7 +249,8 @@ void DebugEvaluate::ContextBuilder::MaterializeReceiver( // 'this' is allocated in an outer context and is is already being // referenced by the current function, so it can be correctly resolved. return; - } else if (local_function->shared()->scope_info()->HasReceiver()) { + } else if (local_function->shared()->scope_info()->HasReceiver() && + !frame_->receiver()->IsTheHole()) { recv = handle(frame_->receiver(), isolate_); } JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check(); diff --git a/test/mjsunit/es6/debug-evaluate-receiver-before-super.js b/test/mjsunit/es6/debug-evaluate-receiver-before-super.js new file mode 100644 index 0000000000..dc8ce2cacd --- /dev/null +++ b/test/mjsunit/es6/debug-evaluate-receiver-before-super.js @@ -0,0 +1,39 @@ +// Copyright 2016 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. + +// Flags: --expose-debug-as debug + +// Test that debug-evaluate doesn't crash when this is used before super() call +// in constructor. + +Debug = debug.Debug + +var result; + +function listener(event, exec_state, event_data, data) +{ + try { + if (event == Debug.DebugEvent.Break) { + result = exec_state.frame(0).evaluate("this.a").value(); + } + } catch (e) { + result = e.message; + } +} + +Debug.setListener(listener); + +class A { constructor () { this.a = 239; } } +class B extends A { + constructor () { + debugger; + assertEquals("Cannot read property 'a' of undefined", result); + super(); + debugger; + assertEquals(239, result); + } +} +new B(); + +Debug.setListener(null);