Index: src/messages.js |
diff --git a/src/messages.js b/src/messages.js |
index cbbb70eb1a8e37392676cc8258cdfb17afacd89b..0109253b9fd13b20a3ad56cde1a646e87951486d 100644 |
--- a/src/messages.js |
+++ b/src/messages.js |
@@ -44,11 +44,11 @@ var kNoLineNumberInfo = 0; |
// If this object gets passed to an error constructor the error will |
// get an accessor for .message that constructs a descriptive error |
// message on access. |
-var kAddMessageAccessorsMarker = { }; |
+const kAddMessageAccessorsMarker = { }; |
-var kMessages = 0; |
- |
-var kReplacementMarkers = [ "%0", "%1", "%2", "%3" ]; |
+// This will be lazily initialized when first needed (and forcibly |
+// overwritten even though it's const). |
+const kMessages = 0; |
function FormatString(format, message) { |
var args = %MessageGetArguments(message); |
@@ -56,14 +56,16 @@ function FormatString(format, message) { |
var arg_num = 0; |
for (var i = 0; i < format.length; i++) { |
var str = format[i]; |
- for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) { |
- if (str == kReplacementMarkers[arg_num]) { |
+ if (str.length == 2 && %_StringCharCodeAt(str, 0) == 0x25) { |
+ // Two-char string starts with "%". |
+ var arg_num = (%_StringCharCodeAt(str, 1) - 0x30) >>> 0; |
+ if (arg_num < 4) { |
+ // str is one of %0, %1, %2 or %3. |
try { |
str = ToDetailString(args[arg_num]); |
} catch (e) { |
str = "#<error>"; |
} |
- break; |
} |
} |
result += str; |
@@ -102,18 +104,16 @@ function ToStringCheckErrorObject(obj) { |
function ToDetailString(obj) { |
- if (obj != null && IS_OBJECT(obj) && |
- obj.toString === $Object.prototype.toString) { |
+ if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) { |
var constructor = obj.constructor; |
- if (!constructor) return ToStringCheckErrorObject(obj); |
- var constructorName = constructor.name; |
- if (!constructorName || !IS_STRING(constructorName)) { |
- return ToStringCheckErrorObject(obj); |
+ if (typeof constructor == "function") { |
+ var constructorName = constructor.name; |
+ if (IS_STRING(constructorName) && constructorName !== "") { |
+ return "#<" + constructorName + ">"; |
+ } |
} |
- return "#<" + constructorName + ">"; |
- } else { |
- return ToStringCheckErrorObject(obj); |
} |
+ return ToStringCheckErrorObject(obj); |
} |
@@ -142,116 +142,132 @@ function MakeGenericError(constructor, type, args) { |
// Helper functions; called from the runtime system. |
function FormatMessage(message) { |
if (kMessages === 0) { |
- kMessages = { |
+ var messagesDictionary = [ |
// Error |
- cyclic_proto: ["Cyclic __proto__ value"], |
- code_gen_from_strings: ["Code generation from strings disallowed for this context"], |
+ "cyclic_proto", ["Cyclic __proto__ value"], |
+ "code_gen_from_strings", ["Code generation from strings disallowed for this context"], |
// TypeError |
- unexpected_token: ["Unexpected token ", "%0"], |
- unexpected_token_number: ["Unexpected number"], |
- unexpected_token_string: ["Unexpected string"], |
- unexpected_token_identifier: ["Unexpected identifier"], |
- unexpected_reserved: ["Unexpected reserved word"], |
- unexpected_strict_reserved: ["Unexpected strict mode reserved word"], |
- unexpected_eos: ["Unexpected end of input"], |
- malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"], |
- unterminated_regexp: ["Invalid regular expression: missing /"], |
- regexp_flags: ["Cannot supply flags when constructing one RegExp from another"], |
- incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"], |
- invalid_lhs_in_assignment: ["Invalid left-hand side in assignment"], |
- invalid_lhs_in_for_in: ["Invalid left-hand side in for-in"], |
- invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"], |
- invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"], |
- multiple_defaults_in_switch: ["More than one default clause in switch statement"], |
- newline_after_throw: ["Illegal newline after throw"], |
- redeclaration: ["%0", " '", "%1", "' has already been declared"], |
- no_catch_or_finally: ["Missing catch or finally after try"], |
- unknown_label: ["Undefined label '", "%0", "'"], |
- uncaught_exception: ["Uncaught ", "%0"], |
- stack_trace: ["Stack Trace:\n", "%0"], |
- called_non_callable: ["%0", " is not a function"], |
- undefined_method: ["Object ", "%1", " has no method '", "%0", "'"], |
- property_not_function: ["Property '", "%0", "' of object ", "%1", " is not a function"], |
- cannot_convert_to_primitive: ["Cannot convert object to primitive value"], |
- not_constructor: ["%0", " is not a constructor"], |
- not_defined: ["%0", " is not defined"], |
- non_object_property_load: ["Cannot read property '", "%0", "' of ", "%1"], |
- non_object_property_store: ["Cannot set property '", "%0", "' of ", "%1"], |
- non_object_property_call: ["Cannot call method '", "%0", "' of ", "%1"], |
- with_expression: ["%0", " has no properties"], |
- illegal_invocation: ["Illegal invocation"], |
- no_setter_in_callback: ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"], |
- apply_non_function: ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"], |
- apply_wrong_args: ["Function.prototype.apply: Arguments list has wrong type"], |
- invalid_in_operator_use: ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"], |
- instanceof_function_expected: ["Expecting a function in instanceof check, but got ", "%0"], |
- instanceof_nonobject_proto: ["Function has non-object prototype '", "%0", "' in instanceof check"], |
- null_to_object: ["Cannot convert null to object"], |
- reduce_no_initial: ["Reduce of empty array with no initial value"], |
- getter_must_be_callable: ["Getter must be a function: ", "%0"], |
- setter_must_be_callable: ["Setter must be a function: ", "%0"], |
- value_and_accessor: ["Invalid property. A property cannot both have accessors and be writable or have a value: ", "%0"], |
- proto_object_or_null: ["Object prototype may only be an Object or null"], |
- property_desc_object: ["Property description must be an object: ", "%0"], |
- redefine_disallowed: ["Cannot redefine property: ", "%0"], |
- define_disallowed: ["Cannot define property:", "%0", ", object is not extensible."], |
- non_extensible_proto: ["%0", " is not extensible"], |
- handler_non_object: ["Proxy.", "%0", " called with non-object as handler"], |
- handler_trap_missing: ["Proxy handler ", "%0", " has no '", "%1", "' trap"], |
- handler_trap_must_be_callable: ["Proxy handler ", "%0", " has non-callable '", "%1", "' trap"], |
- handler_returned_false: ["Proxy handler ", "%0", " returned false for '", "%1", "' trap"], |
- handler_returned_undefined: ["Proxy handler ", "%0", " returned undefined for '", "%1", "' trap"], |
- proxy_prop_not_configurable: ["Trap ", "%1", " of proxy handler ", "%0", " returned non-configurable descriptor for property ", "%2"], |
- proxy_non_object_prop_names: ["Trap ", "%1", " returned non-object ", "%0"], |
- proxy_repeated_prop_name: ["Trap ", "%1", " returned repeated property name ", "%2"], |
- invalid_weakmap_key: ["Invalid value used as weak map key"], |
+ "unexpected_token", ["Unexpected token ", "%0"], |
+ "unexpected_token_number", ["Unexpected number"], |
+ "unexpected_token_string", ["Unexpected string"], |
+ "unexpected_token_identifier", ["Unexpected identifier"], |
+ "unexpected_reserved", ["Unexpected reserved word"], |
+ "unexpected_strict_reserved", ["Unexpected strict mode reserved word"], |
+ "unexpected_eos", ["Unexpected end of input"], |
+ "malformed_regexp", ["Invalid regular expression: /", "%0", "/: ", "%1"], |
+ "unterminated_regexp", ["Invalid regular expression: missing /"], |
+ "regexp_flags", ["Cannot supply flags when constructing one RegExp from another"], |
+ "incompatible_method_receiver", ["Method ", "%0", " called on incompatible receiver ", "%1"], |
+ "invalid_lhs_in_assignment", ["Invalid left-hand side in assignment"], |
+ "invalid_lhs_in_for_in", ["Invalid left-hand side in for-in"], |
+ "invalid_lhs_in_postfix_op", ["Invalid left-hand side expression in postfix operation"], |
+ "invalid_lhs_in_prefix_op", ["Invalid left-hand side expression in prefix operation"], |
+ "multiple_defaults_in_switch", ["More than one default clause in switch statement"], |
+ "newline_after_throw", ["Illegal newline after throw"], |
+ "redeclaration", ["%0", " '", "%1", "' has already been declared"], |
+ "no_catch_or_finally", ["Missing catch or finally after try"], |
+ "unknown_label", ["Undefined label '", "%0", "'"], |
+ "uncaught_exception", ["Uncaught ", "%0"], |
+ "stack_trace", ["Stack Trace:\n", "%0"], |
+ "called_non_callable", ["%0", " is not a function"], |
+ "undefined_method", ["Object ", "%1", " has no method '", "%0", "'"], |
+ "property_not_function", ["Property '", "%0", "' of object ", "%1", " is not a function"], |
+ "cannot_convert_to_primitive", ["Cannot convert object to primitive value"], |
+ "not_constructor", ["%0", " is not a constructor"], |
+ "not_defined", ["%0", " is not defined"], |
+ "non_object_property_load", ["Cannot read property '", "%0", "' of ", "%1"], |
+ "non_object_property_store", ["Cannot set property '", "%0", "' of ", "%1"], |
+ "non_object_property_call", ["Cannot call method '", "%0", "' of ", "%1"], |
+ "with_expression", ["%0", " has no properties"], |
+ "illegal_invocation", ["Illegal invocation"], |
+ "no_setter_in_callback", ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"], |
+ "apply_non_function", ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"], |
+ "apply_wrong_args", ["Function.prototype.apply: Arguments list has wrong type"], |
+ "invalid_in_operator_use", ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"], |
+ "instanceof_function_expected", ["Expecting a function in instanceof check, but got ", "%0"], |
+ "instanceof_nonobject_proto", ["Function has non-object prototype '", "%0", "' in instanceof check"], |
+ "null_to_object", ["Cannot convert null to object"], |
+ "reduce_no_initial", ["Reduce of empty array with no initial value"], |
+ "getter_must_be_callable", ["Getter must be a function: ", "%0"], |
+ "setter_must_be_callable", ["Setter must be a function: ", "%0"], |
+ "value_and_accessor", ["Invalid property. A property cannot both have accessors and be writable or have a value, ", "%0"], |
+ "proto_object_or_null", ["Object prototype may only be an Object or null"], |
+ "property_desc_object", ["Property description must be an object: ", "%0"], |
+ "redefine_disallowed", ["Cannot redefine property: ", "%0"], |
+ "define_disallowed", ["Cannot define property:", "%0", ", object is not extensible."], |
+ "non_extensible_proto", ["%0", " is not extensible"], |
+ "handler_non_object", ["Proxy.", "%0", " called with non-object as handler"], |
+ "handler_trap_missing", ["Proxy handler ", "%0", " has no '", "%1", "' trap"], |
+ "handler_trap_must_be_callable", ["Proxy handler ", "%0", " has non-callable '", "%1", "' trap"], |
+ "handler_returned_false", ["Proxy handler ", "%0", " returned false for '", "%1", "' trap"], |
+ "handler_returned_undefined", ["Proxy handler ", "%0", " returned undefined for '", "%1", "' trap"], |
+ "proxy_prop_not_configurable", ["Trap ", "%1", " of proxy handler ", "%0", " returned non-configurable descriptor for property ", "%2"], |
+ "proxy_non_object_prop_names", ["Trap ", "%1", " returned non-object ", "%0"], |
+ "proxy_repeated_prop_name", ["Trap ", "%1", " returned repeated property name ", "%2"], |
+ "invalid_weakmap_key", ["Invalid value used as weak map key"], |
// RangeError |
- invalid_array_length: ["Invalid array length"], |
- stack_overflow: ["Maximum call stack size exceeded"], |
+ "invalid_array_length", ["Invalid array length"], |
+ "stack_overflow", ["Maximum call stack size exceeded"], |
// SyntaxError |
- unable_to_parse: ["Parse error"], |
- invalid_regexp_flags: ["Invalid flags supplied to RegExp constructor '", "%0", "'"], |
- invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"], |
- illegal_break: ["Illegal break statement"], |
- illegal_continue: ["Illegal continue statement"], |
- illegal_return: ["Illegal return statement"], |
- error_loading_debugger: ["Error loading debugger"], |
- no_input_to_regexp: ["No input to ", "%0"], |
- invalid_json: ["String '", "%0", "' is not valid JSON"], |
- circular_structure: ["Converting circular structure to JSON"], |
- obj_ctor_property_non_object: ["Object.", "%0", " called on non-object"], |
- called_on_null_or_undefined: ["%0", " called on null or undefined"], |
- array_indexof_not_defined: ["Array.getIndexOf: Argument undefined"], |
- object_not_extensible: ["Can't add property ", "%0", ", object is not extensible"], |
- illegal_access: ["Illegal access"], |
- invalid_preparser_data: ["Invalid preparser data for function ", "%0"], |
- strict_mode_with: ["Strict mode code may not include a with statement"], |
- strict_catch_variable: ["Catch variable may not be eval or arguments in strict mode"], |
- too_many_arguments: ["Too many arguments in function call (only 32766 allowed)"], |
- too_many_parameters: ["Too many parameters in function definition (only 32766 allowed)"], |
- too_many_variables: ["Too many variables declared (only 32767 allowed)"], |
- strict_param_name: ["Parameter name eval or arguments is not allowed in strict mode"], |
- strict_param_dupe: ["Strict mode function may not have duplicate parameter names"], |
- strict_var_name: ["Variable name may not be eval or arguments in strict mode"], |
- strict_function_name: ["Function name may not be eval or arguments in strict mode"], |
- strict_octal_literal: ["Octal literals are not allowed in strict mode."], |
- strict_duplicate_property: ["Duplicate data property in object literal not allowed in strict mode"], |
- accessor_data_property: ["Object literal may not have data and accessor property with the same name"], |
- accessor_get_set: ["Object literal may not have multiple get/set accessors with the same name"], |
- strict_lhs_assignment: ["Assignment to eval or arguments is not allowed in strict mode"], |
- strict_lhs_postfix: ["Postfix increment/decrement may not have eval or arguments operand in strict mode"], |
- strict_lhs_prefix: ["Prefix increment/decrement may not have eval or arguments operand in strict mode"], |
- strict_reserved_word: ["Use of future reserved word in strict mode"], |
- strict_delete: ["Delete of an unqualified identifier in strict mode."], |
- strict_delete_property: ["Cannot delete property '", "%0", "' of ", "%1"], |
- strict_const: ["Use of const in strict mode."], |
- strict_function: ["In strict mode code, functions can only be declared at top level or immediately within another function." ], |
- strict_read_only_property: ["Cannot assign to read only property '", "%0", "' of ", "%1"], |
- strict_cannot_assign: ["Cannot assign to read only '", "%0", "' in strict mode"], |
- strict_poison_pill: ["'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them"], |
- strict_caller: ["Illegal access to a strict mode caller function."], |
- unprotected_let: ["Illegal let declaration in unprotected statement context."], |
- }; |
+ "unable_to_parse", ["Parse error"], |
+ "invalid_regexp_flags", ["Invalid flags supplied to RegExp constructor '", "%0", "'"], |
+ "invalid_regexp", ["Invalid RegExp pattern /", "%0", "/"], |
+ "illegal_break", ["Illegal break statement"], |
+ "illegal_continue", ["Illegal continue statement"], |
+ "illegal_return", ["Illegal return statement"], |
+ "error_loading_debugger", ["Error loading debugger"], |
+ "no_input_to_regexp", ["No input to ", "%0"], |
+ "invalid_json", ["String '", "%0", "' is not valid JSON"], |
+ "circular_structure", ["Converting circular structure to JSON"], |
+ "obj_ctor_property_non_object", ["Object.", "%0", " called on non-object"], |
+ "called_on_null_or_undefined", ["%0", " called on null or undefined"], |
+ "array_indexof_not_defined", ["Array.getIndexOf: Argument undefined"], |
+ "object_not_extensible", ["Can't add property ", "%0", ", object is not extensible"], |
+ "illegal_access", ["Illegal access"], |
+ "invalid_preparser_data", ["Invalid preparser data for function ", "%0"], |
+ "strict_mode_with", ["Strict mode code may not include a with statement"], |
+ "strict_catch_variable", ["Catch variable may not be eval or arguments in strict mode"], |
+ "too_many_arguments", ["Too many arguments in function call (only 32766 allowed)"], |
+ "too_many_parameters", ["Too many parameters in function definition (only 32766 allowed)"], |
+ "too_many_variables", ["Too many variables declared (only 32767 allowed)"], |
+ "strict_param_name", ["Parameter name eval or arguments is not allowed in strict mode"], |
+ "strict_param_dupe", ["Strict mode function may not have duplicate parameter names"], |
+ "strict_var_name", ["Variable name may not be eval or arguments in strict mode"], |
+ "strict_function_name", ["Function name may not be eval or arguments in strict mode"], |
+ "strict_octal_literal", ["Octal literals are not allowed in strict mode."], |
+ "strict_duplicate_property", ["Duplicate data property in object literal not allowed in strict mode"], |
+ "accessor_data_property", ["Object literal may not have data and accessor property with the same name"], |
+ "accessor_get_set", ["Object literal may not have multiple get/set accessors with the same name"], |
+ "strict_lhs_assignment", ["Assignment to eval or arguments is not allowed in strict mode"], |
+ "strict_lhs_postfix", ["Postfix increment/decrement may not have eval or arguments operand in strict mode"], |
+ "strict_lhs_prefix", ["Prefix increment/decrement may not have eval or arguments operand in strict mode"], |
+ "strict_reserved_word", ["Use of future reserved word in strict mode"], |
+ "strict_delete", ["Delete of an unqualified identifier in strict mode."], |
+ "strict_delete_property", ["Cannot delete property '", "%0", "' of ", "%1"], |
+ "strict_const", ["Use of const in strict mode."], |
+ "strict_function", ["In strict mode code, functions can only be declared at top level or immediately within another function." ], |
+ "strict_read_only_property", ["Cannot assign to read only property '", "%0", "' of ", "%1"], |
+ "strict_cannot_assign", ["Cannot assign to read only '", "%0", "' in strict mode"], |
+ "strict_poison_pill", ["'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them"], |
+ "strict_caller", ["Illegal access to a strict mode caller function."], |
+ "unprotected_let", ["Illegal let declaration in unprotected statement context."], |
+ ]; |
+ var messages = { __proto__ : null }; |
+ var desc = new PropertyDescriptor(); |
+ desc.setConfigurable(false); |
+ desc.setEnumerable(false); |
+ desc.setWritable(false); |
+ for (var i = 0; i < messagesDictionary.length; i += 2) { |
+ var key = messagesDictionary[i]; |
+ var format = messagesDictionary[i + 1]; |
+ ObjectFreeze(format); |
+ desc.setValue(format); |
+ DefineOwnProperty(messages, key, desc); |
+ } |
+ %PreventExtensions(messages); |
+ %IgnoreAttributesAndSetProperty(builtins, "kMessages", |
+ messages, |
+ DONT_DELETE | DONT_ENUM | READ_ONLY); |
} |
var message_type = %MessageGetType(message); |
var format = kMessages[message_type]; |
@@ -998,64 +1014,6 @@ function FormatRawStackTrace(error, raw_stack) { |
} |
} |
-function DefineError(f) { |
- // Store the error function in both the global object |
- // and the runtime object. The function is fetched |
- // from the runtime object when throwing errors from |
- // within the runtime system to avoid strange side |
- // effects when overwriting the error functions from |
- // user code. |
- var name = f.name; |
- %SetProperty(global, name, f, DONT_ENUM); |
- this['$' + name] = f; |
- // Configure the error function. |
- if (name == 'Error') { |
- // The prototype of the Error object must itself be an error. |
- // However, it can't be an instance of the Error object because |
- // it hasn't been properly configured yet. Instead we create a |
- // special not-a-true-error-but-close-enough object. |
- function ErrorPrototype() {} |
- %FunctionSetPrototype(ErrorPrototype, $Object.prototype); |
- %FunctionSetInstanceClassName(ErrorPrototype, 'Error'); |
- %FunctionSetPrototype(f, new ErrorPrototype()); |
- } else { |
- %FunctionSetPrototype(f, new $Error()); |
- } |
- %FunctionSetInstanceClassName(f, 'Error'); |
- %SetProperty(f.prototype, 'constructor', f, DONT_ENUM); |
- // The name property on the prototype of error objects is not |
- // specified as being read-one and dont-delete. However, allowing |
- // overwriting allows leaks of error objects between script blocks |
- // in the same context in a browser setting. Therefore we fix the |
- // name. |
- %SetProperty(f.prototype, "name", name, DONT_ENUM | DONT_DELETE | READ_ONLY); |
- %SetCode(f, function(m) { |
- if (%_IsConstructCall()) { |
- // Define all the expected properties directly on the error |
- // object. This avoids going through getters and setters defined |
- // on prototype objects. |
- %IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM); |
- %IgnoreAttributesAndSetProperty(this, 'arguments', void 0, DONT_ENUM); |
- %IgnoreAttributesAndSetProperty(this, 'type', void 0, DONT_ENUM); |
- if (m === kAddMessageAccessorsMarker) { |
- // DefineOneShotAccessor always inserts a message property and |
- // ignores setters. |
- DefineOneShotAccessor(this, 'message', function (obj) { |
- return FormatMessage(%NewMessageObject(obj.type, obj.arguments)); |
- }); |
- } else if (!IS_UNDEFINED(m)) { |
- %IgnoreAttributesAndSetProperty(this, |
- 'message', |
- ToString(m), |
- DONT_ENUM); |
- } |
- captureStackTrace(this, f); |
- } else { |
- return new f(m); |
- } |
- }); |
-} |
- |
function captureStackTrace(obj, cons_opt) { |
var stackTraceLimit = $Error.stackTraceLimit; |
if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return; |
@@ -1070,52 +1028,98 @@ function captureStackTrace(obj, cons_opt) { |
}); |
}; |
-$Math.__proto__ = global.Object.prototype; |
- |
-// DefineError is a native function. Use explicit receiver. Otherwise |
-// the receiver will be 'undefined'. |
-this.DefineError(function Error() { }); |
-this.DefineError(function TypeError() { }); |
-this.DefineError(function RangeError() { }); |
-this.DefineError(function SyntaxError() { }); |
-this.DefineError(function ReferenceError() { }); |
-this.DefineError(function EvalError() { }); |
-this.DefineError(function URIError() { }); |
-$Error.captureStackTrace = captureStackTrace; |
+(function () { |
+ // Define special error type constructors. |
+ |
+ function DefineError(f) { |
+ // Store the error function in both the global object |
+ // and the runtime object. The function is fetched |
+ // from the runtime object when throwing errors from |
+ // within the runtime system to avoid strange side |
+ // effects when overwriting the error functions from |
+ // user code. |
+ var name = f.name; |
+ %SetProperty(global, name, f, DONT_ENUM); |
+ builtins['$' + name] = f; |
+ // Configure the error function. |
+ if (name == 'Error') { |
+ // The prototype of the Error object must itself be an error. |
+ // However, it can't be an instance of the Error object because |
+ // it hasn't been properly configured yet. Instead we create a |
+ // special not-a-true-error-but-close-enough object. |
+ function ErrorPrototype() {} |
+ %FunctionSetPrototype(ErrorPrototype, $Object.prototype); |
+ %FunctionSetInstanceClassName(ErrorPrototype, 'Error'); |
+ %FunctionSetPrototype(f, new ErrorPrototype()); |
+ } else { |
+ %FunctionSetPrototype(f, new $Error()); |
+ } |
+ %FunctionSetInstanceClassName(f, 'Error'); |
+ %SetProperty(f.prototype, 'constructor', f, DONT_ENUM); |
+ // The name property on the prototype of error objects is not |
+ // specified as being read-one and dont-delete. However, allowing |
+ // overwriting allows leaks of error objects between script blocks |
+ // in the same context in a browser setting. Therefore we fix the |
+ // name. |
+ %SetProperty(f.prototype, "name", name, |
+ DONT_ENUM | DONT_DELETE | READ_ONLY) ; |
+ %SetCode(f, function(m) { |
+ if (%_IsConstructCall()) { |
+ // Define all the expected properties directly on the error |
+ // object. This avoids going through getters and setters defined |
+ // on prototype objects. |
+ %IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM); |
+ %IgnoreAttributesAndSetProperty(this, 'arguments', void 0, DONT_ENUM); |
+ %IgnoreAttributesAndSetProperty(this, 'type', void 0, DONT_ENUM); |
+ if (m === kAddMessageAccessorsMarker) { |
+ // DefineOneShotAccessor always inserts a message property and |
+ // ignores setters. |
+ DefineOneShotAccessor(this, 'message', function (obj) { |
+ return FormatMessage(%NewMessageObject(obj.type, obj.arguments)); |
+ }); |
+ } else if (!IS_UNDEFINED(m)) { |
+ %IgnoreAttributesAndSetProperty(this, |
+ 'message', |
+ ToString(m), |
+ DONT_ENUM); |
+ } |
+ captureStackTrace(this, f); |
+ } else { |
+ return new f(m); |
+ } |
+ }); |
+ } |
-// Setup extra properties of the Error.prototype object. |
-function setErrorMessage() { |
- var desc = {value: '', |
- enumerable: false, |
- configurable: true, |
- writable: true }; |
- DefineOwnProperty($Error.prototype, |
- 'message', |
- ToPropertyDescriptor(desc), |
- true); |
+ DefineError(function Error() { }); |
+ DefineError(function TypeError() { }); |
+ DefineError(function RangeError() { }); |
+ DefineError(function SyntaxError() { }); |
+ DefineError(function ReferenceError() { }); |
+ DefineError(function EvalError() { }); |
+ DefineError(function URIError() { }); |
+})(); |
-} |
+$Error.captureStackTrace = captureStackTrace; |
-setErrorMessage(); |
+%SetProperty($Error.prototype, 'message', '', DONT_ENUM); |
// Global list of error objects visited during errorToString. This is |
// used to detect cycles in error toString formatting. |
-var visited_errors = new $Array(); |
-var cyclic_error_marker = new $Object(); |
+const visited_errors = new InternalArray(); |
+const cyclic_error_marker = new $Object(); |
-function errorToStringDetectCycle() { |
- if (!%PushIfAbsent(visited_errors, this)) throw cyclic_error_marker; |
+function errorToStringDetectCycle(error) { |
+ if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker; |
try { |
- var type = this.type; |
- if (type && !%_CallFunction(this, "message", ObjectHasOwnProperty)) { |
- var formatted = FormatMessage(%NewMessageObject(type, this.arguments)); |
- return this.name + ": " + formatted; |
+ var type = error.type; |
+ var hasMessage = %_CallFunction(error, "message", ObjectHasOwnProperty); |
+ if (type && !hasMessage) { |
+ var formatted = FormatMessage(%NewMessageObject(type, error.arguments)); |
+ return error.name + ": " + formatted; |
} |
- var message = %_CallFunction(this, "message", ObjectHasOwnProperty) |
- ? (": " + this.message) |
- : ""; |
- return this.name + message; |
+ var message = hasMessage ? (": " + error.message) : ""; |
+ return error.name + message; |
} finally { |
visited_errors.length = visited_errors.length - 1; |
} |
@@ -1131,7 +1135,7 @@ function errorToString() { |
function isCyclicErrorMarker(o) { return o === cyclic_error_marker; } |
try { |
- return %_CallFunction(this, errorToStringDetectCycle); |
+ return errorToStringDetectCycle(this); |
} catch(e) { |
// If this error message was encountered already return the empty |
// string for it instead of recursively formatting it. |