From f2d6b04856275c4a369df92edc69da570f77335e Mon Sep 17 00:00:00 2001 From: Austin Sullivan Date: Tue, 4 Apr 2023 04:38:36 +0000 Subject: [PATCH] rebase + make access checks not throwable --- index.bs | 149 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 88 insertions(+), 61 deletions(-) diff --git a/index.bs b/index.bs index 7a93fd5..85791f5 100644 --- a/index.bs +++ b/index.bs @@ -61,16 +61,31 @@ different storage mechanism with a different API for such files. The entry point A file system entry is either a [=file entry=] or a [=directory entry=]. -Each [=/file system entry=] has an associated query access algorithm, which takes "`read`" -or "`readwrite`" mode and returns a {{PermissionState}}. Unless specified -otherwise it returns "{{PermissionState/denied}}". The algorithm is allowed to throw. - -Each [=/file system entry=] has an associated request access algorithm, which takes -"`read`" or "`readwrite`" mode and returns a {{PermissionState}}. Unless specified -otherwise it returns "{{PermissionState/denied}}". The algorithm is allowed to throw. - -Note: Implementations that only implement this specification and not dependent specifications do not -need to bother implementing [=/file system entry=]'s [=file system entry/query access=] and [=file system entry/request access=]. +Each [=/file system entry=] has an associated +query access +algorithm, which takes "`read`" or "`readwrite`" mode and +returns either a {{PermissionState}} or an [=exception/error name=] that must be +listed in the [=error names table=]. +Unless specified otherwise it returns "{{PermissionState/denied}}". + +Each [=/file system entry=] has an associated +request access +algorithm, which takes "`read`" or "`readwrite`" mode and +returns either a {{PermissionState}} or an [=exception/error name=] that must be +listed in the [=error names table=]. +Unless specified otherwise it returns "{{PermissionState/denied}}". + +

