1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

refactor(core): move op cache sync responsibility to rust space (#10340)

Even if bootstrapping the JS runtime is low level, it's an abstraction leak of 
core to require users to call `Deno.core.ops()` in JS space.

So instead we're introducing a `JsRuntime::sync_ops_cache()` method, 
once we have runtime extensions a new runtime will ensure the ops 
cache is setup (for the provided extensions) and then loading/unloading 
plugins should be the only operations that require op cache syncs
This commit is contained in:
Aaron O'Mullan 2021-04-25 22:00:05 +02:00 committed by GitHub
parent 1c7164257d
commit 83bece56b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 31 additions and 51 deletions

View file

@ -16,13 +16,7 @@ pub fn create_js_runtime(setup: impl FnOnce(&mut JsRuntime)) -> JsRuntime {
setup(&mut rt);
// Init ops
rt.execute(
"init",
r#"
Deno.core.ops();
"#,
)
.unwrap();
rt.sync_ops_cache();
rt
}

View file

@ -210,6 +210,8 @@ fn create_compiler_snapshot(
}
}),
);
js_runtime.sync_ops_cache();
create_snapshot(js_runtime, snapshot_path, files);
}

View file

@ -2122,6 +2122,7 @@ pub fn start(debug: bool) -> Result<JsRuntime, AnyError> {
runtime.register_op("op_respond", op(respond));
runtime.register_op("op_script_names", op(script_names));
runtime.register_op("op_script_version", op(script_version));
runtime.sync_ops_cache();
let init_config = json!({ "debug": debug });
let init_src = format!("globalThis.serverInit({});", init_config);

View file

@ -148,6 +148,7 @@ fn create_web_worker_callback(
if args.use_deno_namespace {
ops::runtime_compiler::init(js_runtime);
}
js_runtime.sync_ops_cache();
}
worker.bootstrap(&options);
@ -218,6 +219,7 @@ pub fn create_main_worker(
// above
ops::errors::init(js_runtime);
ops::runtime_compiler::init(js_runtime);
js_runtime.sync_ops_cache();
}
worker.bootstrap(&options);

View file

@ -496,6 +496,7 @@ pub fn exec(request: Request) -> Result<Response, AnyError> {
runtime.register_op("op_load", op(load));
runtime.register_op("op_resolve", op(resolve));
runtime.register_op("op_respond", op(respond));
runtime.sync_ops_cache();
let startup_source = "globalThis.startup({ legacyFlag: false })";
let request_value = json!({

View file

@ -778,7 +778,6 @@ delete Object.prototype.__proto__;
}
hasStarted = true;
languageService = ts.createLanguageService(host);
core.ops();
setLogDebug(debugFlag, "TSLS");
debug("serverInit()");
}
@ -793,13 +792,9 @@ delete Object.prototype.__proto__;
throw new Error("The compiler runtime already started.");
}
hasStarted = true;
core.ops();
setLogDebug(!!debugFlag, "TS");
}
// Setup the compiler runtime during the build process.
core.ops();
// A build time only op that provides some setup information that is used to
// ensure the snapshot is setup properly.
/** @type {{ buildSpecifier: string; libs: string[] }} */

View file

@ -20,16 +20,7 @@ fn create_js_runtime() -> JsRuntime {
runtime.register_op("nop", |state, _, _| {
Op::Sync(serialize_op_result(Ok(9), state))
});
// Init ops
runtime
.execute(
"init",
r#"
Deno.core.ops();
"#,
)
.unwrap();
runtime.sync_ops_cache();
runtime
}

View file

@ -60,12 +60,14 @@
}
function ops() {
// op id 0 is a special value to retrieve the map of registered ops.
const newOpsCache = Object.fromEntries(opcall(0));
opsCache = Object.freeze(newOpsCache);
return opsCache;
}
function syncOpsCache() {
// op id 0 is a special value to retrieve the map of registered ops.
opsCache = Object.freeze(Object.fromEntries(opcall(0)));
}
function handleAsyncMsgFromRust() {
for (let i = 0; i < arguments.length; i += 2) {
const promiseId = arguments[i];
@ -130,5 +132,6 @@
resources,
registerErrorClass,
handleAsyncMsgFromRust,
syncOpsCache,
});
})(this);

View file

