Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1023)

Unified Diff: src/js/messages.js

Issue 1507273002: Make Error.prototype.toString spec compliant; and fix various side-effect-free error printing metho… (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/isolate.cc ('k') | src/messages.h » ('j') | src/messages.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/js/messages.js
diff --git a/src/js/messages.js b/src/js/messages.js
index dc845ea97adc855fa7d0847374dad1af99e7551a..d0305412b74896a7971e4e435032b5f9a8ee3a05 100644
--- a/src/js/messages.js
+++ b/src/js/messages.js
@@ -23,6 +23,7 @@ var callSitePositionSymbol =
utils.ImportNow("call_site_position_symbol");
var callSiteStrictSymbol =
utils.ImportNow("call_site_strict_symbol");
+var FLAG_harmony_tostring;
var Float32x4ToString;
var formattedStackTraceSymbol =
utils.ImportNow("formatted_stack_trace_symbol");
@@ -41,6 +42,7 @@ var StringCharAt;
var StringIndexOf;
var StringSubstring;
var SymbolToString;
+var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
var Uint16x8ToString;
var Uint32x4ToString;
var Uint8x16ToString;
@@ -66,6 +68,10 @@ utils.Import(function(from) {
Uint8x16ToString = from.Uint8x16ToString;
});
+utils.ImportFromExperimental(function(from) {
+ FLAG_harmony_tostring = from.FLAG_harmony_tostring;
+});
+
// -------------------------------------------------------------------
var GlobalError;
@@ -80,11 +86,35 @@ var GlobalEvalError;
function NoSideEffectsObjectToString() {
if (IS_UNDEFINED(this)) return "[object Undefined]";
if (IS_NULL(this)) return "[object Null]";
- return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
+ var O = TO_OBJECT(this);
+ var builtinTag = %_ClassOf(O);
+ var tag;
+ if (FLAG_harmony_tostring) {
+ tag = %GetDataProperty(O, toStringTagSymbol);
+ if (!IS_STRING(tag)) {
+ tag = builtinTag;
+ }
+ } else {
+ tag = builtinTag;
+ }
+ return `[object ${tag}]`;
+}
+
+function IsErrorObject(obj) {
+ return HAS_PRIVATE(obj, stackTraceSymbol);
}
+function NoSideEffectsErrorToString() {
+ var name = %GetDataProperty(this, "name");
+ var message = %GetDataProperty(this, "message");
+ name = IS_UNDEFINED(name) ? "Error" : NoSideEffectsToString(name);
+ message = IS_UNDEFINED(message) ? "" : NoSideEffectsToString(message);
+ if (name == "") return message;
+ if (message == "") return name;
+ return `${name}: ${message}`;
+}
-function NoSideEffectToString(obj) {
+function NoSideEffectsToString(obj) {
if (IS_STRING(obj)) return obj;
if (IS_NUMBER(obj)) return %_NumberToString(obj);
if (IS_BOOLEAN(obj)) return obj ? 'true' : 'false';
@@ -113,69 +143,26 @@ function NoSideEffectToString(obj) {
case 'bool8x16': return %_Call(Bool8x16ToString, obj);
}
}
- if (IS_OBJECT(obj)
- && %GetDataProperty(obj, "toString") === ObjectToString) {
- var constructor = %GetDataProperty(obj, "constructor");
- if (typeof constructor == "function") {
- var constructorName = constructor.name;
- if (IS_STRING(constructorName) && constructorName !== "") {
- return "#<" + constructorName + ">";
- }
- }
- }
- if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
- return %_Call(ErrorToString, obj);
- }
-
- return %_Call(NoSideEffectsObjectToString, obj);
-}
-
-// To determine whether we can safely stringify an object using ErrorToString
-// without the risk of side-effects, we need to check whether the object is
-// either an instance of a native error type (via '%_ClassOf'), or has Error
-// in its prototype chain and hasn't overwritten 'toString' with something
-// strange and unusual.
-function CanBeSafelyTreatedAsAnErrorObject(obj) {
- switch (%_ClassOf(obj)) {
- case 'Error':
- case 'EvalError':
- case 'RangeError':
- case 'ReferenceError':
- case 'SyntaxError':
- case 'TypeError':
- case 'URIError':
- return true;
- }
-
- var objToString = %GetDataProperty(obj, "toString");
- return obj instanceof GlobalError && objToString === ErrorToString;
-}
-
-
-// When formatting internally created error messages, do not
-// invoke overwritten error toString methods but explicitly use
-// the error to string method. This is to avoid leaking error
-// objects between script tags in a browser setting.
-function ToStringCheckErrorObject(obj) {
- if (CanBeSafelyTreatedAsAnErrorObject(obj)) {
- return %_Call(ErrorToString, obj);
- } else {
- return TO_STRING(obj);
- }
-}
+ if (IS_SPEC_OBJECT(obj)) {
+ // When internally formatting error objects, use a side-effects-free version
+ // of Error.prototype.toString independent of the actually installed
+ // toString method.
+ if (IsErrorObject(obj) ||
+ %GetDataProperty(obj, "toString") === ErrorToString) {
+ return %_Call(NoSideEffectsErrorToString, obj);
+ }
-function ToDetailString(obj) {
- if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) {
- var constructor = obj.constructor;
- if (typeof constructor == "function") {
- var constructorName = constructor.name;
- if (IS_STRING(constructorName) && constructorName !== "") {
- return "#<" + constructorName + ">";
+ if (%GetDataProperty(obj, "toString") === ObjectToString) {
+ var constructor = %GetDataProperty(obj, "constructor");
+ if (IS_FUNCTION(constructor)) {
+ var constructor_name = %FunctionGetName(constructor);
+ if (constructor_name != "") return `#<${constructor_name}>`;
}
}
}
- return ToStringCheckErrorObject(obj);
+
+ return %_Call(NoSideEffectsObjectToString, obj);
}
@@ -200,9 +187,9 @@ function MakeGenericError(constructor, type, arg0, arg1, arg2) {
// Helper functions; called from the runtime system.
function FormatMessage(type, arg0, arg1, arg2) {
- var arg0 = NoSideEffectToString(arg0);
- var arg1 = NoSideEffectToString(arg1);
- var arg2 = NoSideEffectToString(arg2);
+ var arg0 = NoSideEffectsToString(arg0);
+ var arg1 = NoSideEffectsToString(arg1);
+ var arg2 = NoSideEffectsToString(arg2);
try {
return %FormatMessageString(type, arg0, arg1, arg2);
} catch (e) {
@@ -849,20 +836,13 @@ function FormatStackTrace(obj, raw_stack) {
function GetTypeName(receiver, requireConstructor) {
if (IS_NULL_OR_UNDEFINED(receiver)) return null;
- if (%_IsJSProxy(receiver)) {
- return "Proxy";
- };
- var constructor = receiver.constructor;
- if (!constructor) {
- return requireConstructor ? null :
- %_Call(NoSideEffectsObjectToString, receiver);
- }
- var constructorName = constructor.name;
- if (!constructorName) {
- return requireConstructor ? null :
- %_Call(NoSideEffectsObjectToString, receiver);
+ if (%_IsJSProxy(receiver)) return "Proxy";
+
+ var constructor = %GetDataProperty(TO_OBJECT(receiver), "constructor");
+ if (!IS_FUNCTION(constructor)) {
+ return requireConstructor ? null : %_Call(NoSideEffectsToString, receiver);
}
- return constructorName;
+ return %FunctionGetName(constructor);
}
@@ -896,7 +876,7 @@ var StackTraceGetter = function() {
// If the receiver equals the holder, set the formatted stack trace that the
// getter returns.
var StackTraceSetter = function(v) {
- if (HAS_PRIVATE(this, stackTraceSymbol)) {
+ if (IsErrorObject(this)) {
SET_PRIVATE(this, stackTraceSymbol, UNDEFINED);
SET_PRIVATE(this, formattedStackTraceSymbol, v);
}
@@ -956,7 +936,15 @@ function ErrorToString() {
throw MakeTypeError(kCalledOnNonObject, "Error.prototype.toString");
}
- return %ErrorToStringRT(this);
+ var name = this.name;
+ name = IS_UNDEFINED(name) ? "Error" : TO_STRING(name);
+
+ var message = this.message;
+ message = IS_UNDEFINED(message) ? "" : TO_STRING(message);
+
+ if (name == "") return message;
+ if (message == "") return name;
+ return `${name}: ${message}`
}
function MakeError(type, arg0, arg1, arg2) {
@@ -1004,9 +992,8 @@ GlobalError.captureStackTrace = captureStackTrace;
"message_get_column_number", GetColumnNumber,
"message_get_line_number", GetLineNumber,
"message_get_source_line", GetSourceLine,
- "no_side_effect_to_string_fun", NoSideEffectToString,
+ "no_side_effects_to_string_fun", NoSideEffectsToString,
"stack_overflow_boilerplate", StackOverflowBoilerplate,
- "to_detail_string_fun", ToDetailString,
]);
utils.Export(function(to) {
« no previous file with comments | « src/isolate.cc ('k') | src/messages.h » ('j') | src/messages.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698