| Index: src/messages.js
|
| ===================================================================
|
| --- src/messages.js (revision 6955)
|
| +++ src/messages.js (working copy)
|
| @@ -82,23 +82,57 @@
|
| var result = format;
|
| for (var i = 0; i < args.length; i++) {
|
| var str;
|
| - try { str = ToDetailString(args[i]); }
|
| - catch (e) { str = "#<error>"; }
|
| + try {
|
| + str = ToDetailString(args[i]);
|
| + } catch (e) {
|
| + str = "#<error>";
|
| + }
|
| result = ArrayJoin.call(StringSplit.call(result, "%" + i), str);
|
| }
|
| return result;
|
| }
|
|
|
|
|
| +// To check if something is a native error we need to check the
|
| +// concrete native error types. It is not enough to check "obj
|
| +// instanceof $Error" because user code can replace
|
| +// NativeError.prototype.__proto__. User code cannot replace
|
| +// NativeError.prototype though and therefore this is a safe test.
|
| +function IsNativeErrorObject(obj) {
|
| + return (obj instanceof $Error) ||
|
| + (obj instanceof $EvalError) ||
|
| + (obj instanceof $RangeError) ||
|
| + (obj instanceof $ReferenceError) ||
|
| + (obj instanceof $SyntaxError) ||
|
| + (obj instanceof $TypeError) ||
|
| + (obj instanceof $URIError);
|
| +}
|
| +
|
| +
|
| +// 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 (IsNativeErrorObject(obj)) {
|
| + return %_CallFunction(obj, errorToString);
|
| + } else {
|
| + return ToString(obj);
|
| + }
|
| +}
|
| +
|
| +
|
| function ToDetailString(obj) {
|
| if (obj != null && IS_OBJECT(obj) && obj.toString === $Object.prototype.toString) {
|
| var constructor = obj.constructor;
|
| - if (!constructor) return ToString(obj);
|
| + if (!constructor) return ToStringCheckErrorObject(obj);
|
| var constructorName = constructor.name;
|
| - if (!constructorName) return ToString(obj);
|
| + if (!constructorName || !IS_STRING(constructorName)) {
|
| + return ToStringCheckErrorObject(obj);
|
| + }
|
| return "#<" + GetInstanceName(constructorName) + ">";
|
| } else {
|
| - return ToString(obj);
|
| + return ToStringCheckErrorObject(obj);
|
| }
|
| }
|
|
|
| @@ -196,7 +230,17 @@
|
| 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"
|
| + 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",
|
| + 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",
|
| };
|
| }
|
| var format = kMessages[message.type];
|
| @@ -943,7 +987,12 @@
|
| }
|
| %FunctionSetInstanceClassName(f, 'Error');
|
| %SetProperty(f.prototype, 'constructor', f, DONT_ENUM);
|
| - f.prototype.name = name;
|
| + // 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, READ_ONLY | DONT_DELETE);
|
| %SetCode(f, function(m) {
|
| if (%_IsConstructCall()) {
|
| // Define all the expected properties directly on the error
|
| @@ -995,16 +1044,44 @@
|
| // Setup extra properties of the Error.prototype object.
|
| $Error.prototype.message = '';
|
|
|
| -%SetProperty($Error.prototype, 'toString', function toString() {
|
| - var type = this.type;
|
| - if (type && !this.hasOwnProperty("message")) {
|
| - return this.name + ": " + FormatMessage({ type: type, args: this.arguments });
|
| +// 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();
|
| +
|
| +function errorToStringDetectCycle() {
|
| + if (!%PushIfAbsent(visited_errors, this)) throw cyclic_error_marker;
|
| + try {
|
| + var type = this.type;
|
| + if (type && !this.hasOwnProperty("message")) {
|
| + var formatted = FormatMessage({ type: type, args: this.arguments });
|
| + return this.name + ": " + formatted;
|
| + }
|
| + var message = this.hasOwnProperty("message") ? (": " + this.message) : "";
|
| + return this.name + message;
|
| + } finally {
|
| + visited_errors.pop();
|
| }
|
| - var message = this.hasOwnProperty("message") ? (": " + this.message) : "";
|
| - return this.name + message;
|
| -}, DONT_ENUM);
|
| +}
|
|
|
| +function errorToString() {
|
| + // This helper function is needed because access to properties on
|
| + // the builtins object do not work inside of a catch clause.
|
| + function isCyclicErrorMarker(o) { return o === cyclic_error_marker; }
|
|
|
| + try {
|
| + return %_CallFunction(this, errorToStringDetectCycle);
|
| + } catch(e) {
|
| + // If this error message was encountered already return the empty
|
| + // string for it instead of recursively formatting it.
|
| + if (isCyclicErrorMarker(e)) return '';
|
| + else throw e;
|
| + }
|
| +}
|
| +
|
| +%FunctionSetName(errorToString, 'toString');
|
| +%SetProperty($Error.prototype, 'toString', errorToString, DONT_ENUM);
|
| +
|
| // Boilerplate for exceptions for stack overflows. Used from
|
| // Isolate::StackOverflow().
|
| const kStackOverflowBoilerplate = MakeRangeError('stack_overflow', []);
|
|
|