Skip to content

Commit

Permalink
WIP: Pure JS custom host objects
Browse files Browse the repository at this point in the history
This avoids substantial slowdowns caused by host objects using embedded fields.
Depends on: denoland/rusty_v8#1322

Current status:
For some reason v8::Symbol::for_global is returning a different symbol to the one defined in 01_core.js.

```
$ ./target/debug/deno test cli/tests/unit/message_channel_test.ts
running 2 tests from ./cli/tests/unit/message_channel_test.ts
messagechannel ... ok (35ms)
messagechannel clone port ...result=Some(false) constructor=Object keys.length=0, identity hash:560437950 is_object false is_symbol true
result=Some(false) constructor=MessagePort keys.length=4, identity hash:560437950 is_object false is_symbol true
0 symbol "Deno.core.customHostObject" is false, hash 253732785 is_object false is_symbol true
1 symbol "[[webidl.brand]]" is false, hash 764160415 is_object false is_symbol true
2 symbol "undefined" is false, hash 758685447 is_object false is_symbol true
3 symbol "id" is false, hash 997007839 is_object false is_symbol true

Uncaught error from ./cli/tests/unit/message_channel_test.ts FAILED
messagechannel clone port ... cancelled (0ms)
```
  • Loading branch information
lrowe committed Sep 16, 2023
1 parent faebea9 commit 0410188
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 11 deletions.
8 changes: 7 additions & 1 deletion core/01_core.js
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,12 @@ for (let i = 0; i < 10; i++) {
op_shutdown: shutdown,
} = ensureFastOps();

const customHostObjectSymbol = SymbolFor("Deno.core.customHostObject");

function createHostObject() {
return { [customHostObjectSymbol]: true };
}

// Extra Deno.core.* exports
const core = ObjectAssign(globalThis.Deno.core, {
asyncStub,
Expand Down Expand Up @@ -842,7 +848,7 @@ for (let i = 0; i < 10; i++) {
source,
specifier,
) => ops.op_eval_context(source, specifier),
createHostObject: () => ops.op_create_host_object(),
createHostObject,
encode: (text) => ops.op_encode(text),
decode: (buffer) => ops.op_decode(buffer),
serialize: (
Expand Down
1 change: 0 additions & 1 deletion core/ops_builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ crate::extension!(
ops_builtin_v8::op_set_has_tick_scheduled,
ops_builtin_v8::op_eval_context,
ops_builtin_v8::op_queue_microtask,
ops_builtin_v8::op_create_host_object,
ops_builtin_v8::op_encode,
ops_builtin_v8::op_decode,
ops_builtin_v8::op_serialize,
Expand Down
55 changes: 46 additions & 9 deletions core/ops_builtin_v8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,6 @@ pub fn op_queue_microtask(
scope.enqueue_microtask(cb);
}

#[op2(core)]
pub fn op_create_host_object<'a>(
scope: &mut v8::HandleScope<'a>,
) -> v8::Local<'a, v8::Object> {
let template = v8::ObjectTemplate::new(scope);
template.set_internal_field_count(1);
template.new_instance(scope).unwrap()
}

#[op2(core)]
pub fn op_encode<'a>(
scope: &mut v8::HandleScope<'a>,
Expand Down Expand Up @@ -254,6 +245,52 @@ impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
}
}

fn has_custom_host_object<'s>(
&mut self,
_scope: &mut v8::HandleScope<'s>,
) -> bool {
true
}

fn is_host_object<'s>(
&mut self,
scope: &mut v8::HandleScope<'s>,
object: v8::Local<'s, v8::Object>,
) -> Option<bool> {
let description = v8::String::new(scope, "Deno.core.customHostObject").unwrap();
let customHostObject = v8::Symbol::for_global(scope, description);
let result = object.has_own_property(scope, customHostObject.into());
let keys = object.get_own_property_names(scope, v8::GetPropertyNamesArgs {
mode: v8::KeyCollectionMode::OwnOnly,
property_filter: v8::PropertyFilter::SKIP_STRINGS,
index_filter: v8::IndexFilter::SkipIndices,
key_conversion: v8::KeyConversionMode::ConvertToString,
}).unwrap();
println!(
"result={:?} constructor={} keys.length={}, identity hash:{:?} is_object {:?} is_symbol {:?}",
result,
object.get_constructor_name().to_rust_string_lossy(scope),
keys.length(),
customHostObject.get_identity_hash(),
customHostObject.is_object(),
customHostObject.is_symbol(),
);
for i in 0..keys.length() {
let key = keys.get_index(scope, i).unwrap();
let symbol = unsafe { v8::Local::<v8::Symbol>::cast(key) };
println!(
"{} symbol {:?} is {:?}, hash {:?} is_object {:?} is_symbol {:?}",
i,
symbol.description(scope).to_rust_string_lossy(scope),
symbol.strict_equals(customHostObject.into()),
symbol.get_identity_hash(),
symbol.is_object(),
symbol.is_symbol(),
);
}
result
}

fn write_host_object<'s>(
&mut self,
scope: &mut v8::HandleScope<'s>,
Expand Down

0 comments on commit 0410188

Please sign in to comment.