Use toString tag to format receiver in stack traces

This concerns formatting of calls to, e.g., Math.acos in stack traces,
in which the receiver is an object with an attached toString tag. If
such a tag exists, use it to format the receiver typename to ensure that
the stack trace includes 'Math.acos' instead of 'Object.acos'.

R=yangguo@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/2110683007
Cr-Commit-Position: refs/heads/master@{#37513}
This commit is contained in:
jgruber 2016-07-05 00:42:20 -07:00 committed by Commit bot
parent 293bd78829
commit 971468031a
4 changed files with 29 additions and 6 deletions

View File

@ -599,12 +599,7 @@ function FormatStackTrace(obj, raw_stack) {
function GetTypeName(receiver, requireConstructor) {
if (IS_NULL_OR_UNDEFINED(receiver)) return null;
if (IS_PROXY(receiver)) return "Proxy";
var constructor = %GetDataProperty(TO_OBJECT(receiver), "constructor");
if (!IS_FUNCTION(constructor)) {
return requireConstructor ? null : %_Call(NoSideEffectsToString, receiver);
}
return %FunctionGetName(constructor);
return %GetConstructorName(receiver);
}

View File

@ -758,6 +758,15 @@ RUNTIME_FUNCTION(Runtime_GetDataProperty) {
return *JSReceiver::GetDataProperty(object, name);
}
RUNTIME_FUNCTION(Runtime_GetConstructorName) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
CHECK(!object->IsUndefined(isolate) && !object->IsNull(isolate));
Handle<JSReceiver> recv = Object::ToObject(isolate, object).ToHandleChecked();
return *JSReceiver::GetConstructorName(recv);
}
RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
SealHandleScope shs(isolate);

View File

@ -401,6 +401,7 @@ namespace internal {
F(DefineAccessorPropertyUnchecked, 5, 1) \
F(DefineDataPropertyInLiteral, 5, 1) \
F(GetDataProperty, 2, 1) \
F(GetConstructorName, 1, 1) \
F(HasFastPackedElements, 1, 1) \
F(ValueOf, 1, 1) \
F(IsJSReceiver, 1, 1) \

View File

@ -47,4 +47,22 @@ testBuiltinInStackTrace("Date.prototype.getTime.call('')", "at String.getTime");
// C++ builtins.
testBuiltinInStackTrace("Boolean.prototype.toString.call(thrower);",
"at Object.toString");
// Constructor builtins.
testBuiltinInStackTrace("new Date(thrower);", "at new Date");
// Ensure we correctly pick up the receiver's string tag.
testBuiltinInStackTrace("Math.max(thrower);", "at Math.max");
testBuiltinInStackTrace("Math.min(thrower);", "at Math.min");
testBuiltinInStackTrace("Math.acos(thrower);", "at Math.acos");
testBuiltinInStackTrace("Math.asin(thrower);", "at Math.asin");
testBuiltinInStackTrace("Math.fround(thrower);", "at Math.fround");
testBuiltinInStackTrace("Math.imul(thrower);", "at Math.imul");
// As above, but function passed as an argument and then called.
testBuiltinInStackTrace("((f, x) => f(x))(Math.max, thrower);", "at max");
testBuiltinInStackTrace("((f, x) => f(x))(Math.min, thrower);", "at min");
testBuiltinInStackTrace("((f, x) => f(x))(Math.acos, thrower);", "at acos");
testBuiltinInStackTrace("((f, x) => f(x))(Math.asin, thrower);", "at asin");
testBuiltinInStackTrace("((f, x) => f(x))(Math.fround, thrower);", "at fround");
testBuiltinInStackTrace("((f, x) => f(x))(Math.imul, thrower);", "at imul");