3131use crate :: error:: throw_type_error;
3232use crate :: jsapi:: AssertSameCompartment ;
3333use crate :: jsapi:: JS ;
34- use crate :: jsapi:: { ForOfIterator , ForOfIterator_NonIterableBehavior } ;
3534use crate :: jsapi:: { Heap , JS_DefineElement , JS_GetLatin1StringCharsAndLength } ;
36- use crate :: jsapi:: { JSContext , JSObject , JSString , RootedObject , RootedValue } ;
35+ use crate :: jsapi:: { JSContext , JSObject , JSString } ;
3736use crate :: jsapi:: { JS_DeprecatedStringHasLatin1Chars , JS_NewStringCopyUTF8N , JSPROP_ENUMERATE } ;
3837use crate :: jsapi:: { JS_GetTwoByteStringCharsAndLength , NewArrayObject1 } ;
3938use crate :: jsval:: { BooleanValue , DoubleValue , Int32Value , NullValue , UInt32Value , UndefinedValue } ;
4039use crate :: jsval:: { JSVal , ObjectOrNullValue , ObjectValue , StringValue , SymbolValue } ;
4140use crate :: rooted;
41+ use crate :: rust:: for_of;
4242use crate :: rust:: maybe_wrap_value;
43+ use crate :: rust:: ForOfIterationFailure ;
4344use crate :: rust:: { maybe_wrap_object_or_null_value, maybe_wrap_object_value, ToString } ;
4445use crate :: rust:: { HandleValue , MutableHandleValue } ;
4546use crate :: rust:: { ToBoolean , ToInt32 , ToInt64 , ToNumber , ToUint16 , ToUint32 , ToUint64 } ;
4647use libc;
4748use log:: debug;
48- use mozjs_sys:: jsgc:: Rooted ;
4949use num_traits:: PrimInt ;
5050use std:: borrow:: Cow ;
5151use std:: ffi:: CStr ;
52- use std:: mem ;
52+ use std:: ops :: ControlFlow ;
5353use std:: ptr:: NonNull ;
5454use std:: rc:: Rc ;
5555use std:: { ptr, slice} ;
@@ -757,31 +757,6 @@ impl<T: ToJSValConvertible> ToJSValConvertible for Vec<T> {
757757 }
758758}
759759
760- /// Rooting guard for the iterator field of ForOfIterator.
761- /// Behaves like RootedGuard (roots on creation, unroots on drop),
762- /// but borrows and allows access to the whole ForOfIterator, so
763- /// that methods on ForOfIterator can still be used through it.
764- struct ForOfIteratorGuard < ' a > {
765- root : & ' a mut ForOfIterator ,
766- }
767-
768- impl < ' a > ForOfIteratorGuard < ' a > {
769- fn new ( cx : * mut JSContext , root : & ' a mut ForOfIterator ) -> Self {
770- unsafe {
771- Rooted :: add_to_root_stack ( & raw mut root. iterator , cx) ;
772- }
773- ForOfIteratorGuard { root }
774- }
775- }
776-
777- impl < ' a > Drop for ForOfIteratorGuard < ' a > {
778- fn drop ( & mut self ) {
779- unsafe {
780- self . root . iterator . remove_from_root_stack ( ) ;
781- }
782- }
783- }
784-
785760impl < C : Clone , T : FromJSValConvertible < Config = C > > FromJSValConvertible for Vec < T > {
786761 type Config = C ;
787762
@@ -794,57 +769,31 @@ impl<C: Clone, T: FromJSValConvertible<Config = C>> FromJSValConvertible for Vec
794769 return Ok ( ConversionResult :: Failure ( c"Value is not an object" . into ( ) ) ) ;
795770 }
796771
797- // Depending on the version of LLVM in use, bindgen can end up including
798- // a padding field in the ForOfIterator. To support multiple versions of
799- // LLVM that may not have the same fields as a result, we create an empty
800- // iterator instance and initialize a non-empty instance using the empty
801- // instance as a base value.
802- #[ allow( unused_variables) ]
803- let zero = mem:: zeroed ( ) ;
804- let mut iterator = ForOfIterator {
805- cx_ : cx,
806- iterator : RootedObject :: new_unrooted ( ptr:: null_mut ( ) ) ,
807- nextMethod : RootedValue :: new_unrooted ( JSVal { asBits_ : 0 } ) ,
808- index : :: std:: u32:: MAX , // NOT_ARRAY
809- ..zero
810- } ;
811- let iterator = ForOfIteratorGuard :: new ( cx, & mut iterator) ;
812- let iterator: & mut ForOfIterator = & mut * iterator. root ;
813-
814- if !iterator. init (
815- value. into ( ) ,
816- ForOfIterator_NonIterableBehavior :: AllowNonIterable ,
817- ) {
818- return Err ( ( ) ) ;
819- }
820-
821- if iterator. iterator . data . is_null ( ) {
822- return Ok ( ConversionResult :: Failure ( c"Value is not iterable" . into ( ) ) ) ;
823- }
772+ let mut return_value = vec ! [ ] ;
773+ let result = for_of ( cx, value, |iterator_element| {
774+ let conversion_result = T :: from_jsval ( cx, iterator_element, option. clone ( ) )
775+ . map_err ( |_| ForOfIterationFailure :: JSFailed ) ?;
776+ return_value. push ( match conversion_result {
777+ ConversionResult :: Success ( value) => value,
778+ ConversionResult :: Failure ( error) => {
779+ return Err ( ForOfIterationFailure :: Other ( error) ) ;
780+ }
781+ } ) ;
824782
825- let mut ret = vec ! [ ] ;
783+ Ok ( ControlFlow :: Continue ( ( ) ) )
784+ } ) ;
826785
827- loop {
828- let mut done = false ;
829- rooted ! ( in( cx) let mut val = UndefinedValue ( ) ) ;
830- if !iterator. next ( val. handle_mut ( ) . into ( ) , & mut done) {
831- return Err ( ( ) ) ;
786+ match result {
787+ Ok ( _) => Ok ( ConversionResult :: Success ( return_value) ) ,
788+ Err ( ForOfIterationFailure :: ValueIsNotIterable ) => {
789+ Ok ( ConversionResult :: Failure ( c"Value is not iterable" . into ( ) ) )
832790 }
833-
834- if done {
835- break ;
791+ Err ( ForOfIterationFailure :: JSFailed ) => Err ( ( ) ) ,
792+ Err ( ForOfIterationFailure :: Other ( error) ) => {
793+ throw_type_error ( cx, error. as_ref ( ) ) ;
794+ Err ( ( ) )
836795 }
837-
838- ret. push ( match T :: from_jsval ( cx, val. handle ( ) , option. clone ( ) ) ? {
839- ConversionResult :: Success ( v) => v,
840- ConversionResult :: Failure ( e) => {
841- throw_type_error ( cx, e. as_ref ( ) ) ;
842- return Err ( ( ) ) ;
843- }
844- } ) ;
845796 }
846-
847- Ok ( ret) . map ( ConversionResult :: Success )
848797 }
849798}
850799
0 commit comments