1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-22 15:06:54 -05:00

fix(cli/rt): make some web API constructors illegal at runtime (#7468)

This commit is contained in:
Nayeem Rahman 2020-09-19 22:30:59 +01:00 committed by GitHub
parent 79e5b57663
commit aaa5e6613a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 106 additions and 15 deletions

View file

@ -130,11 +130,11 @@ declare namespace Deno {
*/
export function osRelease(): string;
/** **Unstable** new API. yet to be vetted.
/** **Unstable** new API. yet to be vetted.
*
* Displays the total amount of free and used physical and swap memory in the
* system, as well as the buffers and caches used by the kernel.
*
*
* This is similar to the `free` command in Linux
*
* ```ts
@ -1113,7 +1113,7 @@ declare namespace Deno {
/** see: https://w3c.github.io/permissions/#permissionstatus */
export class PermissionStatus {
state: PermissionState;
constructor(state: PermissionState);
constructor();
}
/** **UNSTABLE**: New API, yet to be vetted. Additional consideration is still

View file

@ -1,6 +1,8 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
((window) => {
const illegalConstructorKey = Symbol("illegalConstructorKey");
function isInvalidDate(x) {
return isNaN(x.getTime());
}
@ -146,6 +148,7 @@
}
window.__bootstrap.webUtil = {
illegalConstructorKey,
isInvalidDate,
requiredArguments,
immutableDefine,

View file

@ -2,7 +2,7 @@
((window) => {
const { opNow } = window.__bootstrap.timers;
const { cloneValue } = window.__bootstrap.webUtil;
const { cloneValue, illegalConstructorKey } = window.__bootstrap.webUtil;
const customInspect = Symbol.for("Deno.customInspect");
let performanceEntries = [];
@ -74,7 +74,11 @@
entryType,
startTime,
duration,
key,
) {
if (key != illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
}
this.#name = name;
this.#entryType = entryType;
this.#startTime = startTime;
@ -110,7 +114,7 @@
name,
{ detail = null, startTime = now() } = {},
) {
super(name, "mark", startTime, 0);
super(name, "mark", startTime, 0, illegalConstructorKey);
if (startTime < 0) {
throw new TypeError("startTime cannot be negative");
}
@ -152,8 +156,12 @@
startTime,
duration,
detail = null,
key,
) {
super(name, "measure", startTime, duration);
if (key != illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
}
super(name, "measure", startTime, duration, illegalConstructorKey);
this.#detail = cloneValue(detail);
}
@ -177,6 +185,12 @@
}
class Performance {
constructor(key) {
if (key != illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
}
}
clearMarks(markName) {
if (markName == null) {
performanceEntries = performanceEntries.filter(
@ -302,6 +316,7 @@
typeof startOrMeasureOptions === "object"
? startOrMeasureOptions.detail ?? null
: null,
illegalConstructorKey,
);
performanceEntries.push(entry);
return entry;
@ -312,10 +327,13 @@
}
}
const performance = new Performance(illegalConstructorKey);
window.__bootstrap.performance = {
PerformanceEntry,
PerformanceMark,
PerformanceMeasure,
Performance,
performance,
};
})(this);

View file

@ -2,6 +2,7 @@
((window) => {
const core = window.Deno.core;
const { illegalConstructorKey } = window.__bootstrap.webUtil;
function opQuery(desc) {
return core.jsonOpSync("op_query_permission", desc).state;
@ -16,30 +17,45 @@
}
class PermissionStatus {
constructor(state) {
constructor(state, key) {
if (key != illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
}
this.state = state;
}
// TODO(kt3k): implement onchange handler
}
class Permissions {
constructor(key) {
if (key != illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
}
}
query(desc) {
const state = opQuery(desc);
return Promise.resolve(new PermissionStatus(state));
return Promise.resolve(
new PermissionStatus(state, illegalConstructorKey),
);
}
revoke(desc) {
const state = opRevoke(desc);
return Promise.resolve(new PermissionStatus(state));
return Promise.resolve(
new PermissionStatus(state, illegalConstructorKey),
);
}
request(desc) {
const state = opRequest(desc);
return Promise.resolve(new PermissionStatus(state));
return Promise.resolve(
new PermissionStatus(state, illegalConstructorKey),
);
}
}
const permissions = new Permissions();
const permissions = new Permissions(illegalConstructorKey);
window.__bootstrap.permissions = {
permissions,

View file

@ -235,7 +235,7 @@ delete Object.prototype.__proto__;
crypto: util.readOnly(crypto),
dispatchEvent: util.readOnly(EventTarget.prototype.dispatchEvent),
fetch: util.writable(fetch.fetch),
performance: util.writable(new performance.Performance()),
performance: util.writable(performance.performance),
removeEventListener: util.readOnly(
EventTarget.prototype.removeEventListener,
),

View file

@ -3,6 +3,7 @@ import {
unitTest,
assert,
assertEquals,
assertThrows,
createResolvable,
} from "./test_util.ts";
@ -64,3 +65,19 @@ unitTest(function performanceMeasure() {
}, 100);
});
});
unitTest(function performanceIllegalConstructor() {
assertThrows(() => new Performance(), TypeError, "Illegal constructor.");
});
unitTest(function performanceEntryIllegalConstructor() {
assertThrows(() => new PerformanceEntry(), TypeError, "Illegal constructor.");
});
unitTest(function performanceMeasureIllegalConstructor() {
assertThrows(
() => new PerformanceMeasure(),
TypeError,
"Illegal constructor.",
);
});

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { unitTest, assertThrowsAsync } from "./test_util.ts";
import { unitTest, assertThrows, assertThrowsAsync } from "./test_util.ts";
unitTest(async function permissionInvalidName(): Promise<void> {
await assertThrowsAsync(async () => {
@ -13,3 +13,15 @@ unitTest(async function permissionNetInvalidUrl(): Promise<void> {
await Deno.permissions.query({ name: "net", url: ":" });
}, URIError);
});
unitTest(function permissionsIllegalConstructor() {
assertThrows(() => new Deno.Permissions(), TypeError, "Illegal constructor.");
});
unitTest(function permissionStatusIllegalConstructor() {
assertThrows(
() => new Deno.PermissionStatus(),
TypeError,
"Illegal constructor.",
);
});

View file

@ -5,6 +5,8 @@
const signalAbort = Symbol("signalAbort");
const remove = Symbol("remove");
const illegalConstructorKey = Symbol("illegalConstructorKey");
class AbortSignal extends EventTarget {
#aborted = false;
#abortAlgorithms = new Set();
@ -29,7 +31,10 @@
this.#abortAlgorithms.delete(algorithm);
}
constructor() {
constructor(key) {
if (key != illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
}
super();
this.onabort = null;
this.addEventListener("abort", (evt) => {
@ -50,7 +55,7 @@
}
class AbortController {
#signal = new AbortSignal();
#signal = new AbortSignal(illegalConstructorKey);
get signal() {
return this.#signal;

View file

@ -9,6 +9,19 @@ function assertEquals(left, right) {
assert(left === right);
}
function assertThrows(fn) {
let error = null;
try {
fn();
} catch (error_) {
error = error_;
}
if (error == null) {
throw new Error("Didn't throw.");
}
return error;
}
function basicAbortController() {
controller = new AbortController();
assert(controller);
@ -64,12 +77,19 @@ function controllerHasProperToString() {
assertEquals(actual, "[object AbortController]");
}
function abortSignalIllegalConstructor() {
const error = assertThrows(() => new AbortSignal());
assert(error instanceof TypeError);
assertEquals(error.message, "Illegal constructor.");
}
function main() {
basicAbortController();
signalCallsOnabort();
signalEventListener();
onlyAbortsOnce();
controllerHasProperToString();
abortSignalIllegalConstructor();
}
main();