diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index d043f485e2..9102500bfe 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -292,20 +292,29 @@ core.registerErrorBuilder( }, ); -function runtimeStart(runtimeOptions, source) { +function runtimeStart( + denoVersion, + v8Version, + tsVersion, + target, + debugFlag, + noColor, + isTty, + source, +) { core.setMacrotaskCallback(timers.handleTimerMacrotask); core.setMacrotaskCallback(promiseRejectMacrotaskCallback); core.setWasmStreamingCallback(fetch.handleWasmStreaming); core.setReportExceptionCallback(event.reportException); ops.op_set_format_exception_callback(formatException); version.setVersions( - runtimeOptions.denoVersion, - runtimeOptions.v8Version, - runtimeOptions.tsVersion, + denoVersion, + v8Version, + tsVersion, ); - core.setBuildInfo(runtimeOptions.target); - util.setLogDebug(runtimeOptions.debugFlag, source); - colors.setNoColor(runtimeOptions.noColor || !runtimeOptions.isTty); + core.setBuildInfo(target); + util.setLogDebug(debugFlag, source); + colors.setNoColor(noColor || !isTty); // deno-lint-ignore prefer-primordials Error.prepareStackTrace = core.prepareStackTrace; } @@ -403,6 +412,27 @@ function bootstrapMainRuntime(runtimeOptions) { if (hasBootstrapped) { throw new Error("Worker runtime already bootstrapped"); } + + const [ + args, + cpuCount, + debugFlag, + denoVersion, + locale, + location_, + noColor, + isTty, + tsVersion, + unstableFlag, + pid, + ppid, + target, + v8Version, + userAgent, + inspectFlag, + _, + ] = runtimeOptions; + performance.setTimeOrigin(DateNow()); globalThis_ = globalThis; @@ -414,15 +444,15 @@ function bootstrapMainRuntime(runtimeOptions) { // If the `--location` flag isn't set, make `globalThis.location` `undefined` and // writable, so that they can mock it themselves if they like. If the flag was // set, define `globalThis.location`, using the provided value. - if (runtimeOptions.location == null) { + if (location_ === undefined) { mainRuntimeGlobalProperties.location = { writable: true, }; } else { - location.setLocationHref(runtimeOptions.location); + location.setLocationHref(location_); } - if (runtimeOptions.unstableFlag) { + if (unstableFlag) { ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope); } ObjectDefineProperties(globalThis, mainRuntimeGlobalProperties); @@ -432,7 +462,7 @@ function bootstrapMainRuntime(runtimeOptions) { }); ObjectSetPrototypeOf(globalThis, Window.prototype); - if (runtimeOptions.inspectFlag) { + if (inspectFlag) { const consoleFromV8 = core.console; const consoleFromDeno = globalThis.console; wrapConsole(consoleFromDeno, consoleFromV8); @@ -449,11 +479,19 @@ function bootstrapMainRuntime(runtimeOptions) { core.setPromiseRejectCallback(promiseRejectCallback); - runtimeStart(runtimeOptions); + runtimeStart( + denoVersion, + v8Version, + tsVersion, + target, + debugFlag, + noColor, + isTty, + ); - setNumCpus(runtimeOptions.cpuCount); - setUserAgent(runtimeOptions.userAgent); - setLanguage(runtimeOptions.locale); + setNumCpus(cpuCount); + setUserAgent(userAgent); + setLanguage(locale); // These have to initialized here and not in `90_deno_ns.js` because // the op function that needs to be passed will be invalidated by creating @@ -477,14 +515,14 @@ function bootstrapMainRuntime(runtimeOptions) { }); ObjectDefineProperties(finalDenoNs, { - pid: util.readOnly(runtimeOptions.pid), - ppid: util.readOnly(runtimeOptions.ppid), - noColor: util.readOnly(runtimeOptions.noColor), - args: util.readOnly(ObjectFreeze(runtimeOptions.args)), + pid: util.readOnly(pid), + ppid: util.readOnly(ppid), + noColor: util.readOnly(noColor), + args: util.readOnly(ObjectFreeze(args)), mainModule: util.getterOnly(opMainModule), }); - if (runtimeOptions.unstableFlag) { + if (unstableFlag) { ObjectAssign(finalDenoNs, denoNsUnstable); // These have to initialized here and not in `90_deno_ns.js` because // the op function that needs to be passed will be invalidated by creating @@ -502,7 +540,7 @@ function bootstrapMainRuntime(runtimeOptions) { // `Deno` with `Deno` namespace from "./deno.ts". ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs)); - util.log("args", runtimeOptions.args); + util.log("args", args); } function bootstrapWorkerRuntime( @@ -514,6 +552,26 @@ function bootstrapWorkerRuntime( throw new Error("Worker runtime already bootstrapped"); } + const [ + args, + cpuCount, + debugFlag, + denoVersion, + locale, + location_, + noColor, + isTty, + tsVersion, + unstableFlag, + pid, + _ppid, + target, + v8Version, + _userAgent, + _inspectFlag, + enableTestingFeaturesFlag, + ] = runtimeOptions; + performance.setTimeOrigin(DateNow()); globalThis_ = globalThis; @@ -524,7 +582,7 @@ function bootstrapWorkerRuntime( delete globalThis.bootstrap; hasBootstrapped = true; - if (runtimeOptions.unstableFlag) { + if (unstableFlag) { ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope); } ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties); @@ -534,7 +592,7 @@ function bootstrapWorkerRuntime( close: util.nonEnumerable(workerClose), postMessage: util.writable(postMessage), }); - if (runtimeOptions.enableTestingFeaturesFlag) { + if (enableTestingFeaturesFlag) { ObjectDefineProperty( globalThis, "importScripts", @@ -562,14 +620,20 @@ function bootstrapWorkerRuntime( }); runtimeStart( - runtimeOptions, + denoVersion, + v8Version, + tsVersion, + target, + debugFlag, + noColor, + isTty, internalName ?? name, ); - location.setLocationHref(runtimeOptions.location); + location.setLocationHref(location_); - setNumCpus(runtimeOptions.cpuCount); - setLanguage(runtimeOptions.locale); + setNumCpus(cpuCount); + setLanguage(locale); globalThis.pollForMessages = pollForMessages; @@ -594,7 +658,7 @@ function bootstrapWorkerRuntime( core, }); - if (runtimeOptions.unstableFlag) { + if (unstableFlag) { ObjectAssign(finalDenoNs, denoNsUnstable); // These have to initialized here and not in `90_deno_ns.js` because // the op function that needs to be passed will be invalidated by creating @@ -608,9 +672,9 @@ function bootstrapWorkerRuntime( }); } ObjectDefineProperties(finalDenoNs, { - pid: util.readOnly(runtimeOptions.pid), - noColor: util.readOnly(runtimeOptions.noColor), - args: util.readOnly(ObjectFreeze(runtimeOptions.args)), + pid: util.readOnly(pid), + noColor: util.readOnly(noColor), + args: util.readOnly(ObjectFreeze(args)), }); // Setup `Deno` global - we're actually overriding already // existing global `Deno` with `Deno` namespace from "./deno.ts". diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index ab06ab649c..b50e916103 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -556,8 +556,7 @@ impl WebWorker { // WebWorkers can have empty string as name. { let scope = &mut self.js_runtime.handle_scope(); - let options_v8 = - deno_core::serde_v8::to_v8(scope, options.as_json()).unwrap(); + let args = options.as_v8(scope); let bootstrap_fn = self.bootstrap_fn_global.take().unwrap(); let bootstrap_fn = v8::Local::new(scope, bootstrap_fn); let undefined = v8::undefined(scope); @@ -568,7 +567,7 @@ impl WebWorker { .unwrap() .into(); bootstrap_fn - .call(scope, undefined.into(), &[options_v8, name_str, id_str]) + .call(scope, undefined.into(), &[args.into(), name_str, id_str]) .unwrap(); } // TODO(bartlomieju): this could be done using V8 API, without calling `execute_script`. diff --git a/runtime/worker.rs b/runtime/worker.rs index 42874f2094..a8fd6b1dab 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -361,13 +361,12 @@ impl MainWorker { pub fn bootstrap(&mut self, options: &BootstrapOptions) { let scope = &mut self.js_runtime.handle_scope(); - let options_v8 = - deno_core::serde_v8::to_v8(scope, options.as_json()).unwrap(); + let args = options.as_v8(scope); let bootstrap_fn = self.bootstrap_fn_global.take().unwrap(); let bootstrap_fn = v8::Local::new(scope, bootstrap_fn); let undefined = v8::undefined(scope); bootstrap_fn - .call(scope, undefined.into(), &[options_v8]) + .call(scope, undefined.into(), &[args.into()]) .unwrap(); } diff --git a/runtime/worker_bootstrap.rs b/runtime/worker_bootstrap.rs index 12abceca65..09725122cf 100644 --- a/runtime/worker_bootstrap.rs +++ b/runtime/worker_bootstrap.rs @@ -1,7 +1,6 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use deno_core::serde_json; -use deno_core::serde_json::json; +use deno_core::v8; use deno_core::ModuleSpecifier; use std::thread; @@ -58,28 +57,135 @@ impl Default for BootstrapOptions { } impl BootstrapOptions { - pub fn as_json(&self) -> serde_json::Value { - json!({ - // Shared bootstrap args - "args": self.args, - "cpuCount": self.cpu_count, - "debugFlag": self.debug_flag, - "denoVersion": self.runtime_version, - "locale": self.locale, - "location": self.location, - "noColor": self.no_color, - "isTty": self.is_tty, - "tsVersion": self.ts_version, - "unstableFlag": self.unstable, - // Web worker only - "enableTestingFeaturesFlag": self.enable_testing_features, - // Env values - "pid": std::process::id(), - "ppid": ppid(), - "target": env!("TARGET"), - "v8Version": deno_core::v8_version(), - "userAgent": self.user_agent, - "inspectFlag": self.inspect, - }) + pub fn as_v8<'s>( + &self, + scope: &mut v8::HandleScope<'s>, + ) -> v8::Local<'s, v8::Array> { + let array = v8::Array::new(scope, 17); + + { + let args = v8::Array::new(scope, self.args.len() as i32); + for (idx, arg) in self.args.iter().enumerate() { + let arg_str = v8::String::new(scope, arg).unwrap(); + args.set_index(scope, idx as u32, arg_str.into()); + } + array.set_index(scope, 0, args.into()); + } + + { + let val = v8::Integer::new(scope, self.cpu_count as i32); + array.set_index(scope, 1, val.into()); + } + + { + let val = v8::Boolean::new(scope, self.debug_flag); + array.set_index(scope, 2, val.into()); + } + + { + let val = v8::String::new_from_one_byte( + scope, + self.runtime_version.as_bytes(), + v8::NewStringType::Internalized, + ) + .unwrap(); + array.set_index(scope, 3, val.into()); + } + + { + let val = v8::String::new_from_one_byte( + scope, + self.locale.as_bytes(), + v8::NewStringType::Normal, + ) + .unwrap(); + array.set_index(scope, 4, val.into()); + } + + { + let val: v8::Local = if let Some(location) = &self.location { + v8::String::new(scope, location.as_str()).unwrap().into() + } else { + v8::undefined(scope).into() + }; + + array.set_index(scope, 5, val); + } + + { + let val = v8::Boolean::new(scope, self.no_color); + array.set_index(scope, 6, val.into()); + } + + { + let val = v8::Boolean::new(scope, self.is_tty); + array.set_index(scope, 7, val.into()); + } + + { + let val = v8::String::new_from_one_byte( + scope, + self.ts_version.as_bytes(), + v8::NewStringType::Normal, + ) + .unwrap(); + array.set_index(scope, 8, val.into()); + } + + { + let val = v8::Boolean::new(scope, self.unstable); + array.set_index(scope, 9, val.into()); + } + + { + let val = v8::Integer::new(scope, std::process::id() as i32); + array.set_index(scope, 10, val.into()); + } + + { + let val = v8::Integer::new(scope, ppid() as i32); + array.set_index(scope, 11, val.into()); + } + + { + let val = v8::String::new_external_onebyte_static( + scope, + env!("TARGET").as_bytes(), + ) + .unwrap(); + array.set_index(scope, 12, val.into()); + } + + { + let val = v8::String::new_from_one_byte( + scope, + deno_core::v8_version().as_bytes(), + v8::NewStringType::Normal, + ) + .unwrap(); + array.set_index(scope, 13, val.into()); + } + + { + let val = v8::String::new_from_one_byte( + scope, + self.user_agent.as_bytes(), + v8::NewStringType::Normal, + ) + .unwrap(); + array.set_index(scope, 14, val.into()); + } + + { + let val = v8::Boolean::new(scope, self.inspect); + array.set_index(scope, 15, val.into()); + } + + { + let val = v8::Boolean::new(scope, self.enable_testing_features); + array.set_index(scope, 16, val.into()); + } + + array } }