| Index: src/messages.js
|
| diff --git a/src/messages.js b/src/messages.js
|
| index 0a50ae7861e5e6f1032c4673dfb4aed904db2611..5fcb3889aa36056c7dbcde9f81422a2cd096b306 100644
|
| --- a/src/messages.js
|
| +++ b/src/messages.js
|
| @@ -820,7 +820,7 @@ function CallSiteGetMethodName() {
|
| %_CallFunction(this.receiver,
|
| ownName,
|
| ObjectLookupSetter) === this.fun ||
|
| - this.receiver[ownName] === this.fun)) {
|
| + %GetDataProperty(this.receiver, ownName) === this.fun)) {
|
| // To handle DontEnum properties we guess that the method has
|
| // the same name as the function.
|
| return ownName;
|
| @@ -829,8 +829,7 @@ function CallSiteGetMethodName() {
|
| for (var prop in this.receiver) {
|
| if (%_CallFunction(this.receiver, prop, ObjectLookupGetter) === this.fun ||
|
| %_CallFunction(this.receiver, prop, ObjectLookupSetter) === this.fun ||
|
| - (!%_CallFunction(this.receiver, prop, ObjectLookupGetter) &&
|
| - this.receiver[prop] === this.fun)) {
|
| + %GetDataProperty(this.receiver, prop) === this.fun) {
|
| // If we find more than one match bail out to avoid confusion.
|
| if (name) {
|
| return null;
|
| @@ -933,12 +932,14 @@ function CallSiteToString() {
|
| var typeName = GetTypeName(this, true);
|
| var methodName = this.getMethodName();
|
| if (functionName) {
|
| - if (typeName && functionName.indexOf(typeName) != 0) {
|
| + if (typeName &&
|
| + %_CallFunction(functionName, typeName, StringIndexOf) != 0) {
|
| line += typeName + ".";
|
| }
|
| line += functionName;
|
| - if (methodName && functionName.lastIndexOf("." + methodName) !=
|
| - functionName.length - methodName.length - 1) {
|
| + if (methodName &&
|
| + (%_CallFunction(functionName, "." + methodName, StringIndexOf) !=
|
| + functionName.length - methodName.length - 1)) {
|
| line += " [as " + methodName + "]";
|
| }
|
| } else {
|
| @@ -1016,17 +1017,37 @@ function FormatEvalOrigin(script) {
|
| return eval_origin;
|
| }
|
|
|
| -function FormatStackTrace(error, frames) {
|
| - var lines = [];
|
| +
|
| +function FormatErrorString(error) {
|
| try {
|
| - lines.push(error.toString());
|
| + return %_CallFunction(error, ErrorToString);
|
| } catch (e) {
|
| try {
|
| - lines.push("<error: " + e + ">");
|
| + return "<error: " + e + ">";
|
| } catch (ee) {
|
| - lines.push("<error>");
|
| + return "<error>";
|
| }
|
| }
|
| +}
|
| +
|
| +
|
| +function GetStackFrames(raw_stack) {
|
| + var frames = new InternalArray();
|
| + for (var i = 0; i < raw_stack.length; i += 4) {
|
| + var recv = raw_stack[i];
|
| + var fun = raw_stack[i + 1];
|
| + var code = raw_stack[i + 2];
|
| + var pc = raw_stack[i + 3];
|
| + var pos = %FunctionGetPositionForOffset(code, pc);
|
| + frames.push(new CallSite(recv, fun, pos));
|
| + }
|
| + return frames;
|
| +}
|
| +
|
| +
|
| +function FormatStackTrace(error_string, frames) {
|
| + var lines = new InternalArray();
|
| + lines.push(error_string);
|
| for (var i = 0; i < frames.length; i++) {
|
| var frame = frames[i];
|
| var line;
|
| @@ -1042,25 +1063,9 @@ function FormatStackTrace(error, frames) {
|
| }
|
| lines.push(" at " + line);
|
| }
|
| - return lines.join("\n");
|
| + return %_CallFunction(lines, "\n", ArrayJoin);
|
| }
|
|
|
| -function FormatRawStackTrace(error, raw_stack) {
|
| - var frames = [ ];
|
| - for (var i = 0; i < raw_stack.length; i += 4) {
|
| - var recv = raw_stack[i];
|
| - var fun = raw_stack[i + 1];
|
| - var code = raw_stack[i + 2];
|
| - var pc = raw_stack[i + 3];
|
| - var pos = %FunctionGetPositionForOffset(code, pc);
|
| - frames.push(new CallSite(recv, fun, pos));
|
| - }
|
| - if (IS_FUNCTION($Error.prepareStackTrace)) {
|
| - return $Error.prepareStackTrace(error, frames);
|
| - } else {
|
| - return FormatStackTrace(error, frames);
|
| - }
|
| -}
|
|
|
| function GetTypeName(obj, requireConstructor) {
|
| var constructor = obj.receiver.constructor;
|
| @@ -1076,6 +1081,7 @@ function GetTypeName(obj, requireConstructor) {
|
| return constructorName;
|
| }
|
|
|
| +
|
| function captureStackTrace(obj, cons_opt) {
|
| var stackTraceLimit = $Error.stackTraceLimit;
|
| if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return;
|
| @@ -1085,14 +1091,30 @@ function captureStackTrace(obj, cons_opt) {
|
| var raw_stack = %CollectStackTrace(obj,
|
| cons_opt ? cons_opt : captureStackTrace,
|
| stackTraceLimit);
|
| +
|
| + // Don't be lazy if the error stack formatting is custom (observable).
|
| + if (IS_FUNCTION($Error.prepareStackTrace)) {
|
| + var custom_stacktrace_fun = $Error.prepareStackTrace;
|
| + // Use default error formatting for the case that custom formatting throws.
|
| + $Error.prepareStackTrace = null;
|
| + var array = [];
|
| + %MoveArrayContents(GetStackFrames(raw_stack), array);
|
| + obj.stack = custom_stacktrace_fun(obj, array);
|
| + $Error.prepareStackTrace = custom_stacktrace_fun;
|
| + return;
|
| + }
|
| +
|
| + var error_string = FormatErrorString(obj);
|
| // Note that 'obj' and 'this' maybe different when called on objects that
|
| // have the error object on its prototype chain. The getter replaces itself
|
| // with a data property as soon as the stack trace has been formatted.
|
| var getter = function() {
|
| - var value = FormatRawStackTrace(obj, raw_stack);
|
| + var value = FormatStackTrace(error_string, GetStackFrames(raw_stack));
|
| %DefineOrRedefineDataProperty(obj, 'stack', value, NONE);
|
| return value;
|
| };
|
| + %MarkOneShotGetter(getter);
|
| +
|
| // The 'stack' property of the receiver is set as data property. If
|
| // the receiver is the same as holder, this accessor pair is replaced.
|
| var setter = function(v) {
|
| @@ -1239,6 +1261,8 @@ function SetUpStackOverflowBoilerplate() {
|
| // error object copy, but can be found on the prototype chain of 'this'.
|
| // When the stack trace is formatted, this accessor property is replaced by
|
| // a data property.
|
| + var error_string = boilerplate.name + ": " + boilerplate.message;
|
| +
|
| function getter() {
|
| var holder = this;
|
| while (!IS_ERROR(holder)) {
|
| @@ -1246,11 +1270,13 @@ function SetUpStackOverflowBoilerplate() {
|
| if (holder == null) return MakeSyntaxError('illegal_access', []);
|
| }
|
| var raw_stack = %GetOverflowedRawStackTrace(holder);
|
| - var result = IS_ARRAY(raw_stack) ? FormatRawStackTrace(holder, raw_stack)
|
| - : void 0;
|
| + var result = IS_ARRAY(raw_stack)
|
| + ? FormatStackTrace(error_string, GetStackFrames(raw_stack))
|
| + : void 0;
|
| %DefineOrRedefineDataProperty(holder, 'stack', result, NONE);
|
| return result;
|
| }
|
| + %MarkOneShotGetter(getter);
|
|
|
| // The 'stack' property of the receiver is set as data property. If
|
| // the receiver is the same as holder, this accessor pair is replaced.
|
|
|