mirror of
https://github.com/denoland/deno
synced 2024-08-25 02:57:22 +00:00
Provide option to delete Deno namespace in worker (#2717)
This commit is contained in:
parent
aaa7a3eac4
commit
ddee2dff14
|
@ -196,8 +196,10 @@ fn create_worker_and_state(
|
|||
s.status(status, msg).expect("shell problem");
|
||||
}
|
||||
});
|
||||
// TODO(kevinkassimo): maybe make include_deno_namespace also configurable?
|
||||
let state =
|
||||
ThreadSafeState::new(flags, argv, ops::op_selector_std, progress).unwrap();
|
||||
ThreadSafeState::new(flags, argv, ops::op_selector_std, progress, true)
|
||||
.unwrap();
|
||||
let worker = Worker::new(
|
||||
"main".to_string(),
|
||||
startup_data::deno_isolate_init(),
|
||||
|
|
|
@ -204,6 +204,7 @@ table FormatErrorRes {
|
|||
// Create worker as host
|
||||
table CreateWorker {
|
||||
specifier: string;
|
||||
include_deno_namespace: bool;
|
||||
}
|
||||
|
||||
table CreateWorkerRes {
|
||||
|
|
|
@ -2069,6 +2069,10 @@ fn op_create_worker(
|
|||
let cmd_id = base.cmd_id();
|
||||
let inner = base.inner_as_create_worker().unwrap();
|
||||
let specifier = inner.specifier().unwrap();
|
||||
// Only include deno namespace if requested AND current worker
|
||||
// has included namespace (to avoid escalation).
|
||||
let include_deno_namespace =
|
||||
inner.include_deno_namespace() && state.include_deno_namespace;
|
||||
|
||||
let parent_state = state.clone();
|
||||
|
||||
|
@ -2077,13 +2081,15 @@ fn op_create_worker(
|
|||
parent_state.argv.clone(),
|
||||
op_selector_std,
|
||||
parent_state.progress.clone(),
|
||||
include_deno_namespace,
|
||||
)?;
|
||||
let rid = child_state.resource.rid;
|
||||
let name = format!("USER-WORKER-{}", specifier);
|
||||
let deno_main_call = format!("denoMain({})", include_deno_namespace);
|
||||
|
||||
let mut worker =
|
||||
Worker::new(name, startup_data::deno_isolate_init(), child_state);
|
||||
worker.execute("denoMain()").unwrap();
|
||||
worker.execute(&deno_main_call).unwrap();
|
||||
worker.execute("workerMain()").unwrap();
|
||||
|
||||
let module_specifier = ModuleSpecifier::resolve_url_or_path(specifier)?;
|
||||
|
|
|
@ -84,6 +84,8 @@ pub struct State {
|
|||
pub js_compiler: JsCompiler,
|
||||
pub json_compiler: JsonCompiler,
|
||||
pub ts_compiler: TsCompiler,
|
||||
|
||||
pub include_deno_namespace: bool,
|
||||
}
|
||||
|
||||
impl Clone for ThreadSafeState {
|
||||
|
@ -151,6 +153,7 @@ impl ThreadSafeState {
|
|||
argv_rest: Vec<String>,
|
||||
dispatch_selector: ops::OpSelector,
|
||||
progress: Progress,
|
||||
include_deno_namespace: bool,
|
||||
) -> Result<Self, ErrBox> {
|
||||
let custom_root = env::var("DENO_DIR").map(String::into).ok();
|
||||
|
||||
|
@ -223,6 +226,7 @@ impl ThreadSafeState {
|
|||
ts_compiler,
|
||||
js_compiler: JsCompiler {},
|
||||
json_compiler: JsonCompiler {},
|
||||
include_deno_namespace,
|
||||
};
|
||||
|
||||
Ok(ThreadSafeState(Arc::new(state)))
|
||||
|
@ -302,6 +306,7 @@ impl ThreadSafeState {
|
|||
argv,
|
||||
ops::op_selector_std,
|
||||
Progress::new(),
|
||||
true,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
|
|
@ -126,6 +126,7 @@ mod tests {
|
|||
argv,
|
||||
op_selector_std,
|
||||
Progress::new(),
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
let state_ = state.clone();
|
||||
|
@ -155,6 +156,7 @@ mod tests {
|
|||
argv,
|
||||
op_selector_std,
|
||||
Progress::new(),
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
let state_ = state.clone();
|
||||
|
@ -182,7 +184,7 @@ mod tests {
|
|||
let mut flags = flags::DenoFlags::default();
|
||||
flags.reload = true;
|
||||
let state =
|
||||
ThreadSafeState::new(flags, argv, op_selector_std, Progress::new())
|
||||
ThreadSafeState::new(flags, argv, op_selector_std, Progress::new(), true)
|
||||
.unwrap();
|
||||
let state_ = state.clone();
|
||||
tokio_util::run(lazy(move || {
|
||||
|
|
|
@ -29,8 +29,12 @@ SharedQueue Binary Layout
|
|||
const INDEX_RECORDS = 3 + MAX_RECORDS;
|
||||
const HEAD_INIT = 4 * INDEX_RECORDS;
|
||||
|
||||
// Available on start due to bindings.
|
||||
const Deno = window[GLOBAL_NAMESPACE];
|
||||
const core = Deno[CORE_NAMESPACE];
|
||||
// Warning: DO NOT use window.Deno after this point.
|
||||
// It is possible that the Deno namespace has been deleted.
|
||||
// Use the above local Deno and core variable instead.
|
||||
|
||||
let sharedBytes;
|
||||
let shared32;
|
||||
|
@ -165,7 +169,7 @@ SharedQueue Binary Layout
|
|||
const success = push(control);
|
||||
// If successful, don't use first argument of core.send.
|
||||
const arg0 = success ? null : control;
|
||||
return window.Deno.core.send(arg0, zeroCopy);
|
||||
return Deno.core.send(arg0, zeroCopy);
|
||||
}
|
||||
|
||||
const denoCore = {
|
||||
|
|
|
@ -25,7 +25,7 @@ const console = new Console(core.print);
|
|||
window.console = console;
|
||||
window.workerMain = workerMain;
|
||||
export default function denoMain(): void {
|
||||
os.start("TS");
|
||||
os.start(true, "TS");
|
||||
}
|
||||
|
||||
const ASSETS = "$asset$";
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { window } from "./window";
|
||||
|
||||
// This allows us to access core in API even if we
|
||||
// dispose window.Deno
|
||||
export const core = window.Deno.core as DenoCore;
|
||||
|
|
|
@ -32,7 +32,6 @@ import * as request from "./request";
|
|||
// 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
|
||||
|
@ -71,7 +70,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.
|
||||
immutableDefine(window, "Deno", deno);
|
||||
window.Deno = deno;
|
||||
Object.freeze(window.Deno);
|
||||
|
||||
// Globally available functions and object instances.
|
||||
|
|
|
@ -18,8 +18,11 @@ import { setLocation } from "./location";
|
|||
// builtin modules
|
||||
import * as deno from "./deno";
|
||||
|
||||
export default function denoMain(name?: string): void {
|
||||
const startResMsg = os.start(name);
|
||||
export default function denoMain(
|
||||
preserveDenoNamespace: boolean = true,
|
||||
name?: string
|
||||
): void {
|
||||
const startResMsg = os.start(preserveDenoNamespace, name);
|
||||
|
||||
setVersions(startResMsg.denoVersion()!, startResMsg.v8Version()!);
|
||||
|
||||
|
|
20
js/os.ts
20
js/os.ts
|
@ -112,7 +112,10 @@ function sendStart(): msg.StartRes {
|
|||
// This function bootstraps an environment within Deno, it is shared both by
|
||||
// the runtime and the compiler environments.
|
||||
// @internal
|
||||
export function start(source?: string): msg.StartRes {
|
||||
export function start(
|
||||
preserveDenoNamespace = true,
|
||||
source?: string
|
||||
): msg.StartRes {
|
||||
core.setAsyncHandler(handleAsyncMsgFromRust);
|
||||
|
||||
// First we send an empty `Start` message to let the privileged side know we
|
||||
|
@ -124,9 +127,18 @@ 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);
|
||||
if (preserveDenoNamespace) {
|
||||
util.immutableDefine(window, "Deno", window.Deno);
|
||||
// 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);
|
||||
// core.sharedQueue is an object so we should also freeze it.
|
||||
Object.freeze(window.Deno.core.sharedQueue);
|
||||
} else {
|
||||
// Remove window.Deno
|
||||
delete window.Deno;
|
||||
assert(window.Deno === undefined);
|
||||
}
|
||||
|
||||
return startResMsg;
|
||||
}
|
||||
|
|
|
@ -20,10 +20,17 @@ export function decodeMessage(dataIntArray: Uint8Array): any {
|
|||
return JSON.parse(dataJson);
|
||||
}
|
||||
|
||||
function createWorker(specifier: string): number {
|
||||
function createWorker(
|
||||
specifier: string,
|
||||
includeDenoNamespace: boolean
|
||||
): number {
|
||||
const builder = flatbuffers.createBuilder();
|
||||
const specifier_ = builder.createString(specifier);
|
||||
const inner = msg.CreateWorker.createCreateWorker(builder, specifier_);
|
||||
const inner = msg.CreateWorker.createCreateWorker(
|
||||
builder,
|
||||
specifier_,
|
||||
includeDenoNamespace
|
||||
);
|
||||
const baseRes = sendSync(builder, msg.Any.CreateWorker, inner);
|
||||
assert(baseRes != null);
|
||||
assert(
|
||||
|
@ -149,6 +156,18 @@ export interface Worker {
|
|||
closed: Promise<void>;
|
||||
}
|
||||
|
||||
// TODO(kevinkassimo): Maybe implement reasonable web worker options?
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface WorkerOptions {}
|
||||
|
||||
/** Extended Deno Worker initialization options.
|
||||
* `noDenoNamespace` hides global `window.Deno` namespace for
|
||||
* spawned worker and nested workers spawned by it (default: false).
|
||||
*/
|
||||
export interface DenoWorkerOptions extends WorkerOptions {
|
||||
noDenoNamespace?: boolean;
|
||||
}
|
||||
|
||||
export class WorkerImpl implements Worker {
|
||||
private readonly rid: number;
|
||||
private isClosing: boolean = false;
|
||||
|
@ -157,8 +176,12 @@ export class WorkerImpl implements Worker {
|
|||
public onmessage?: (data: any) => void;
|
||||
public onmessageerror?: () => void;
|
||||
|
||||
constructor(specifier: string) {
|
||||
this.rid = createWorker(specifier);
|
||||
constructor(specifier: string, options?: DenoWorkerOptions) {
|
||||
let includeDenoNamespace = true;
|
||||
if (options && options.noDenoNamespace) {
|
||||
includeDenoNamespace = false;
|
||||
}
|
||||
this.rid = createWorker(specifier, includeDenoNamespace);
|
||||
this.run();
|
||||
this.isClosedPromise = hostGetWorkerClosed(this.rid);
|
||||
this.isClosedPromise.then(
|
||||
|
|
2
tests/039_worker_deno_ns.test
Normal file
2
tests/039_worker_deno_ns.test
Normal file
|
@ -0,0 +1,2 @@
|
|||
args: run --reload tests/039_worker_deno_ns.ts
|
||||
output: tests/039_worker_deno_ns.ts.out
|
25
tests/039_worker_deno_ns.ts
Normal file
25
tests/039_worker_deno_ns.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
const w1 = new Worker("./tests/039_worker_deno_ns/has_ns.ts");
|
||||
const w2 = new Worker("./tests/039_worker_deno_ns/no_ns.ts", {
|
||||
noDenoNamespace: true
|
||||
});
|
||||
let w1MsgCount = 0;
|
||||
let w2MsgCount = 0;
|
||||
w1.onmessage = (msg): void => {
|
||||
console.log(msg.data);
|
||||
w1MsgCount++;
|
||||
if (w1MsgCount === 1) {
|
||||
w1.postMessage("CONTINUE");
|
||||
} else {
|
||||
w2.postMessage("START");
|
||||
}
|
||||
};
|
||||
w2.onmessage = (msg): void => {
|
||||
console.log(msg.data);
|
||||
w2MsgCount++;
|
||||
if (w2MsgCount === 1) {
|
||||
w2.postMessage("CONTINUE");
|
||||
} else {
|
||||
Deno.exit(0);
|
||||
}
|
||||
};
|
||||
w1.postMessage("START");
|
4
tests/039_worker_deno_ns.ts.out
Normal file
4
tests/039_worker_deno_ns.ts.out
Normal file
|
@ -0,0 +1,4 @@
|
|||
has_ns.ts: is window.Deno available: true
|
||||
[SPAWNED BY has_ns.ts] maybe_ns.ts: is window.Deno available: true
|
||||
no_ns.ts: is window.Deno available: false
|
||||
[SPAWNED BY no_ns.ts] maybe_ns.ts: is window.Deno available: false
|
10
tests/039_worker_deno_ns/has_ns.ts
Normal file
10
tests/039_worker_deno_ns/has_ns.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
onmessage = (msg): void => {
|
||||
if (msg.data === "START") {
|
||||
postMessage("has_ns.ts: is window.Deno available: " + !!window.Deno);
|
||||
} else {
|
||||
const worker = new Worker("./tests/039_worker_deno_ns/maybe_ns.ts");
|
||||
worker.onmessage = (msg): void => {
|
||||
postMessage("[SPAWNED BY has_ns.ts] " + msg.data);
|
||||
};
|
||||
}
|
||||
};
|
1
tests/039_worker_deno_ns/maybe_ns.ts
Normal file
1
tests/039_worker_deno_ns/maybe_ns.ts
Normal file
|
@ -0,0 +1 @@
|
|||
postMessage("maybe_ns.ts: is window.Deno available: " + !!window.Deno);
|
10
tests/039_worker_deno_ns/no_ns.ts
Normal file
10
tests/039_worker_deno_ns/no_ns.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
onmessage = (msg): void => {
|
||||
if (msg.data === "START") {
|
||||
postMessage("no_ns.ts: is window.Deno available: " + !!window.Deno);
|
||||
} else {
|
||||
const worker = new Worker("./tests/039_worker_deno_ns/maybe_ns.ts");
|
||||
worker.onmessage = (msg): void => {
|
||||
postMessage("[SPAWNED BY no_ns.ts] " + msg.data);
|
||||
};
|
||||
}
|
||||
};
|
Loading…
Reference in a new issue