summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/js/deno_unstable.ts3
-rw-r--r--cli/js/globals.ts36
-rw-r--r--cli/js/lib.deno.ns.d.ts93
-rw-r--r--cli/js/lib.deno.shared_globals.d.ts54
-rw-r--r--cli/js/lib.deno.unstable.d.ts114
-rw-r--r--cli/js/ops/permissions.ts1
-rw-r--r--cli/js/permissions.ts79
-rw-r--r--cli/js/web/navigator.ts12
-rw-r--r--cli/js/web/permissions.ts181
-rw-r--r--cli/tests/025_hrtime.ts2
-rw-r--r--cli/tests/057_revoke_permissions.ts4
-rw-r--r--cli/tests/unit/permissions_test.ts53
-rw-r--r--cli/tests/unit/test_util.ts2
-rwxr-xr-xcli/tests/unit/unit_test_runner.ts2
-rw-r--r--std/permissions/mod.ts10
15 files changed, 403 insertions, 243 deletions
diff --git a/cli/js/deno_unstable.ts b/cli/js/deno_unstable.ts
index 8744abba4..7d75c1c6a 100644
--- a/cli/js/deno_unstable.ts
+++ b/cli/js/deno_unstable.ts
@@ -19,9 +19,6 @@ export { shutdown, ShutdownMode } from "./net.ts";
export { listen, listenDatagram, connect } from "./net_unstable.ts";
export { startTls } from "./tls.ts";
export { kill } from "./ops/process.ts";
-export { permissions, Permissions } from "./permissions.ts";
-export { PermissionStatus } from "./permissions.ts";
-export type { PermissionName, PermissionState } from "./permissions.ts";
export { DiagnosticCategory } from "./diagnostics.ts";
export type {
Diagnostic,
diff --git a/cli/js/globals.ts b/cli/js/globals.ts
index 4548c8304..da6288bd2 100644
--- a/cli/js/globals.ts
+++ b/cli/js/globals.ts
@@ -7,7 +7,6 @@ import * as abortSignal from "./web/abort_signal.ts";
import * as blob from "./web/blob.ts";
import * as consoleTypes from "./web/console.ts";
import * as csprng from "./ops/get_random_values.ts";
-import type * as promiseTypes from "./web/promise.ts";
import * as customEvent from "./web/custom_event.ts";
import * as domException from "./web/dom_exception.ts";
import * as domFile from "./web/dom_file.ts";
@@ -17,16 +16,19 @@ import * as eventTarget from "./web/event_target.ts";
import * as formData from "./web/form_data.ts";
import * as fetchTypes from "./web/fetch.ts";
import * as headers from "./web/headers.ts";
+import * as navigator from "./web/navigator.ts";
+import * as permissions from "./web/permissions.ts";
+import * as performanceUtil from "./web/performance.ts";
+import type * as promiseTypes from "./web/promise.ts";
+import * as queuingStrategy from "./web/streams/queuing_strategy.ts";
+import * as readableStream from "./web/streams/readable_stream.ts";
+import * as request from "./web/request.ts";
import * as textEncoding from "./web/text_encoding.ts";
import * as timers from "./web/timers.ts";
+import * as transformStream from "./web/streams/transform_stream.ts";
import * as url from "./web/url.ts";
import * as urlSearchParams from "./web/url_search_params.ts";
import * as workers from "./web/workers.ts";
-import * as performanceUtil from "./web/performance.ts";
-import * as request from "./web/request.ts";
-import * as readableStream from "./web/streams/readable_stream.ts";
-import * as transformStream from "./web/streams/transform_stream.ts";
-import * as queuingStrategy from "./web/streams/queuing_strategy.ts";
import * as writableStream from "./web/streams/writable_stream.ts";
// These imports are not exposed and therefore are fine to just import the
@@ -221,24 +223,28 @@ export const windowOrWorkerGlobalScopeProperties = {
queuingStrategy.ByteLengthQueuingStrategyImpl
),
CountQueuingStrategy: nonEnumerable(queuingStrategy.CountQueuingStrategyImpl),
- crypto: readOnly(csprng),
- File: nonEnumerable(domFile.DomFileImpl),
CustomEvent: nonEnumerable(customEvent.CustomEventImpl),
+ crypto: readOnly(csprng),
DOMException: nonEnumerable(domException.DOMExceptionImpl),
ErrorEvent: nonEnumerable(errorEvent.ErrorEventImpl),
Event: nonEnumerable(event.EventImpl),
EventTarget: nonEnumerable(eventTarget.EventTargetImpl),
- URL: nonEnumerable(url.URLImpl),
- URLSearchParams: nonEnumerable(urlSearchParams.URLSearchParamsImpl),
- Headers: nonEnumerable(headers.HeadersImpl),
+ File: nonEnumerable(domFile.DomFileImpl),
FormData: nonEnumerable(formData.FormDataImpl),
- TextEncoder: nonEnumerable(textEncoding.TextEncoder),
- TextDecoder: nonEnumerable(textEncoding.TextDecoder),
+ Headers: nonEnumerable(headers.HeadersImpl),
+ navigator: nonEnumerable(new navigator.NavigatorImpl()),
+ Navigator: nonEnumerable(navigator.NavigatorImpl),
+ performance: writable(new performanceUtil.Performance()),
+ Permissions: nonEnumerable(permissions.PermissionsImpl),
+ PermissionStatus: nonEnumerable(permissions.PermissionStatusImpl),
ReadableStream: nonEnumerable(readableStream.ReadableStreamImpl),
- TransformStream: nonEnumerable(transformStream.TransformStreamImpl),
Request: nonEnumerable(request.Request),
Response: nonEnumerable(fetchTypes.Response),
- performance: writable(new performanceUtil.Performance()),
+ TextDecoder: nonEnumerable(textEncoding.TextDecoder),
+ TextEncoder: nonEnumerable(textEncoding.TextEncoder),
+ TransformStream: nonEnumerable(transformStream.TransformStreamImpl),
+ URL: nonEnumerable(url.URLImpl),
+ URLSearchParams: nonEnumerable(urlSearchParams.URLSearchParamsImpl),
Worker: nonEnumerable(workers.WorkerImpl),
WritableStream: nonEnumerable(writableStream.WritableStreamImpl),
};
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts
index 4a3417b5d..0b46a0c4d 100644
--- a/cli/js/lib.deno.ns.d.ts
+++ b/cli/js/lib.deno.ns.d.ts
@@ -19,6 +19,40 @@ declare interface ImportMeta {
main: boolean;
}
+declare interface Permissions {
+ /** Resolves to the current status of a permission.
+ *
+ * ```ts
+ * const status = await navigator.permissions.query({ name: "read", path: "/etc" });
+ * if (status.state === "granted") {
+ * data = await Deno.readFile("/etc/passwd");
+ * }
+ * ```
+ */
+ query(permissionDesc: Deno.PermissionDescriptor): Promise<PermissionStatus>;
+
+ /** Requests the permission, and resolves to the state of the permission.
+ *
+ * ```ts
+ * const status = await navigator.permissions.request({ name: "env" });
+ * if (status.state === "granted") {
+ * console.log(Deno.dir("home");
+ * } else {
+ * console.log("'env' permission is denied.");
+ * }
+ * ```
+ */
+ request(permissionDesc: Deno.PermissionDescriptor): Promise<PermissionStatus>;
+
+ /** Revokes a permission, and resolves to the state of the permission.
+ *
+ * ```ts
+ * const status = await Deno.revoke({ name: "run" });
+ * ```
+ */
+ revoke(permissionDesc: Deno.PermissionDescriptor): Promise<PermissionStatus>;
+}
+
declare namespace Deno {
/** A set of error constructors that are raised by Deno APIs. */
export const errors: {
@@ -1897,6 +1931,65 @@ declare namespace Deno {
* Requires `allow-run` permission. */
export function run<T extends RunOptions = RunOptions>(opt: T): Process<T>;
+ /** The name of a "powerful feature" which needs permission.
+ *
+ * See: https://w3c.github.io/permissions/#permission-registry
+ *
+ * Note that the definition of `PermissionName` in the above spec is swapped
+ * out for a set of Deno permissions which are not web-compatible. */
+ export type PermissionName =
+ | "run"
+ | "read"
+ | "write"
+ | "net"
+ | "env"
+ | "plugin"
+ | "hrtime";
+
+ export interface RunPermissionDescriptor {
+ name: "run";
+ }
+
+ export interface ReadPermissionDescriptor {
+ name: "read";
+ path?: string;
+ }
+
+ export interface WritePermissionDescriptor {
+ name: "write";
+ path?: string;
+ }
+
+ export interface NetPermissionDescriptor {
+ name: "net";
+ url?: string;
+ }
+
+ export interface EnvPermissionDescriptor {
+ name: "env";
+ }
+
+ export interface PluginPermissionDescriptor {
+ name: "plugin";
+ }
+
+ export interface HrtimePermissionDescriptor {
+ name: "hrtime";
+ }
+
+ /** Permission descriptors which define a permission and can be queried,
+ * requested, or revoked.
+ *
+ * See: https://w3c.github.io/permissions/#permission-descriptor */
+ export type PermissionDescriptor =
+ | RunPermissionDescriptor
+ | ReadPermissionDescriptor
+ | WritePermissionDescriptor
+ | NetPermissionDescriptor
+ | EnvPermissionDescriptor
+ | PluginPermissionDescriptor
+ | HrtimePermissionDescriptor;
+
interface InspectOptions {
depth?: number;
}
diff --git a/cli/js/lib.deno.shared_globals.d.ts b/cli/js/lib.deno.shared_globals.d.ts
index 0c32bd0ed..3492c0da1 100644
--- a/cli/js/lib.deno.shared_globals.d.ts
+++ b/cli/js/lib.deno.shared_globals.d.ts
@@ -1556,6 +1556,60 @@ declare const AbortSignal: {
new (): AbortSignal;
};
+type PermissionState = "denied" | "granted" | "prompt";
+
+interface PermissionStatusEventMap {
+ change: Event;
+}
+
+interface PermissionStatus extends EventTarget {
+ onchange: ((this: PermissionStatus, ev: Event) => any) | null;
+ readonly state: PermissionState;
+ addEventListener<K extends keyof PermissionStatusEventMap>(
+ type: K,
+ listener: (this: PermissionStatus, ev: PermissionStatusEventMap[K]) => any,
+ options?: boolean | AddEventListenerOptions
+ ): void;
+ addEventListener(
+ type: string,
+ listener: EventListenerOrEventListenerObject,
+ options?: boolean | AddEventListenerOptions
+ ): void;
+ removeEventListener<K extends keyof PermissionStatusEventMap>(
+ type: K,
+ listener: (this: PermissionStatus, ev: PermissionStatusEventMap[K]) => any,
+ options?: boolean | EventListenerOptions
+ ): void;
+ removeEventListener(
+ type: string,
+ listener: EventListenerOrEventListenerObject,
+ options?: boolean | EventListenerOptions
+ ): void;
+}
+
+/** Deno does not currently support any of the browser permissions, and so the
+ * `name` property of the global types is `undefined`. The Deno permissions
+ * that are supported are defined in the `lib.deno.ns.d.ts` and pull from the
+ * `Deno` namespace. */
+declare interface PermissionDescriptor {
+ name: undefined;
+}
+
+declare interface Permissions {
+ query(permissionDesc: PermissionDescriptor): Promise<PermissionStatus>;
+}
+
+declare const Permissions: {
+ prototype: Permissions;
+ new (): Permissions;
+};
+
+declare class Navigator {
+ readonly permissions: Permissions;
+}
+
+declare const navigator: Navigator;
+
interface ErrorConstructor {
/** See https://v8.dev/docs/stack-trace-api#stack-trace-collection-for-custom-exceptions. */
// eslint-disable-next-line @typescript-eslint/ban-types
diff --git a/cli/js/lib.deno.unstable.d.ts b/cli/js/lib.deno.unstable.d.ts
index cec4f7f46..f237cd4be 100644
--- a/cli/js/lib.deno.unstable.d.ts
+++ b/cli/js/lib.deno.unstable.d.ts
@@ -956,120 +956,6 @@ declare namespace Deno {
* Requires `allow-run` permission. */
export function kill(pid: number, signo: number): void;
- /** The name of a "powerful feature" which needs permission.
- *
- * See: https://w3c.github.io/permissions/#permission-registry
- *
- * Note that the definition of `PermissionName` in the above spec is swapped
- * out for a set of Deno permissions which are not web-compatible. */
- export type PermissionName =
- | "run"
- | "read"
- | "write"
- | "net"
- | "env"
- | "plugin"
- | "hrtime";
-
- /** The current status of the permission.
- *
- * See: https://w3c.github.io/permissions/#status-of-a-permission */
- export type PermissionState = "granted" | "denied" | "prompt";
-
- export interface RunPermissionDescriptor {
- name: "run";
- }
-
- export interface ReadPermissionDescriptor {
- name: "read";
- path?: string;
- }
-
- export interface WritePermissionDescriptor {
- name: "write";
- path?: string;
- }
-
- export interface NetPermissionDescriptor {
- name: "net";
- /** Optional url associated with this descriptor.
- *
- * If specified: must be a valid url. Expected format: <scheme>://<host_or_ip>[:port][/path]
- * If the scheme is unknown, callers should specify some scheme, such as x:// na:// unknown://
- *
- * See: https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml */
- url?: string;
- }
-
- export interface EnvPermissionDescriptor {
- name: "env";
- }
-
- export interface PluginPermissionDescriptor {
- name: "plugin";
- }
-
- export interface HrtimePermissionDescriptor {
- name: "hrtime";
- }
-
- /** Permission descriptors which define a permission and can be queried,
- * requested, or revoked.
- *
- * See: https://w3c.github.io/permissions/#permission-descriptor */
- export type PermissionDescriptor =
- | RunPermissionDescriptor
- | ReadPermissionDescriptor
- | WritePermissionDescriptor
- | NetPermissionDescriptor
- | EnvPermissionDescriptor
- | PluginPermissionDescriptor
- | HrtimePermissionDescriptor;
-
- export class Permissions {
- /** Resolves to the current status of a permission.
- *
- * ```ts
- * const status = await Deno.permissions.query({ name: "read", path: "/etc" });
- * if (status.state === "granted") {
- * data = await Deno.readFile("/etc/passwd");
- * }
- * ```
- */
- query(desc: PermissionDescriptor): Promise<PermissionStatus>;
-
- /** Revokes a permission, and resolves to the state of the permission.
- *
- * const status = await Deno.permissions.revoke({ name: "run" });
- * assert(status.state !== "granted")
- */
- revoke(desc: PermissionDescriptor): Promise<PermissionStatus>;
-
- /** Requests the permission, and resolves to the state of the permission.
- *
- * ```ts
- * const status = await Deno.permissions.request({ name: "env" });
- * if (status.state === "granted") {
- * console.log(Deno.dir("home");
- * } else {
- * console.log("'env' permission is denied.");
- * }
- * ```
- */
- request(desc: PermissionDescriptor): Promise<PermissionStatus>;
- }
-
- /** **UNSTABLE**: Under consideration to move to `navigator.permissions` to
- * match web API. It could look like `navigator.permissions.query({ name: Deno.symbols.read })`.
- */
- export const permissions: Permissions;
-
- /** see: https://w3c.github.io/permissions/#permissionstatus */
- export class PermissionStatus {
- state: PermissionState;
- constructor(state: PermissionState);
- }
-
/** **UNSTABLE**: New API, yet to be vetted. Additional consideration is still
* necessary around the permissions required.
*
diff --git a/cli/js/ops/permissions.ts b/cli/js/ops/permissions.ts
index 74b9ba0f0..cb1cd7402 100644
--- a/cli/js/ops/permissions.ts
+++ b/cli/js/ops/permissions.ts
@@ -1,7 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync } from "./dispatch_json.ts";
-import type { PermissionState } from "../permissions.ts";
interface PermissionRequest {
name: string;
diff --git a/cli/js/permissions.ts b/cli/js/permissions.ts
deleted file mode 100644
index ab0612ad4..000000000
--- a/cli/js/permissions.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-
-import * as permissionsOps from "./ops/permissions.ts";
-
-export type PermissionName =
- | "read"
- | "write"
- | "net"
- | "env"
- | "run"
- | "plugin"
- | "hrtime";
-// NOTE: Keep in sync with cli/permissions.rs
-
-export type PermissionState = "granted" | "denied" | "prompt";
-
-export interface RunPermissionDescriptor {
- name: "run";
-}
-
-export interface ReadPermissionDescriptor {
- name: "read";
- path?: string;
-}
-
-export interface WritePermissionDescriptor {
- name: "write";
- path?: string;
-}
-
-export interface NetPermissionDescriptor {
- name: "net";
- url?: string;
-}
-
-export interface EnvPermissionDescriptor {
- name: "env";
-}
-
-export interface PluginPermissionDescriptor {
- name: "plugin";
-}
-
-export interface HrtimePermissionDescriptor {
- name: "hrtime";
-}
-
-export type PermissionDescriptor =
- | RunPermissionDescriptor
- | ReadPermissionDescriptor
- | WritePermissionDescriptor
- | NetPermissionDescriptor
- | EnvPermissionDescriptor
- | PluginPermissionDescriptor
- | HrtimePermissionDescriptor;
-
-export class PermissionStatus {
- constructor(public state: PermissionState) {}
- // TODO(kt3k): implement onchange handler
-}
-
-export class Permissions {
- query(desc: PermissionDescriptor): Promise<PermissionStatus> {
- const state = permissionsOps.query(desc);
- return Promise.resolve(new PermissionStatus(state));
- }
-
- revoke(desc: PermissionDescriptor): Promise<PermissionStatus> {
- const state = permissionsOps.revoke(desc);
- return Promise.resolve(new PermissionStatus(state));
- }
-
- request(desc: PermissionDescriptor): Promise<PermissionStatus> {
- const state = permissionsOps.request(desc);
- return Promise.resolve(new PermissionStatus(state));
- }
-}
-
-export const permissions = new Permissions();
diff --git a/cli/js/web/navigator.ts b/cli/js/web/navigator.ts
new file mode 100644
index 000000000..351c311d0
--- /dev/null
+++ b/cli/js/web/navigator.ts
@@ -0,0 +1,12 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+
+import { PermissionsImpl as Permissions } from "./permissions.ts";
+
+export class NavigatorImpl implements Navigator {
+ permissions = new Permissions();
+}
+
+Object.defineProperty(NavigatorImpl, "name", {
+ value: "Navigator",
+ configurable: true,
+});
diff --git a/cli/js/web/permissions.ts b/cli/js/web/permissions.ts
new file mode 100644
index 000000000..b8ddc26a7
--- /dev/null
+++ b/cli/js/web/permissions.ts
@@ -0,0 +1,181 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+
+import * as permissionsOps from "../ops/permissions.ts";
+import { EventTargetImpl as EventTarget } from "./event_target.ts";
+
+const permissionNames = [
+ "read",
+ "write",
+ "net",
+ "env",
+ "run",
+ "plugin",
+ "hrtime",
+] as const;
+
+type PermissionName = typeof permissionNames[number];
+
+interface RunPermissionDescriptor {
+ name: "run";
+}
+
+interface ReadPermissionDescriptor {
+ name: "read";
+ path?: string;
+}
+
+interface WritePermissionDescriptor {
+ name: "write";
+ path?: string;
+}
+
+interface NetPermissionDescriptor {
+ name: "net";
+ url?: string;
+}
+
+interface EnvPermissionDescriptor {
+ name: "env";
+}
+
+interface PluginPermissionDescriptor {
+ name: "plugin";
+}
+
+interface HrtimePermissionDescriptor {
+ name: "hrtime";
+}
+
+type DenoPermissionDescriptor =
+ | RunPermissionDescriptor
+ | ReadPermissionDescriptor
+ | WritePermissionDescriptor
+ | NetPermissionDescriptor
+ | EnvPermissionDescriptor
+ | PluginPermissionDescriptor
+ | HrtimePermissionDescriptor;
+
+interface StatusCacheValue {
+ state: PermissionState;
+ status: PermissionStatusImpl;
+}
+
+export class PermissionStatusImpl extends EventTarget
+ implements PermissionStatus {
+ #state: { state: PermissionState };
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ onchange: ((this: PermissionStatus, event: Event) => any) | null = null;
+
+ get state(): PermissionState {
+ return this.#state.state;
+ }
+
+ constructor(state: { state: PermissionState }) {
+ super();
+ this.#state = state;
+ }
+
+ dispatchEvent(event: Event): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ let dispatched = super.dispatchEvent(event as any);
+ if (dispatched && this.onchange) {
+ this.onchange.call(this, event);
+ dispatched = !event.defaultPrevented;
+ }
+ return dispatched;
+ }
+
+ get [Symbol.toStringTag](): string {
+ return "PermissionStatus";
+ }
+}
+
+/** A cache of `PermissionStatus` objects and their last known state. */
+const statusCache = new Map<string, StatusCacheValue>();
+
+/** Cache the state of a descriptor and return its `PermissionStatus`. */
+function cache(
+ desc: DenoPermissionDescriptor,
+ state: PermissionState
+): PermissionStatusImpl {
+ let key = desc.name;
+ if ((desc.name === "read" || desc.name === "write") && desc.path) {
+ key += `-${desc.path}`;
+ } else if (desc.name === "net" && desc.url) {
+ key += `-${desc.url}`;
+ }
+ if (statusCache.has(key)) {
+ const status = statusCache.get(key)!;
+ if (status.state !== state) {
+ status.state = state;
+ status.status.dispatchEvent(new Event("change", { cancelable: false }));
+ }
+ return status.status;
+ }
+ const status: { state: PermissionState; status?: PermissionStatusImpl } = {
+ state,
+ };
+ status.status = new PermissionStatusImpl(status);
+ statusCache.set(key, status as StatusCacheValue);
+ return status.status;
+}
+
+function isValidDescriptor(
+ desc: PermissionDescriptor | DenoPermissionDescriptor
+): desc is DenoPermissionDescriptor {
+ return permissionNames.includes(desc.name as PermissionName);
+}
+
+export class PermissionsImpl implements Permissions {
+ query(
+ desc: PermissionDescriptor | DenoPermissionDescriptor
+ ): Promise<PermissionStatus> {
+ if (!isValidDescriptor(desc)) {
+ return Promise.reject(
+ new TypeError(
+ `The provided value "${desc.name}" is not a valid permission name.`
+ )
+ );
+ }
+ const state = permissionsOps.query(desc);
+ return Promise.resolve(cache(desc, state) as PermissionStatus);
+ }
+
+ revoke(
+ desc: PermissionDescriptor | DenoPermissionDescriptor
+ ): Promise<PermissionStatus> {
+ if (!isValidDescriptor(desc)) {
+ return Promise.reject(
+ new TypeError(
+ `The provided value "${desc.name}" is not a valid permission name.`
+ )
+ );
+ }
+ const state = permissionsOps.revoke(desc);
+ return Promise.resolve(cache(desc, state) as PermissionStatus);
+ }
+
+ request(
+ desc: PermissionDescriptor | DenoPermissionDescriptor
+ ): Promise<PermissionStatus> {
+ if (!isValidDescriptor(desc)) {
+ return Promise.reject(
+ new TypeError(
+ `The provided value "${desc.name}" is not a valid permission name.`
+ )
+ );
+ }
+ const state = permissionsOps.request(desc);
+ return Promise.resolve(cache(desc, state) as PermissionStatus);
+ }
+}
+
+Object.defineProperty(PermissionStatusImpl, "name", {
+ value: "PermissionStatus",
+ configurable: true,
+});
+Object.defineProperty(PermissionsImpl, "name", {
+ value: "Permissions",
+ configurable: true,
+});
diff --git a/cli/tests/025_hrtime.ts b/cli/tests/025_hrtime.ts
index 9f60b7a77..fef39ffdb 100644
--- a/cli/tests/025_hrtime.ts
+++ b/cli/tests/025_hrtime.ts
@@ -1,5 +1,5 @@
window.onload = async (): Promise<void> => {
console.log(performance.now() % 2 !== 0);
- await Deno.permissions.revoke({ name: "hrtime" });
+ await navigator.permissions.revoke({ name: "hrtime" });
console.log(performance.now() % 2 === 0);
};
diff --git a/cli/tests/057_revoke_permissions.ts b/cli/tests/057_revoke_permissions.ts
index de8deecb4..4a39112d2 100644
--- a/cli/tests/057_revoke_permissions.ts
+++ b/cli/tests/057_revoke_permissions.ts
@@ -18,11 +18,11 @@ export function assert(cond: unknown): asserts cond {
function genFunc(grant: Deno.PermissionName): [string, () => Promise<void>] {
const gen: () => Promise<void> = async function Granted(): Promise<void> {
- const status0 = await Deno.permissions.query({ name: grant });
+ const status0 = await navigator.permissions.query({ name: grant });
assert(status0 != null);
assert(status0.state === "granted");
- const status1 = await Deno.permissions.revoke({ name: grant });
+ const status1 = await navigator.permissions.revoke({ name: grant });
assert(status1 != null);
assert(status1.state === "prompt");
};
diff --git a/cli/tests/unit/permissions_test.ts b/cli/tests/unit/permissions_test.ts
index 7528768a1..0de6a774b 100644
--- a/cli/tests/unit/permissions_test.ts
+++ b/cli/tests/unit/permissions_test.ts
@@ -1,27 +1,40 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { unitTest, assert } from "./test_util.ts";
+
+import { unitTest, assert, assertThrowsAsync } from "./test_util.ts";
unitTest(async function permissionInvalidName(): Promise<void> {
- let thrown = false;
- try {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- await Deno.permissions.query({ name: "foo" as any });
- } catch (e) {
- thrown = true;
- assert(e instanceof Error);
- } finally {
- assert(thrown);
- }
+ await assertThrowsAsync(async () => {
+ // @ts-expect-error name should not accept "foo"
+ await navigator.permissions.query({ name: "foo" });
+ }, TypeError);
});
unitTest(async function permissionNetInvalidUrl(): Promise<void> {
- let thrown = false;
- try {
- await Deno.permissions.query({ name: "net", url: ":" });
- } catch (e) {
- thrown = true;
- assert(e instanceof URIError);
- } finally {
- assert(thrown);
- }
+ await assertThrowsAsync(async () => {
+ await navigator.permissions.query({ name: "net", url: ":" });
+ }, URIError);
+});
+
+unitTest(async function permissionQueryReturnsEventTarget(): Promise<void> {
+ const status = await navigator.permissions.query({ name: "hrtime" });
+ assert(["granted", "denied", "prompt"].includes(status.state));
+ let called = false;
+ status.addEventListener("change", () => {
+ called = true;
+ });
+ status.dispatchEvent(new Event("change"));
+ assert(called);
+ assert(status === (await navigator.permissions.query({ name: "hrtime" })));
+});
+
+unitTest(async function permissionQueryForReadReturnsSameStatus() {
+ const status1 = await navigator.permissions.query({
+ name: "read",
+ path: ".",
+ });
+ const status2 = await navigator.permissions.query({
+ name: "read",
+ path: ".",
+ });
+ assert(status1 === status2);
});
diff --git a/cli/tests/unit/test_util.ts b/cli/tests/unit/test_util.ts
index 25da7a638..dd6c858d2 100644
--- a/cli/tests/unit/test_util.ts
+++ b/cli/tests/unit/test_util.ts
@@ -42,7 +42,7 @@ export function fmtPerms(perms: Permissions): string {
}
const isGranted = async (name: Deno.PermissionName): Promise<boolean> =>
- (await Deno.permissions.query({ name })).state === "granted";
+ (await navigator.permissions.query({ name })).state === "granted";
export async function getProcessPermissions(): Promise<Permissions> {
return {
diff --git a/cli/tests/unit/unit_test_runner.ts b/cli/tests/unit/unit_test_runner.ts
index b2e872200..c7c494278 100755
--- a/cli/tests/unit/unit_test_runner.ts
+++ b/cli/tests/unit/unit_test_runner.ts
@@ -49,7 +49,7 @@ async function dropWorkerPermissions(
});
for (const perm of permsToDrop) {
- await Deno.permissions.revoke({ name: perm });
+ await navigator.permissions.revoke({ name: perm });
}
}
diff --git a/std/permissions/mod.ts b/std/permissions/mod.ts
index b7f80117b..d27b0c80d 100644
--- a/std/permissions/mod.ts
+++ b/std/permissions/mod.ts
@@ -1,7 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-const { PermissionDenied } = Deno.errors;
-
function getPermissionString(descriptors: Deno.PermissionDescriptor[]): string {
return descriptors.length
? ` ${descriptors
@@ -63,9 +61,9 @@ export async function grant(
? descriptor
: [descriptor, ...descriptors];
for (const descriptor of descriptors) {
- let state = (await Deno.permissions.query(descriptor)).state;
+ let state = (await navigator.permissions.query(descriptor)).state;
if (state === "prompt") {
- state = (await Deno.permissions.request(descriptor)).state;
+ state = (await navigator.permissions.request(descriptor)).state;
}
if (state === "granted") {
result.push(descriptor);
@@ -105,13 +103,13 @@ export async function grantOrThrow(
? descriptor
: [descriptor, ...descriptors];
for (const descriptor of descriptors) {
- const { state } = await Deno.permissions.request(descriptor);
+ const { state } = await navigator.permissions.request(descriptor);
if (state !== "granted") {
denied.push(descriptor);
}
}
if (denied.length) {
- throw new PermissionDenied(
+ throw new Deno.errors.PermissionDenied(
`The following permissions have not been granted:\n${getPermissionString(
denied
)}`