Skip to content

Commit eba7d2d

Browse files
committed
deps: V8: cherry-pick ad21d212fc14
Original commit message: Preserve "proper method names" as-is in error.stack. This changes the logic for generating method names in `error.stack` to prepend an inferred type name only when the function name is a valid ECMAScript identifiers and does not equal the inferred type name, to (1) give developers more control over the exact name shown in `error.stack`, as well as (2) avoid confusion in the presence of renaming of local variables. Previously we'd leave the function name as-is if it was prefixed by the inferred type name, but that condition is unnecessarily strict, and led to a bunch of inconsistencies around special names like `<instance_member_initializer>` where this dynamic approached often prefixed it with the correct type name, but also sometimes got it wrong and prepended `Object.`, which is very unfortunate and misleading. Specifically for these special names, we'll add logic later in the parser to infer a useful (complete) name. The design doc (https://bit.ly/devtools-method-names-in-stack-traces) contains more background and examples of why we do this change. Doc: https://bit.ly/devtools-method-names-in-stack-traces Fixed: chromium:1294619 Bug: chromium:1283435 Change-Id: Ib8b528ba25255dcd07e9d11044c562c11d699bcb Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3565724 Reviewed-by: Yang Guo <yangguo@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/main@{#79748} Refs: v8/v8@ad21d21 PR-URL: #42657 Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
1 parent 004137e commit eba7d2d

14 files changed

+102
-65
lines changed

common.gypi

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
# Reset this number to 0 on major V8 upgrades.
3838
# Increment by one for each non-official patch applied to deps/v8.
39-
'v8_embedder_string': '-node.11',
39+
'v8_embedder_string': '-node.12',
4040

4141
##### V8 defaults for Node.js #####
4242

deps/v8/src/api/api.cc

+1-24
Original file line numberDiff line numberDiff line change
@@ -2537,29 +2537,6 @@ MaybeLocal<Module> ScriptCompiler::CompileModule(
25372537
return ToApiHandle<Module>(i_isolate->factory()->NewSourceTextModule(shared));
25382538
}
25392539

2540-
namespace {
2541-
bool IsIdentifier(i::Isolate* isolate, i::Handle<i::String> string) {
2542-
string = i::String::Flatten(isolate, string);
2543-
const int length = string->length();
2544-
if (length == 0) return false;
2545-
if (!i::IsIdentifierStart(string->Get(0))) return false;
2546-
i::DisallowGarbageCollection no_gc;
2547-
i::String::FlatContent flat = string->GetFlatContent(no_gc);
2548-
if (flat.IsOneByte()) {
2549-
auto vector = flat.ToOneByteVector();
2550-
for (int i = 1; i < length; i++) {
2551-
if (!i::IsIdentifierPart(vector[i])) return false;
2552-
}
2553-
} else {
2554-
auto vector = flat.ToUC16Vector();
2555-
for (int i = 1; i < length; i++) {
2556-
if (!i::IsIdentifierPart(vector[i])) return false;
2557-
}
2558-
}
2559-
return true;
2560-
}
2561-
} // namespace
2562-
25632540
// static
25642541
V8_WARN_UNUSED_RESULT MaybeLocal<Function> ScriptCompiler::CompileFunction(
25652542
Local<Context> context, Source* source, size_t arguments_count,
@@ -2608,7 +2585,7 @@ MaybeLocal<Function> ScriptCompiler::CompileFunctionInternal(
26082585
isolate->factory()->NewFixedArray(static_cast<int>(arguments_count));
26092586
for (int i = 0; i < static_cast<int>(arguments_count); i++) {
26102587
i::Handle<i::String> argument = Utils::OpenHandle(*arguments[i]);
2611-
if (!IsIdentifier(isolate, argument)) return Local<Function>();
2588+
if (!i::String::IsIdentifier(isolate, argument)) return Local<Function>();
26122589
arguments_list->set(i, *argument);
26132590
}
26142591

deps/v8/src/objects/call-site-info.cc

+2-9
Original file line numberDiff line numberDiff line change
@@ -629,12 +629,6 @@ void AppendFileLocation(Isolate* isolate, Handle<CallSiteInfo> frame,
629629
}
630630
}
631631

632-
int StringIndexOf(Isolate* isolate, Handle<String> subject,
633-
Handle<String> pattern) {
634-
if (pattern->length() > subject->length()) return -1;
635-
return String::IndexOf(isolate, subject, pattern, 0);
636-
}
637-
638632
// Returns true iff
639633
// 1. the subject ends with '.' + pattern, or
640634
// 2. subject == pattern.
@@ -676,9 +670,8 @@ void AppendMethodCall(Isolate* isolate, Handle<CallSiteInfo> frame,
676670
Handle<String> function_string = Handle<String>::cast(function_name);
677671
if (IsNonEmptyString(type_name)) {
678672
Handle<String> type_string = Handle<String>::cast(type_name);
679-
bool starts_with_type_name =
680-
(StringIndexOf(isolate, function_string, type_string) == 0);
681-
if (!starts_with_type_name) {
673+
if (String::IsIdentifier(isolate, function_string) &&
674+
!String::Equals(isolate, function_string, type_string)) {
682675
builder->AppendString(type_string);
683676
builder->AppendCharacter('.');
684677
}

deps/v8/src/objects/string.cc

+29
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,35 @@ bool String::HasOneBytePrefix(base::Vector<const char> str) {
15581558

15591559
namespace {
15601560

1561+
template <typename Char>
1562+
bool IsIdentifierVector(const base::Vector<Char>& vec) {
1563+
if (vec.empty()) {
1564+
return false;
1565+
}
1566+
if (!IsIdentifierStart(vec[0])) {
1567+
return false;
1568+
}
1569+
for (size_t i = 1; i < vec.size(); ++i) {
1570+
if (!IsIdentifierPart(vec[i])) {
1571+
return false;
1572+
}
1573+
}
1574+
return true;
1575+
}
1576+
1577+
} // namespace
1578+
1579+
// static
1580+
bool String::IsIdentifier(Isolate* isolate, Handle<String> str) {
1581+
str = String::Flatten(isolate, str);
1582+
DisallowGarbageCollection no_gc;
1583+
String::FlatContent flat = str->GetFlatContent(no_gc);
1584+
return flat.IsOneByte() ? IsIdentifierVector(flat.ToOneByteVector())
1585+
: IsIdentifierVector(flat.ToUC16Vector());
1586+
}
1587+
1588+
namespace {
1589+
15611590
template <typename Char>
15621591
uint32_t HashString(String string, size_t start, int length, uint64_t seed,
15631592
PtrComprCageBase cage_base,

deps/v8/src/objects/string.h

+3
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,9 @@ class String : public TorqueGeneratedString<String, Name> {
391391
V8_EXPORT_PRIVATE bool HasOneBytePrefix(base::Vector<const char> str);
392392
V8_EXPORT_PRIVATE inline bool IsOneByteEqualTo(base::Vector<const char> str);
393393

394+
// Returns true if the |str| is a valid ECMAScript identifier.
395+
static bool IsIdentifier(Isolate* isolate, Handle<String> str);
396+
394397
// Return a UTF8 representation of the string. The string is null
395398
// terminated but may optionally contain nulls. Length is returned
396399
// in length_output if length_output is not a null pointer The string

deps/v8/test/message/fail/class-fields-static-throw.js

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright 2018 the V8 project authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
//
5-
// TODO(gsathya): Remove 'Function' from stack trace.
64

75
class X {
86
static x = foo();
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
*%(basename)s:8: ReferenceError: foo is not defined
1+
*%(basename)s:6: ReferenceError: foo is not defined
22
static x = foo();
33
^
44
ReferenceError: foo is not defined
5-
at Function.<static_initializer> (*%(basename)s:8:14)
5+
at <static_initializer> (*%(basename)s:6:14)
66
at *%(basename)s:1:1

deps/v8/test/message/fail/class-fields-throw.out

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
x = foo();
33
^
44
ReferenceError: foo is not defined
5-
at X.<instance_members_initializer> (*%(basename)s:6:7)
5+
at <instance_members_initializer> (*%(basename)s:6:7)
66
at new X (*%(basename)s:5:1)
7-
at *%(basename)s:9:1
7+
at *%(basename)s:9:1

deps/v8/test/message/fail/class-private-field-reinitialization.out

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
class B extends A { #x; }
33
^
44
TypeError: Cannot initialize #x twice on the same object
5-
at Object.<instance_members_initializer> (*%(basename)s:7:21)
5+
at <instance_members_initializer> (*%(basename)s:7:21)
66
at new B (*%(basename)s:7:1)
77
at *%(basename)s:10:1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2022 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// Check that the user configured method name ('SomeClass.someMethod') is used
6+
// as-is in error.stack output without prepending the inferred type name ('A').
7+
const A = function() {};
8+
A.prototype.a = function() {
9+
throw new Error;
10+
};
11+
Object.defineProperty(A.prototype.a, 'name', {value: 'SomeClass.someMethod'});
12+
(new A).a();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright 2022 the V8 project authors. All rights reserved.
2+
# Use of this source code is governed by a BSD-style license that can be
3+
# found in the LICENSE file.
4+
5+
*%(basename)s:9: Error
6+
throw new Error;
7+
^
8+
Error
9+
at SomeClass.someMethod [as a] (*%(basename)s:9:9)
10+
at *%(basename)s:12:9
11+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2022 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// Check that the dynamic type name ('A') is not prepended to the inferred
6+
// method name ('C.a') in error.stack output.
7+
const A = function() {};
8+
const C = A;
9+
C.prototype.a = function() {
10+
throw new Error;
11+
};
12+
(new A).a();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright 2022 the V8 project authors. All rights reserved.
2+
# Use of this source code is governed by a BSD-style license that can be
3+
# found in the LICENSE file.
4+
5+
*%(basename)s:10: Error
6+
throw new Error;
7+
^
8+
Error
9+
at C.a (*%(basename)s:10:9)
10+
at *%(basename)s:12:9
11+

deps/v8/test/mjsunit/stack-traces-class-fields.js

+15-24
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,13 @@ function testClassInstantiation() {
7575

7676
// ReferenceError: FAIL is not defined
7777
// at thrower
78-
// at X.<instance_members_initializer>
78+
// at <instance_members_initializer>
7979
// at new X
8080
// at testClassInstantiation
8181
// at testTrace
8282
testTrace(
83-
"during class instantiation",
84-
testClassInstantiation,
85-
["thrower", "X.<instance_members_initializer>", "new X"],
86-
["anonymous"]
87-
);
83+
'during class instantiation', testClassInstantiation,
84+
['thrower', '<instance_members_initializer>', 'new X'], ['anonymous']);
8885

8986
function testClassInstantiationWithSuper() {
9087
class Base {}
@@ -98,16 +95,14 @@ function testClassInstantiationWithSuper() {
9895

9996
// ReferenceError: FAIL is not defined
10097
// at thrower
101-
// at X.<instance_members_initializer>
98+
// at <instance_members_initializer>
10299
// at new X
103100
// at testClassInstantiation
104101
// at testTrace
105102
testTrace(
106-
"during class instantiation with super",
107-
testClassInstantiationWithSuper,
108-
["thrower", "X.<instance_members_initializer>", "new X"],
109-
["Base", "anonymous"]
110-
);
103+
'during class instantiation with super', testClassInstantiationWithSuper,
104+
['thrower', '<instance_members_initializer>', 'new X'],
105+
['Base', 'anonymous']);
111106

112107
function testClassInstantiationWithSuper2() {
113108
class Base {}
@@ -124,16 +119,14 @@ function testClassInstantiationWithSuper2() {
124119

125120
// ReferenceError: FAIL is not defined
126121
// at thrower
127-
// at X.<instance_members_initializer>
122+
// at <instance_members_initializer>
128123
// at new X
129124
// at testClassInstantiation
130125
// at testTrace
131126
testTrace(
132-
"during class instantiation with super2",
133-
testClassInstantiationWithSuper2,
134-
["thrower", "X.<instance_members_initializer>", "new X"],
135-
["Base", "anonymous"]
136-
);
127+
'during class instantiation with super2', testClassInstantiationWithSuper2,
128+
['thrower', '<instance_members_initializer>', 'new X'],
129+
['Base', 'anonymous']);
137130

138131
function testClassInstantiationWithSuper3() {
139132
class Base {
@@ -151,17 +144,15 @@ function testClassInstantiationWithSuper3() {
151144

152145
// ReferenceError: FAIL is not defined
153146
// at thrower
154-
// at X.<instance_members_initializer>
147+
// at <instance_members_initializer>
155148
// at new Base
156149
// at new X
157150
// at testClassInstantiationWithSuper3
158151
// at testTrace
159152
testTrace(
160-
"during class instantiation with super3",
161-
testClassInstantiationWithSuper3,
162-
["thrower", "X.<instance_members_initializer>", "new Base", "new X"],
163-
["anonymous"]
164-
);
153+
'during class instantiation with super3', testClassInstantiationWithSuper3,
154+
['thrower', '<instance_members_initializer>', 'new Base', 'new X'],
155+
['anonymous']);
165156

166157
function testClassFieldCall() {
167158
class X {

0 commit comments

Comments
 (0)