Skip to content

Commit

Permalink
Expand JS error serialization
Browse files Browse the repository at this point in the history
* Generalize the framework to work on any NativeError types introduced by the JS spec, instead of listing them explicitly in a way that could require future updates.
* Also include WebAssembly Error classes.
* Switch semantics for serializing/deserializing "message". Previously, we would check for the presence of the property, and if it was a data property, get its value, and then ToString() it. Now, we just Get() it and then structured-serialize the result. We also unconditionally install it on the other side, regardless of whether it was present on the original. This new property-cloning procedure is more general.
* Use these new more general property cloning procedure on "cause" (for all errors) and "errors" (for objects that present as "AggregateError" objects).

Closes #5716.
  • Loading branch information
domenic committed Jul 16, 2021
1 parent 74a7491 commit 5da5838
Showing 1 changed file with 65 additions and 45 deletions.
110 changes: 65 additions & 45 deletions source
Expand Up @@ -2764,19 +2764,15 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<dfn>@@isConcatSpreadable</dfn>,
<dfn>@@toPrimitive</dfn>, and
<dfn>@@toStringTag</dfn></li>
<li><dfn data-x-href="https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard"><var>NativeError</var></dfn></li>
<li><dfn data-x-href="https://tc39.es/ecma262/#sec-well-known-intrinsic-objects">Well-Known Intrinsic Objects</dfn>, including
<dfn data-x-href="https://tc39.es/ecma262/#sec-properties-of-the-array-prototype-object">%Array.prototype%</dfn>,
<dfn data-x-href="https://tc39.es/ecma262/#sec-properties-of-the-error-prototype-object">%Error.prototype%</dfn>,
<dfn>%EvalError.prototype%</dfn>,
<dfn data-x-href="https://tc39.es/ecma262/#sec-properties-of-the-aggregate-error-prototype-objects">%AggregateError.prototype%</dfn>,
<dfn data-x-href="https://tc39.es/ecma262/#sec-properties-of-the-function-prototype-object">%Function.prototype%</dfn>,
<dfn data-x-href="https://tc39.es/ecma262/#sec-json.parse">%JSON.parse%</dfn>,
<dfn data-x-href="https://tc39.es/ecma262/#sec-properties-of-the-object-prototype-object">%Object.prototype%</dfn>,
<dfn data-x-href="https://tc39.es/ecma262/#sec-object.prototype.valueof">%Object.prototype.valueOf%</dfn>,
<dfn>%RangeError.prototype%</dfn>,
<dfn>%ReferenceError.prototype%</dfn>,
<dfn>%SyntaxError.prototype%</dfn>,
<dfn>%TypeError.prototype%</dfn>, and
<dfn>%URIError.prototype%</dfn></li>
<dfn data-x-href="https://tc39.es/ecma262/#sec-object.prototype.valueof">%Object.prototype.valueOf%</dfn>.</li>

<li>The <dfn data-x="js-prod-FunctionBody" data-x-href="https://tc39.es/ecma262/#prod-FunctionBody"><i>FunctionBody</i></dfn> production</li>
<li>The <dfn data-x="js-prod-Module" data-x-href="https://tc39.es/ecma262/#prod-Module"><i>Module</i></dfn> production</li>
Expand Down Expand Up @@ -2890,6 +2886,14 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li>The <dfn data-x="js-HostGetSupportedImportAssertions" data-x-href="https://tc39.es/proposal-import-assertions/#sec-hostgetsupportedimportassertions">HostGetSupportedImportAssertions</dfn> abstract operation</li>
</ul>

<p>User agents that support JavaScript must also implement the <cite>Error Cause</cite>
proposal. The following terms are defined there, and used in this specification: <ref
spec=JSERRORCAUSE></p>

<ul class="brief">
<li><dfn data-x-href="https://tc39.es/proposal-error-cause/#sec-createnonenumerabledatapropertyorthrow">CreateNonEnumerableDataPropertyOrThrow</dfn></li>
</ul>

<p>The following terms are defined in the <cite>JSON modules</cite> proposal and used in this
specification: <ref spec=JSJSONMODULES></p>

Expand All @@ -2908,6 +2912,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

<ul class="brief">
<li><dfn data-x-href="https://webassembly.github.io/spec/js-api/#module"><code>WebAssembly.Module</code></dfn></li>
<li><dfn data-x-href="https://webassembly.github.io/spec/js-api/#error-objects">WebAssembly Error class</dfn></li>
</ul>
</dd>

