Skip to content

Commit 208fd00

Browse files
Update spec.emu
1 parent 2852be1 commit 208fd00

File tree

1 file changed

+69
-61
lines changed

1 file changed

+69
-61
lines changed

spec.emu

Lines changed: 69 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ contributors: Arthur Fiorette, Arlen Beiler
1212

1313
<emu-intro id="sec-intro">
1414
<h1>Introduction</h1>
15+
<emu-note>
16+
<p><strong>Important Notice:</strong> Until this proposal is accepted by ECMA, this spec.emu file might not reflect the latest updates to the proposal. Readers should base their understanding primarily on the current <a href="https://github.com/arthurfiorette/proposal-try-operator/blob/main/README.md">README.md</a> file, which serves as the authoritative source during the proposal stage. This specification is an imagination of what the final specification might look like and while it can be trusted as a reference, the README.md has higher importance at this stage of the project.</p>
17+
</emu-note>
1518
<p>This proposal introduces a `try` operator and `Result` class to JavaScript for improved error handling ergonomics. The `try` operator evaluates an expression within an implicit try-catch block and returns a `Result` instance containing either the successful value or the caught error.</p>
1619
</emu-intro>
1720

@@ -20,13 +23,25 @@ contributors: Arthur Fiorette, Arlen Beiler
2023

2124
<emu-clause id="sec-result-constructor">
2225
<h1>The Result Constructor</h1>
23-
<p>The Result constructor is not intended to be called as a constructor. It throws a *TypeError* exception if called with `new`.</p>
26+
<p>The Result constructor is the %Result% intrinsic object. When called as a constructor, it creates and initializes a new Result object.</p>
2427

2528
<emu-clause id="sec-result">
26-
<h1>Result ( )</h1>
27-
<p>When `Result` is called, the following steps are taken:</p>
29+
<h1>Result ( _ok_, _error_, _value_ )</h1>
30+
<p>When `Result` is called with arguments _ok_, _error_, and _value_, the following steps are taken:</p>
2831
<emu-alg>
29-
1. Throw a *TypeError* exception.
32+
1. If NewTarget is *undefined*, throw a *TypeError* exception.
33+
1. Let _result_ be ? OrdinaryCreateFromConstructor(NewTarget, *"%Result.prototype%"*, « [[ResultState]], [[ResultValue]], [[ResultError]] »).
34+
1. Let _booleanOk_ be ToBoolean(_ok_).
35+
1. Perform ! CreateDataPropertyOrThrow(_result_, *"ok"*, _booleanOk_).
36+
1. If _booleanOk_ is *true*, then
37+
1. Set _result_.[[ResultState]] to ~success~.
38+
1. Set _result_.[[ResultValue]] to _value_.
39+
1. Perform ! CreateDataPropertyOrThrow(_result_, *"value"*, _value_).
40+
1. Else,
41+
1. Set _result_.[[ResultState]] to ~failure~.
42+
1. Set _result_.[[ResultError]] to _error_.
43+
1. Perform ! CreateDataPropertyOrThrow(_result_, *"error"*, _error_).
44+
1. Return _result_.
3045
</emu-alg>
3146
</emu-clause>
3247
</emu-clause>
@@ -38,9 +53,7 @@ contributors: Arthur Fiorette, Arlen Beiler
3853
<h1>Result.ok ( _value_ )</h1>
3954
<p>When the `Result.ok` method is called with argument _value_, the following steps are taken:</p>
4055
<emu-alg>
41-
1. Let _result_ be OrdinaryObjectCreate(%Result.prototype%, « [[ResultState]], [[ResultValue]] »).
42-
1. Set _result_.[[ResultState]] to ~success~.
43-
1. Set _result_.[[ResultValue]] to _value_.
56+
1. Let _result_ be ? Construct(%Result%, « *true*, *undefined*, _value_ »).
4457
1. Return _result_.
4558
</emu-alg>
4659
</emu-clause>
@@ -49,24 +62,45 @@ contributors: Arthur Fiorette, Arlen Beiler
4962
<h1>Result.error ( _error_ )</h1>
5063
<p>When the `Result.error` method is called with argument _error_, the following steps are taken:</p>
5164
<emu-alg>
52-
1. Let _result_ be OrdinaryObjectCreate(%Result.prototype%, « [[ResultState]], [[ResultError]] »).
53-
1. Set _result_.[[ResultState]] to ~failure~.
54-
1. Set _result_.[[ResultError]] to _error_.
65+
1. Let _result_ be ? Construct(%Result%, « *false*, _error_, *undefined* »).
5566
1. Return _result_.
5667
</emu-alg>
5768
</emu-clause>
5869

