6.6 Registration of ops

Operations, often referred to as "Ops," play a crucial role in Deno. Ops act as the primary connectors between JavaScript and Rust, effectively forming a bridge between the two. This interaction happens back and forth, allowing seamless communication. Ops are essential because V8 strictly adheres to the ECMAScript specification, the standard for JavaScript. Any functionality that goes beyond this specification must be provided as an external reference. Even fundamental actions like using console.log require an external op call, as the ECMAScript specification doesn't encompass console output.

In the previous chapter, we explored how external references are registered with V8. We will now quickly revisit that concept. Additionally, we will look into built-in and ext ops. This section will specifically focus on the registration process for ops. Later on, we will examine how ops are triggered during runtime and how the system manages their responses.

Overview

In short:

Ops are low-level functions that are implemented in Rust to support the high-level functions in JS.

For example, crypto.randomUUID is a high-level function, and the corresponding Rust op is implemented by op_crypto_random_uuid.

The high-level JS function is;

randomUUID() {
  webidl.assertBranded(this, CryptoPrototype);
  return ops.op_crypto_random_uuid();
}

The corresponding low-level OP is:

pub fn op_crypto_random_uuid(state: &mut OpState) -> Result<String, AnyError> {
  let maybe_seeded_rng = state.try_borrow_mut::<StdRng>();
  let uuid = if let Some(seeded_rng) = maybe_seeded_rng {
    let mut bytes = [0u8; 16];
    seeded_rng.fill(&mut bytes);
    uuid::Builder::from_bytes(bytes)
      .with_version(uuid::Version::Random)
      .into_uuid()
  } else {
    uuid::Uuid::new_v4()
  };

  Ok(uuid.to_string())
}

In Deno, operations (OPs) typically have a one-to-one mapping. This means that one JavaScript API directly corresponds to one Rust operation (OP). All the operations (OPs) follow a consistent pattern, from the initial setup to processing the result. The following outlines the typical phases of an operation (OP):

Deno operations progress through various stages. The diagram above illustrates the standard operation state machine. Let's examine each state:

  1. Register handler

    • In this step, an operation handler is registered.

  2. Waiting to get called

    • This state resembles an idle condition where the operation awaits a call.

  3. Dispatch

    • Dispatch involves moving across the bridge from V8 to Deno.

  4. Execute

    • Deno executes the operation's handler.

  5. Process result

    • The outcome is sent back to V8, where it undergoes processing in JavaScript.

    • This step is akin to returning from the bridge.

The process of dispatching and result processing happens during runtime. We will discuss the details later. For now, our focus is on registering operations.

Types of Ops

All the operations can be divided into two main categories:

  1. Sync Operations:

    • In sync operations, the request and response are processed one after the other, in a step-by-step manner.

    • During the execution of sync operations, the process is blocked, meaning it waits for each step to complete before moving forward.

  2. Async Operations:

    • Async operations, on the other hand, handle requests and responses asynchronously, which means they can process multiple tasks concurrently.

    • The execution of async operations is not blocked, allowing the program to continue with other tasks while waiting for certain operations to finish.

Certain operations fall distinctly into either of these categories, while some operations can belong to both. For instance, operations like getting and setting environment variables are categorized as sync operations. Another example involves reading a file, which can involve both sync and async operations, depending on the specific operation and the user's choice.

The suitability of async operations varies based on the nature of the operation. Some operations are better suited for sync processing, and thus only have sync variants. On the other hand, for operations like reading a file, the decision to use sync or async mode is up to the user. If dealing with a particularly large file, the user might opt for async reading to improve efficiency.

Registration