Dependent specifications may consider this API a +[=powerful feature=]. However, unlike other [=powerful features=] whose +[=permission request algorithm=] may throw, [=/file system entry=]'s +[=file system entry/query access=] and [=file system entry/request access=] +algorithms must run [=in parallel=] on the [=file system queue=] and are +therefore not allowed to throw. Instead, the caller is expected to [=/reject=] +as appropriate should these algorithms return an [=exception/error name=]. + +Note: Implementations that only implement this specification and not dependent +specifications do not need to bother implementing [=/file system entry=]'s +[=file system entry/query access=] and [=file system entry/request access=]. Issue(101): Make access check algorithms associated with a FileSystemHandle. @@ -504,31 +519,33 @@ The createWritable(|options|) method 1. Let |result| be [=a new promise=]. 1. Let |locator| be [=this=]'s [=FileSystemHandle/locator=]. 1. Let |realm| be [=this=]'s [=relevant Realm=]. -1. [=Queue a storage task=] with [=this=]'s [=relevant global object=] to - [=enqueue the following steps=] to the [=file system queue=]: +1. Let |global| be [=this=]'s [=relevant global object=]. +1. [=Enqueue the following steps=] to the [=file system queue=]: 1. Let |entry| be the result of [=locating an entry=] given |locator|. 1. Let |access| be the result of running |entry|'s [=file system entry/request access=] given "`readwrite`". - If that throws an exception, [=reject=] |result| with that exception and - abort these steps. - 1. If |access| is not "{{PermissionState/granted}}", - [=reject=] |result| with a "{{NotAllowedError}}" {{DOMException}} and - abort these steps. - - 1. If |entry| is `null`, [=/reject=] |result| with a - "{{NotFoundError}}" {{DOMException}} and abort. + 1. If |access| is not "{{PermissionState/granted}}": + 1. Set |requestAccessError| to |access| if |access| is an + [=exception/error name=]; otherwise, "{{NotAllowedError}}". + 1. [=Queue a storage task=] with |global| to [=/reject=] |result| with a + |requestAccessError| {{DOMException}} and abort these steps. + + 1. If |entry| is `null`, [=queue a storage task=] with |global| to [=/reject=] + |result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps. 1. [=Assert=]: |entry| is a [=file entry=]. 1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=] with "`shared`" on |entry|. - 1. If |lockResult| is "`failure`", [=reject=] |result| with a + 1. If |lockResult| is "`failure`", [=queue a storage task=] with |global| to + [=/reject=] |result| with a "{{NoModificationAllowedError}}" {{DOMException}} and abort these steps. - 1. Let |stream| be the result of creating a new `FileSystemWritableFileStream` - for |entry| in |realm|. - 1. If |options|'s {{FileSystemCreateWritableOptions/keepExistingData}} is true: - 1. Set |stream|'s [=[[buffer]]=] to a copy of |entry|'s [=file entry/binary data=]. - 1. [=/Resolve=] |result| with |stream|. + 1. [=Queue a storage task=] with |global| to run these steps: + 1. Let |stream| be the result of creating a new `FileSystemWritableFileStream` + for |entry| in |realm|. + 1. If |options|'s {{FileSystemCreateWritableOptions/keepExistingData}} is true: + 1. Set |stream|'s [=[[buffer]]=] to a copy of |entry|'s [=file entry/binary data=]. + 1. [=/Resolve=] |result| with |stream|. 1. Return |result|. @@ -562,31 +579,36 @@ The createSyncAccessHandle() method s 1. Let |result| be [=a new promise=]. 1. Let |locator| be [=this=]'s [=FileSystemHandle/locator=]. 1. Let |realm| be [=this=]'s [=relevant Realm=]. +1. Let |global| be [=this=]'s [=relevant global object=]. 1. [=Enqueue the following steps=] to the [=file system queue=]: 1. Let |entry| be the result of [=locating an entry=] given |locator|. 1. Let |access| be the result of running |entry|'s [=file system entry/request access=] given "`readwrite`". - If that throws an exception, [=reject=] |result| with that exception and - abort these steps. - 1. If |access| is not "{{PermissionState/granted}}", [=reject=] |result| with - a "{{NotAllowedError}}" {{DOMException}} and abort these steps. - - 1. If |entry| is `null`, [=/reject=] |result| with a - "{{NotFoundError}}" {{DOMException}} and abort. + 1. If |access| is not "{{PermissionState/granted}}": + 1. Set |requestAccessError| to |access| if |access| is an + [=exception/error name=]; otherwise, "{{NotAllowedError}}". + 1. [=Queue a storage task=] with |global| to [=/reject=] |result| with a + |requestAccessError| {{DOMException}} and abort these steps. + + 1. If |entry| is `null`, [=queue a storage task=] with |global| to [=/reject=] + |result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps. 1. [=Assert=]: |entry| is a [=file entry=]. - 1. If |entry| does not represent a [=/file system entry=] in an [=origin private file system=], - [=reject=] |result| with an "{{InvalidStateError}}" {{DOMException}} and + 1. If |entry| does not represent a [=/file system entry=] in an + [=origin private file system=], [=queue a storage task=] with |global| to + [=/reject=] |result| with an "{{InvalidStateError}}" {{DOMException}} and abort these steps. 1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=] with "`exclusive`" on |entry|. - 1. If |lockResult| is "`failure`", [=reject=] |result| with a + 1. If |lockResult| is "`failure`", [=queue a storage task=] with |global| to + [=/reject=] |result| with a "{{NoModificationAllowedError}}" {{DOMException}} and abort these steps. - 1. Let |handle| be the result of creating a new `FileSystemSyncAccessHandle` - for |entry| in |realm|. - 1. [=/Resolve=] |result| with |handle|. + 1. [=Queue a storage task=] with |global| to run these steps: + 1. Let |handle| be the result of creating a new `FileSystemSyncAccessHandle` + for |entry| in |realm|. + 1. [=/Resolve=] |result| with |handle|. 1. Return |result|. @@ -707,7 +729,7 @@ and its async iterator |iterator|: [=file system entry/query access=] given "`read`". 1. If |access| is not "{{PermissionState/granted}}", - [=reject=] |promise| with a "{{NotAllowedError}}" {{DOMException}} and + [=/reject=] |promise| with a "{{NotAllowedError}}" {{DOMException}} and return |promise|. 1. Let |child| be a [=/file system entry=] in |directory|'s [=directory entry/children=], @@ -774,7 +796,7 @@ The getFileHandle(|name|, |options|)getDirectoryHandle(|name|, |option 1. If |options|.{{FileSystemGetDirectoryOptions/create}} is true: 1. Let |access| be the result of running |entry|'s [=file system entry/request access=] given "`readwrite`". - If that throws an exception, [=reject=] |result| with that exception and abort. + If that throws an exception, [=/reject=] |result| with that exception and abort. 1. Otherwise: 1. Let |access| be the result of running |entry|'s [=file system entry/query access=] given "`read`". @@ -915,7 +937,7 @@ The removeEntry(|name|, |options|)