diff --git a/changelog.d/9913-test-mock-prototype.md b/changelog.d/9913-test-mock-prototype.md new file mode 100644 index 0000000000..04063d419e --- /dev/null +++ b/changelog.d/9913-test-mock-prototype.md @@ -0,0 +1 @@ +`node:test`'s `mock.method()` now replaces declared class prototype methods for instance dispatch and restores their original behavior, while recording calls and receiver identity like Node. diff --git a/crates/perry-runtime/src/node_submodules/test.rs b/crates/perry-runtime/src/node_submodules/test.rs index cb70c0b994..15acb0c498 100644 --- a/crates/perry-runtime/src/node_submodules/test.rs +++ b/crates/perry-runtime/src/node_submodules/test.rs @@ -367,6 +367,22 @@ fn set_property_value(target: f64, property: &str, value: f64) { } } +fn set_method_property_value(target: f64, property: &str, value: f64) { + let raw = raw_ptr_from_value(target); + if let Some(class_id) = crate::object::class_id_for_decl_prototype_object(raw) { + unsafe { + crate::object::js_register_prototype_method( + class_id, + property.as_ptr(), + property.len(), + value, + ); + } + } else { + set_property_value(target, property, value); + } +} + fn get_property_value(target: f64, property: &str) -> f64 { let raw = raw_ptr_from_value(target); if raw >= 0x10000 && crate::closure::is_closure_ptr(raw) { @@ -691,7 +707,7 @@ fn restore_mock_state(id: i64) { target, property, original, - }) => set_property_value(target, &property, original), + }) => set_method_property_value(target, &property, original), Some(MockRestoreTarget::ObjectAccessor { target, property, @@ -1036,7 +1052,7 @@ extern "C" fn mock_method_thunk( original, }, ); - set_property_value(target.get_nanbox_f64(), &property_name, function); + set_method_property_value(target.get_nanbox_f64(), &property_name, function); function } diff --git a/test-parity/node-suite/test/mock-fn/prototype-method.ts b/test-parity/node-suite/test/mock-fn/prototype-method.ts index c6e2756b69..bcf7138aeb 100644 --- a/test-parity/node-suite/test/mock-fn/prototype-method.ts +++ b/test-parity/node-suite/test/mock-fn/prototype-method.ts @@ -1,7 +1,10 @@ import { mock } from "node:test"; class Counter { - constructor(public value: number) {} + value: number; + constructor(value: number) { + this.value = value; + } read() { return this.value; }