You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Ensure object creation specifies the realm
"Realm" is an ECMAScript concept best explained in
https://html.spec.whatwg.org/multipage/webappapis.html#realms-and-their-counterparts
Newly created JS objects must be associated with a Realm; while older
specs didn't do this explicitly, best practice is to be explicit about
this, especially for steps running "in parallel", or in algorithms
separate from method steps. Do so!
This also adds lint tests to try and catch future violations. Note
that dictionaries (e.g. MLOperatorDescriptor) are Infra "ordered maps"
it the body of spec algorithms, not JS objects, so they don't have a
realm. Conversion to a JS object when returning a dictionary to script
is handled by WebIDL bindings logic.
Also note that DOMExceptions, either thrown or as promise rejection
values, are not given a realm. This is a known issue across all web
specs and is tracked in whatwg/webidl#135.
Resolveswebmachinelearning#793.
* Don't double-init realm; and don't need realm for dicts
* Variable name improvement from @fdwr
Copy file name to clipboardExpand all lines: index.bs
+35-29Lines changed: 35 additions & 29 deletions
Original file line number
Diff line number
Diff line change
@@ -810,13 +810,13 @@ The <dfn dfn-for=MLContextOptions dfn-type=dict-member>powerPreference</dfn> opt
810
810
<summary>
811
811
To <dfn>create a context</dfn> given [=realm=] |realm| and |options| (a {{GPUDevice}} or {{MLContextOptions}}), run these steps:
812
812
</summary>
813
-
1. Let |context| be a new {{MLContext}}object with |realm|.
813
+
1. Let |context| be a new {{MLContext}}in |realm|.
814
814
1. If |options| is a {{GPUDevice}} object:
815
815
1. Set |context|.{{MLContext/[[contextType]]}} to "[=context type/webgpu=]".
816
816
1. Set |context|.{{MLContext/[[powerPreference]]}} to {{MLPowerPreference/"default"}}.
817
817
1. Otherwise:
818
818
1. Set |context|.{{MLContext/[[contextType]]}} to "[=context type/default=]".
819
-
1. Set |context|.{{MLContext/[[lost]]}} to [=a new promise=].
819
+
1. Set |context|.{{MLContext/[[lost]]}} to [=a new promise=] in |realm|.
820
820
1. If |options|["{{MLContextOptions/powerPreference}}"][=map/exists=], then set |context|.{{MLContext/[[powerPreference]]}} to |options|["{{MLContextOptions/powerPreference}}"].
821
821
1. Otherwise, set |context|.{{MLContext/[[powerPreference]]}} to {{MLPowerPreference/"default"}}.
822
822
1. If the user agent cannot support |context|.{{MLContext/[[contextType]]}} and |context|.{{MLContext/[[powerPreference]]}}, return failure.
@@ -828,9 +828,9 @@ The <dfn dfn-for=MLContextOptions dfn-type=dict-member>powerPreference</dfn> opt
828
828
The <dfn method for=ML>createContext(|options|)</dfn> steps are:
829
829
</summary>
830
830
1. Let |global| be [=this=]'s [=relevant global object=].
831
-
1. If |global|'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, return [=a new promise=][=rejected=] with a "{{SecurityError}}" {{DOMException}}.
832
831
1. Let |realm| be [=this=]'s [=relevant realm=].
833
-
1. Let |promise| be [=a new promise=].
832
+
1. If |global|'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, return [=a new promise=] in |realm| [=rejected=] with a "{{SecurityError}}" {{DOMException}}.
833
+
1. Let |promise| be [=a new promise=] in |realm|.
834
834
1. Run the following steps [=in parallel=].
835
835
1. Let |context| be the result of [=creating a context=] given |realm| and |options|. If that returns failure, then [=queue an ML task=] with |global| to [=reject=] |promise| with a "{{NotSupportedError}}" {{DOMException}} and abort these steps.
836
836
1. [=Queue an ML task=] with |global| to [=resolve=] |promise| with |context|.
@@ -842,9 +842,9 @@ The <dfn dfn-for=MLContextOptions dfn-type=dict-member>powerPreference</dfn> opt
842
842
The <dfn method for=ML>createContext(|gpuDevice|)</dfn> method steps are:
843
843
</summary>
844
844
1. Let |global| be [=this=]'s [=relevant global object=].
845
-
1. If |global|'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, return [=a new promise=][=rejected=] with a "{{SecurityError}}" {{DOMException}}.
846
845
1. Let |realm| be [=this=]'s [=relevant realm=].
847
-
1. Let |promise| be [=a new promise=].
846
+
1. If |global|'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, return [=a new promise=] in |realm| [=rejected=] with a "{{SecurityError}}" {{DOMException}}.
847
+
1. Let |promise| be [=a new promise=] in |realm|.
848
848
1. Run the following steps [=in parallel=].
849
849
1. Let |context| be the result of [=creating a context=] given |realm| and |gpuDevice|. If that returns failure, then [=queue an ML task=] with |global| to [=reject=] |promise| with a "{{NotSupportedError}}" {{DOMException}} and abort these steps.
850
850
1. [=Queue an ML task=] with |global| to [=resolve=] |promise| with |context|.
@@ -1043,9 +1043,10 @@ Creates an {{MLTensor}} associated with this {{MLContext}}.
1043
1043
The <dfn method for=MLContext>createTensor(|descriptor|)</dfn> method steps are:
1044
1044
</summary>
1045
1045
1. Let |global| be [=this=]'s [=relevant global object=].
1046
-
1. If [=this=][=MLContext/is lost=], then return [=a new promise=][=rejected=] with an "{{InvalidStateError}}" {{DOMException}}.
1046
+
1. Let |realm| be [=this=]'s [=relevant realm=].
1047
+
1. If [=this=][=MLContext/is lost=], then return [=a new promise=] in |realm| [=rejected=] with an "{{InvalidStateError}}" {{DOMException}}.
1047
1048
1. Let |tensor| be the result of [=creating an MLTensor=] given [=this=], and |descriptor|.
1048
-
1. Let |promise| be [=a new promise=].
1049
+
1. Let |promise| be [=a new promise=] in |realm|.
1049
1050
1. Enqueue the following steps to [=this=].{{MLContext/[[timeline]]}}:
1050
1051
1. Run these steps, but [=/abort when=][=this=][=MLContext/is lost=]:
1051
1052
1. Create |tensor|.{{MLTensor/[[data]]}} given |descriptor| and initialize all bytes to zeros.
@@ -1072,10 +1073,10 @@ Reads back the {{MLTensor/[[data]]}} of an {{MLTensor}} from the {{MLContext}}.{
1072
1073
</summary>
1073
1074
1. Let |global| be [=this=]'s [=relevant global object=].
1074
1075
1. Let |realm| be [=this=]'s [=relevant realm=].
1075
-
1. If |tensor|.{{MLTensor/[[context]]}} is not [=this=], then return [=a new promise=][=rejected=] with a {{TypeError}}.
1076
-
1. If |tensor|.{{MLTensor/[[isDestroyed]]}} is true, then return [=a new promise=][=rejected=] with a {{TypeError}}.
1077
-
1. If |tensor|.{{MLTensor/[[descriptor]]}}.{{MLTensorDescriptor/readable}} is false, then return [=a new promise=][=rejected=] with a {{TypeError}}.
1078
-
1. Let |promise| be [=a new promise=].
1076
+
1. If |tensor|.{{MLTensor/[[context]]}} is not [=this=], then return [=a new promise=]in |realm| [=rejected=] with a {{TypeError}}.
1077
+
1. If |tensor|.{{MLTensor/[[isDestroyed]]}} is true, then return [=a new promise=]in |realm| [=rejected=] with a {{TypeError}}.
1078
+
1. If |tensor|.{{MLTensor/[[descriptor]]}}.{{MLTensorDescriptor/readable}} is false, then return [=a new promise=]in |realm| [=rejected=] with a {{TypeError}}.
1079
+
1. Let |promise| be [=a new promise=] in |realm|.
1079
1080
1. Enqueue the following steps to |tensor|.{{MLTensor/[[context]]}}.{{MLContext/[[timeline]]}}:
1080
1081
1. Run these steps, but [=/abort when=][=this=][=MLContext/is lost=]:
1081
1082
1. Let |bytes| be a [=/byte sequence=] containing a copy of |tensor|.{{MLTensor/[[data]]}}.
@@ -1102,11 +1103,12 @@ Bring-your-own-buffer variant of {{MLContext/readTensor(tensor)}}. Reads back th
1102
1103
The <dfn method for=MLContext>readTensor(|tensor|, |outputData|)</dfn> method steps are:
1103
1104
</summary>
1104
1105
1. Let |global| be [=this=]'s [=relevant global object=].
1105
-
1. If |tensor|.{{MLTensor/[[context]]}} is not [=this=], then return [=a new promise=][=rejected=] with a {{TypeError}}.
1106
-
1. If |tensor|.{{MLTensor/[[isDestroyed]]}} is true, then return [=a new promise=][=rejected=] with a {{TypeError}}.
1107
-
1. If |tensor|.{{MLTensor/[[descriptor]]}}.{{MLTensorDescriptor/readable}} is false, then return [=a new promise=][=rejected=] with a {{TypeError}}.
1108
-
1. If [=validating buffer with descriptor=] given |outputData| and |tensor|.{{MLTensor/[[descriptor]]}} returns false, then return [=a new promise=][=rejected=] with a {{TypeError}}.
1109
-
1. Let |promise| be [=a new promise=].
1106
+
1. Let |realm| be [=this=]'s [=relevant realm=].
1107
+
1. If |tensor|.{{MLTensor/[[context]]}} is not [=this=], then return [=a new promise=] in |realm| [=rejected=] with a {{TypeError}}.
1108
+
1. If |tensor|.{{MLTensor/[[isDestroyed]]}} is true, then return [=a new promise=] in |realm| [=rejected=] with a {{TypeError}}.
1109
+
1. If |tensor|.{{MLTensor/[[descriptor]]}}.{{MLTensorDescriptor/readable}} is false, then return [=a new promise=] in |realm| [=rejected=] with a {{TypeError}}.
1110
+
1. If [=validating buffer with descriptor=] given |outputData| and |tensor|.{{MLTensor/[[descriptor]]}} returns false, then return [=a new promise=] in |realm| [=rejected=] with a {{TypeError}}.
1111
+
1. Let |promise| be [=a new promise=] in |realm|.
1110
1112
1. Enqueue the following steps to |tensor|.{{MLTensor/[[context]]}}.{{MLContext/[[timeline]]}}:
1111
1113
1. Run these steps, but [=/abort when=][=this=][=MLContext/is lost=]:
1112
1114
1. Let |bytes| be a [=/byte sequence=] containing a copy of |tensor|.{{MLTensor/[[data]]}}.
@@ -1473,7 +1475,8 @@ The {{MLOperand}} objects are created by the methods of {{MLGraphBuilder}}, inte
1473
1475
<summary>
1474
1476
To <dfn>create an MLOperand</dfn> given {{MLGraphBuilder}} |builder| and {{MLOperandDescriptor}} |desc|, run the following steps:
1475
1477
</summary>
1476
-
1. Let |operand| be a new {{MLOperand}}.
1478
+
1. Let |realm| be |builder|'s [=relevant realm=].
1479
+
1. Let |operand| be a new {{MLOperand}} in |realm|.
1477
1480
1. Set |operand|.{{MLOperand/[[builder]]}} to |builder|.
1478
1481
1. Set |operand|.{{MLOperand/[[descriptor]]}} to |desc|.
1479
1482
1. Return |operand|.
@@ -1483,8 +1486,10 @@ The {{MLOperand}} objects are created by the methods of {{MLGraphBuilder}}, inte
1483
1486
<summary>
1484
1487
To <dfn>copy an MLOperand</dfn> given {{MLOperand}} |operand|, run the following steps:
1485
1488
</summary>
1486
-
1. Let |result| be a new {{MLOperand}}.
1487
-
1. Set |result|.{{MLOperand/[[builder]]}} to |operand|.{{MLOperand/[[builder]]}}.
1489
+
1. Let |builder| be |operand|.{{MLOperand/[[builder]]}}.
1490
+
1. Let |realm| be |builder|'s [=relevant realm=].
1491
+
1. Let |result| be a new {{MLOperand}} in |realm|.
1492
+
1. Set |result|.{{MLOperand/[[builder]]}} to |builder|.
1488
1493
1. Set |result|.{{MLOperand/[[descriptor]]}} to |operand|.{{MLOperand/[[descriptor]]}}.
1489
1494
1. If |operand|.{{MLOperand/[[name]]}}[=map/exists=], then set |result|.{{MLOperand/[[name]]}} to |operand|.{{MLOperand/[[name]]}}.
1490
1495
1. Return |result|.
@@ -1582,7 +1587,8 @@ An {{MLTensor}} is created by its associated {{MLContext}}.
1582
1587
<summary>
1583
1588
To <dfn>create an MLTensor</dfn> given {{MLContext}} |context| and {{MLTensorDescriptor}} |descriptor|, run the following steps:
1584
1589
</summary>
1585
-
1. Let |tensor| be a new {{MLTensor}}.
1590
+
1. Let |realm| be |context|'s [=relevant realm=].
1591
+
1. Let |tensor| be a new {{MLTensor}} in |realm|.
1586
1592
1. Set |tensor|.{{MLTensor/[[context]]}} to |context|.
1587
1593
1. Set |tensor|.{{MLTensor/[[descriptor]]}} to |descriptor|.
1588
1594
1. Set |tensor|.{{MLTensor/[[isDestroyed]]}} to false.
@@ -1771,12 +1777,13 @@ Build a composed graph up to a given output operand into a computational graph a
1771
1777
<summary>
1772
1778
The <dfn method for=MLGraphBuilder>build(|outputs|)</dfn> method steps are:
1773
1779
</summary>
1774
-
1. If [=this=][=MLGraphBuilder/can not build=], then return [=a new promise=][=rejected=] with an "{{InvalidStateError}}" {{DOMException}}.
1775
-
1. If |outputs| is empty, then return [=a new promise=][=rejected=] with a {{TypeError}}.
1780
+
1. Let |realm| be [=this=]'s [=relevant realm=].
1781
+
1. If [=this=][=MLGraphBuilder/can not build=], then return [=a new promise=] in |realm| [=rejected=] with an "{{InvalidStateError}}" {{DOMException}}.
1782
+
1. If |outputs| is empty, then return [=a new promise=] in |realm| [=rejected=] with a {{TypeError}}.
1776
1783
1. [=map/For each=] |name| → |operand| of |outputs|:
1777
-
1. If |name| is empty, then return [=a new promise=][=rejected=] with a {{TypeError}}.
1778
-
1. If [=MLGraphBuilder/validating operand=] given [=this=] and |operand| returns false, then return [=a new promise=][=rejected=] with a {{TypeError}}.
1779
-
1. If |operand| is in [=this=]'s [=MLGraphBuilder/graph=]'s [=computational graph/inputs=] or [=computational graph/constants=], then return [=a new promise=][=rejected=] with a {{TypeError}}.
1784
+
1. If |name| is empty, then return [=a new promise=]in |realm| [=rejected=] with a {{TypeError}}.
1785
+
1. If [=MLGraphBuilder/validating operand=] given [=this=] and |operand| returns false, then return [=a new promise=]in |realm| [=rejected=] with a {{TypeError}}.
1786
+
1. If |operand| is in [=this=]'s [=MLGraphBuilder/graph=]'s [=computational graph/inputs=] or [=computational graph/constants=], then return [=a new promise=]in |realm| [=rejected=] with a {{TypeError}}.
1780
1787
1. Let |operands| be a new empty [=/set=].
1781
1788
1. Let |operators| be a new empty [=/set=].
1782
1789
1. Let |inputs| be a new empty [=/set=].
@@ -1789,16 +1796,15 @@ Build a composed graph up to a given output operand into a computational graph a
1789
1796
1. [=list/For each=] |input| of |operand|.{{MLOperand/[[operator]]}}'s [=operator/inputs=]:
1790
1797
1. [=queue/Enqueue=] |input| to |queue|.
1791
1798
1. Let |global| be [=this=]'s [=relevant global object=].
1792
-
1. Let |realm| be [=this=]'s [=relevant realm=].
1793
-
1. Let |graph| be a new {{MLGraph}} with |realm|.
1799
+
1. Let |graph| be a new {{MLGraph}} in |realm|.
1794
1800
1. Set |graph|.{{MLGraph/[[context]]}} to [=this=].{{MLGraphBuilder/[[context]]}}.
1795
1801
1. Set |graph|.{{MLGraph/[[isDestroyed]]}} to false.
1796
1802
1. [=set/For each=] |operand| in |inputs|:
1797
1803
1. Set |graph|.{{MLGraph/[[inputDescriptors]]}}[|operand|.{{MLOperand/[[name]]}}] to |operand|.{{MLOperand/[[descriptor]]}}.
1798
1804
1. [=map/For each=] |name| → |operand| of |outputs|:
1799
1805
1. Set |graph|.{{MLGraph/[[outputDescriptors]]}}[|name|] to |operand|.{{MLOperand/[[descriptor]]}}.
1800
1806
1. Set [=this=].{{MLGraphBuilder/[[hasBuilt]]}} to true.
1801
-
1. Let |promise| be [=a new promise=].
1807
+
1. Let |promise| be [=a new promise=] in |realm|.
1802
1808
1. Run the following steps [=in parallel=]:
1803
1809
1. Run these steps, but [=/abort when=] |graph|.{{MLGraph/[[context]]}}[=MLContext/is lost=]:
1804
1810
1. Let |graphImpl| be the result of converting [=this=]'s [=MLGraphBuilder/graph=] with |operands|, |operators|, |inputs|, and |outputs|'s [=map/values=] into an [=implementation-defined=] format which can be interpreted by the underlying platform.
0 commit comments