-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(core): JsRuntime::replace_op #13219
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not in favour of this.
Op-middleware allows wrapping/replacing/disabling ops with a single primitive, e.g:
let my_ext = Extension::builder()
.middleware(|name, opfn| match name {
"op_print" => deno_core::void_op_sync(),
_ => opfn,
})
.build();
Any reason why this pattern doesn't work for your aforementioned use-cases ?
pub fn replace_op<F>(&mut self, name: &str, op_fn: F) -> OpId | ||
where | ||
F: Fn(Rc<RefCell<OpState>>, OpPayload) -> Op + 'static, | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side discussion: it might makes sense to someday rewrite these (replace_op, register_op, etc.) to:
pub fn frob_op(&mut self, name: &str, op_fn: Rc<OpFn>) {
// ...
}
Because right now they turn into a combinatorial explosion of monomorphized calls.
Truthfully, that's probably more relevant for op_sync()
and op_async()
because they're called way more often than register_op()
- approx. 300 vs. 35 calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mid-term I would be in favour of only allowing ops to be registered declaratively at init via Extensions.
Enabling op-middleware for overrides in lieu of imperative .replace_op() etc... Impacts denoland#13219, denoland#12938, denoland#13122
The goal of this PR is clearly to replace ops at runtime and without overhead. |
#13122 and #12938 both replace ops at isolate-boot time. Op-middleware handles precisely this use-case and there's no difference in opcall overhead for the replaced ops. |
At isolate creation time isn't at runtime but maybe that's sufficient for the two linked use cases. |
It is sufficient for the aforementioned use-cases and dynamically replacing ops at runtime is an anti-pattern IMO unless we're discussing "plugins" but that's off the table. So in short unless there's a very clear use-case that middleware doesn't already solve, we should not add this API. I refactored the CLI code in #13223 so @bartlomieju can easily slot in his |
Possible additional use-case: #12918 If it's not possible to move op_apply_source_map, op_format_diagnostic and op_format_file_name into deno_runtime due to dependencies on cli then presumably deno_runtime will need alternative implementations that are then replaced in cli? |
Adds a new API to "JsRuntime" that allows to replace (or overwrite) an existing op
with a new handler.
This is kind of "very unsafe, but I know what I'm doing, please leave me alone" API,
but has actual use cases in:
calling "Deno.exit()" API in test code
over a socket to a notebook frontend