@@ -28,67 +28,77 @@ pub(super) fn get_hook_function<'scope>(
2828pub ( super ) fn set_hook_slots (
2929 scope : & mut PinScope < ' _ , ' _ > ,
3030 abi : AbiVersion ,
31- hooks : & [ ( ModuleHook , Local < ' _ , Function > ) ] ,
31+ hooks : & [ ( ModuleHookKey , Local < ' _ , Function > ) ] ,
3232) -> ExcResult < ( ) > {
3333 // Make sure to call `set_slot` first, as it creates the annex
3434 // and `set_embedder_data` is currently buggy.
3535 let ctx = scope. get_current_context ( ) ;
36- let hooks_info = HooksInfo :: get_or_create ( & ctx) ;
36+ let hooks_info = HooksInfo :: get_or_create ( & ctx, abi)
37+ . map_err ( |_| TypeError ( "cannot call `register_hooks` from different versions" ) . throw ( scope) ) ?;
3738 for & ( hook, func) in hooks {
3839 hooks_info
39- . register ( hook, abi )
40+ . register ( hook)
4041 . map_err ( |_| TypeError ( "cannot call `register_hooks` multiple times" ) . throw ( scope) ) ?;
4142 ctx. set_embedder_data ( hook. to_slot_index ( ) , func. into ( ) ) ;
4243 }
4344 Ok ( ( ) )
4445}
4546
4647#[ derive( enum_map:: Enum , Copy , Clone ) ]
47- pub ( in crate :: host :: v8 ) enum ModuleHook {
48+ pub ( in super :: super ) enum ModuleHookKey {
4849 DescribeModule ,
4950 CallReducer ,
5051}
5152
52- impl ModuleHook {
53+ impl ModuleHookKey {
5354 /// Returns the index for the slot that holds the module function hook.
5455 /// The index is passed to `v8::Context::{get,set}_embedder_data`.
5556 fn to_slot_index ( self ) -> i32 {
5657 match self {
57- ModuleHook :: DescribeModule => 20 ,
58- ModuleHook :: CallReducer => 21 ,
58+ // high numbers to avoid overlapping with rusty_v8 - can be
59+ // reverted to just 0, 1... once denoland/rusty_v8#1868 merges
60+ ModuleHookKey :: DescribeModule => 20 ,
61+ ModuleHookKey :: CallReducer => 21 ,
5962 }
6063 }
6164}
6265
6366/// Holds the `AbiVersion` used by the module
6467/// and the module hooks registered by the module
6568/// for that version.
66- #[ derive( Default ) ]
6769struct HooksInfo {
68- abi : OnceCell < AbiVersion > ,
69- registered : EnumMap < ModuleHook , OnceCell < ( ) > > ,
70+ abi : AbiVersion ,
71+ registered : EnumMap < ModuleHookKey , OnceCell < ( ) > > ,
7072}
7173
7274impl HooksInfo {
7375 /// Returns, and possibly creates, the [`HooksInfo`] stored in `ctx`.
74- fn get_or_create ( ctx : & Context ) -> Rc < Self > {
75- ctx. get_slot ( ) . unwrap_or_else ( || {
76- let this = Rc :: < Self > :: default ( ) ;
77- ctx. set_slot ( this. clone ( ) ) ;
78- this
79- } )
76+ ///
77+ /// Returns an error if `abi` doesn't match the abi version in the
78+ /// already existing `HooksInfo`.
79+ fn get_or_create ( ctx : & Context , abi : AbiVersion ) -> Result < Rc < Self > , ( ) > {
80+ match ctx. get_slot :: < Self > ( ) {
81+ Some ( this) if this. abi == abi => Ok ( this) ,
82+ Some ( _) => Err ( ( ) ) ,
83+ None => {
84+ let this = Rc :: new ( Self {
85+ abi,
86+ registered : EnumMap :: default ( ) ,
87+ } ) ;
88+ ctx. set_slot ( this. clone ( ) ) ;
89+ Ok ( this)
90+ }
91+ }
8092 }
8193
82- fn register ( & self , hook : ModuleHook , abi : AbiVersion ) -> Result < ( ) , ( ) > {
83- if * self . abi . get_or_init ( || abi) != abi {
84- return Err ( ( ) ) ;
85- }
94+ /// Mark down the given `hook` as registered, returning an error if it already was.
95+ fn register ( & self , hook : ModuleHookKey ) -> Result < ( ) , ( ) > {
8696 self . registered [ hook] . set ( ( ) )
8797 }
8898
8999 /// Returns the `AbiVersion` for the given `hook`, if any.
90- fn get ( & self , hook : ModuleHook ) -> Option < AbiVersion > {
91- self . registered [ hook] . get ( ) . and ( self . abi . get ( ) . copied ( ) )
100+ fn get ( & self , hook : ModuleHookKey ) -> Option < AbiVersion > {
101+ self . registered [ hook] . get ( ) . map ( |_| self . abi )
92102 }
93103}
94104
@@ -99,7 +109,7 @@ pub(in super::super) struct HookFunction<'scope>(pub AbiVersion, pub Local<'scop
99109/// Returns the hook function previously registered in [`register_hooks`].
100110pub ( in super :: super ) fn get_hook < ' scope > (
101111 scope : & mut PinScope < ' scope , ' _ > ,
102- hook : ModuleHook ,
112+ hook : ModuleHookKey ,
103113) -> Option < HookFunction < ' scope > > {
104114 let ctx = scope. get_current_context ( ) ;
105115 let hooks = ctx. get_slot :: < HooksInfo > ( ) ?;
0 commit comments