| Index: src/js/messages.js
|
| diff --git a/src/js/messages.js b/src/js/messages.js
|
| index d0305412b74896a7971e4e435032b5f9a8ee3a05..dc845ea97adc855fa7d0847374dad1af99e7551a 100644
|
| --- a/src/js/messages.js
|
| +++ b/src/js/messages.js
|
| @@ -23,7 +23,6 @@
|
| 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");
|
| @@ -42,7 +41,6 @@
|
| var StringIndexOf;
|
| var StringSubstring;
|
| var SymbolToString;
|
| -var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
| var Uint16x8ToString;
|
| var Uint32x4ToString;
|
| var Uint8x16ToString;
|
| @@ -68,10 +66,6 @@
|
| Uint8x16ToString = from.Uint8x16ToString;
|
| });
|
|
|
| -utils.ImportFromExperimental(function(from) {
|
| - FLAG_harmony_tostring = from.FLAG_harmony_tostring;
|
| -});
|
| -
|
| // -------------------------------------------------------------------
|
|
|
| var GlobalError;
|
| @@ -86,35 +80,11 @@
|
| function NoSideEffectsObjectToString() {
|
| if (IS_UNDEFINED(this)) return "[object Undefined]";
|
| if (IS_NULL(this)) return "[object Null]";
|
| - 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 NoSideEffectsToString(obj) {
|
| + return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
|
| +}
|
| +
|
| +
|
| +function NoSideEffectToString(obj) {
|
| if (IS_STRING(obj)) return obj;
|
| if (IS_NUMBER(obj)) return %_NumberToString(obj);
|
| if (IS_BOOLEAN(obj)) return obj ? 'true' : 'false';
|
| @@ -143,26 +113,69 @@
|
| case 'bool8x16': return %_Call(Bool8x16ToString, 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);
|
| - }
|
| -
|
| - 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}>`;
|
| + 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);
|
| + }
|
| +}
|
| +
|
| +
|
| +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 + ">";
|
| + }
|
| + }
|
| + }
|
| + return ToStringCheckErrorObject(obj);
|
| }
|
|
|
|
|
| @@ -187,9 +200,9 @@
|
|
|
| // Helper functions; called from the runtime system.
|
| function FormatMessage(type, arg0, arg1, arg2) {
|
| - var arg0 = NoSideEffectsToString(arg0);
|
| - var arg1 = NoSideEffectsToString(arg1);
|
| - var arg2 = NoSideEffectsToString(arg2);
|
| + var arg0 = NoSideEffectToString(arg0);
|
| + var arg1 = NoSideEffectToString(arg1);
|
| + var arg2 = NoSideEffectToString(arg2);
|
| try {
|
| return %FormatMessageString(type, arg0, arg1, arg2);
|
| } catch (e) {
|
| @@ -836,13 +849,20 @@
|
|
|
| function GetTypeName(receiver, requireConstructor) {
|
| if (IS_NULL_OR_UNDEFINED(receiver)) return null;
|
| - if (%_IsJSProxy(receiver)) return "Proxy";
|
| -
|
| - var constructor = %GetDataProperty(TO_OBJECT(receiver), "constructor");
|
| - if (!IS_FUNCTION(constructor)) {
|
| - return requireConstructor ? null : %_Call(NoSideEffectsToString, receiver);
|
| - }
|
| - return %FunctionGetName(constructor);
|
| + 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);
|
| + }
|
| + return constructorName;
|
| }
|
|
|
|
|
| @@ -876,7 +896,7 @@
|
| // If the receiver equals the holder, set the formatted stack trace that the
|
| // getter returns.
|
| var StackTraceSetter = function(v) {
|
| - if (IsErrorObject(this)) {
|
| + if (HAS_PRIVATE(this, stackTraceSymbol)) {
|
| SET_PRIVATE(this, stackTraceSymbol, UNDEFINED);
|
| SET_PRIVATE(this, formattedStackTraceSymbol, v);
|
| }
|
| @@ -936,15 +956,7 @@
|
| throw MakeTypeError(kCalledOnNonObject, "Error.prototype.toString");
|
| }
|
|
|
| - 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}`
|
| + return %ErrorToStringRT(this);
|
| }
|
|
|
| function MakeError(type, arg0, arg1, arg2) {
|
| @@ -992,8 +1004,9 @@
|
| "message_get_column_number", GetColumnNumber,
|
| "message_get_line_number", GetLineNumber,
|
| "message_get_source_line", GetSourceLine,
|
| - "no_side_effects_to_string_fun", NoSideEffectsToString,
|
| + "no_side_effect_to_string_fun", NoSideEffectToString,
|
| "stack_overflow_boilerplate", StackOverflowBoilerplate,
|
| + "to_detail_string_fun", ToDetailString,
|
| ]);
|
|
|
| utils.Export(function(to) {
|
|
|