Expand Down Expand Up @@ -8325,26 +8330,35 @@ interface <dfn interface>DOMStringList</dfn> {
<li><p>Let <var>name</var> be ? <span data-x="js-Get">Get</span>(<var>value</var>,
"name").</p></li>

<li><p>If <var>name</var> is not one of "Error", "EvalError", "RangeError", "ReferenceError",
"SyntaxError", "TypeError", or "URIError", then set <var>name</var> to "Error".</p></li>
<li><p>If <var>name</var> is neither "AggregateError", nor one of the
<span><var>NativeError</var></span> names, nor one of the <span>WebAssembly Error class</span>
names, then set <var>name</var> to "Error".</p></li>

<li><p>Let <var>message</var> be ? <span>StructuredSerializeInternal</span>(? <span
data-x="js-Get">Get</span>(<var>value</var>, "message"), <var>forStorage</var>,
<var>memory</var>).</p></li>

<li><p>Let <var>cause</var> be ? <span>StructuredSerializeInternal</span>(? <span
data-x="js-Get">Get</span>(<var>value</var>, "cause"), <var>forStorage</var>,
<var>memory</var>).</p></li>

<li><p>Let <var>valueMessageDesc</var> be ? <var>value</var>.[[GetOwnProperty]]("<code
data-x="">message</code>").</p></li>
<li><p>Let <var>errors</var> be undefined.</p></li>

<li><p>Let <var>message</var> be undefined if
<span>IsDataDescriptor</span>(<var>valueMessageDesc</var>) is false, and
? <span>ToString</span>(<var>valueMessageDesc</var>.[[Value]]) otherwise.</p></li>
<li><p>If <var>name</var> is "AggregateError", then set <var>errors</var> to ?
<span>StructuredSerializeInternal</span>(? <span data-x="js-Get">Get</span>(<var>value</var>,
"errors"), <var>forStorage</var>, <var>memory</var>).</p></li>

<li><p>Set <var>serialized</var> to { [[Type]]: "Error", [[Name]]: <var>name</var>,
[[Message]]: <var>message</var> }.</p></li>
[[Message]]: <var>message</var>, [[Cause]]: <var>cause</var>, [[Errors]]: <var>errors</var>
}.</p></li>

<li>
<p>User agents should attach a serialized representation of any interesting accompanying
data which are not yet specified, notably the <code data-x="">stack</code> property, to
<p>User agents should attach a serialized representation of any interesting accompanying data
which are not yet specified, notably the <code data-x="">stack</code> property, to
<var>serialized</var>.</p>

<p class="note">See the <cite>Error Stacks</cite> proposal for in-progress work on
specifying this data. <ref spec=JSERRORSTACKS></p>
<p class="note">See the <cite>Error Stacks</cite> proposal for in-progress work on specifying
this data. <ref spec=JSERRORSTACKS></p>
</li>
</ol>
</li>
Expand Down Expand Up @@ -8520,8 +8534,8 @@ interface <dfn interface>DOMStringList</dfn> {
<p>If ! <span>HasOwnProperty</span>(<var>value</var>, <var>key</var>) is true, then:</p>

<ol>
<li><p>Let <var>inputValue</var> be ? <var>value</var>.[[Get]](<var>key</var>,
<var>value</var>).</p></li>
<li><p>Let <var>inputValue</var> be ? <span data-x="js-Get">Get</span>(<var>value</var>,
<var>key</var>).</p></li>

<li><p>Let <var>outputValue</var> be ?
<span>StructuredSerializeInternal</span>(<var>inputValue</var>, <var>forStorage</var>,
Expand Down Expand Up @@ -8737,38 +8751,41 @@ o.myself = o;</code></pre>
<p>Otherwise, if <var>serialized</var>.[[Type]] is "Error", then:</p>

<ol>
<li><p>Let <var>prototype</var> be <span>%Error.prototype%</span>.</p></li>

<li><p>If <var>serialized</var>.[[Name]] is "EvalError", then set <var>prototype</var> to
<span>%EvalError.prototype%</span>.</p></li>
<li><p>Let <var>name</var> be <var>serialized</var>.[[Name]].</p></li>

<li><p>If <var>serialized</var>.[[Name]] is "RangeError", then set <var>prototype</var>
to <span>%RangeError.prototype%</span>.</p></li>
<li><p>Let <var>prototype</var> be
<var>targetRealm</var>.[[Intrinsics]].[[%<var>name</var>%.prototype]], or the equivalent if
<var>name</var> is a <span>WebAssembly Error class</span> name.</p></li>

<li><p>If <var>serialized</var>.[[Name]] is "ReferenceError", then set
<var>prototype</var> to <span>%ReferenceError.prototype%</span>.</p></li>
<li><p>Set <var>value</var> to ! <span>ObjectCreate</span>(<var>prototype</var>, «
[[ErrorData]] »).</p></li>

<li><p>If <var>serialized</var>.[[Name]] is "SyntaxError", then set <var>prototype</var>
to <span>%SyntaxError.prototype%</span>.</p></li>
<li><p>Let <var>message</var> be ?
<span>StructuredDeserialize</span>(<var>serialized</var>.[[Message]], <var>targetRealm</var>,
<var>memory</var>).</p></li>

<li><p>If <var>serialized</var>.[[Name]] is "TypeError", then set <var>prototype</var> to
<span>%TypeError.prototype%</span>.</p></li>
<li><p>Perform ! <span>CreateNonEnumerableDataPropertyOrThrow</span>(<var>value</var>,
"message", <var>message</var>).</p></li>

<li><p>If <var>serialized</var>.[[Name]] is "URIError", then set <var>prototype</var> to
<span>%URIError.prototype%</span>.</p></li>
<li><p>Let <var>cause</var> be ?
<span>StructuredDeserialize</span>(<var>serialized</var>.[[Cause]], <var>targetRealm</var>,
<var>memory</var>).</p></li>

<li><p>Let <var>message</var> be <var>serialized</var>.[[Message]].</p></li>
<li><p>Perform ! <span>CreateNonEnumerableDataPropertyOrThrow</span>(<var>value</var>, "cause",
<var>cause</var>).</p></li>

<li><p>Set <var>value</var> to ! <span>ObjectCreate</span>(<var>prototype</var>, «
[[ErrorData]] »).</p></li>
<li>
<p>If <var>name</var> is "AggregateError", then:</p>

<li><p>Let <var>messageDesc</var> be <span>PropertyDescriptor</span>{ [[Value]]:
<var>message</var>, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true
}.</p></li>
<ol>
<li><p>Let <var>errors</var> be ?
<span>StructuredDeserialize</span>(<var>serialized</var>.[[Errors]], <var>targetRealm</var>,
<var>memory</var>).</p></li>

<li><p>If <var>message</var> is not undefined, then perform !
<span>OrdinaryDefineOwnProperty</span>(<var>value</var>, "<code data-x="">message</code>",
<var>messageDesc</var>).</p></li>
<li><p>Perform ! <span>CreateNonEnumerableDataPropertyOrThrow</span>(<var>value</var>,
"errors", <var>errors</var>).</p></li>
</ol>
</li>

<li><p>Any interesting accompanying data attached to <var>serialized</var> should be
deserialized and attached to <var>value</var>.</p></li>
Expand Down Expand Up @@ -125405,6 +125422,9 @@ INSERT INTERFACES HERE
<dt id="refsJPEG">[JPEG]</dt>
<dd><cite><a href="https://www.w3.org/Graphics/JPEG/jfif3.pdf">JPEG File Interchange Format</a></cite>, E. Hamilton.</dd>

<dt id="refsJSERRORCAUSE">[JSERRORCAUSE]</dt>
<dd><cite><a href="https://tc39.es/proposal-error-cause/">Error Cause</a></cite>. Ecma International.</dd>

<dt id="refsJSERRORSTACKS">[JSERRORSTACKS]</dt>
<dd>(Non-normative) <cite><a href="https://tc39.es/proposal-error-stacks/">Error Stacks</a></cite>. Ecma International.</dd>

Expand Down Expand Up @@ -125671,7 +125691,7 @@ INSERT INTERFACES HERE
<dd><cite><a href="https://wicg.github.io/uuid/">uuid</a></cite>, B. Coe, R. Kieffer, C. Tavan. WICG.</dd>

<dt id="refsWASMJS">[WASMJS]</dt>
<dd>(Non-normative) <cite><a href="https://webassembly.github.io/spec/js-api/">WebAssembly JavaScript Interface</a></cite>, D. Ehrenberg. W3C.</dd>
<dd><cite><a href="https://webassembly.github.io/spec/js-api/">WebAssembly JavaScript Interface</a></cite>, D. Ehrenberg. W3C.</dd>

<dt id="refsWCAG">[WCAG]</dt>
<dd>(Non-normative) <cite><a href="https://w3c.github.io/wcag/guidelines/">Web Content Accessibility Guidelines (WCAG)</a></cite>, A. Kirkpatrick, J. O Connor, A. Campbell, M. Cooper. W3C.</dd>
Expand Down

0 comments on commit 5da5838

Please sign in to comment.