Op registration happens at startup. Deno registers all of its low-level ops right at the process startup. There two sources of OPs:

  • Built-in OPs: These OPs are part of Deno core. These cover the most basic & fundamental OPs. Some examples are - op_print, op_resources, op_read, op_write, op_encode, op_decode, etc.

  • EXT OPs: These OPs come from Deno's ext modules. As we know that the ext modules are a close combination of JS APIs alongwith their low-level OPs. The OPs coming from EXT usually have the 1:1 mapping from JS API to the OP. Some examples are - op_fetch, op_crypto_sign_key, op_crypto_get_random_values, etc.

The code in the main worker below registers all the OPs with V8 as external references:

pub fn from_options(
    main_module: ModuleSpecifier,
    permissions: PermissionsContainer,
    mut options: WorkerOptions,
  ) -> Self {
    deno_core::extension!(deno_permissions_worker,
      options = {
        permissions: PermissionsContainer,
        unstable: bool,
        enable_testing_features: bool,
      },
      state = |state, options| {
        state.put::<PermissionsContainer>(options.permissions);
        state.put(ops::UnstableChecker { unstable: options.unstable });
        state.put(ops::TestingFeaturesEnabled(options.enable_testing_features));
      },
    );

    // Permissions: many ops depend on this
    let unstable = options.bootstrap.unstable;
    let enable_testing_features = options.bootstrap.enable_testing_features;
    let exit_code = ExitCode(Arc::new(AtomicI32::new(0)));
    let create_cache = options.cache_storage_dir.map(|storage_dir| {
      let create_cache_fn = move || SqliteBackedCache::new(storage_dir.clone());
      CreateCache(Arc::new(create_cache_fn))
    });

    // NOTE(bartlomieju): ordering is important here, keep it in sync with
    // `runtime/build.rs`, `runtime/web_worker.rs` and `cli/build.rs`!
    let mut extensions = vec![
      // Web APIs
      deno_webidl::deno_webidl::init_ops_and_esm(),
      deno_console::deno_console::init_ops_and_esm(),
      deno_url::deno_url::init_ops_and_esm(),
      deno_web::deno_web::init_ops_and_esm::<PermissionsContainer>(
        options.blob_store.clone(),
        options.bootstrap.location.clone(),
      ),
      deno_fetch::deno_fetch::init_ops_and_esm::<PermissionsContainer>(
        deno_fetch::Options {
          user_agent: options.bootstrap.user_agent.clone(),
          root_cert_store_provider: options.root_cert_store_provider.clone(),
          unsafely_ignore_certificate_errors: options
            .unsafely_ignore_certificate_errors
            .clone(),
          file_fetch_handler: Rc::new(deno_fetch::FsFetchHandler),
          ..Default::default()
        },
      ),
      deno_cache::deno_cache::init_ops_and_esm::<SqliteBackedCache>(
        create_cache,
      ),
      deno_websocket::deno_websocket::init_ops_and_esm::<PermissionsContainer>(
        options.bootstrap.user_agent.clone(),
        options.root_cert_store_provider.clone(),
        options.unsafely_ignore_certificate_errors.clone(),
      ),
      deno_webstorage::deno_webstorage::init_ops_and_esm(
        options.origin_storage_dir.clone(),
      ),
      deno_crypto::deno_crypto::init_ops_and_esm(options.seed),
      deno_broadcast_channel::deno_broadcast_channel::init_ops_and_esm(
        options.broadcast_channel.clone(),
        unstable,
      ),
      deno_ffi::deno_ffi::init_ops_and_esm::<PermissionsContainer>(unstable),
      deno_net::deno_net::init_ops_and_esm::<PermissionsContainer>(
        options.root_cert_store_provider.clone(),
        unstable,
        options.unsafely_ignore_certificate_errors.clone(),
      ),
      deno_tls::deno_tls::init_ops_and_esm(),
      deno_kv::deno_kv::init_ops_and_esm(
        MultiBackendDbHandler::remote_or_sqlite::<PermissionsContainer>(
          options.origin_storage_dir.clone(),
        ),
        unstable,
      ),
      deno_napi::deno_napi::init_ops_and_esm::<PermissionsContainer>(),
      deno_http::deno_http::init_ops_and_esm::<DefaultHttpPropertyExtractor>(),
      deno_io::deno_io::init_ops_and_esm(Some(options.stdio)),
      deno_fs::deno_fs::init_ops_and_esm::<PermissionsContainer>(
        unstable,
        options.fs.clone(),
      ),
      deno_node::deno_node::init_ops_and_esm::<PermissionsContainer>(
        options.npm_resolver,
        options.fs,
      ),
      // Ops from this crate
      ops::runtime::deno_runtime::init_ops_and_esm(main_module.clone()),
      ops::worker_host::deno_worker_host::init_ops_and_esm(
        options.create_web_worker_cb.clone(),
        options.format_js_error_fn.clone(),
      ),
      ops::fs_events::deno_fs_events::init_ops_and_esm(),
      ops::os::deno_os::init_ops_and_esm(exit_code.clone()),
      ops::permissions::deno_permissions::init_ops_and_esm(),
      ops::process::deno_process::init_ops_and_esm(),
      ops::signal::deno_signal::init_ops_and_esm(),
      ops::tty::deno_tty::init_ops_and_esm(),
      ops::http::deno_http_runtime::init_ops_and_esm(),
      deno_permissions_worker::init_ops_and_esm(
        permissions,
        unstable,
        enable_testing_features,
      ),
      runtime::init_ops_and_esm(),
    ];

    for extension in &mut extensions {
      #[cfg(not(feature = "__runtime_js_sources"))]
      {
        extension.js_files = std::borrow::Cow::Borrowed(&[]);
        extension.esm_files = std::borrow::Cow::Borrowed(&[]);
        extension.esm_entry_point = None;
      }
      #[cfg(feature = "__runtime_js_sources")]
      {
        for source in extension.esm_files.to_mut() {
          maybe_transpile_source(source).unwrap();
        }
        for source in extension.js_files.to_mut() {
          maybe_transpile_source(source).unwrap();
        }
      }
    }

    extensions.extend(std::mem::take(&mut options.extensions));

    #[cfg(all(feature = "include_js_files_for_snapshotting", feature = "dont_create_runtime_snapshot", not(feature = "__runtime_js_sources")))]
    options.startup_snapshot.as_ref().expect("Sources are not embedded, snapshotting was disabled and a user snapshot was not provided.");

    // Clear extension modules from the module map, except preserve `node:*`
    // modules.
    let preserve_snapshotted_modules =
      Some(SUPPORTED_BUILTIN_NODE_MODULES_WITH_PREFIX);

    let mut js_runtime = JsRuntime::new(RuntimeOptions {
      module_loader: Some(options.module_loader.clone()),
      startup_snapshot: options
        .startup_snapshot
        .or_else(crate::js::deno_isolate_init),
      create_params: options.create_params,
      source_map_getter: options.source_map_getter,
      get_error_class_fn: options.get_error_class_fn,
      shared_array_buffer_store: options.shared_array_buffer_store.clone(),
      compiled_wasm_module_store: options.compiled_wasm_module_store.clone(),
      extensions,
      preserve_snapshotted_modules,
      inspector: options.maybe_inspector_server.is_some(),
      is_main: true,
      ..Default::default()
    });

    if let Some(server) = options.maybe_inspector_server.clone() {
      server.register_inspector(
        main_module.to_string(),
        &mut js_runtime,
        options.should_break_on_first_statement
          || options.should_wait_for_inspector_session,
      );

      // Put inspector handle into the op state so we can put a breakpoint when
      // executing a CJS entrypoint.
      let op_state = js_runtime.op_state();
      let inspector = js_runtime.inspector();
      op_state.borrow_mut().put(inspector);
    }

    let bootstrap_fn_global = {
      let context = js_runtime.main_context();
      let scope = &mut js_runtime.handle_scope();
      let context_local = v8::Local::new(scope, context);
      let global_obj = context_local.global(scope);
      let bootstrap_str =
        v8::String::new_external_onebyte_static(scope, b"bootstrap").unwrap();
      let bootstrap_ns: v8::Local<v8::Object> = global_obj
        .get(scope, bootstrap_str.into())
        .unwrap()
        .try_into()
        .unwrap();
      let main_runtime_str =
        v8::String::new_external_onebyte_static(scope, b"mainRuntime").unwrap();
      let bootstrap_fn =
        bootstrap_ns.get(scope, main_runtime_str.into()).unwrap();
      let bootstrap_fn =
        v8::Local::<v8::Function>::try_from(bootstrap_fn).unwrap();
      v8::Global::new(scope, bootstrap_fn)
    };

    Self {
      js_runtime,
      should_break_on_first_statement: options.should_break_on_first_statement,
      should_wait_for_inspector_session: options
        .should_wait_for_inspector_session,
      exit_code,
      bootstrap_fn_global: Some(bootstrap_fn_global),
    }
  }

