@@ -467,7 +467,7 @@ func TestCallWithNull(t *testing.T) {
467
467
func TestReflection (t * testing.T ) {
468
468
o := js .Global .Call ("eval" , "({ answer: 42 })" )
469
469
if reflect .ValueOf (o ).Interface ().(* js.Object ) != o {
470
- t .Fail ()
470
+ t .Fatal ()
471
471
}
472
472
473
473
type S struct {
@@ -477,18 +477,19 @@ func TestReflection(t *testing.T) {
477
477
478
478
v := reflect .ValueOf (& s ).Elem ()
479
479
if v .Field (0 ).Interface ().(* js.Object ).Get ("answer" ).Int () != 42 {
480
- t .Fail ()
480
+ t .Fatal ()
481
481
}
482
482
if v .Field (0 ).MethodByName ("Get" ).Call ([]reflect.Value {reflect .ValueOf ("answer" )})[0 ].Interface ().(* js.Object ).Int () != 42 {
483
- t .Fail ()
483
+ t .Fatal ()
484
484
}
485
485
v .Field (0 ).Set (reflect .ValueOf (js .Global .Call ("eval" , "({ answer: 100 })" )))
486
486
if s .Field .Get ("answer" ).Int () != 100 {
487
- t .Fail ()
487
+ t .Fatal ()
488
488
}
489
489
490
- if fmt .Sprintf ("%+v" , s ) != "{Field:[object Object]}" {
491
- t .Fail ()
490
+ expFmt := "{Field:[object Object]}"
491
+ if v := fmt .Sprintf ("%+v" , s ); v != expFmt {
492
+ t .Fatalf ("fmt out was: %q; expected %q" , v , expFmt )
492
493
}
493
494
}
494
495
@@ -620,3 +621,207 @@ func TestStructWithNonIdentifierJSTag(t *testing.T) {
620
621
t .Errorf ("value via js.Object.Get gave %q, want %q" , got , want )
621
622
}
622
623
}
624
+
625
+ // Internalize is used as a helper type to test $internalize. A struct is used
626
+ // in order that all of the Go types can be verified (otherwise we are limited
627
+ // to the methods on *Object). Where methods on *Object exist they too will be
628
+ // tested
629
+ type Internalize struct {
630
+ * js.Object
631
+
632
+ string string `js:"string"`
633
+ bool bool `js:"bool"`
634
+ }
635
+
636
+ func TestInternalizeString (t * testing.T ) {
637
+ fieldName := "string"
638
+ zero := ""
639
+
640
+ s := & Internalize {Object : js .Global .Get ("Object" ).New ()}
641
+
642
+ // *************
643
+ // undefined
644
+ // *************
645
+ s .Object .Set (fieldName , jsundefined ())
646
+
647
+ // via struct field
648
+ if v := s .string ; v != zero {
649
+ t .Fatalf ("expected string field to be %q, got %q" , zero , v )
650
+ }
651
+
652
+ // via *js.Object.String()
653
+ if v := s .Object .Get (fieldName ).String (); v != zero {
654
+ t .Fatalf ("expected string field via *js.Object.String() to be %q, got %q" , zero , v )
655
+ }
656
+
657
+ // *************
658
+ // null
659
+ // *************
660
+ s .Object .Set (fieldName , jsnull ())
661
+
662
+ // via struct field
663
+ if v := s .string ; v != zero {
664
+ t .Fatalf ("expected string field to be %q, got %q" , zero , v )
665
+ }
666
+
667
+ // via *js.Object.String()
668
+ if v := s .Object .Get (fieldName ).String (); v != zero {
669
+ t .Fatalf ("expected string field via *js.Object.String() to be %q, got %q" , zero , v )
670
+ }
671
+
672
+ // *************
673
+ // valid primitive string
674
+ // *************
675
+ exp := "ok"
676
+ s .Object .Set (fieldName , jsval (`"` + exp + `"` ))
677
+
678
+ // via struct field
679
+ if v := s .string ; v != exp {
680
+ t .Fatalf ("expected string field to be %q, got %q" , zero , v )
681
+ }
682
+
683
+ // via *js.Object.String()
684
+ if v := s .Object .Get (fieldName ).String (); v != exp {
685
+ t .Fatalf ("expected string field via *js.Object.String() to be %q, got %q" , zero , v )
686
+ }
687
+
688
+ // *************
689
+ // valid String object
690
+ // *************
691
+ s .Object .Set (fieldName , jsval (`new String("` + exp + `")` ))
692
+
693
+ // via struct field
694
+ if v := s .string ; v != exp {
695
+ t .Fatalf ("expected string field to be %q, got %q" , zero , v )
696
+ }
697
+
698
+ // via *js.Object.String()
699
+ if v := s .Object .Get (fieldName ).String (); v != exp {
700
+ t .Fatalf ("expected string field via *js.Object.String() to be %q, got %q" , zero , v )
701
+ }
702
+
703
+ // *************
704
+ // invalid
705
+ // *************
706
+ s .Object .Set (fieldName , jsval ("5" ))
707
+
708
+ shouldRuntimePanic (t , "runtime error: tried to internalize non-string value of type number/Number" , func () {
709
+ _ = s .string
710
+ })
711
+
712
+ shouldRuntimePanic (t , "runtime error: tried to internalize non-string value of type number/Number" , func () {
713
+ _ = s .Object .Get (fieldName ).String ()
714
+ })
715
+ }
716
+
717
+ func TestInternalizeBool (t * testing.T ) {
718
+ fieldName := "bool"
719
+ zero := false
720
+
721
+ s := & Internalize {Object : js .Global .Get ("Object" ).New ()}
722
+
723
+ // *************
724
+ // undefined
725
+ // *************
726
+ s .Object .Set (fieldName , jsundefined ())
727
+
728
+ // via struct field
729
+ if v := s .bool ; v != zero {
730
+ t .Fatalf ("expected bool field to be %q, got %q" , zero , v )
731
+ }
732
+
733
+ // via *js.Object.Bool()
734
+ if v := s .Object .Get (fieldName ).Bool (); v != zero {
735
+ t .Fatalf ("expected bool field via *js.Object.Bool() to be %q, got %q" , zero , v )
736
+ }
737
+
738
+ // *************
739
+ // null
740
+ // *************
741
+ s .Object .Set (fieldName , jsnull ())
742
+
743
+ // via struct field
744
+ if v := s .bool ; v != zero {
745
+ t .Fatalf ("expected bool field to be %q, got %q" , zero , v )
746
+ }
747
+
748
+ // via *js.Object.Bool()
749
+ if v := s .Object .Get (fieldName ).Bool (); v != zero {
750
+ t .Fatalf ("expected bool field via *js.Object.Bool() to be %q, got %q" , zero , v )
751
+ }
752
+
753
+ // *************
754
+ // valid primitive bool
755
+ // *************
756
+ exp := true
757
+ s .Object .Set (fieldName , jsval (`true` ))
758
+
759
+ // via struct field
760
+ if v := s .bool ; v != exp {
761
+ t .Fatalf ("expected bool field to be %v, got %v" , exp , v )
762
+ }
763
+
764
+ // via *js.Object.Bool()
765
+ if v := s .Object .Get (fieldName ).Bool (); v != exp {
766
+ t .Fatalf ("expected bool field via *js.Object.Bool() to be %q, got %q" , zero , v )
767
+ }
768
+
769
+ // *************
770
+ // valid Bool object
771
+ // *************
772
+ s .Object .Set (fieldName , jsval (`new Boolean(true)` ))
773
+
774
+ // via struct field
775
+ if v := s .bool ; v != exp {
776
+ t .Fatalf ("expected bool field to be %q, got %q" , zero , v )
777
+ }
778
+
779
+ // via *js.Object.Bool()
780
+ if v := s .Object .Get (fieldName ).Bool (); v != exp {
781
+ t .Fatalf ("expected bool field via *js.Object.Bool() to be %q, got %q" , zero , v )
782
+ }
783
+
784
+ // *************
785
+ // invalid
786
+ // *************
787
+ s .Object .Set (fieldName , jsval ("5" ))
788
+
789
+ shouldRuntimePanic (t , "runtime error: tried to internalize non-bool value of type number/Number" , func () {
790
+ _ = s .bool
791
+ })
792
+
793
+ shouldRuntimePanic (t , "runtime error: tried to internalize non-bool value of type number/Number" , func () {
794
+ _ = s .Object .Get (fieldName ).Bool ()
795
+ })
796
+ }
797
+
798
+ func jsval (v string ) * js.Object {
799
+ return js .Global .Call ("eval" , v )
800
+ }
801
+
802
+ func jsnull () * js.Object {
803
+ return js .Global .Call ("eval" , "null" )
804
+ }
805
+
806
+ func jsundefined () * js.Object {
807
+ return js .Global .Call ("eval" , "undefined" )
808
+ }
809
+
810
+ func consolelog (args ... interface {}) {
811
+ js .Global .Get ("console" ).Call ("log" , args ... )
812
+ }
813
+
814
+ func shouldRuntimePanic (t * testing.T , msg string , f func ()) {
815
+ defer func () {
816
+ err , ok := recover ().(error )
817
+ if ! ok {
818
+ t .Fatalf ("expected to have had to handle panic; we didn't see a panic" )
819
+ }
820
+
821
+ if err .Error () != msg {
822
+ t .Fatalf ("expected error %q, got %q" , msg , err )
823
+ }
824
+ }()
825
+
826
+ f ()
827
+ }
0 commit comments