Repository: denoland/deno_core
Pull request #409 (2024-01-03 04:00:55)

chore(core): remove opAsync and ref/unrefOp


Patch:
diff --git a/core/01_core.js b/core/01_core.js
index fbc559d..27a76b0 100644
--- a/core/01_core.js
+++ b/core/01_core.js
@@ -27,7 +27,6 @@
     Proxy,
     RangeError,
     ReferenceError,
-    ReflectHas,
     ReflectApply,
     SafeArrayIterator,
     SafeMap,
@@ -531,33 +530,6 @@
     return (ops[opName] = fn);
   }
 
-  /* BEGIN TEMPLATE opAsync */
-  /* DO NOT MODIFY: use rebuild_async_stubs.js to regenerate */
-  function opAsync(opName, ...args) {
-    const id = nextPromiseId;
-    try {
-      const maybeResult = asyncOps[opName](id, ...new SafeArrayIterator(args));
-      if (maybeResult !== undefined) {
-        return PromiseResolve(maybeResult);
-      }
-    } catch (err) {
-      if (!ReflectHas(asyncOps, opName)) {
-        return PromiseReject(new TypeError(`${opName} is not a registered op`));
-      }
-      ErrorCaptureStackTrace(err, opAsync);
-      return PromiseReject(err);
-    }
-    nextPromiseId = (id + 1) & 0xffffffff;
-    let promise = PromisePrototypeThen(
-      setPromise(id),
-      unwrapOpError(eventLoopTick),
-    );
-    promise = handleOpCallTracing(opName, id, promise);
-    promise[promiseIdSymbol] = id;
-    return promise;
-  }
-  /* END TEMPLATE */
-
   function handleOpCallTracing(opName, promiseId, p) {
     if (opCallTracingEnabled) {
       const stack = StringPrototypeSlice(new Error().stack, 6);
@@ -929,7 +901,6 @@
   const core = ObjectAssign(globalThis.Deno.core, {
     asyncStub,
     ensureFastOps,
-    opAsync,
     resources,
     metrics,
     registerErrorBuilder,
@@ -943,8 +914,6 @@
     enableOpCallTracing,
     isOpCallTracingEnabled,
     opCallTraces,
-    refOp,
-    unrefOp,
     refOpPromise,
     unrefOpPromise,
     setReportExceptionCallback,
diff --git a/core/README.md b/core/README.md
index e26f670..06f395c 100644
--- a/core/README.md
+++ b/core/README.md
@@ -16,10 +16,9 @@ keeps track of all pending tasks (async ops, dynamic module loads). It is user's
 responsibility to drive that loop by using `JsRuntime::run_event_loop` method -
 it must be executed in the context of Rust's future executor (eg. tokio, smol).
 
-Rust functions can be registered in JavaScript using `deno_core::Extension`. Use
-the `Deno.core.ops.op_name()` and `Deno.core.opAsync("op_name", ...)` functions
-to trigger the op function callback. A conventional way to write ops is using
-the [`deno_ops`](https://github.com/denoland/deno/blob/main/ops) crate.
+Rust functions can be registered in JavaScript using `deno_core::Extension`. A
+conventional way to write ops is using the
+[`deno_ops`](https://github.com/denoland/deno/blob/main/ops) crate.
 
 Documentation for this crate is thin at the moment. Please see
 [hello_world.rs](https://github.com/denoland/deno_core/blob/main/core/examples/hello_world.rs)
diff --git a/core/benches/ops/async.rs b/core/benches/ops/async.rs
index 83e449a..2e474e2 100644
--- a/core/benches/ops/async.rs
+++ b/core/benches/ops/async.rs
@@ -234,17 +234,6 @@ fn bench_op_async_void_deferred_return(b: &mut Bencher) {
   );
 }
 
-/// Tests the overhead of opAsync.
-fn bench_op_async_void_indirect(b: &mut Bencher) {
-  bench_op(
-    b,
-    BENCH_COUNT,
-    "op_async_void",
-    0,
-    "accum += await opAsync('op_async_void');",
-  );
-}
-
 macro_rules! bench_void {
   ($bench:ident, $op:ident) => {
     fn $bench(b: &mut Bencher) {
@@ -290,7 +279,6 @@ benchmark_group!(
   bench_op_async_yield_lazy_nofast,
   bench_op_async_yield_deferred,
   bench_op_async_yield_deferred_nofast,
-  bench_op_async_void_indirect,
   bench_op_async_void,
   bench_op_async_void_lazy,
   bench_op_async_void_lazy_nofast,
diff --git a/core/benches/ops/async_harness.js b/core/benches/ops/async_harness.js
index d70669f..daf1ce5 100644
--- a/core/benches/ops/async_harness.js
+++ b/core/benches/ops/async_harness.js
@@ -9,7 +9,6 @@ async function run() {
   const LARGE_STRING_UTF8_1000 = "\u1000".repeat(1000);
   const BUFFER = new Uint8Array(1024);
   const ARRAYBUFFER = new ArrayBuffer(1024);
-  const opAsync = Deno.core.opAsync;
   const { __OP__: op } = Deno.core.ensureFastOps();
   const { op_make_external } = Deno.core.ensureFastOps();
   const EXTERNAL = op_make_external();
diff --git a/core/lib.deno_core.d.ts b/core/lib.deno_core.d.ts
index 6c76958..8281e74 100644
--- a/core/lib.deno_core.d.ts
+++ b/core/lib.deno_core.d.ts
@@ -10,20 +10,6 @@ declare namespace Deno {
     /** Returns a proxy that generates the fast versions of sync and async ops. */
     function ensureFastOps(): any;
 
-    /** Call an op in Rust, and asynchronously receive the result. */
-    function opAsync(
-      opName: string,
-      ...args: any[]
-    ): Promise<any>;
-
-    /** Mark following promise as "ref", ie. event loop won't exit
-     * until all "ref" promises are resolved. All async ops are "ref" by default. */
-    function refOp(promiseId: number): void;
-
-    /** Mark following promise as "unref", ie. event loop will exit
-     * if there are only "unref" promises left. */
-    function unrefOp(promiseId: number): void;
-
     /** Mark following promise as "ref", ie. event loop won't exit
      * until all "ref" promises are resolved. All async ops are "ref" by default. */
     function refOpPromise<T>(promise: Promise<T>): void;
diff --git a/core/rebuild_async_stubs.js b/core/rebuild_async_stubs.js
index dc1fa5e..778cad3 100755
--- a/core/rebuild_async_stubs.js
+++ b/core/rebuild_async_stubs.js
@@ -4,7 +4,7 @@
 const doNotModify =
   "/* DO NOT MODIFY: use rebuild_async_stubs.js to regenerate */\n";
 
-// The template function we build opAsync and op_async_N functions from
+// The template function we build op_async_N functions from
 function __TEMPLATE__(__ARGS_PARAM__) {
   const id = nextPromiseId;
   try {
@@ -60,28 +60,14 @@ ${func};
 }
 asyncStubCases += "/* END TEMPLATE */";
 
-const opAsync = "/* BEGIN TEMPLATE opAsync */\n" + doNotModify +
-  templateString
-    .replaceAll(/__TEMPLATE__/g, "opAsync")
-    .replaceAll(/__ARGS_PARAM__/g, "opName, ...args")
-    .replaceAll(/__ARGS__/g, "id, ...new SafeArrayIterator(args)")
-    .replaceAll(/__OP__/g, "asyncOps[opName]")
-    .replaceAll(
-      /__ERR__;/g,
-      "if (!ReflectHas(asyncOps, opName)) {\n      return PromiseReject(new TypeError(`${opName} is not a registered op`));\n    }",
-    ) +
-  "\n/* END TEMPLATE */";
-
 const asyncStubIndent =
   corePristine.match(/^([\t ]+)(?=TEMPLATE-setUpAsyncStub)/m)[0];
-const opAsyncIndent = corePristine.match(/^([\t ]+)(?=TEMPLATE-opAsync)/m)[0];
 
 const coreOutput = corePristine
   .replace(
     /[\t ]+TEMPLATE-setUpAsyncStub/,
     asyncStubCases.replaceAll(/^/gm, asyncStubIndent),
-  )
-  .replace(/[\t ]+TEMPLATE-opAsync/, opAsync.replaceAll(/^/gm, opAsyncIndent));
+  );
 
 if (Deno.args[0] === "--check") {
   if (coreOutput !== coreJs) {


Test patch:
diff --git a/core/modules/tests.rs b/core/modules/tests.rs
index 3f92994..9418f51 100644
--- a/core/modules/tests.rs
+++ b/core/modules/tests.rs
@@ -682,8 +682,8 @@ async fn dyn_import_op() {
   );
 
   let loader = Rc::new(TestingModuleLoader::new(StaticModuleLoader::new([
-    (Url::parse("file:///main.js").unwrap(), ascii_str!("(async () => { await import('./dynamic.js'); await Deno.core.opAsync('op_wait'); })();")),
-    (Url::parse("file:///dynamic.js").unwrap(), ascii_str!("await Deno.core.opAsync('op_test');")),
+    (Url::parse("file:///main.js").unwrap(), ascii_str!("const { op_wait } = Deno.core.ensureFastOps(); (async () => { await import('./dynamic.js'); await op_wait(); })();")),
+    (Url::parse("file:///dynamic.js").unwrap(), ascii_str!("const { op_test } = Deno.core.ensureFastOps(); await op_test();")),
   ])));
   let barrier = Barrier::new(2);
   let mut runtime = JsRuntime::new(RuntimeOptions {
@@ -695,7 +695,7 @@ async fn dyn_import_op() {
     .load_main_module(
       &Url::parse("file:///root.js").unwrap(),
       Some(ascii_str!(
-        "import 'file:///main.js'; await Deno.core.opAsync('op_wait');"
+        "import 'file:///main.js'; const { op_wait } = Deno.core.ensureFastOps(); await op_wait();"
       )),
     )
     .await
diff --git a/core/runtime/tests/error.rs b/core/runtime/tests/error.rs
index c225ae3..bf064fb 100644
--- a/core/runtime/tests/error.rs
+++ b/core/runtime/tests/error.rs
@@ -85,8 +85,9 @@ if (errMessage !== "higher-level sync error: original sync error") {
       r#"
 (async () => {
   let errMessage;
+  const { op_err_async } = Deno.core.ensureFastOps(); 
   try {
-    await Deno.core.opAsync("op_err_async");
+    await op_err_async();
   } catch (err) {
     errMessage = err.message;
   }
diff --git a/core/runtime/tests/jsrealm.rs b/core/runtime/tests/jsrealm.rs
index cb32998..b67f7ed 100644
--- a/core/runtime/tests/jsrealm.rs
+++ b/core/runtime/tests/jsrealm.rs
@@ -99,7 +99,10 @@ async fn js_realm_ref_unref_ops() {
       .execute_script_static(
         runtime.v8_isolate(),
         "",
-        r#"var promise =Deno.core.opAsync("op_pending")"#,
+        r#"
+        const { op_pending } = Deno.core.ensureFastOps();
+        var promise = op_pending();
+        "#,
       )
       .unwrap();
     assert!(matches!(
diff --git a/core/runtime/tests/misc.rs b/core/runtime/tests/misc.rs
index 5928979..3228fb0 100644
--- a/core/runtime/tests/misc.rs
+++ b/core/runtime/tests/misc.rs
@@ -121,7 +121,7 @@ async fn test_wakers_for_async_ops() {
     .execute_script(
       "",
       FastString::from_static(
-        "(async () => { await Deno.core.opAsync('op_async_sleep'); })()",
+        "const { op_async_sleep } = Deno.core.ensureFastOps(); (async () => { await op_async_sleep(); })()",
       ),
     )
     .unwrap();
@@ -662,7 +662,7 @@ async fn test_set_macrotask_callback_set_next_tick_callback() {
     .execute_script_static(
       "macrotasks_and_nextticks.js",
       r#"
-
+      const { op_async_sleep } = Deno.core.ensureFastOps();
       (async function () {
         const results = [];
         Deno.core.setMacrotaskCallback(() => {
@@ -674,7 +674,7 @@ async fn test_set_macrotask_callback_set_next_tick_callback() {
           Deno.core.setHasTickScheduled(false);
         });
         Deno.core.setHasTickScheduled(true);
-        await Deno.core.opAsync('op_async_sleep');
+        await op_async_sleep();
         if (results[0] != "nextTick") {
           throw new Error(`expected nextTick, got: ${results[0]}`);
         }
@@ -826,6 +826,7 @@ async fn test_promise_rejection_handler_generic(
     function throwError() {
       throw new Error("boom");
     }
+    const { op_void_async, op_void_async_deferred } = Deno.core.ensureFastOps();
     if (test != "no_handler") {
       Deno.core.setUnhandledPromiseRejectionHandler((promise, rejection) => {
         if (test.startsWith("exception_")) {
@@ -840,9 +841,9 @@ async fn test_promise_rejection_handler_generic(
     }
     if (test != "no_reject") {
       if (test.startsWith("async_op_eager_")) {
-        Deno.core.opAsync("op_void_async").then(() => { Deno.core.ops.op_breakpoint(); throw new Error("fail") });
+        op_void_async().then(() => { Deno.core.ops.op_breakpoint(); throw new Error("fail") });
       } else if (test.startsWith("async_op_deferred_")) {
-        Deno.core.opAsync("op_void_async_deferred").then(() => { Deno.core.ops.op_breakpoint(); throw new Error("fail") });
+        op_void_async_deferred().then(() => { Deno.core.ops.op_breakpoint(); throw new Error("fail") });
       } else if (test.startsWith("throw_")) {
         Deno.core.ops.op_breakpoint();
         throw new Error("fail");
@@ -979,7 +980,7 @@ async fn test_dynamic_import_module_error_stack() {
     ),
     (
       Url::parse("file:///import.js").unwrap(),
-      ascii_str!("await Deno.core.opAsync(\"op_async_error\");"),
+      ascii_str!("const { op_async_error } = Deno.core.ensureFastOps(); await op_async_error();"),
     ),
   ]);
   let mut runtime = JsRuntime::new(RuntimeOptions {
@@ -1003,13 +1004,13 @@ async fn test_dynamic_import_module_error_stack() {
   assert_eq!(
     js_error.to_string(),
     "Error: foo
-    at async file:///import.js:1:1"
+    at async file:///import.js:1:55"
   );
 }
 
 #[tokio::test]
 #[should_panic(
-  expected = "Top-level await is not allowed in extensions (mod:tla:2:1)"
+  expected = "Top-level await is not allowed in extensions (mod:tla:3:13)"
 )]
 async fn tla_in_esm_extensions_panics() {
   #[op2(async)]
@@ -1025,8 +1026,9 @@ async fn tla_in_esm_extensions_panics() {
         specifier: "mod:tla",
         code: ExtensionFileSourceCode::IncludedInBinary(
           r#"
-await Deno.core.opAsync('op_wait', 0);
-export const TEST = "foo";
+            const { op_wait } = Deno.core.ensureFastOps();
+            await op_wait(0);
+            export const TEST = "foo";
         "#,
         ),
       },
diff --git a/core/runtime/tests/ops.rs b/core/runtime/tests/ops.rs
index 6fc83ce..0f7db50 100644
--- a/core/runtime/tests/ops.rs
+++ b/core/runtime/tests/ops.rs
@@ -52,7 +52,7 @@ async fn test_async_opstate_borrow() {
   runtime
     .execute_script_static(
       "op_async_borrow.js",
-      "Deno.core.opAsync(\"op_async_borrow\")",
+      "const { op_async_borrow } = Deno.core.ensureFastOps(); op_async_borrow();",
     )
     .unwrap();
   runtime.run_event_loop(Default::default()).await.unwrap();
@@ -126,18 +126,18 @@ async fn test_async_op_serialize_object_with_numbers_as_keys() {
     .execute_script_static(
       "op_async_serialize_object_with_numbers_as_keys.js",
       r#"
-
-Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", {
-lines: {
-  100: {
-    unit: "m"
-  },
-  200: {
-    unit: "cm"
-  }
-}
-})
-"#,
+        const { op_async_serialize_object_with_numbers_as_keys } = Deno.core.ensureFastOps();
+        op_async_serialize_object_with_numbers_as_keys({
+          lines: {
+            100: {
+              unit: "m"
+            },
+            200: {
+              unit: "cm"
+            }
+          }
+        });
+      "#,
     )
     .unwrap();
   runtime.run_event_loop(Default::default()).await.unwrap();
@@ -445,10 +445,10 @@ fn test_dispatch() {
       "filename.js",
       r#"
       let control = 42;
-
-      Deno.core.opAsync("op_test", control);
+      const { op_test } = Deno.core.ensureFastOps();
+      op_test(control);
       async function main() {
-        Deno.core.opAsync("op_test", control);
+        op_test(control);
       }
       main();
       "#,
@@ -464,8 +464,8 @@ fn test_dispatch_no_zero_copy_buf() {
     .execute_script_static(
       "filename.js",
       r#"
-
-      Deno.core.opAsync("op_test", 0);
+      const { op_test } = Deno.core.ensureFastOps();
+      op_test(0);
       "#,
     )
     .unwrap();