Let's look at the master function that register all the Ops with V8:

pub(crate) fn external_references(
  ops: &[OpCtx],
  additional_references: &[v8::ExternalReference],
) -> v8::ExternalReferences {
  // Overallocate a bit, it's better than having to resize the vector.
  let mut references =
    Vec::with_capacity(4 + (ops.len() * 4) + additional_references.len());

  references.push(v8::ExternalReference {
    function: call_console.map_fn_to(),
  });
  references.push(v8::ExternalReference {
    function: import_meta_resolve.map_fn_to(),
  });
  references.push(v8::ExternalReference {
    function: catch_dynamic_import_promise_error.map_fn_to(),
  });
  references.push(v8::ExternalReference {
    function: empty_fn.map_fn_to(),
  });

  for ctx in ops {
    let ctx_ptr = ctx as *const OpCtx as _;
    references.push(v8::ExternalReference { pointer: ctx_ptr });
    references.push(v8::ExternalReference {
      function: ctx.decl.v8_fn_ptr,
    });
    if let Some(fast_fn) = &ctx.decl.fast_fn {
      references.push(v8::ExternalReference {
        pointer: fast_fn.function as _,
      });
      references.push(v8::ExternalReference {
        pointer: ctx.fast_fn_c_info.unwrap().as_ptr() as _,
      });
    }
  }

  references.extend_from_slice(additional_references);

  let refs = v8::ExternalReferences::new(&references);
  // Leak, V8 takes ownership of the references.
  std::mem::forget(references);
  refs
}

