Netflix / x-element

A dead simple starting point for custom elements.
Apache License 2.0
28 stars 12 forks source link

Use error cause for template errors. #128

Closed theengineear closed 8 months ago

theengineear commented 1 year ago

The error cause TC39 proposal was accepted in 2022 and is available in Chrome, Safari, and Firefox.

We currently use the following to inject helpful context into otherwise out-of-context errors in render:

  render() {
    const { template, properties, renderRoot } = XElement.#hosts.get(this);
    const result = template(properties, this);
    try {
      render(result, renderRoot);
    } catch (error) {
      const pathString = XElement.#toPathString(this);
      error.message = `${error.message} — Invalid template for "${this.constructor.name}" at path "${pathString}"`;
      throw error;
    }
  }

Instead, we could simply throw our own error and set the cause appropriately:

  render() {
    const { template, properties, renderRoot } = XElement.#hosts.get(this);
    const result = template(properties, this);
    try {
      render(result, renderRoot);
    } catch (error) {
      const pathString = XElement.#toPathString(this);
      const message = `${error.message} — Invalid template for "${this.constructor.name}" at path "${pathString}"`;
      throw new Error(message, { cause: error });
    }
  }

This built-in "error chaining" allows you to link an arbitrary number of errors together without needing to mutate anything (or make up a bespoke pattern). Let's do it.

theengineear commented 8 months ago

Looked into this today — unfortunately, we’re still blocked by Chrome. Error causes are (surprisingly) still not printed in the console… which makes them pretty unhelpful! See Chrome bug. You can compare / contrast with the screen-grabs pictured below. Firefox is doing the thing we want already. I think other vendors have concerns maybe around recursion? I (admittedly) didn’t read too much into the thread in that Chrome bug.

Screenshot 2024-02-13 at 1 15 37 PM Screenshot 2024-02-13 at 1 16 26 PM
theengineear commented 8 months ago

Note that the way we currently manage error chaining is to mutate the original error — however, some custom error classes attempt to be immutable / read-only and actually throw an error when you try to do this. I.e., it’s presenting as an actual bug currently, but I wouldn’t feel comfortable changing this behavior until we could reliably see that chained error in the Chrome console.

theengineear commented 8 months ago

I think I have a way around this — I'll continue to just embed the original message, but will just not mutate the original error. That should suffice here.