1#[cfg(feature = "std")]
2mod multi_threaded;
3mod single_threaded;
4
5use alloc::{boxed::Box, vec, vec::Vec};
6use bevy_utils::prelude::DebugName;
7use core::any::TypeId;
8
9pub use self::single_threaded::SingleThreadedExecutor;
10
11#[cfg(feature = "std")]
12pub use self::multi_threaded::{MainThreadExecutor, MultiThreadedExecutor};
13
14pub use fixedbitset::FixedBitSet;
15
16use crate::{
17 change_detection::{CheckChangeTicks, Tick},
18 error::{BevyError, ErrorContext, Result},
19 prelude::{IntoSystemSet, SystemSet},
20 query::FilteredAccessSet,
21 schedule::{
22 ConditionWithAccess, InternedSystemSet, SystemKey, SystemSetKey, SystemTypeSet,
23 SystemWithAccess,
24 },
25 system::{RunSystemError, System, SystemIn, SystemStateFlags},
26 world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, World},
27};
28
29pub trait SystemExecutor: Send + Sync {
31 fn init(&mut self, schedule: &SystemSchedule);
33 fn run(
35 &mut self,
36 schedule: &mut SystemSchedule,
37 world: &mut World,
38 skip_systems: Option<&FixedBitSet>,
39 error_handler: fn(BevyError, ErrorContext),
40 );
41 fn set_apply_final_deferred(&mut self, value: bool);
43}
44
45pub fn default_executor() -> Box<dyn SystemExecutor> {
50 #[cfg(all(
51 not(target_arch = "wasm32"),
52 feature = "std",
53 feature = "multi_threaded"
54 ))]
55 {
56 Box::new(MultiThreadedExecutor::new())
57 }
58 #[cfg(any(
59 target_arch = "wasm32",
60 not(feature = "std"),
61 not(feature = "multi_threaded")
62 ))]
63 {
64 Box::new(SingleThreadedExecutor::new())
65 }
66}
67
68#[derive(Default)]
74pub struct SystemSchedule {
75 pub(super) system_ids: Vec<SystemKey>,
77 pub(super) systems: Vec<SystemWithAccess>,
79 pub(super) system_conditions: Vec<Vec<ConditionWithAccess>>,
81 #[cfg_attr(
84 not(feature = "std"),
85 expect(dead_code, reason = "currently only used with the std feature")
86 )]
87 pub(super) system_dependencies: Vec<usize>,
88 #[cfg_attr(
91 not(feature = "std"),
92 expect(dead_code, reason = "currently only used with the std feature")
93 )]
94 pub(super) system_dependents: Vec<Vec<usize>>,
95 pub(super) sets_with_conditions_of_systems: Vec<FixedBitSet>,
98 pub(super) set_ids: Vec<SystemSetKey>,
100 pub(super) set_conditions: Vec<Vec<ConditionWithAccess>>,
102 pub(super) systems_in_sets_with_conditions: Vec<FixedBitSet>,
107}
108
109impl SystemSchedule {
110 pub const fn new() -> Self {
112 Self {
113 systems: Vec::new(),
114 system_conditions: Vec::new(),
115 set_conditions: Vec::new(),
116 system_ids: Vec::new(),
117 set_ids: Vec::new(),
118 system_dependencies: Vec::new(),
119 system_dependents: Vec::new(),
120 sets_with_conditions_of_systems: Vec::new(),
121 systems_in_sets_with_conditions: Vec::new(),
122 }
123 }
124
125 pub unsafe fn systems_mut(&mut self) -> &mut Vec<SystemWithAccess> {
131 &mut self.systems
132 }
133}
134
135#[doc(alias = "apply_system_buffers")]
160pub struct ApplyDeferred;
161
162pub(super) fn is_apply_deferred(system: &dyn System<In = (), Out = ()>) -> bool {
164 system.system_type() == TypeId::of::<ApplyDeferred>()
165}
166
167impl System for ApplyDeferred {
168 type In = ();
169 type Out = ();
170
171 fn name(&self) -> DebugName {
172 DebugName::borrowed("bevy_ecs::apply_deferred")
173 }
174
175 fn flags(&self) -> SystemStateFlags {
176 SystemStateFlags::NON_SEND | SystemStateFlags::EXCLUSIVE
178 }
179
180 unsafe fn run_unsafe(
181 &mut self,
182 _input: SystemIn<'_, Self>,
183 _world: UnsafeWorldCell,
184 ) -> Result<Self::Out, RunSystemError> {
185 Ok(())
188 }
189
190 #[cfg(feature = "hotpatching")]
191 #[inline]
192 fn refresh_hotpatch(&mut self) {}
193
194 fn run(
195 &mut self,
196 _input: SystemIn<'_, Self>,
197 _world: &mut World,
198 ) -> Result<Self::Out, RunSystemError> {
199 Ok(())
202 }
203
204 fn apply_deferred(&mut self, _world: &mut World) {}
205
206 fn queue_deferred(&mut self, _world: DeferredWorld) {}
207
208 fn initialize(&mut self, _world: &mut World) -> FilteredAccessSet {
209 FilteredAccessSet::new()
210 }
211
212 fn check_change_tick(&mut self, _check: CheckChangeTicks) {}
213
214 fn default_system_sets(&self) -> Vec<InternedSystemSet> {
215 vec![SystemTypeSet::<Self>::new().intern()]
216 }
217
218 fn get_last_run(&self) -> Tick {
219 Tick::MAX
221 }
222
223 fn set_last_run(&mut self, _last_run: Tick) {}
224}
225
226impl IntoSystemSet<()> for ApplyDeferred {
227 type Set = SystemTypeSet<Self>;
228
229 fn into_system_set(self) -> Self::Set {
230 SystemTypeSet::<Self>::new()
231 }
232}
233
234mod __rust_begin_short_backtrace {
243 use core::hint::black_box;
244
245 #[cfg(feature = "std")]
246 use crate::world::unsafe_world_cell::UnsafeWorldCell;
247 use crate::{
248 error::Result,
249 system::{ReadOnlySystem, RunSystemError, ScheduleSystem},
250 world::World,
251 };
252
253 #[cfg(feature = "std")]
257 #[inline(never)]
258 pub(super) unsafe fn run_unsafe(
259 system: &mut ScheduleSystem,
260 world: UnsafeWorldCell,
261 ) -> Result<(), RunSystemError> {
262 let result = unsafe { system.run_unsafe((), world) };
264 black_box(());
266 result
267 }
268
269 #[cfg(feature = "std")]
273 #[inline(never)]
274 pub(super) unsafe fn readonly_run_unsafe<O: 'static>(
275 system: &mut dyn ReadOnlySystem<In = (), Out = O>,
276 world: UnsafeWorldCell,
277 ) -> Result<O, RunSystemError> {
278 black_box(unsafe { system.run_unsafe((), world) })
281 }
282
283 #[cfg(feature = "std")]
284 #[inline(never)]
285 pub(super) fn run(
286 system: &mut ScheduleSystem,
287 world: &mut World,
288 ) -> Result<(), RunSystemError> {
289 let result = system.run((), world);
290 black_box(());
292 result
293 }
294
295 #[inline(never)]
296 pub(super) fn run_without_applying_deferred(
297 system: &mut ScheduleSystem,
298 world: &mut World,
299 ) -> Result<(), RunSystemError> {
300 let result = system.run_without_applying_deferred((), world);
301 black_box(());
303 result
304 }
305
306 #[inline(never)]
307 pub(super) fn readonly_run<O: 'static>(
308 system: &mut dyn ReadOnlySystem<In = (), Out = O>,
309 world: &mut World,
310 ) -> Result<O, RunSystemError> {
311 black_box(system.run((), world))
313 }
314}
315
316#[cfg(test)]
317mod tests {
318 use crate::{
319 prelude::{Component, In, IntoSystem, Resource, Schedule},
320 schedule::{MultiThreadedExecutor, SingleThreadedExecutor},
321 system::{Populated, Res, ResMut, Single},
322 world::World,
323 };
324
325 #[derive(Component)]
326 struct TestComponent;
327
328 #[derive(Resource, Default)]
329 struct TestState {
330 populated_ran: bool,
331 single_ran: bool,
332 }
333
334 #[derive(Resource, Default)]
335 struct Counter(u8);
336
337 fn set_single_state(mut _single: Single<&TestComponent>, mut state: ResMut<TestState>) {
338 state.single_ran = true;
339 }
340
341 fn set_populated_state(
342 mut _populated: Populated<&TestComponent>,
343 mut state: ResMut<TestState>,
344 ) {
345 state.populated_ran = true;
346 }
347
348 #[test]
349 fn single_and_populated_skipped_and_run_singlethreaded() {
350 let mut schedule = Schedule::default();
351 schedule.set_executor(SingleThreadedExecutor::new());
352 single_and_populated_skipped_and_run("SingleThreaded", schedule);
353 }
354
355 #[test]
356 fn single_and_populated_skipped_and_run_multithreaded() {
357 let mut schedule = Schedule::default();
358 schedule.set_executor(MultiThreadedExecutor::new());
359 single_and_populated_skipped_and_run("MultiThreaded", schedule);
360 }
361
362 #[expect(clippy::print_stdout, reason = "std and println are allowed in tests")]
363 fn single_and_populated_skipped_and_run(name: &str, mut schedule: Schedule) {
364 std::println!("Testing executor: {name}");
365
366 let mut world = World::new();
367 world.init_resource::<TestState>();
368
369 schedule.add_systems((set_single_state, set_populated_state));
370 schedule.run(&mut world);
371
372 let state = world.get_resource::<TestState>().unwrap();
373 assert!(!state.single_ran);
374 assert!(!state.populated_ran);
375
376 world.spawn(TestComponent);
377
378 schedule.run(&mut world);
379 let state = world.get_resource::<TestState>().unwrap();
380 assert!(state.single_ran);
381 assert!(state.populated_ran);
382 }
383
384 fn look_for_missing_resource(_res: Res<TestState>) {}
385
386 #[test]
387 #[should_panic]
388 fn missing_resource_panics_single_threaded() {
389 let mut world = World::new();
390 let mut schedule = Schedule::default();
391
392 schedule.set_executor(SingleThreadedExecutor::new());
393 schedule.add_systems(look_for_missing_resource);
394 schedule.run(&mut world);
395 }
396
397 #[test]
398 #[should_panic]
399 fn missing_resource_panics_multi_threaded() {
400 let mut world = World::new();
401 let mut schedule = Schedule::default();
402
403 schedule.set_executor(MultiThreadedExecutor::new());
404 schedule.add_systems(look_for_missing_resource);
405 schedule.run(&mut world);
406 }
407
408 #[test]
409 fn piped_systems_first_system_skipped() {
410 fn pipe_out(_single: Single<&TestComponent>) -> u8 {
412 42
413 }
414
415 fn pipe_in(_input: In<u8>, mut counter: ResMut<Counter>) {
416 counter.0 += 1;
417 }
418
419 let mut world = World::new();
420 world.init_resource::<Counter>();
421 let mut schedule = Schedule::default();
422
423 schedule.add_systems(pipe_out.pipe(pipe_in));
424 schedule.run(&mut world);
425
426 let counter = world.resource::<Counter>();
427 assert_eq!(counter.0, 0);
428 }
429
430 #[test]
431 fn piped_system_second_system_skipped() {
432 fn pipe_out(mut counter: ResMut<Counter>) -> u8 {
434 counter.0 += 1;
435 42
436 }
437
438 fn pipe_in(_input: In<u8>, _single: Single<&TestComponent>, mut counter: ResMut<Counter>) {
440 counter.0 += 1;
441 }
442
443 let mut world = World::new();
444 world.init_resource::<Counter>();
445 let mut schedule = Schedule::default();
446
447 schedule.add_systems(pipe_out.pipe(pipe_in));
448 schedule.run(&mut world);
449 let counter = world.resource::<Counter>();
450 assert_eq!(counter.0, 1);
451 }
452
453 #[test]
454 #[should_panic]
455 fn piped_system_first_system_panics() {
456 fn pipe_out(_res: Res<TestState>) -> u8 {
458 42
459 }
460
461 fn pipe_in(_input: In<u8>) {}
462
463 let mut world = World::new();
464 let mut schedule = Schedule::default();
465
466 schedule.add_systems(pipe_out.pipe(pipe_in));
467 schedule.run(&mut world);
468 }
469
470 #[test]
471 #[should_panic]
472 fn piped_system_second_system_panics() {
473 fn pipe_out() -> u8 {
474 42
475 }
476
477 fn pipe_in(_input: In<u8>, _res: Res<TestState>) {}
479
480 let mut world = World::new();
481 let mut schedule = Schedule::default();
482
483 schedule.add_systems(pipe_out.pipe(pipe_in));
484 schedule.run(&mut world);
485 }
486
487 #[test]
490 fn piped_system_skip_and_panic() {
491 fn pipe_out(_single: Single<&TestComponent>) -> u8 {
493 42
494 }
495
496 fn pipe_in(_input: In<u8>, _res: Res<TestState>) {}
498
499 let mut world = World::new();
500 let mut schedule = Schedule::default();
501
502 schedule.add_systems(pipe_out.pipe(pipe_in));
503 schedule.run(&mut world);
504 }
505
506 #[test]
507 #[should_panic]
508 fn piped_system_panic_and_skip() {
509 fn pipe_out(_res: Res<TestState>) -> u8 {
512 42
513 }
514
515 fn pipe_in(_input: In<u8>, _single: Single<&TestComponent>) {}
517
518 let mut world = World::new();
519 let mut schedule = Schedule::default();
520
521 schedule.add_systems(pipe_out.pipe(pipe_in));
522 schedule.run(&mut world);
523 }
524
525 #[test]
526 #[should_panic]
527 fn piped_system_panic_and_panic() {
528 fn pipe_out(_res: Res<TestState>) -> u8 {
531 42
532 }
533
534 fn pipe_in(_input: In<u8>, _res: Res<TestState>) {}
536
537 let mut world = World::new();
538 let mut schedule = Schedule::default();
539
540 schedule.add_systems(pipe_out.pipe(pipe_in));
541 schedule.run(&mut world);
542 }
543
544 #[test]
545 fn piped_system_skip_and_skip() {
546 fn pipe_out(_single: Single<&TestComponent>, mut counter: ResMut<Counter>) -> u8 {
549 counter.0 += 1;
550 42
551 }
552
553 fn pipe_in(_input: In<u8>, _single: Single<&TestComponent>, mut counter: ResMut<Counter>) {
555 counter.0 += 1;
556 }
557
558 let mut world = World::new();
559 world.init_resource::<Counter>();
560 let mut schedule = Schedule::default();
561
562 schedule.add_systems(pipe_out.pipe(pipe_in));
563 schedule.run(&mut world);
564
565 let counter = world.resource::<Counter>();
566 assert_eq!(counter.0, 0);
567 }
568}
569
570#[cfg(test)]
571mod validation_tests {
572 use crate::{
573 prelude::{Component, In, IntoSystem, Resource, Schedule},
574 schedule::{MultiThreadedExecutor, SingleThreadedExecutor},
575 system::{
576 DynParamBuilder, DynSystemParam, ExclusiveSystemParam, Local, ParamBuilder, ParamSet,
577 Query, Res, ResMut, RunSystemError, RunSystemOnce, Single, SystemMeta,
578 SystemParamBuilder, SystemParamValidationError,
579 },
580 world::World,
581 };
582
583 #[derive(Component)]
584 struct TestComponent;
585
586 #[derive(Resource, Default)]
587 struct Counter(u8);
588
589 #[derive(Resource)]
591 struct MissingResource;
592
593 struct AlwaysInvalid;
595
596 impl ExclusiveSystemParam for AlwaysInvalid {
597 type State = ();
598 type Item<'s> = AlwaysInvalid;
599
600 fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
601
602 fn get_param<'s>(
603 _state: &'s mut Self::State,
604 _system_meta: &SystemMeta,
605 ) -> Result<Self::Item<'s>, SystemParamValidationError> {
606 Err(SystemParamValidationError::invalid::<Self>(
607 "always invalid",
608 ))
609 }
610 }
611
612 #[test]
613 fn function_system_validation_failure_is_error() {
614 fn system(_res: Res<MissingResource>) {}
615
616 let mut world = World::new();
617 let result = world.run_system_once(system);
618 assert!(
619 matches!(result, Err(RunSystemError::Failed(_))),
620 "Expected Failed, got {result:?}"
621 );
622 }
623
624 #[test]
625 fn function_system_validation_skip() {
626 fn system(_single: Single<&TestComponent>) {}
627
628 let mut world = World::new();
629 let result = world.run_system_once(system);
630 assert!(
631 matches!(result, Err(RunSystemError::Skipped(_))),
632 "Expected Skipped, got {result:?}"
633 );
634 }
635
636 #[test]
637 fn function_system_validation_success() {
638 fn system(_res: Res<Counter>) {}
639
640 let mut world = World::new();
641 world.init_resource::<Counter>();
642 let result = world.run_system_once(system);
643 assert!(result.is_ok(), "Expected Ok, got {result:?}");
644 }
645
646 #[test]
647 fn adapter_system_validation_failure() {
648 fn system(_res: Res<MissingResource>) -> u32 {
649 42
650 }
651
652 let mut world = World::new();
653 let result = world.run_system_once(system.map(|_x| {}));
654 assert!(
655 matches!(result, Err(RunSystemError::Failed(_))),
656 "Expected Failed from adapter system, got {result:?}"
657 );
658 }
659
660 #[test]
661 fn adapter_system_validation_skip() {
662 fn system(_single: Single<&TestComponent>) -> u32 {
663 42
664 }
665
666 let mut world = World::new();
667 let result = world.run_system_once(system.map(|_x| {}));
668 assert!(
669 matches!(result, Err(RunSystemError::Skipped(_))),
670 "Expected Skipped from adapter system, got {result:?}"
671 );
672 }
673
674 #[test]
675 fn pipe_system_validation_failure_in_first() {
676 fn first(_res: Res<MissingResource>) -> u32 {
677 42
678 }
679 fn second(_input: In<u32>) {}
680
681 let mut world = World::new();
682 let result = world.run_system_once(first.pipe(second));
683 assert!(
684 matches!(result, Err(RunSystemError::Failed(_))),
685 "Expected Failed from pipe first system, got {result:?}"
686 );
687 }
688
689 #[test]
690 fn pipe_system_validation_failure_in_second() {
691 fn first() -> u32 {
692 42
693 }
694 fn second(_input: In<u32>, _res: Res<MissingResource>) {}
695
696 let mut world = World::new();
697 let result = world.run_system_once(first.pipe(second));
698 assert!(
699 matches!(result, Err(RunSystemError::Failed(_))),
700 "Expected Failed from pipe second system, got {result:?}"
701 );
702 }
703
704 #[test]
705 fn pipe_system_validation_skip_in_first() {
706 fn first(_single: Single<&TestComponent>) -> u32 {
707 42
708 }
709 fn second(_input: In<u32>) {}
710
711 let mut world = World::new();
712 let result = world.run_system_once(first.pipe(second));
713 assert!(
714 matches!(result, Err(RunSystemError::Skipped(_))),
715 "Expected Skipped from pipe first system, got {result:?}"
716 );
717 }
718
719 #[test]
720 fn pipe_system_validation_skip_in_second() {
721 fn first() -> u32 {
722 42
723 }
724
725 fn second(_input: In<u32>, _single: Single<&TestComponent>) {}
726
727 let mut world = World::new();
728 let result = world.run_system_once(first.pipe(second));
729 assert!(
730 matches!(result, Err(RunSystemError::Skipped(_))),
731 "Expected Skipped from pipe second system, got {result:?}"
732 );
733 }
734
735 #[test]
736 fn builder_system_validation_failure() {
737 fn system(_res: Res<MissingResource>) {}
738
739 let mut world = World::new();
740 let result = world.run_system_once(ParamBuilder.build_system(system));
741 assert!(
742 matches!(result, Err(RunSystemError::Failed(_))),
743 "Expected Failed from builder system, got {result:?}"
744 );
745 }
746
747 #[test]
748 fn builder_system_validation_skip() {
749 fn system(_single: Single<&TestComponent>) {}
750
751 let mut world = World::new();
752 let result = world.run_system_once(ParamBuilder.build_system(system));
753 assert!(
754 matches!(result, Err(RunSystemError::Skipped(_))),
755 "Expected Skipped from builder system, got {result:?}"
756 );
757 }
758
759 #[test]
760 fn dyn_system_param_validation_failure() {
761 let mut world = World::new();
762 let system = (DynParamBuilder::new::<Res<MissingResource>>(ParamBuilder),)
763 .build_state(&mut world)
764 .build_system(|_param: DynSystemParam| {});
765 let result = world.run_system_once(system);
766 assert!(
767 matches!(result, Err(RunSystemError::Failed(_))),
768 "Expected Failed from DynSystemParam system, got {result:?}"
769 );
770 }
771
772 #[test]
773 fn dyn_system_param_validation_skip() {
774 let mut world = World::new();
775 let system = (DynParamBuilder::new::<Single<&TestComponent>>(ParamBuilder),)
776 .build_state(&mut world)
777 .build_system(|_param: DynSystemParam| {});
778 let result = world.run_system_once(system);
779 assert!(
780 matches!(result, Err(RunSystemError::Skipped(_))),
781 "Expected Skipped from DynSystemParam system, got {result:?}"
782 );
783 }
784
785 #[test]
786 fn dyn_system_param_validation_success() {
787 let mut world = World::new();
788 world.init_resource::<Counter>();
789 let system = (DynParamBuilder::new::<Res<Counter>>(ParamBuilder),)
790 .build_state(&mut world)
791 .build_system(|_param: DynSystemParam| {});
792 let result = world.run_system_once(system);
793 assert!(
794 result.is_ok(),
795 "Expected Ok from DynSystemParam system, got {result:?}"
796 );
797 }
798
799 #[test]
800 fn exclusive_system_validation_failure() {
801 fn system(_world: &mut World, _param: AlwaysInvalid) {}
802
803 let mut world = World::new();
804 let result = world.run_system_once(system);
805 assert!(
806 matches!(result, Err(RunSystemError::Failed(_))),
807 "Expected Failed from exclusive system, got {result:?}"
808 );
809 }
810
811 #[test]
812 fn exclusive_system_validation_success() {
813 fn system(_world: &mut World, mut _local: Local<u32>) {}
814
815 let mut world = World::new();
816 let result = world.run_system_once(system);
817 assert!(
818 result.is_ok(),
819 "Expected Ok from exclusive system, got {result:?}"
820 );
821 }
822
823 #[test]
824 fn validation_skips_system_in_schedule_singlethreaded() {
825 let mut schedule = Schedule::default();
826 schedule.set_executor(SingleThreadedExecutor::new());
827 validation_skips_system_in_schedule("SingleThreaded", schedule);
828 }
829
830 #[test]
831 fn validation_skips_system_in_schedule_multithreaded() {
832 let mut schedule = Schedule::default();
833 schedule.set_executor(MultiThreadedExecutor::new());
834 validation_skips_system_in_schedule("MultiThreaded", schedule);
835 }
836
837 fn validation_skips_system_in_schedule(name: &str, mut schedule: Schedule) {
838 fn skippable_system(_single: Single<&TestComponent>, mut counter: ResMut<Counter>) {
841 counter.0 += 1;
842 }
843
844 let mut world = World::new();
845 world.init_resource::<Counter>();
846
847 schedule.add_systems(skippable_system);
848
849 schedule.run(&mut world);
851 assert_eq!(
852 world.resource::<Counter>().0,
853 0,
854 "System should have been skipped with {name}"
855 );
856 }
857
858 #[test]
859 fn param_set_validation_skip() {
860 fn system(mut _set: ParamSet<(Single<&TestComponent>,)>) {}
863
864 let mut world = World::new();
865 let result = world.run_system_once(system);
866 assert!(
867 matches!(result, Err(RunSystemError::Skipped(_))),
868 "Expected Skipped from ParamSet with invalid Single, got {result:?}"
869 );
870 }
871
872 #[test]
873 fn param_set_validation_failure() {
874 fn system(mut _set: ParamSet<(Query<&TestComponent>, Res<MissingResource>)>) {}
877
878 let mut world = World::new();
879 let result = world.run_system_once(system);
880 assert!(
881 matches!(result, Err(RunSystemError::Failed(_))),
882 "Expected Failed from ParamSet with missing resource, got {result:?}"
883 );
884 }
885
886 #[test]
887 fn param_set_validation_success() {
888 fn system(mut set: ParamSet<(Query<&TestComponent>, Res<Counter>)>) {
890 let _q = set.p0();
891 }
892
893 let mut world = World::new();
894 world.init_resource::<Counter>();
895 let result = world.run_system_once(system);
896 assert!(
897 result.is_ok(),
898 "Expected Ok from ParamSet with valid params, got {result:?}"
899 );
900 }
901}