From c8db224efed08d7722c9951cde048d731db050d3 Mon Sep 17 00:00:00 2001 From: "Kevin (Kun) \"Kassimo\" Qian" Date: Fri, 19 Apr 2019 17:39:54 -0700 Subject: [PATCH] Make Deno/Deno.core not deletable/writable (#2153) --- js/globals.ts | 5 +++-- js/globals_test.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ js/os.ts | 5 +++++ js/util.ts | 15 +++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/js/globals.ts b/js/globals.ts index fae14773bd..6ebf3ddfdd 100644 --- a/js/globals.ts +++ b/js/globals.ts @@ -5,7 +5,7 @@ // library. // Modules which will make up part of the global public API surface should be -// imported as namespaces, so when the runtime tpye library is generated they +// imported as namespaces, so when the runtime type library is generated they // can be expressed as a namespace in the type library. import { window } from "./window"; import * as blob from "./blob"; @@ -29,6 +29,7 @@ import * as performanceUtil from "./performance"; // These imports are not exposed and therefore are fine to just import the // symbols required. import { core } from "./core"; +import { immutableDefine } from "./util"; // During the build process, augmentations to the variable `window` in this // file are tracked and created as part of default library that is built into @@ -44,7 +45,7 @@ window.window = window; // This is the Deno namespace, it is handled differently from other window // properties when building the runtime type library, as the whole module // is flattened into a single namespace. -window.Deno = deno; +immutableDefine(window, "Deno", deno); Object.freeze(window.Deno); // ref https://console.spec.whatwg.org/#console-namespace diff --git a/js/globals_test.ts b/js/globals_test.ts index 60b5601341..4937e6c9a5 100644 --- a/js/globals_test.ts +++ b/js/globals_test.ts @@ -33,3 +33,47 @@ test(function DenoNamespaceIsFrozen() { test(function webAssemblyExists() { assert(typeof WebAssembly.compile === "function"); }); + +test(function DenoNamespaceImmutable() { + const denoCopy = window.Deno; + try { + // @ts-ignore + Deno = 1; + } catch {} + assert(denoCopy === Deno); + try { + // @ts-ignore + window.Deno = 1; + } catch {} + assert(denoCopy === Deno); + try { + delete window.Deno; + } catch {} + assert(denoCopy === Deno); + + const { readFile } = Deno; + try { + // @ts-ignore + Deno.readFile = 1; + } catch {} + assert(readFile === Deno.readFile); + try { + delete window.Deno.readFile; + } catch {} + assert(readFile === Deno.readFile); + + // @ts-ignore + const { print } = Deno.core; + try { + // @ts-ignore + Deno.core.print = 1; + } catch {} + // @ts-ignore + assert(print === Deno.core.print); + try { + // @ts-ignore + delete Deno.core.print; + } catch {} + // @ts-ignore + assert(print === Deno.core.print); +}); diff --git a/js/os.ts b/js/os.ts index 86a2c4943c..5dc5521b4d 100644 --- a/js/os.ts +++ b/js/os.ts @@ -6,6 +6,7 @@ import * as flatbuffers from "./flatbuffers"; import { TextDecoder } from "./text_encoding"; import { assert } from "./util"; import * as util from "./util"; +import { window } from "./window"; /** The current process id of the runtime. */ export let pid: number; @@ -168,5 +169,9 @@ export function start(source?: string): msg.StartRes { setGlobals(startResMsg.pid(), startResMsg.noColor(), startResMsg.execPath()!); + // Deno.core could ONLY be safely frozen here (not in globals.ts) + // since shared_queue.js will modify core properties. + Object.freeze(window.Deno.core); + return startResMsg; } diff --git a/js/util.ts b/js/util.ts index b81b96aca2..348e36a1f2 100644 --- a/js/util.ts +++ b/js/util.ts @@ -131,6 +131,21 @@ export function requiredArguments( } } +// @internal +export function immutableDefine( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + o: any, + p: string | number | symbol, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + value: any +): void { + Object.defineProperty(o, p, { + value, + configurable: false, + writable: false + }); +} + // Returns values from a WeakMap to emulate private properties in JavaScript export function getPrivateValue< K extends object,