@ -56,6 +56,7 @@ fn main() {
Ok(sum)
}),
);
runtime.sync_ops_cache();
// Now we see how to invoke the ops we just defined. The runtime automatically
// contains a Deno.core object with several functions for interacting with it.
@ -64,11 +65,7 @@ fn main() {
.execute(
"<init>",
r#"
// First we initialize the ops cache.
// This maps op names to their id's.
Deno.core.ops();
// Then we define a print function that uses
// Define a print function that uses
// our op_print op to display the stringified argument.
const _newline = new Uint8Array([10]);
function print(value) {

View file

@ -54,8 +54,6 @@ async function serve(rid) {
}
async function main() {
Deno.core.ops();
const listenerRid = listen();
Deno.core.print(`http_bench_ops listening on http://127.0.0.1:4544/\n`);

View file

@ -116,6 +116,7 @@ fn create_js_runtime() -> JsRuntime {
runtime.register_op("accept", deno_core::op_async(op_accept));
runtime.register_op("read", deno_core::op_async(op_read));
runtime.register_op("write", deno_core::op_async(op_write));
runtime.sync_ops_cache();
runtime
}

View file

@ -25,15 +25,15 @@ use std::rc::Rc;
/// ```ignore
/// let mut runtime = JsRuntime::new(...);
/// runtime.register_op("hello", deno_core::op_sync(Self::hello_op));
/// runtime.sync_ops_cache();
/// ```
///
/// ...it can be invoked from JS using the provided name, for example:
/// ```js
/// Deno.core.ops();
/// let result = Deno.core.opSync("function_name", args);
/// ```
///
/// The `Deno.core.ops()` statement is needed once before any op calls, for initialization.
/// `runtime.sync_ops_cache()` must be called after registering new ops
/// A more complete example is available in the examples directory.
pub fn op_sync<F, V, R>(op_fn: F) -> Box<OpFn>
where
@ -63,15 +63,15 @@ where
/// ```ignore
/// let mut runtime = JsRuntime::new(...);
/// runtime.register_op("hello", deno_core::op_async(Self::hello_op));
/// runtime.sync_ops_cache();
/// ```
///
/// ...it can be invoked from JS using the provided name, for example:
/// ```js
/// Deno.core.ops();
/// let future = Deno.core.opAsync("function_name", args);
/// ```
///
/// The `Deno.core.ops()` statement is needed once before any op calls, for initialization.
/// `runtime.sync_ops_cache()` must be called after registering new ops
/// A more complete example is available in the examples directory.
pub fn op_async<F, V, R, RV>(op_fn: F) -> Box<OpFn>
where
@ -116,13 +116,11 @@ mod tests {
}
runtime.register_op("op_throw", op_async(op_throw));
runtime.sync_ops_cache();
runtime
.execute(
"<init>",
r#"
// First we initialize the ops cache. This maps op names to their id's.
Deno.core.ops();
async function f1() {
await Deno.core.opAsync('op_throw', 'hello');
}

View file

@ -367,6 +367,11 @@ impl JsRuntime {
state.js_recv_cb.replace(v8::Global::new(scope, cb));
}
/// Ensures core.js has the latest op-name to op-id mappings
pub fn sync_ops_cache(&mut self) {
self.execute("<anon>", "Deno.core.syncOpsCache()").unwrap()
}
/// Returns the runtime's op state, which can be used to maintain ops
/// and access resources between op calls.
pub fn op_state(&mut self) -> Rc<RefCell<OpState>> {
@ -2140,6 +2145,7 @@ pub mod tests {
module_loader: Some(loader),
..Default::default()
});
runtime.sync_ops_cache();
runtime
.execute(
"file:///dyn_import3.js",
@ -2149,8 +2155,6 @@ pub mod tests {
if (mod.b() !== 'b') {
throw Error("bad");
}
// Now do any op
Deno.core.ops();
})();
"#,
)

View file

@ -15,6 +15,7 @@ fn create_js_runtime() -> JsRuntime {
"op_url_stringify_search_params",
op_sync(deno_url::op_url_stringify_search_params),
);
runtime.sync_ops_cache();
runtime
.execute(
@ -23,14 +24,6 @@ fn create_js_runtime() -> JsRuntime {
)
.unwrap();
deno_url::init(&mut runtime);
runtime
.execute(
"init",
r#"
Deno.core.ops();
"#,
)
.unwrap();
runtime
.execute("setup", "const { URL } = globalThis.__bootstrap.url;")
.unwrap();

View file

@ -142,8 +142,6 @@ delete Object.prototype.__proto__;
}
function runtimeStart(runtimeOptions, source) {
core.ops();
core.setMacrotaskCallback(timers.handleTimerMacrotask);
version.setVersions(
runtimeOptions.denoVersion,

View file

@ -284,6 +284,7 @@ impl WebWorker {
t.add(stream);
}
}
js_runtime.sync_ops_cache();
worker
}

View file

@ -171,6 +171,7 @@ impl MainWorker {
t.add(stream);
}
}
js_runtime.sync_ops_cache();
worker
}