Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

Add message to error stack #2311

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 38 additions & 21 deletions src/intrinsics/ecma262/Error.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@

import type { Realm } from "../../realm.js";
import type { LexicalEnvironment } from "../../environment.js";
import { ObjectValue, FunctionValue, NativeFunctionValue, StringValue } from "../../values/index.js";
import {
AbstractValue,
ObjectValue,
FunctionValue,
NativeFunctionValue,
StringValue,
Value,
} from "../../values/index.js";
import { Get } from "../../methods/index.js";
import { Create, Properties, To } from "../../singletons.js";
import invariant from "../../invariant.js";
import buildExpressionTemplate from "../../utils/builder.js";
import type { BabelNodeSourceLocation } from "@babel/types";

export default function(realm: Realm): NativeFunctionValue {
Expand Down Expand Up @@ -76,23 +84,23 @@ export function describeLocation(
return location;
}

function buildStack(realm: Realm, context: ObjectValue) {
const buildStackTemplateSrc = 'A + (B ? ": " + B : "") + C';
const buildStackTemplate = buildExpressionTemplate(buildStackTemplateSrc);

function buildStack(realm: Realm, context: ObjectValue): Value {
invariant(context.$ErrorData);

let stack = context.$ErrorData.contextStack;
if (!stack) return realm.intrinsics.undefined;

let lines = [];
let header = "";

header += To.ToStringPartial(realm, Get(realm, context, "name"));
let header = To.ToStringPartial(realm, Get(realm, context, "name"));

let msg = Get(realm, context, "message");
if (!msg.mightBeUndefined()) {
msg = To.ToStringPartial(realm, msg);
if (msg) header += `: ${msg}`;
let message = Get(realm, context, "message");
if (!message.mightBeUndefined()) {
message = To.ToStringValue(realm, message);
} else {
msg.throwIfNotConcrete();
message.throwIfNotConcrete();
}

for (let executionContext of stack.reverse()) {
Expand All @@ -106,8 +114,17 @@ function buildStack(realm: Realm, context: ObjectValue) {
);
if (locString !== undefined) lines.push(locString);
}

return new StringValue(realm, `${header}\n ${lines.join("\n ")}`);
let footer = `\n ${lines.join("\n ")}`;

return message instanceof StringValue
? new StringValue(realm, `${header}${message.value ? `: ${message.value}` : ""}${footer}`)
: AbstractValue.createFromTemplate(
realm,
buildStackTemplate,
StringValue,
[new StringValue(realm, header), message, new StringValue(realm, footer)],
buildStackTemplateSrc
);
}

export function build(name: string, realm: Realm, inheritError?: boolean = true): NativeFunctionValue {
Expand All @@ -122,15 +139,6 @@ export function build(name: string, realm: Realm, inheritError?: boolean = true)
locationData: undefined,
};

// Build a text description of the stack.
let stackDesc = {
value: buildStack(realm, O),
enumerable: false,
configurable: true,
writable: true,
};
Properties.DefinePropertyOrThrow(realm, O, "stack", stackDesc);

// 3. If message is not undefined, then
if (!message.mightBeUndefined()) {
// a. Let msg be ? ToString(message).
Expand All @@ -150,6 +158,15 @@ export function build(name: string, realm: Realm, inheritError?: boolean = true)
message.throwIfNotConcrete();
}

// Build a text description of the stack.
let stackDesc = {
value: buildStack(realm, O),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildStack does not yet handle abstract messages. You can add such support by emitting the stack as a string template. Alternatively, you could just comment out the throw with a TODO comment, along with an issue describing what needs to be done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

enumerable: false,
configurable: true,
writable: true,
};
Properties.DefinePropertyOrThrow(realm, O, "stack", stackDesc);

// 4. Return O.
return O;
});
Expand Down