From aa2a8b806674e397f4bc20ce930a25e7e179dc51 Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Mon, 29 Jul 2024 12:33:26 -0700 Subject: [PATCH] Specify behavior around context loss and error reporting. Based on @mingmingtasd's work in the Chromium prototype implementation. For #477 --- index.bs | 37 +++++++++++++++++++++++++++++++++++++ tools/lint.mjs | 4 ++++ 2 files changed, 41 insertions(+) diff --git a/index.bs b/index.bs index 4aed546b..5ee57f85 100644 --- a/index.bs +++ b/index.bs @@ -817,6 +817,7 @@ The powerPreference opt 1. Set |context|.{{MLContext/[[powerPreference]]}} to {{MLPowerPreference/"default"}}. 1. Otherwise: 1. Set |context|.{{MLContext/[[contextType]]}} to "[=context type/default=]". + 1. Set |context|.{{MLContext/[[lost]]}} to [=a new promise=]. 1. If |options|["{{MLContextOptions/deviceType}}"] [=map/exists=], then set |context|.{{MLContext/[[deviceType]]}} to |options|["{{MLContextOptions/deviceType}}"]. Otherwise, set |context|.{{MLContext/[[deviceType]]}} to {{MLDeviceType/"cpu"}}. 1. If |options|["{{MLContextOptions/powerPreference}}"] [=map/exists=], then set |context|.{{MLContext/[[powerPreference]]}} to |options|["{{MLContextOptions/powerPreference}}"]. Otherwise, set |context|.{{MLContext/[[powerPreference]]}} to {{MLPowerPreference/"default"}}. 1. If the user agent cannot support |context|.{{MLContext/[[contextType]]}}, |context|.{{MLContext/[[deviceType]]}} and |context|.{{MLContext/[[powerPreference]]}}, return failure. @@ -862,10 +863,16 @@ dictionary MLComputeResult { MLNamedArrayBufferViews outputs; }; +dictionary MLContextLostInfo { + DOMString message; +}; + [SecureContext, Exposed=(Window, DedicatedWorker)] interface MLContext { Promise compute( MLGraph graph, MLNamedArrayBufferViews inputs, MLNamedArrayBufferViews outputs); + + readonly attribute Promise lost; }; @@ -881,6 +888,9 @@ interface MLContext { : \[[powerPreference]] of type {{MLPowerPreference}}. :: The {{MLContext}}'s {{MLPowerPreference}}. + : \[[lost]] of type {{Promise}}<{{MLContextLostInfo}}>. + :: + A {{Promise}} that is resolved when the {{MLContext}}'s underlying execution device is no longer available. @@ -978,6 +988,7 @@ Note: Invocations of {{MLContext/compute()}} will fail if any of the {{MLContext 1. Let |global| be [=this=]'s [=relevant global object=]. 1. Let |realm| be [=this=]'s [=relevant realm=]. + 1. If [=this=] [=MLContext/is lost=], then [=exception/throw=] an "{{InvalidStateError}}" {{DOMException}}. 1. If |graph|.{{MLGraph/[[context]]}} is not [=this=], then return [=a new promise=] [=rejected=] with a {{TypeError}}. 1. If |graph|.{{MLGraph/[[context]]}}.{{MLContext/[[contextType]]}} is not "[=context type/default=]", then return [=a new promise=] [=rejected=] with an "{{OperationError}}" {{DOMException}}. 1. [=map/For each=] |name| → |descriptor| of |graph|.{{MLGraph/[[inputDescriptors]]}}: @@ -1039,6 +1050,31 @@ Note: Invocations of {{MLContext/compute()}} will fail if any of the {{MLContext +### Errors ### {#api-mlcontext-errors} + +
+ +When an {{MLContext}} |context| is no longer available to fulfill requests, run the following steps: + + 1. Let |global| be |context|'s [=relevant global object=]. + 1. [=Queue an ML task=] with |global| to run these steps: + 1. Let |info| be a new {{MLContextLostInfo}}. + 1. Set |info|.{{MLContextLostInfo/message}} to an [=implementation-defined=] value. + 1. [=Resolve=] |context|.{{MLContext/[[lost]]}} with |info|. +
+ +
+ : message + :: An [=implementation-defined=] message providing information about the error that occurred. +
+ +
+The lost getter steps are to return [=this=]'s {{MLContext/[[lost]]}} {{Promise}}. +
+ +A {{MLContext}} is lost if its {{MLContext/[[lost]]}} {{Promise}} is settled. + + ## {{MLGraph}} interface ## {#api-mlgraph} The {{MLGraph}} interface represents a compiled computational graph. A compiled graph once constructed is immutable and cannot be subsequently changed. @@ -1309,6 +1345,7 @@ The {{MLGraphBuilder}}.{{MLGraphBuilder/build()}} method compiles the graph buil The [=new=] MLGraphBuilder(|context|) constructor steps are: 1. If [=this=]'s [=relevant global object=]'s [=associated Document=] is not [=allowed to use=] the [=webnn-feature|webnn=] feature, then [=exception/throw=] a "{{SecurityError}}" {{DOMException}}. + 1. If |context| [=MLContext/is lost=], then [=exception/throw=] an "{{InvalidStateError}}" {{DOMException}}. 1. Set [=this=].{{MLGraphBuilder/[[context]]}} to |context|. 1. Set [=this=].{{MLGraphBuilder/[[hasBuilt]]}} to false. diff --git a/tools/lint.mjs b/tools/lint.mjs index 7c934ffc..233a24bb 100755 --- a/tools/lint.mjs +++ b/tools/lint.mjs @@ -232,6 +232,10 @@ for (const algorithm of root.querySelectorAll('.algorithm')) { // Lambda argument declarations // e.g. "Let validationSteps given MLOperandDescriptor descriptor be..." seen.add(name); + } else if (new RegExp('^When .* \\b' + name + '\\b').test(text)) { + // Reactive argument declarations + // e.g. "When something bad happens to MLContext context, ..." + seen.add(name); } else if (!seen.has(name)) { error(`Uninitialized variable "${name}" in "${algorithm.getAttribute('data-algorithm')}": ${text}`); seen.add(name);