5970
<emu-clause id="sec-result.try">
60-
<h1>Result.try ( _fn_, ..._args_ )</h1>
61-
<p>When the `Result.try` method is called with argument _fn_ and optional arguments _args_, the following steps are taken:</p>
71+
<h1>Result.try ( _arg_, ..._args_ )</h1>
72+
<p>When the `Result.try` method is called with argument _arg_ and optional arguments _args_, the following steps are taken:</p>
6273
<emu-alg>
63-
1. If IsCallable(_fn_) is *false*, throw a *TypeError* exception.
64-
1. Let _result_ be Completion(Call(_fn_, *undefined*, _args_)).
65-
1. If _result_ is an abrupt completion, then
66-
1. Return ! Call(%Result.error%, %Result%, « _result_.[[Value]] »).
67-
1. Else,
68-
1. Return ! Call(%Result.ok%, %Result%, « _result_.[[Value]] »).
74+
1. Let _completion_ be Completion(ResultTryImplementation(_arg_, _args_)).
75+
1. If _completion_ is an abrupt completion, then
76+
1. Return ! Call(%Result.error%, %Result%, « _completion_.[[Value]] »).
77+
1. Return _completion_.[[Value]].
6978
</emu-alg>
79+
80+
<emu-clause id="sec-result-try-implementation" type="abstract operation">
81+
<h1>ResultTryImplementation ( _arg_, _args_ )</h1>
82+
<dl class="header">
83+
</dl>
84+
<emu-alg>
85+
1. Let _result_ be *undefined*.
86+
1. If IsCallable(_arg_) is *true*, then
87+
1. Let _callResult_ be Completion(Call(_arg_, *undefined*, _args_)).
88+
1. If _callResult_ is an abrupt completion, then
89+
1. Return ! Call(%Result.error%, %Result%, « _callResult_.[[Value]] »).
90+
1. Set _result_ to _callResult_.[[Value]].
91+
1. Else,
92+
1. Set _result_ to _arg_.
93+
1. If _result_ is an Object and IsPromise(_result_) is *true*, then
94+
1. Let _fulfillmentHandler_ be a new Abstract Closure with parameters (_value_) that captures nothing and performs the following steps when called:
95+
1. Return ! Call(%Result.ok%, %Result%, « _value_ »).
96+
1. Let _rejectionHandler_ be a new Abstract Closure with parameters (_reason_) that captures nothing and performs the following steps when called:
97+
1. Return ! Call(%Result.error%, %Result%, « _reason_ »).
98+
1. Let _onFulfilled_ be CreateBuiltinFunction(_fulfillmentHandler_, 1, *""*, « »).
99+
1. Let _onRejected_ be CreateBuiltinFunction(_rejectionHandler_, 1, *""*, « »).
100+
1. Return PerformPromiseThen(_result_, _onFulfilled_, _onRejected_).
101+
1. Return ! Call(%Result.ok%, %Result%, « _result_ »).
102+
</emu-alg>
103+
</emu-clause>
70104
</emu-clause>
71105

72106
<emu-clause id="sec-result.prototype">
@@ -85,39 +119,6 @@ contributors: Arthur Fiorette, Arlen Beiler
85119
<li>has a [[Prototype]] internal slot whose value is %Object.prototype%.</li>
86120
</ul>
87121

