deno.land / x / deno@v1.28.2 / runtime / js / 10_permissions.js
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license."use strict";
((window) => { const { ops } = Deno.core; const { Event } = window.__bootstrap.event; const { EventTarget } = window.__bootstrap.eventTarget; const { pathFromURL } = window.__bootstrap.util; const { illegalConstructorKey } = window.__bootstrap.webUtil; const { ArrayIsArray, ArrayPrototypeIncludes, ArrayPrototypeMap, ArrayPrototypeSlice, Map, MapPrototypeGet, MapPrototypeHas, MapPrototypeSet, FunctionPrototypeCall, PromiseResolve, PromiseReject, ReflectHas, SymbolFor, TypeError, } = window.__bootstrap.primordials;
/** * @typedef StatusCacheValue * @property {PermissionState} state * @property {PermissionStatus} status */
/** @type {ReadonlyArray<"read" | "write" | "net" | "env" | "sys" | "run" | "ffi" | "hrtime">} */ const permissionNames = [ "read", "write", "net", "env", "sys", "run", "ffi", "hrtime", ];
/** * @param {Deno.PermissionDescriptor} desc * @returns {Deno.PermissionState} */ function opQuery(desc) { return ops.op_query_permission(desc); }
/** * @param {Deno.PermissionDescriptor} desc * @returns {Deno.PermissionState} */ function opRevoke(desc) { return ops.op_revoke_permission(desc); }
/** * @param {Deno.PermissionDescriptor} desc * @returns {Deno.PermissionState} */ function opRequest(desc) { return ops.op_request_permission(desc); }
class PermissionStatus extends EventTarget { /** @type {{ state: Deno.PermissionState }} */ #state;
/** @type {((this: PermissionStatus, event: Event) => any) | null} */ onchange = null;
/** @returns {Deno.PermissionState} */ get state() { return this.#state.state; }
/** * @param {{ state: Deno.PermissionState }} state * @param {unknown} key */ constructor(state = null, key = null) { if (key != illegalConstructorKey) { throw new TypeError("Illegal constructor."); } super(); this.#state = state; }
/** * @param {Event} event * @returns {boolean} */ dispatchEvent(event) { let dispatched = super.dispatchEvent(event); if (dispatched && this.onchange) { FunctionPrototypeCall(this.onchange, this, event); dispatched = !event.defaultPrevented; } return dispatched; }
[SymbolFor("Deno.privateCustomInspect")](inspect) { return `${this.constructor.name} ${ inspect({ state: this.state, onchange: this.onchange }) }`; } }
/** @type {Map<string, StatusCacheValue>} */ const statusCache = new Map();
/** * @param {Deno.PermissionDescriptor} desc * @param {Deno.PermissionState} state * @returns {PermissionStatus} */ function cache(desc, state) { let { name: key } = desc; if ( (desc.name === "read" || desc.name === "write" || desc.name === "ffi") && ReflectHas(desc, "path") ) { key += `-${desc.path}&`; } else if (desc.name === "net" && desc.host) { key += `-${desc.host}&`; } else if (desc.name === "run" && desc.command) { key += `-${desc.command}&`; } else if (desc.name === "env" && desc.variable) { key += `-${desc.variable}&`; } else if (desc.name === "sys" && desc.kind) { key += `-${desc.kind}&`; } else { key += "$"; } if (MapPrototypeHas(statusCache, key)) { const status = MapPrototypeGet(statusCache, key); if (status.state !== state) { status.state = state; status.status.dispatchEvent(new Event("change", { cancelable: false })); } return status.status; } /** @type {{ state: Deno.PermissionState; status?: PermissionStatus }} */ const status = { state }; status.status = new PermissionStatus(status, illegalConstructorKey); MapPrototypeSet(statusCache, key, status); return status.status; }
/** * @param {unknown} desc * @returns {desc is Deno.PermissionDescriptor} */ function isValidDescriptor(desc) { return typeof desc === "object" && desc !== null && ArrayPrototypeIncludes(permissionNames, desc.name); }
class Permissions { constructor(key = null) { if (key != illegalConstructorKey) { throw new TypeError("Illegal constructor."); } }
query(desc) { if (!isValidDescriptor(desc)) { return PromiseReject( new TypeError( `The provided value "${desc?.name}" is not a valid permission name.`, ), ); }
if ( desc.name === "read" || desc.name === "write" || desc.name === "ffi" ) { desc.path = pathFromURL(desc.path); } else if (desc.name === "run") { desc.command = pathFromURL(desc.command); }
const state = opQuery(desc); return PromiseResolve(cache(desc, state)); }
revoke(desc) { if (!isValidDescriptor(desc)) { return PromiseReject( new TypeError( `The provided value "${desc?.name}" is not a valid permission name.`, ), ); }
if (desc.name === "read" || desc.name === "write") { desc.path = pathFromURL(desc.path); } else if (desc.name === "run") { desc.command = pathFromURL(desc.command); }
const state = opRevoke(desc); return PromiseResolve(cache(desc, state)); }
request(desc) { if (!isValidDescriptor(desc)) { return PromiseReject( new TypeError( `The provided value "${desc?.name}" is not a valid permission name.`, ), ); }
if (desc.name === "read" || desc.name === "write") { desc.path = pathFromURL(desc.path); } else if (desc.name === "run") { desc.command = pathFromURL(desc.command); }
const state = opRequest(desc); return PromiseResolve(cache(desc, state)); } }
const permissions = new Permissions(illegalConstructorKey);
/** Converts all file URLs in FS allowlists to paths. */ function serializePermissions(permissions) { if (typeof permissions == "object" && permissions != null) { const serializedPermissions = {}; for (const key of ["read", "write", "run", "ffi"]) { if (ArrayIsArray(permissions[key])) { serializedPermissions[key] = ArrayPrototypeMap( permissions[key], (path) => pathFromURL(path), ); } else { serializedPermissions[key] = permissions[key]; } } for (const key of ["env", "hrtime", "net", "sys"]) { if (ArrayIsArray(permissions[key])) { serializedPermissions[key] = ArrayPrototypeSlice(permissions[key]); } else { serializedPermissions[key] = permissions[key]; } } return serializedPermissions; } return permissions; }
window.__bootstrap.permissions = { serializePermissions, permissions, Permissions, PermissionStatus, };})(this);
Version Info