@@ -179,37 +179,53 @@ impl Plugin for RhaiScriptingPlugin {
179
179
}
180
180
}
181
181
182
- /// Load a rhai context from a script.
183
- pub fn rhai_context_load (
182
+ // NEW helper function to load content into an existing context without clearing previous definitions.
183
+ fn load_rhai_content_into_context (
184
+ context : & mut RhaiScriptContext ,
184
185
script : & ScriptId ,
185
186
content : & [ u8 ] ,
186
187
initializers : & [ ContextInitializer < RhaiScriptingPlugin > ] ,
187
188
pre_handling_initializers : & [ ContextPreHandlingInitializer < RhaiScriptingPlugin > ] ,
188
189
runtime : & mut RhaiRuntime ,
189
- ) -> Result < RhaiScriptContext , ScriptError > {
190
+ ) -> Result < ( ) , ScriptError > {
190
191
let mut ast = runtime. compile ( std:: str:: from_utf8 ( content) ?) ?;
191
192
ast. set_source ( script. to_string ( ) ) ;
192
-
193
- let mut context = RhaiScriptContext {
194
- ast,
195
- scope : Scope :: new ( ) ,
196
- } ;
197
193
initializers
198
194
. iter ( )
199
- . try_for_each ( |init| init ( script, & mut context) ) ?;
200
-
195
+ . try_for_each ( |init| init ( script, context) ) ?;
201
196
pre_handling_initializers
202
197
. iter ( )
203
- . try_for_each ( |init| init ( script, Entity :: from_raw ( 0 ) , & mut context) ) ?;
204
-
205
- runtime . eval_ast_with_scope ( & mut context . scope , & context . ast ) ? ;
206
- // do not invoke top level statements after the first time we run the script
207
- context . ast . clear_statements ( ) ;
198
+ . try_for_each ( |init| init ( script, Entity :: from_raw ( 0 ) , context) ) ?;
199
+ runtime . eval_ast_with_scope ( & mut context . scope , & ast ) ? ;
200
+ // Unlike before, do not clear statements so that definitions persist.
201
+ Ok ( ( ) )
202
+ }
208
203
204
+ /// Load a rhai context from a script.
205
+ pub fn rhai_context_load (
206
+ script : & ScriptId ,
207
+ content : & [ u8 ] ,
208
+ initializers : & [ ContextInitializer < RhaiScriptingPlugin > ] ,
209
+ pre_handling_initializers : & [ ContextPreHandlingInitializer < RhaiScriptingPlugin > ] ,
210
+ runtime : & mut RhaiRuntime ,
211
+ ) -> Result < RhaiScriptContext , ScriptError > {
212
+ let mut context = RhaiScriptContext {
213
+ // Using an empty AST as a placeholder.
214
+ ast : AST :: empty ( ) ,
215
+ scope : Scope :: new ( ) ,
216
+ } ;
217
+ load_rhai_content_into_context (
218
+ & mut context,
219
+ script,
220
+ content,
221
+ initializers,
222
+ pre_handling_initializers,
223
+ runtime,
224
+ ) ?;
209
225
Ok ( context)
210
226
}
211
227
212
- /// Reload a rhai context from a script.
228
+ /// Reload a rhai context from a script. New content is appended to the existing context.
213
229
pub fn rhai_context_reload (
214
230
script : & ScriptId ,
215
231
content : & [ u8 ] ,
@@ -218,14 +234,14 @@ pub fn rhai_context_reload(
218
234
pre_handling_initializers : & [ ContextPreHandlingInitializer < RhaiScriptingPlugin > ] ,
219
235
runtime : & mut RhaiRuntime ,
220
236
) -> Result < ( ) , ScriptError > {
221
- * context = rhai_context_load (
237
+ load_rhai_content_into_context (
238
+ context,
222
239
script,
223
240
content,
224
241
initializers,
225
242
pre_handling_initializers,
226
243
runtime,
227
- ) ?;
228
- Ok ( ( ) )
244
+ )
229
245
}
230
246
231
247
#[ allow( clippy:: too_many_arguments) ]
@@ -278,3 +294,45 @@ pub fn rhai_callback_handler(
278
294
}
279
295
}
280
296
}
297
+
298
+ #[ cfg( test) ]
299
+ mod test {
300
+ use super :: * ;
301
+
302
+ #[ test]
303
+ fn test_reload_doesnt_overwrite_old_context ( ) {
304
+ let mut runtime = RhaiRuntime :: new ( ) ;
305
+ let script_id = ScriptId :: from ( "asd.rhai" ) ;
306
+ let initializers: Vec < ContextInitializer < RhaiScriptingPlugin > > = vec ! [ ] ;
307
+ let pre_handling_initializers: Vec < ContextPreHandlingInitializer < RhaiScriptingPlugin > > =
308
+ vec ! [ ] ;
309
+
310
+ // Load first content defining a function that returns 42.
311
+ let mut context = rhai_context_load (
312
+ & script_id,
313
+ b"let hello = 2;" ,
314
+ & initializers,
315
+ & pre_handling_initializers,
316
+ & mut runtime,
317
+ )
318
+ . unwrap ( ) ;
319
+
320
+ // Reload with additional content defining a second function that returns 24.
321
+ rhai_context_reload (
322
+ & script_id,
323
+ b"let hello2 = 3" ,
324
+ & mut context,
325
+ & initializers,
326
+ & pre_handling_initializers,
327
+ & mut runtime,
328
+ )
329
+ . unwrap ( ) ;
330
+
331
+ // get first var
332
+ let hello = context. scope . get_value :: < i64 > ( "hello" ) . unwrap ( ) ;
333
+ assert_eq ! ( hello, 2 ) ;
334
+ // get second var
335
+ let hello2 = context. scope . get_value :: < i64 > ( "hello2" ) . unwrap ( ) ;
336
+ assert_eq ! ( hello2, 3 ) ;
337
+ }
338
+ }
0 commit comments