mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
Provide option to delete Deno namespace in worker (#2717)
This commit is contained in:
parent
aaa7a3eac4
commit
ddee2dff14
18 changed files with 128 additions and 17 deletions
|
@ -196,8 +196,10 @@ fn create_worker_and_state(
|
||||||
s.status(status, msg).expect("shell problem");
|
s.status(status, msg).expect("shell problem");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// TODO(kevinkassimo): maybe make include_deno_namespace also configurable?
|
||||||
let state =
|
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(
|
let worker = Worker::new(
|
||||||
"main".to_string(),
|
"main".to_string(),
|
||||||
startup_data::deno_isolate_init(),
|
startup_data::deno_isolate_init(),
|
||||||
|
|
|
@ -204,6 +204,7 @@ table FormatErrorRes {
|
||||||
// Create worker as host
|
// Create worker as host
|
||||||
table CreateWorker {
|
table CreateWorker {
|
||||||
specifier: string;
|
specifier: string;
|
||||||
|
include_deno_namespace: bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
table CreateWorkerRes {
|
table CreateWorkerRes {
|
||||||
|
|
|
@ -2069,6 +2069,10 @@ fn op_create_worker(
|
||||||
let cmd_id = base.cmd_id();
|
let cmd_id = base.cmd_id();
|
||||||
let inner = base.inner_as_create_worker().unwrap();
|
let inner = base.inner_as_create_worker().unwrap();
|
||||||
let specifier = inner.specifier().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();
|
let parent_state = state.clone();
|
||||||
|
|
||||||
|
@ -2077,13 +2081,15 @@ fn op_create_worker(
|
||||||
parent_state.argv.clone(),
|
parent_state.argv.clone(),
|
||||||
op_selector_std,
|
op_selector_std,
|
||||||
parent_state.progress.clone(),
|
parent_state.progress.clone(),
|
||||||
|
include_deno_namespace,
|
||||||
)?;
|
)?;
|
||||||
let rid = child_state.resource.rid;
|
let rid = child_state.resource.rid;
|
||||||
let name = format!("USER-WORKER-{}", specifier);
|
let name = format!("USER-WORKER-{}", specifier);
|
||||||
|
let deno_main_call = format!("denoMain({})", include_deno_namespace);
|
||||||
|
|
||||||
let mut worker =
|
let mut worker =
|
||||||
Worker::new(name, startup_data::deno_isolate_init(), child_state);
|
Worker::new(name, startup_data::deno_isolate_init(), child_state);
|
||||||
worker.execute("denoMain()").unwrap();
|
worker.execute(&deno_main_call).unwrap();
|
||||||
worker.execute("workerMain()").unwrap();
|
worker.execute("workerMain()").unwrap();
|
||||||
|
|
||||||
let module_specifier = ModuleSpecifier::resolve_url_or_path(specifier)?;
|
let module_specifier = ModuleSpecifier::resolve_url_or_path(specifier)?;
|
||||||
|
|
|
@ -84,6 +84,8 @@ pub struct State {
|
||||||
pub js_compiler: JsCompiler,
|
pub js_compiler: JsCompiler,
|
||||||
pub json_compiler: JsonCompiler,
|
pub json_compiler: JsonCompiler,
|
||||||
pub ts_compiler: TsCompiler,
|
pub ts_compiler: TsCompiler,
|
||||||
|
|
||||||
|
pub include_deno_namespace: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for ThreadSafeState {
|
impl Clone for ThreadSafeState {
|
||||||
|
@ -151,6 +153,7 @@ impl ThreadSafeState {
|
||||||
argv_rest: Vec<String>,
|
argv_rest: Vec<String>,
|
||||||
dispatch_selector: ops::OpSelector,
|
dispatch_selector: ops::OpSelector,
|
||||||
progress: Progress,
|
progress: Progress,
|
||||||
|
include_deno_namespace: bool,
|
||||||
) -> Result<Self, ErrBox> {
|
) -> Result<Self, ErrBox> {
|
||||||
let custom_root = env::var("DENO_DIR").map(String::into).ok();
|
let custom_root = env::var("DENO_DIR").map(String::into).ok();
|
||||||
|
|
||||||
|
@ -223,6 +226,7 @@ impl ThreadSafeState {
|
||||||
ts_compiler,
|
ts_compiler,
|
||||||
js_compiler: JsCompiler {},
|
js_compiler: JsCompiler {},
|
||||||
json_compiler: JsonCompiler {},
|
json_compiler: JsonCompiler {},
|
||||||
|
include_deno_namespace,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ThreadSafeState(Arc::new(state)))
|
Ok(ThreadSafeState(Arc::new(state)))
|
||||||
|
@ -302,6 +306,7 @@ impl ThreadSafeState {
|
||||||
argv,
|
argv,
|
||||||
ops::op_selector_std,
|
ops::op_selector_std,
|
||||||
Progress::new(),
|
Progress::new(),
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,7 @@ mod tests {
|
||||||
argv,
|
argv,
|
||||||
op_selector_std,
|
op_selector_std,
|
||||||
Progress::new(),
|
Progress::new(),
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let state_ = state.clone();
|
let state_ = state.clone();
|
||||||
|
@ -155,6 +156,7 @@ mod tests {
|
||||||
argv,
|
argv,
|
||||||
op_selector_std,
|
op_selector_std,
|
||||||
Progress::new(),
|
Progress::new(),
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let state_ = state.clone();
|
let state_ = state.clone();
|
||||||
|
@ -182,7 +184,7 @@ mod tests {
|
||||||
let mut flags = flags::DenoFlags::default();
|
let mut flags = flags::DenoFlags::default();
|
||||||
flags.reload = true;
|
flags.reload = true;
|
||||||
let state =
|
let state =
|
||||||
ThreadSafeState::new(flags, argv, op_selector_std, Progress::new())
|
ThreadSafeState::new(flags, argv, op_selector_std, Progress::new(), true)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let state_ = state.clone();
|
let state_ = state.clone();
|
||||||
tokio_util::run(lazy(move || {
|
tokio_util::run(lazy(move || {
|
||||||
|
|
|
@ -29,8 +29,12 @@ SharedQueue Binary Layout
|
||||||
const INDEX_RECORDS = 3 + MAX_RECORDS;
|
const INDEX_RECORDS = 3 + MAX_RECORDS;
|
||||||
const HEAD_INIT = 4 * INDEX_RECORDS;
|
const HEAD_INIT = 4 * INDEX_RECORDS;
|
||||||
|
|
||||||
|
// Available on start due to bindings.
|
||||||
const Deno = window[GLOBAL_NAMESPACE];
|
const Deno = window[GLOBAL_NAMESPACE];
|
||||||
const core = Deno[CORE_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 sharedBytes;
|
||||||
let shared32;
|
let shared32;
|
||||||
|
@ -165,7 +169,7 @@ SharedQueue Binary Layout
|
||||||
const success = push(control);
|
const success = push(control);
|
||||||
// If successful, don't use first argument of core.send.
|
// If successful, don't use first argument of core.send.
|
||||||
const arg0 = success ? null : control;
|
const arg0 = success ? null : control;
|
||||||
return window.Deno.core.send(arg0, zeroCopy);
|
return Deno.core.send(arg0, zeroCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
const denoCore = {
|
const denoCore = {
|
||||||
|
|
|
@ -25,7 +25,7 @@ const console = new Console(core.print);
|
||||||
window.console = console;
|
window.console = console;
|
||||||
window.workerMain = workerMain;
|
window.workerMain = workerMain;
|
||||||
export default function denoMain(): void {
|
export default function denoMain(): void {
|
||||||
os.start("TS");
|
os.start(true, "TS");
|
||||||
}
|
}
|
||||||
|
|
||||||
const ASSETS = "$asset$";
|
const ASSETS = "$asset$";
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||||
import { window } from "./window";
|
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;
|
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
|
// These imports are not exposed and therefore are fine to just import the
|
||||||
// symbols required.
|
// symbols required.
|
||||||
import { core } from "./core";
|
import { core } from "./core";
|
||||||
import { immutableDefine } from "./util";
|
|
||||||
|
|
||||||
// During the build process, augmentations to the variable `window` in this
|
// 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
|
// 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
|
// This is the Deno namespace, it is handled differently from other window
|
||||||
// properties when building the runtime type library, as the whole module
|
// properties when building the runtime type library, as the whole module
|
||||||
// is flattened into a single namespace.
|
// is flattened into a single namespace.
|
||||||
immutableDefine(window, "Deno", deno);
|
window.Deno = deno;
|
||||||
Object.freeze(window.Deno);
|
Object.freeze(window.Deno);
|
||||||
|
|
||||||
// Globally available functions and object instances.
|
// Globally available functions and object instances.
|
||||||
|
|
|
@ -18,8 +18,11 @@ import { setLocation } from "./location";
|
||||||
// builtin modules
|
// builtin modules
|
||||||
import * as deno from "./deno";
|
import * as deno from "./deno";
|
||||||
|
|
||||||
export default function denoMain(name?: string): void {
|
export default function denoMain(
|
||||||
const startResMsg = os.start(name);
|
preserveDenoNamespace: boolean = true,
|
||||||
|
name?: string
|
||||||
|
): void {
|
||||||
|
const startResMsg = os.start(preserveDenoNamespace, name);
|
||||||
|
|
||||||
setVersions(startResMsg.denoVersion()!, startResMsg.v8Version()!);
|
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
|
// This function bootstraps an environment within Deno, it is shared both by
|
||||||
// the runtime and the compiler environments.
|
// the runtime and the compiler environments.
|
||||||
// @internal
|
// @internal
|
||||||
export function start(source?: string): msg.StartRes {
|
export function start(
|
||||||
|
preserveDenoNamespace = true,
|
||||||
|
source?: string
|
||||||
|
): msg.StartRes {
|
||||||
core.setAsyncHandler(handleAsyncMsgFromRust);
|
core.setAsyncHandler(handleAsyncMsgFromRust);
|
||||||
|
|
||||||
// First we send an empty `Start` message to let the privileged side know we
|
// 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()!);
|
setGlobals(startResMsg.pid(), startResMsg.noColor(), startResMsg.execPath()!);
|
||||||
|
|
||||||
// Deno.core could ONLY be safely frozen here (not in globals.ts)
|
if (preserveDenoNamespace) {
|
||||||
// since shared_queue.js will modify core properties.
|
util.immutableDefine(window, "Deno", window.Deno);
|
||||||
Object.freeze(window.Deno.core);
|
// 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;
|
return startResMsg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,17 @@ export function decodeMessage(dataIntArray: Uint8Array): any {
|
||||||
return JSON.parse(dataJson);
|
return JSON.parse(dataJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createWorker(specifier: string): number {
|
function createWorker(
|
||||||
|
specifier: string,
|
||||||
|
includeDenoNamespace: boolean
|
||||||
|
): number {
|
||||||
const builder = flatbuffers.createBuilder();
|
const builder = flatbuffers.createBuilder();
|
||||||
const specifier_ = builder.createString(specifier);
|
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);
|
const baseRes = sendSync(builder, msg.Any.CreateWorker, inner);
|
||||||
assert(baseRes != null);
|
assert(baseRes != null);
|
||||||
assert(
|
assert(
|
||||||
|
@ -149,6 +156,18 @@ export interface Worker {
|
||||||
closed: Promise<void>;
|
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 {
|
export class WorkerImpl implements Worker {
|
||||||
private readonly rid: number;
|
private readonly rid: number;
|
||||||
private isClosing: boolean = false;
|
private isClosing: boolean = false;
|
||||||
|
@ -157,8 +176,12 @@ export class WorkerImpl implements Worker {
|
||||||
public onmessage?: (data: any) => void;
|
public onmessage?: (data: any) => void;
|
||||||
public onmessageerror?: () => void;
|
public onmessageerror?: () => void;
|
||||||
|
|
||||||
constructor(specifier: string) {
|
constructor(specifier: string, options?: DenoWorkerOptions) {
|
||||||
this.rid = createWorker(specifier);
|
let includeDenoNamespace = true;
|
||||||
|
if (options && options.noDenoNamespace) {
|
||||||
|
includeDenoNamespace = false;
|
||||||
|
}
|
||||||
|
this.rid = createWorker(specifier, includeDenoNamespace);
|
||||||
this.run();
|
this.run();
|
||||||
this.isClosedPromise = hostGetWorkerClosed(this.rid);
|
this.isClosedPromise = hostGetWorkerClosed(this.rid);
|
||||||
this.isClosedPromise.then(
|
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…
Add table
Reference in a new issue