88-
<emu-clause id="sec-result.prototype.ok">
89-
<h1>get Result.prototype.ok</h1>
90-
<p>`Result.prototype.ok` is an accessor property whose set accessor function is *undefined*. Its get accessor function performs the following steps:</p>
91-
<emu-alg>
92-
1. Let _result_ be the *this* value.
93-
1. Perform ? RequireInternalSlot(_result_, [[ResultState]]).
94-
1. If _result_.[[ResultState]] is ~success~, return *true*.
95-
1. Return *false*.
96-
</emu-alg>
97-
</emu-clause>
98-
99-
<emu-clause id="sec-result.prototype.value">
100-
<h1>get Result.prototype.value</h1>
101-
<p>`Result.prototype.value` is an accessor property whose set accessor function is *undefined*. Its get accessor function performs the following steps:</p>
102-
<emu-alg>
103-
1. Let _result_ be the *this* value.
104-
1. Perform ? RequireInternalSlot(_result_, [[ResultState]]).
105-
1. If _result_.[[ResultState]] is ~failure~, throw a *TypeError* exception.
106-
1. Return _result_.[[ResultValue]].
107-
</emu-alg>
108-
</emu-clause>
109-
110-
<emu-clause id="sec-result.prototype.error">
111-
<h1>get Result.prototype.error</h1>
112-
<p>`Result.prototype.error` is an accessor property whose set accessor function is *undefined*. Its get accessor function performs the following steps:</p>
113-
<emu-alg>
114-
1. Let _result_ be the *this* value.
115-
1. Perform ? RequireInternalSlot(_result_, [[ResultState]]).
116-
1. If _result_.[[ResultState]] is ~success~, throw a *TypeError* exception.
117-
1. Return _result_.[[ResultError]].
118-
</emu-alg>
119-
</emu-clause>
120-
121122
<emu-clause id="sec-result.prototype-@@iterator">
122123
<h1>Result.prototype [ %Symbol.iterator% ] ( )</h1>
123124
<p>When the %Symbol.iterator% method is called, the following steps are taken:</p>
@@ -177,15 +178,22 @@ contributors: Arthur Fiorette, Arlen Beiler
177178
1. Let _index_ be _iterator_.[[ResultIteratorNextIndex]].
178179
1. If _index_ is 0, then
179180
1. Set _iterator_.[[ResultIteratorNextIndex]] to 1.
180-
1. Return CreateIteratorResultObject(_result_.[[ResultState]] is ~success~, *false*).
181+
1. Let _okValue_ be ? Get(_result_, *"ok"*).
182+
1. Return CreateIteratorResultObject(_okValue_, *false*).
181183
1. Else if _index_ is 1, then
182184
1. Set _iterator_.[[ResultIteratorNextIndex]] to 2.
183-
1. If _result_.[[ResultState]] is ~success~, return CreateIteratorResultObject(*undefined*, *false*).
184-
1. Else, return CreateIteratorResultObject(_result_.[[ResultError]], *false*).
185+
1. If ? HasProperty(_result_, *"error"*) is *true*, then
186+
1. Let _errorValue_ be ? Get(_result_, *"error"*).
187+
1. Return CreateIteratorResultObject(_errorValue_, *false*).
188+
1. Else,
189+
1. Return CreateIteratorResultObject(*undefined*, *false*).
185190
1. Else if _index_ is 2, then
186191
1. Set _iterator_.[[ResultIteratorNextIndex]] to 3.
187-
1. If _result_.[[ResultState]] is ~success~, return CreateIteratorResultObject(_result_.[[ResultValue]], *false*).
188-
1. Else, return CreateIteratorResultObject(*undefined*, *false*).
192+
1. If ? HasProperty(_result_, *"value"*) is *true*, then
193+
1. Let _valueValue_ be ? Get(_result_, *"value"*).
194+
1. Return CreateIteratorResultObject(_valueValue_, *false*).
195+
1. Else,
196+
1. Return CreateIteratorResultObject(*undefined*, *false*).
189197
1. Else,
190198
1. Return CreateIteratorResultObject(*undefined*, *true*).
191199
</emu-alg>
@@ -218,13 +226,13 @@ contributors: Arthur Fiorette, Arlen Beiler
218226
<h1>Runtime Semantics: Evaluation</h1>
219227
<emu-grammar>UnaryExpression : `try` UnaryExpression</emu-grammar>
220228
<emu-alg>
221-
1. Let _expr_ be the result of evaluating |UnaryExpression|.
222-
1. If _expr_ is an abrupt completion, then
223-
1. Return ! Call(%Result.error%, %Result%, « _expr_.[[Value]] »).
224-
1. Let _value_ be ! GetValue(_expr_).
229+
1. Let _exprRef_ be Completion(Evaluation of |UnaryExpression|).
230+
1. If _exprRef_ is an abrupt completion, then
231+
1. Return ! Call(%Result.error%, %Result%, « _exprRef_.[[Value]] »).
232+
1. Let _value_ be Completion(GetValue(_exprRef_)).
225233
1. If _value_ is an abrupt completion, then
226234
1. Return ! Call(%Result.error%, %Result%, « _value_.[[Value]] »).
227-
1. Return ! Call(%Result.ok%, %Result%, « _value_ »).
235+
1. Return ! Call(%Result.ok%, %Result%, « _value_.[[Value]] »).
228236
</emu-alg>
229237
</emu-clause>
230238
</emu-clause>

0 commit comments

Comments
 (0)