github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/string_test.go (about)

     1  package goja
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  	"unicode/utf16"
     7  )
     8  
     9  func TestStringOOBProperties(t *testing.T) {
    10  	const SCRIPT = `
    11  	var string = new String("str");
    12  	
    13  	string[4] = 1;
    14  	string[4];
    15  	`
    16  
    17  	testScript(SCRIPT, valueInt(1), t)
    18  }
    19  
    20  func TestImportedString(t *testing.T) {
    21  	vm := New()
    22  
    23  	testUnaryOp := func(a, expr string, result interface{}, t *testing.T) {
    24  		v, err := vm.RunString("a => " + expr)
    25  		if err != nil {
    26  			t.Fatal(err)
    27  		}
    28  		var fn func(a Value) (Value, error)
    29  		err = vm.ExportTo(v, &fn)
    30  		if err != nil {
    31  			t.Fatal(err)
    32  		}
    33  		for _, aa := range []Value{newStringValue(a), vm.ToValue(a)} {
    34  			res, err := fn(aa)
    35  			if err != nil {
    36  				t.Fatal(err)
    37  			}
    38  			if res.Export() != result {
    39  				t.Fatalf("%s, a:%v(%T). expected: %v, actual: %v", expr, aa, aa, result, res)
    40  			}
    41  		}
    42  	}
    43  
    44  	testBinaryOp := func(a, b, expr string, result interface{}, t *testing.T) {
    45  		v, err := vm.RunString("(a, b) => " + expr)
    46  		if err != nil {
    47  			t.Fatal(err)
    48  		}
    49  		var fn func(a, b Value) (Value, error)
    50  		err = vm.ExportTo(v, &fn)
    51  		if err != nil {
    52  			t.Fatal(err)
    53  		}
    54  		for _, aa := range []Value{newStringValue(a), vm.ToValue(a)} {
    55  			for _, bb := range []Value{newStringValue(b), vm.ToValue(b)} {
    56  				res, err := fn(aa, bb)
    57  				if err != nil {
    58  					t.Fatal(err)
    59  				}
    60  				if res.Export() != result {
    61  					t.Fatalf("%s, a:%v(%T), b:%v(%T). expected: %v, actual: %v", expr, aa, aa, bb, bb, result, res)
    62  				}
    63  			}
    64  		}
    65  	}
    66  
    67  	strs := []string{"shortAscii", "longlongAscii1234567890123456789", "short юникод", "long юникод 1234567890 юникод \U0001F600", "юникод", "Ascii", "long", "код"}
    68  	indexOfResults := [][]int{
    69  		/*
    70  			const strs = ["shortAscii", "longlongAscii1234567890123456789", "short юникод", "long юникод 1234567890 юникод \u{1F600}", "юникод", "Ascii", "long", "код"];
    71  
    72  			strs.forEach(a => {
    73  			    console.log("{", strs.map(b => a.indexOf(b)).join(", "), "},");
    74  			});
    75  		*/
    76  		{0, -1, -1, -1, -1, 5, -1, -1},
    77  		{-1, 0, -1, -1, -1, 8, 0, -1},
    78  		{-1, -1, 0, -1, 6, -1, -1, 9},
    79  		{-1, -1, -1, 0, 5, -1, 0, 8},
    80  		{-1, -1, -1, -1, 0, -1, -1, 3},
    81  		{-1, -1, -1, -1, -1, 0, -1, -1},
    82  		{-1, -1, -1, -1, -1, -1, 0, -1},
    83  		{-1, -1, -1, -1, -1, -1, -1, 0},
    84  	}
    85  
    86  	lastIndexOfResults := [][]int{
    87  		/*
    88  			strs.forEach(a => {
    89  			    console.log("{", strs.map(b => a.lastIndexOf(b)).join(", "), "},");
    90  			});
    91  		*/
    92  		{0, -1, -1, -1, -1, 5, -1, -1},
    93  		{-1, 0, -1, -1, -1, 8, 4, -1},
    94  		{-1, -1, 0, -1, 6, -1, -1, 9},
    95  		{-1, -1, -1, 0, 23, -1, 0, 26},
    96  		{-1, -1, -1, -1, 0, -1, -1, 3},
    97  		{-1, -1, -1, -1, -1, 0, -1, -1},
    98  		{-1, -1, -1, -1, -1, -1, 0, -1},
    99  		{-1, -1, -1, -1, -1, -1, -1, 0},
   100  	}
   101  
   102  	pad := func(s, p string, n int, start bool) string {
   103  		if n == 0 {
   104  			return s
   105  		}
   106  		if p == "" {
   107  			p = " "
   108  		}
   109  		var b strings.Builder
   110  		ss := utf16.Encode([]rune(s))
   111  		b.Grow(n)
   112  		n -= len(ss)
   113  		if !start {
   114  			b.WriteString(s)
   115  		}
   116  		if n > 0 {
   117  			pp := utf16.Encode([]rune(p))
   118  			for n > 0 {
   119  				if n > len(pp) {
   120  					b.WriteString(p)
   121  					n -= len(pp)
   122  				} else {
   123  					b.WriteString(string(utf16.Decode(pp[:n])))
   124  					n = 0
   125  				}
   126  			}
   127  		}
   128  		if start {
   129  			b.WriteString(s)
   130  		}
   131  		return b.String()
   132  	}
   133  
   134  	for i, a := range strs {
   135  		testUnaryOp(a, "JSON.parse(JSON.stringify(a))", a, t)
   136  		testUnaryOp(a, "a.length", int64(len(utf16.Encode([]rune(a)))), t)
   137  		for j, b := range strs {
   138  			testBinaryOp(a, b, "a === b", a == b, t)
   139  			testBinaryOp(a, b, "a == b", a == b, t)
   140  			testBinaryOp(a, b, "a + b", a+b, t)
   141  			testBinaryOp(a, b, "a > b", strings.Compare(a, b) > 0, t)
   142  			testBinaryOp(a, b, "`A${a}B${b}C`", "A"+a+"B"+b+"C", t)
   143  			testBinaryOp(a, b, "a.indexOf(b)", int64(indexOfResults[i][j]), t)
   144  			testBinaryOp(a, b, "a.lastIndexOf(b)", int64(lastIndexOfResults[i][j]), t)
   145  			testBinaryOp(a, b, "a.padStart(32, b)", pad(a, b, 32, true), t)
   146  			testBinaryOp(a, b, "a.padEnd(32, b)", pad(a, b, 32, false), t)
   147  			testBinaryOp(a, b, "a.replace(b, '')", strings.Replace(a, b, "", 1), t)
   148  		}
   149  	}
   150  }
   151  
   152  func TestStringFromUTF16(t *testing.T) {
   153  	s := StringFromUTF16([]uint16{})
   154  	if s.Length() != 0 || !s.SameAs(asciiString("")) {
   155  		t.Fatal(s)
   156  	}
   157  
   158  	s = StringFromUTF16([]uint16{0xD800})
   159  	if s.Length() != 1 || s.CharAt(0) != 0xD800 {
   160  		t.Fatal(s)
   161  	}
   162  
   163  	s = StringFromUTF16([]uint16{'A', 'B'})
   164  	if !s.SameAs(asciiString("AB")) {
   165  		t.Fatal(s)
   166  	}
   167  }
   168  
   169  func TestStringBuilder(t *testing.T) {
   170  	t.Run("writeUTF8String-switch", func(t *testing.T) {
   171  		var sb StringBuilder
   172  		sb.WriteUTF8String("Head")
   173  		sb.WriteUTF8String("1ábc")
   174  		if res := sb.String().String(); res != "Head1ábc" {
   175  			t.Fatal(res)
   176  		}
   177  	})
   178  }
   179  
   180  func BenchmarkASCIIConcat(b *testing.B) {
   181  	vm := New()
   182  
   183  	b.ResetTimer()
   184  	b.ReportAllocs()
   185  	for i := 0; i < b.N; i++ {
   186  		_, err := vm.RunString(`{let result = "ab";
   187  		for (let i = 0 ; i < 10;i++) {
   188  			result += result;
   189  		}}`)
   190  		if err != nil {
   191  			b.Fatalf("Unexpected errors %s", err)
   192  		}
   193  	}
   194  }