|
@@ -1,6 +1,10 @@
|
|
|
package goja
|
|
|
|
|
|
-import "testing"
|
|
|
+import (
|
|
|
+ "strings"
|
|
|
+ "testing"
|
|
|
+ "unicode/utf16"
|
|
|
+)
|
|
|
|
|
|
func TestStringOOBProperties(t *testing.T) {
|
|
|
const SCRIPT = `
|
|
@@ -13,6 +17,137 @@ func TestStringOOBProperties(t *testing.T) {
|
|
|
testScript(SCRIPT, valueInt(1), t)
|
|
|
}
|
|
|
|
|
|
+func TestImportedString(t *testing.T) {
|
|
|
+ vm := New()
|
|
|
+
|
|
|
+ testUnaryOp := func(a, expr string, result interface{}, t *testing.T) {
|
|
|
+ v, err := vm.RunString("a => " + expr)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ var fn func(a Value) (Value, error)
|
|
|
+ err = vm.ExportTo(v, &fn)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ for _, aa := range []Value{newStringValue(a), vm.ToValue(a)} {
|
|
|
+ res, err := fn(aa)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ if res.Export() != result {
|
|
|
+ t.Fatalf("%s, a:%v(%T). expected: %v, actual: %v", expr, aa, aa, result, res)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ testBinaryOp := func(a, b, expr string, result interface{}, t *testing.T) {
|
|
|
+ v, err := vm.RunString("(a, b) => " + expr)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ var fn func(a, b Value) (Value, error)
|
|
|
+ err = vm.ExportTo(v, &fn)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ for _, aa := range []Value{newStringValue(a), vm.ToValue(a)} {
|
|
|
+ for _, bb := range []Value{newStringValue(b), vm.ToValue(b)} {
|
|
|
+ res, err := fn(aa, bb)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ if res.Export() != result {
|
|
|
+ t.Fatalf("%s, a:%v(%T), b:%v(%T). expected: %v, actual: %v", expr, aa, aa, bb, bb, result, res)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ strs := []string{"shortAscii", "longlongAscii1234567890123456789", "short юникод", "long юникод 1234567890 юникод \U0001F600", "юникод", "Ascii", "long", "код"}
|
|
|
+ indexOfResults := [][]int{
|
|
|
+ /*
|
|
|
+ const strs = ["shortAscii", "longlongAscii1234567890123456789", "short юникод", "long юникод 1234567890 юникод \u{1F600}", "юникод", "Ascii", "long", "код"];
|
|
|
+
|
|
|
+ strs.forEach(a => {
|
|
|
+ console.log("{", strs.map(b => a.indexOf(b)).join(", "), "},");
|
|
|
+ });
|
|
|
+ */
|
|
|
+ {0, -1, -1, -1, -1, 5, -1, -1},
|
|
|
+ {-1, 0, -1, -1, -1, 8, 0, -1},
|
|
|
+ {-1, -1, 0, -1, 6, -1, -1, 9},
|
|
|
+ {-1, -1, -1, 0, 5, -1, 0, 8},
|
|
|
+ {-1, -1, -1, -1, 0, -1, -1, 3},
|
|
|
+ {-1, -1, -1, -1, -1, 0, -1, -1},
|
|
|
+ {-1, -1, -1, -1, -1, -1, 0, -1},
|
|
|
+ {-1, -1, -1, -1, -1, -1, -1, 0},
|
|
|
+ }
|
|
|
+
|
|
|
+ lastIndexOfResults := [][]int{
|
|
|
+ /*
|
|
|
+ strs.forEach(a => {
|
|
|
+ console.log("{", strs.map(b => a.lastIndexOf(b)).join(", "), "},");
|
|
|
+ });
|
|
|
+ */
|
|
|
+ {0, -1, -1, -1, -1, 5, -1, -1},
|
|
|
+ {-1, 0, -1, -1, -1, 8, 4, -1},
|
|
|
+ {-1, -1, 0, -1, 6, -1, -1, 9},
|
|
|
+ {-1, -1, -1, 0, 23, -1, 0, 26},
|
|
|
+ {-1, -1, -1, -1, 0, -1, -1, 3},
|
|
|
+ {-1, -1, -1, -1, -1, 0, -1, -1},
|
|
|
+ {-1, -1, -1, -1, -1, -1, 0, -1},
|
|
|
+ {-1, -1, -1, -1, -1, -1, -1, 0},
|
|
|
+ }
|
|
|
+
|
|
|
+ pad := func(s, p string, n int, start bool) string {
|
|
|
+ if n == 0 {
|
|
|
+ return s
|
|
|
+ }
|
|
|
+ if p == "" {
|
|
|
+ p = " "
|
|
|
+ }
|
|
|
+ var b strings.Builder
|
|
|
+ ss := utf16.Encode([]rune(s))
|
|
|
+ b.Grow(n)
|
|
|
+ n -= len(ss)
|
|
|
+ if !start {
|
|
|
+ b.WriteString(s)
|
|
|
+ }
|
|
|
+ if n > 0 {
|
|
|
+ pp := utf16.Encode([]rune(p))
|
|
|
+ for n > 0 {
|
|
|
+ if n > len(pp) {
|
|
|
+ b.WriteString(p)
|
|
|
+ n -= len(pp)
|
|
|
+ } else {
|
|
|
+ b.WriteString(string(utf16.Decode(pp[:n])))
|
|
|
+ n = 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if start {
|
|
|
+ b.WriteString(s)
|
|
|
+ }
|
|
|
+ return b.String()
|
|
|
+ }
|
|
|
+
|
|
|
+ for i, a := range strs {
|
|
|
+ testUnaryOp(a, "JSON.parse(JSON.stringify(a))", a, t)
|
|
|
+ for j, b := range strs {
|
|
|
+ testBinaryOp(a, b, "a === b", a == b, t)
|
|
|
+ testBinaryOp(a, b, "a == b", a == b, t)
|
|
|
+ testBinaryOp(a, b, "a + b", a+b, t)
|
|
|
+ testBinaryOp(a, b, "a > b", strings.Compare(a, b) > 0, t)
|
|
|
+ testBinaryOp(a, b, "`A${a}B${b}C`", "A"+a+"B"+b+"C", t)
|
|
|
+ testBinaryOp(a, b, "a.indexOf(b)", int64(indexOfResults[i][j]), t)
|
|
|
+ testBinaryOp(a, b, "a.lastIndexOf(b)", int64(lastIndexOfResults[i][j]), t)
|
|
|
+ testBinaryOp(a, b, "a.padStart(32, b)", pad(a, b, 32, true), t)
|
|
|
+ testBinaryOp(a, b, "a.padEnd(32, b)", pad(a, b, 32, false), t)
|
|
|
+ testBinaryOp(a, b, "a.replace(b, '')", strings.Replace(a, b, "", 1), t)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func BenchmarkASCIIConcat(b *testing.B) {
|
|
|
vm := New()
|
|
|
|