Although the code of OPs is in Rust, they're invoked from JS space. Therefore, each OP has a corresponding registration function in JS too. This also comes from Deno core.

Deno.__op__registerOp = function (isAsync, op, opName) {
  const core = Deno.core;
  if (isAsync) {
    if (core.ops[opName] !== undefined) {
      return;
    }
    core.asyncOps[opName] = op;
    const fn = function (...args) {
      if (this !== core.ops) {
        // deno-lint-ignore prefer-primordials
        throw new Error(
          "An async stub cannot be separated from Deno.core.ops. Use ???",
        );
      }
      return core.asyncStub(opName, args);
    };
    fn.name = opName;
    core.ops[opName] = fn;
  } else {
    core.ops[opName] = op;
  }
};

The call to registerOp called from Rust code:

pub(crate) fn initialize_context<'s>(
  scope: &mut v8::HandleScope<'s>,
  context: v8::Local<'s, v8::Context>,
  op_ctxs: &[OpCtx],
  init_mode: InitMode,
) -> v8::Local<'s, v8::Context> {
  let global = context.global(scope);

  let mut codegen = String::with_capacity(op_ctxs.len() * 200);
  codegen.push_str(include_str!("bindings.js"));
  _ = writeln!(
    codegen,
    "Deno.__op__ = function(opFns, callConsole, console) {{"
  );
  if init_mode == InitMode::New {
    _ = writeln!(codegen, "Deno.__op__console(callConsole, console);");
  }
  for op_ctx in op_ctxs {
    if op_ctx.decl.enabled {
      _ = writeln!(
        codegen,
        "Deno.__op__registerOp({}, opFns[{}], \"{}\");",
        op_ctx.decl.is_async, op_ctx.id, op_ctx.decl.name
      );
    } else {
      _ = writeln!(
        codegen,
        "Deno.__op__unregisterOp({}, \"{}\");",
        op_ctx.decl.is_async, op_ctx.decl.name
      );
    }
  }
  codegen.push_str("Deno.__op__cleanup();");
  _ = writeln!(codegen, "}}");

  let script = v8::String::new_from_one_byte(
    scope,
    codegen.as_bytes(),
    v8::NewStringType::Normal,
  )
  .unwrap();
  let script = v8::Script::compile(scope, script, None).unwrap();
  script.run(scope);

  let deno = get(scope, global, b"Deno", "Deno");
  let op_fn: v8::Local<v8::Function> =
    get(scope, deno, b"__op__", "Deno.__op__");
  let recv = v8::undefined(scope);
  let op_fns = v8::Array::new(scope, op_ctxs.len() as i32);
  for op_ctx in op_ctxs {
    let op_fn = op_ctx_function(scope, op_ctx);
    op_fns.set_index(scope, op_ctx.id as u32, op_fn.into());
  }
  if init_mode == InitMode::FromSnapshot {
    op_fn.call(scope, recv.into(), &[op_fns.into()]);
  } else {
    // Bind functions to Deno.core.*
    let call_console_fn = v8::Function::new(scope, call_console).unwrap();

    // Bind v8 console object to Deno.core.console
    let extra_binding_obj = context.get_extras_binding_object(scope);
    let console_obj: v8::Local<v8::Object> = get(
      scope,
      extra_binding_obj,
      b"console",
      "ExtrasBindingObject.console",
    );

    op_fn.call(
      scope,
      recv.into(),
      &[op_fns.into(), call_console_fn.into(), console_obj.into()],
    );
  }

  context
}

