| 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) {
|
|
|