At the time of writing, there are 478 ops that get registered. Here is the complete list:

op_close
op_try_close
op_print
op_resources
op_wasm_streaming_feed
op_wasm_streaming_set_url
op_void_sync
op_error_async
op_error_async_deferred
op_void_async
op_void_async_deferred
op_add
op_add_async
op_read
op_read_all
op_write
op_read_sync
op_write_sync
op_write_all
op_write_type_error
op_shutdown
op_metrics
op_format_file_name
op_is_proxy
op_str_byte_length
op_ref_op
op_unref_op
op_set_promise_reject_callback
op_run_microtasks
op_has_tick_scheduled
op_set_has_tick_scheduled
op_eval_context
op_queue_microtask
op_create_host_object
op_encode
op_decode
op_serialize
op_deserialize
op_set_promise_hooks
op_get_promise_details
op_get_proxy_details
op_get_non_index_property_names
op_get_constructor_name
op_memory_usage
op_set_wasm_streaming_callback
op_abort_wasm_streaming
op_destructure_error
op_dispatch_exception
op_op_names
op_apply_source_map
op_set_format_exception_callback
op_event_loop_has_more_work
op_store_pending_promise_rejection
op_remove_pending_promise_rejection
op_has_pending_promise_rejection
op_arraybuffer_was_detached
op_url_reparse
op_url_parse
op_url_get_serialization
op_url_parse_with_base
op_url_parse_search_params
op_url_stringify_search_params
op_urlpattern_parse
op_urlpattern_process_match_input
op_base64_decode
op_base64_encode
op_base64_atob
op_base64_btoa
op_encoding_normalize_label
op_encoding_decode_single
op_encoding_decode_utf8
op_encoding_new_decoder
op_encoding_decode
op_encoding_encode_into
op_encode_binary_string
op_blob_create_part
op_blob_slice_part
op_blob_read_part
op_blob_remove_part
op_blob_create_object_url
op_blob_revoke_object_url
op_blob_from_object_url
op_message_port_create_entangled
op_message_port_post_message
op_message_port_recv_message
op_compression_new
op_compression_write
op_compression_finish
op_now
op_timer_handle
op_cancel_handle
op_sleep
op_transfer_arraybuffer
op_readable_stream_resource_allocate
op_readable_stream_resource_get_sink
op_readable_stream_resource_write_error
op_readable_stream_resource_write_buf
op_readable_stream_resource_close
op_readable_stream_resource_await_close
op_fetch
op_fetch_send
op_fetch_response_upgrade
op_fetch_custom_client
op_cache_storage_open
op_cache_storage_has
op_cache_storage_delete
op_cache_put
op_cache_put_finish
op_cache_match
op_cache_delete
op_ws_check_permission_and_cancel_handle
op_ws_create
op_ws_close
op_ws_next_event
op_ws_get_buffer
op_ws_get_buffer_as_string
op_ws_get_error
op_ws_send_binary
op_ws_send_text
op_ws_send_binary_async
op_ws_send_text_async
op_ws_send_ping
op_ws_send_pong
op_ws_get_buffered_amount
op_webstorage_length
op_webstorage_key
op_webstorage_set
op_webstorage_get
op_webstorage_remove
op_webstorage_clear
op_webstorage_iterate_keys
op_crypto_get_random_values
op_crypto_generate_key
op_crypto_sign_key
op_crypto_verify_key
op_crypto_derive_bits
op_crypto_import_key
op_crypto_export_key
op_crypto_encrypt
op_crypto_decrypt
op_crypto_subtle_digest
op_crypto_random_uuid
op_crypto_wrap_key
op_crypto_unwrap_key
op_crypto_base64url_decode
op_crypto_base64url_encode
op_crypto_generate_x25519_keypair
op_crypto_derive_bits_x25519
op_crypto_import_spki_x25519
op_crypto_import_pkcs8_x25519
op_crypto_generate_ed25519_keypair
op_crypto_import_spki_ed25519
op_crypto_import_pkcs8_ed25519
op_crypto_sign_ed25519
op_crypto_verify_ed25519
op_crypto_export_spki_ed25519
op_crypto_export_pkcs8_ed25519
op_crypto_jwk_x_ed25519
op_crypto_export_spki_x25519
op_crypto_export_pkcs8_x25519
op_broadcast_subscribe
op_broadcast_unsubscribe
op_broadcast_send
op_broadcast_recv
op_ffi_load
op_ffi_get_static
op_ffi_call_nonblocking
op_ffi_call_ptr
op_ffi_call_ptr_nonblocking
op_ffi_ptr_create
op_ffi_ptr_equals
op_ffi_ptr_of
op_ffi_ptr_offset
op_ffi_ptr_value
op_ffi_get_buf
op_ffi_buf_copy_into
op_ffi_cstr_read
op_ffi_read_bool
op_ffi_read_u8
op_ffi_read_i8
op_ffi_read_u16
op_ffi_read_i16
op_ffi_read_u32
op_ffi_read_i32
op_ffi_read_u64
op_ffi_read_i64
op_ffi_read_f32
op_ffi_read_f64
op_ffi_read_ptr
op_ffi_unsafe_callback_create
op_ffi_unsafe_callback_close
op_ffi_unsafe_callback_ref
op_net_accept_tcp
op_net_connect_tcp
op_net_listen_tcp
op_net_listen_udp
op_node_unstable_net_listen_udp
op_net_recv_udp
op_net_send_udp
op_net_join_multi_v4_udp
op_net_join_multi_v6_udp
op_net_leave_multi_v4_udp
op_net_leave_multi_v6_udp
op_net_set_multi_loopback_udp
op_net_set_multi_ttl_udp
op_dns_resolve
op_set_nodelay
op_set_keepalive
op_tls_start
op_net_connect_tls
op_net_listen_tls
op_net_accept_tls
op_tls_handshake
op_net_accept_unix
op_net_connect_unix
op_net_listen_unix
op_net_listen_unixpacket
op_node_unstable_net_listen_unixpacket
op_net_recv_unixpacket
op_net_send_unixpacket
op_kv_database_open
op_kv_snapshot_read
op_kv_atomic_write
op_kv_encode_cursor
op_kv_dequeue_next_message
op_kv_finish_dequeued_message
op_napi_open
op_http_accept
op_http_headers
op_http_shutdown
op_http_upgrade_websocket
op_http_websocket_accept_header
op_http_write_headers
op_http_write_resource
op_http_write
op_http_get_request_header
op_http_get_request_headers
op_http_get_request_method_and_url
op_http_read_request_body
op_http_serve_on
op_http_serve
op_http_set_promise_complete
op_http_set_response_body_bytes
op_http_set_response_body_resource
op_http_set_response_body_text
op_http_set_response_header
op_http_set_response_headers
op_http_set_response_trailers
op_http_track
op_http_upgrade_websocket_next
op_http_upgrade_raw
op_raw_write_vectored
op_can_write_vectored
op_http_try_wait
op_http_wait
op_fs_cwd
op_fs_umask
op_fs_chdir
op_fs_open_sync
op_fs_open_async
op_fs_mkdir_sync
op_fs_mkdir_async
op_fs_chmod_sync
op_fs_chmod_async
op_fs_chown_sync
op_fs_chown_async
op_fs_remove_sync
op_fs_remove_async
op_fs_copy_file_sync
op_fs_copy_file_async
op_fs_stat_sync
op_fs_stat_async
op_fs_lstat_sync
op_fs_lstat_async
op_fs_realpath_sync
op_fs_realpath_async
op_fs_read_dir_sync
op_fs_read_dir_async
op_fs_rename_sync
op_fs_rename_async
op_fs_link_sync
op_fs_link_async
op_fs_symlink_sync
op_fs_symlink_async
op_fs_read_link_sync
op_fs_read_link_async
op_fs_truncate_sync
op_fs_truncate_async
op_fs_utime_sync
op_fs_utime_async
op_fs_make_temp_dir_sync
op_fs_make_temp_dir_async
op_fs_make_temp_file_sync
op_fs_make_temp_file_async
op_fs_write_file_sync
op_fs_write_file_async
op_fs_read_file_sync
op_fs_read_file_async
op_fs_read_file_text_sync
op_fs_read_file_text_async
op_fs_seek_sync
op_fs_seek_async
op_fs_fdatasync_sync
op_fs_fdatasync_async
op_fs_fsync_sync
op_fs_fsync_async
op_fs_fstat_sync
op_fs_fstat_async
op_fs_flock_sync
op_fs_flock_async
op_fs_funlock_sync
op_fs_funlock_async
op_fs_ftruncate_sync
op_fs_ftruncate_async
op_fs_futime_sync
op_fs_futime_async
op_node_create_decipheriv
op_node_cipheriv_encrypt
op_node_cipheriv_final
op_node_create_cipheriv
op_node_create_hash
op_node_get_hashes
op_node_decipheriv_decrypt
op_node_decipheriv_final
op_node_hash_update
op_node_hash_update_str
op_node_hash_digest
op_node_hash_digest_hex
op_node_hash_clone
op_node_private_encrypt
op_node_private_decrypt
op_node_public_encrypt
op_node_check_prime
op_node_check_prime_async
op_node_check_prime_bytes
op_node_check_prime_bytes_async
op_node_gen_prime
op_node_gen_prime_async
op_node_pbkdf2
op_node_pbkdf2_async
op_node_hkdf
op_node_hkdf_async
op_node_generate_secret
op_node_generate_secret_async
op_node_sign
op_node_generate_rsa
op_node_generate_rsa_async
op_node_dsa_generate
op_node_dsa_generate_async
op_node_ec_generate
op_node_ec_generate_async
op_node_ed25519_generate
op_node_ed25519_generate_async
op_node_x25519_generate
op_node_x25519_generate_async
op_node_dh_generate_group
op_node_dh_generate_group_async
op_node_dh_generate
op_node_dh_generate2
op_node_dh_compute_secret
op_node_dh_generate_async
op_node_verify
op_node_random_int
op_node_scrypt_sync
op_node_scrypt_async
op_node_ecdh_generate_keys
op_node_ecdh_compute_secret
op_node_ecdh_compute_public_key
op_node_x509_parse
op_node_x509_ca
op_node_x509_check_email
op_node_x509_fingerprint
op_node_x509_fingerprint256
op_node_x509_fingerprint512
op_node_x509_get_issuer
op_node_x509_get_subject
op_node_x509_get_valid_from
op_node_x509_get_valid_to
op_node_x509_get_serial_number
op_node_x509_key_usage
op_node_sys_to_uv_error
op_v8_cached_data_version_tag
op_v8_get_heap_statistics
op_node_idna_domain_to_ascii
op_node_idna_domain_to_unicode
op_node_idna_punycode_decode
op_node_idna_punycode_encode
op_zlib_new
op_zlib_close
op_zlib_close_if_pending
op_zlib_write
op_zlib_write_async
op_zlib_init
op_zlib_reset
op_brotli_compress
op_brotli_compress_async
op_create_brotli_compress
op_brotli_compress_stream
op_brotli_compress_stream_end
op_brotli_decompress
op_brotli_decompress_async
op_create_brotli_decompress
op_brotli_decompress_stream
op_brotli_decompress_stream_end
op_node_http_request
op_node_os_get_priority
op_node_os_set_priority
op_node_os_username
op_node_build_os
op_is_any_arraybuffer
op_node_is_promise_rejected
op_require_init_paths
op_require_node_module_paths
op_require_proxy_path
op_require_is_deno_dir_package
op_require_resolve_deno_dir
op_require_is_request_relative
op_require_resolve_lookup_paths
op_require_try_self_parent_path
op_require_try_self
op_require_real_path
op_require_path_is_absolute
op_require_path_dirname
op_require_stat
op_require_path_resolve
op_require_path_basename
op_require_read_file
op_require_as_file_path
op_require_resolve_exports
op_require_read_closest_package_json
op_require_read_package_scope
op_require_package_imports_resolve
op_require_break_on_next_statement
op_main_module
op_ppid
op_create_worker
op_host_terminate_worker
op_host_post_message
op_host_recv_ctrl
op_host_recv_message
op_fs_events_open
op_fs_events_poll
op_env
op_exec_path
op_exit
op_delete_env
op_get_env
op_gid
op_hostname
op_loadavg
op_network_interfaces
op_os_release
op_os_uptime
op_node_unstable_os_uptime
op_set_env
op_set_exit_code
op_system_memory_info
op_uid
op_runtime_memory_usage
op_query_permission
op_revoke_permission
op_request_permission
op_spawn_child
op_spawn_wait
op_spawn_sync
op_spawn_kill
op_run
op_run_status
op_kill
op_signal_bind
op_signal_unbind
op_signal_poll
op_stdin_set_raw
op_isatty
op_console_size
op_http_start
op_http_upgrade
op_npm_process_state

Once again, the call to OP happens like this:

randomUUID() {
  webidl.assertBranded(this, CryptoPrototype);
  return ops.op_crypto_random_uuid();
}

--

That was all about ops registration. Let's move on to module evaluation.

Last updated