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

     1  package goja
     2  
     3  import "testing"
     4  
     5  func TestSubstr(t *testing.T) {
     6  	const SCRIPT = `
     7  assert.sameValue('abc'.substr(0, false), '', 'start: 0, length: false');
     8  assert.sameValue('abc'.substr(1, false), '', 'start: 1, length: false');
     9  assert.sameValue('abc'.substr(2, false), '', 'start: 2, length: false');
    10  assert.sameValue('abc'.substr(3, false), '', 'start: 3, length: false');
    11  
    12  assert.sameValue('abc'.substr(0, NaN), '', 'start: 0, length: NaN');
    13  assert.sameValue('abc'.substr(1, NaN), '', 'start: 1, length: NaN');
    14  assert.sameValue('abc'.substr(2, NaN), '', 'start: 2, length: NaN');
    15  assert.sameValue('abc'.substr(3, NaN), '', 'start: 3, length: NaN');
    16  
    17  assert.sameValue('abc'.substr(0, ''), '', 'start: 0, length: ""');
    18  assert.sameValue('abc'.substr(1, ''), '', 'start: 1, length: ""');
    19  assert.sameValue('abc'.substr(2, ''), '', 'start: 2, length: ""');
    20  assert.sameValue('abc'.substr(3, ''), '', 'start: 3, length: ""');
    21  
    22  assert.sameValue('abc'.substr(0, null), '', 'start: 0, length: null');
    23  assert.sameValue('abc'.substr(1, null), '', 'start: 1, length: null');
    24  assert.sameValue('abc'.substr(2, null), '', 'start: 2, length: null');
    25  assert.sameValue('abc'.substr(3, null), '', 'start: 3, length: null');
    26  
    27  assert.sameValue('abc'.substr(0, -1), '', '0, -1');
    28  assert.sameValue('abc'.substr(0, -2), '', '0, -2');
    29  assert.sameValue('abc'.substr(0, -3), '', '0, -3');
    30  assert.sameValue('abc'.substr(0, -4), '', '0, -4');
    31  
    32  assert.sameValue('abc'.substr(1, -1), '', '1, -1');
    33  assert.sameValue('abc'.substr(1, -2), '', '1, -2');
    34  assert.sameValue('abc'.substr(1, -3), '', '1, -3');
    35  assert.sameValue('abc'.substr(1, -4), '', '1, -4');
    36  
    37  assert.sameValue('abc'.substr(2, -1), '', '2, -1');
    38  assert.sameValue('abc'.substr(2, -2), '', '2, -2');
    39  assert.sameValue('abc'.substr(2, -3), '', '2, -3');
    40  assert.sameValue('abc'.substr(2, -4), '', '2, -4');
    41  
    42  assert.sameValue('abc'.substr(3, -1), '', '3, -1');
    43  assert.sameValue('abc'.substr(3, -2), '', '3, -2');
    44  assert.sameValue('abc'.substr(3, -3), '', '3, -3');
    45  assert.sameValue('abc'.substr(3, -4), '', '3, -4');
    46  
    47  assert.sameValue('abc'.substr(0, 1), 'a', '0, 1');
    48  assert.sameValue('abc'.substr(0, 2), 'ab', '0, 1');
    49  assert.sameValue('abc'.substr(0, 3), 'abc', '0, 1');
    50  assert.sameValue('abc'.substr(0, 4), 'abc', '0, 1');
    51  
    52  assert.sameValue('abc'.substr(1, 1), 'b', '1, 1');
    53  assert.sameValue('abc'.substr(1, 2), 'bc', '1, 1');
    54  assert.sameValue('abc'.substr(1, 3), 'bc', '1, 1');
    55  assert.sameValue('abc'.substr(1, 4), 'bc', '1, 1');
    56  
    57  assert.sameValue('abc'.substr(2, 1), 'c', '2, 1');
    58  assert.sameValue('abc'.substr(2, 2), 'c', '2, 1');
    59  assert.sameValue('abc'.substr(2, 3), 'c', '2, 1');
    60  assert.sameValue('abc'.substr(2, 4), 'c', '2, 1');
    61  
    62  assert.sameValue('abc'.substr(3, 1), '', '3, 1');
    63  assert.sameValue('abc'.substr(3, 2), '', '3, 1');
    64  assert.sameValue('abc'.substr(3, 3), '', '3, 1');
    65  assert.sameValue('abc'.substr(3, 4), '', '3, 1');
    66  
    67  assert.sameValue('abc'.substr(0), 'abc', 'start: 0, length: unspecified');
    68  assert.sameValue('abc'.substr(1), 'bc', 'start: 1, length: unspecified');
    69  assert.sameValue('abc'.substr(2), 'c', 'start: 2, length: unspecified');
    70  assert.sameValue('abc'.substr(3), '', 'start: 3, length: unspecified');
    71  
    72  assert.sameValue(
    73    'abc'.substr(0, undefined), 'abc', 'start: 0, length: undefined'
    74  );
    75  assert.sameValue(
    76    'abc'.substr(1, undefined), 'bc', 'start: 1, length: undefined'
    77  );
    78  assert.sameValue(
    79    'abc'.substr(2, undefined), 'c', 'start: 2, length: undefined'
    80  );
    81  assert.sameValue(
    82    'abc'.substr(3, undefined), '', 'start: 3, length: undefined'
    83  );
    84  
    85  assert.sameValue('A—', String.fromCharCode(65, 0x2014));
    86  
    87  	`
    88  
    89  	testScriptWithTestLib(SCRIPT, _undefined, t)
    90  }
    91  
    92  func TestStringMatchSym(t *testing.T) {
    93  	const SCRIPT = `
    94  function Prefix(p) {
    95  	this.p = p;
    96  }
    97  
    98  Prefix.prototype[Symbol.match] = function(s) {
    99  	return s.substring(0, this.p.length) === this.p;
   100  }
   101  
   102  var prefix1 = new Prefix("abc");
   103  var prefix2 = new Prefix("def");
   104  
   105  "abc123".match(prefix1) === true && "abc123".match(prefix2) === false &&
   106  "def123".match(prefix1) === false && "def123".match(prefix2) === true;
   107  `
   108  	testScript(SCRIPT, valueTrue, t)
   109  }
   110  
   111  func TestStringMatchAllSym(t *testing.T) {
   112  	const SCRIPT = `
   113  function Prefix(p) {
   114  	this.p = p;
   115  }
   116  
   117  Prefix.prototype[Symbol.matchAll] = function(s) {
   118  	return s.substring(0, this.p.length) === this.p;
   119  }
   120  
   121  var prefix1 = new Prefix("abc");
   122  var prefix2 = new Prefix("def");
   123  
   124  "abc123".matchAll(prefix1) === true && "abc123".matchAll(prefix2) === false &&
   125  "def123".matchAll(prefix1) === false && "def123".matchAll(prefix2) === true;
   126  `
   127  	testScript(SCRIPT, valueTrue, t)
   128  }
   129  
   130  func TestGenericSplitter(t *testing.T) {
   131  	const SCRIPT = `
   132  function MyRegexp(pattern, flags) {
   133  	if (pattern instanceof MyRegexp) {
   134  		pattern = pattern.wrapped;
   135  	}
   136  	this.wrapped = new RegExp(pattern, flags);
   137  }
   138  
   139  MyRegexp.prototype.exec = function() {
   140  	return this.wrapped.exec.apply(this.wrapped, arguments);
   141  }
   142  
   143  Object.defineProperty(MyRegexp.prototype, "lastIndex", {
   144  	get: function() {
   145  		return this.wrapped.lastIndex;
   146  	},
   147  	set: function(v) {
   148  		this.wrapped.lastIndex = v;
   149  	}
   150  });
   151  
   152  Object.defineProperty(MyRegexp.prototype, "flags", {
   153  	get: function() {
   154  		return this.wrapped.flags;
   155  	}
   156  });
   157  
   158  MyRegexp[Symbol.species] = MyRegexp;
   159  MyRegexp.prototype[Symbol.split] = RegExp.prototype[Symbol.split];
   160  
   161  var r = new MyRegexp(/ /);
   162  var res = "a b c".split(r);
   163  res.length === 3 && res[0] === "a" && res[1] === "b" && res[2] === "c";
   164  `
   165  	testScript(SCRIPT, valueTrue, t)
   166  }
   167  
   168  func TestStringIterSurrPair(t *testing.T) {
   169  	const SCRIPT = `
   170  var lo = '\uD834';
   171  var hi = '\uDF06';
   172  var pair = lo + hi;
   173  var string = 'a' + pair + 'b' + lo + pair + hi + lo;
   174  var iterator = string[Symbol.iterator]();
   175  var result;
   176  
   177  result = iterator.next();
   178  if (result.value !== 'a') {
   179  	throw new Error("at 0: " + result.value);
   180  }
   181  result = iterator.next();
   182  if (result.value !== pair) {
   183  	throw new Error("at 1: " + result.value);
   184  }
   185  
   186  `
   187  	testScript(SCRIPT, _undefined, t)
   188  }
   189  
   190  func TestValueStringBuilder(t *testing.T) {
   191  	t.Run("substringASCII", func(t *testing.T) {
   192  		t.Parallel()
   193  		var sb StringBuilder
   194  		str := newStringValue("a\U00010000b")
   195  		sb.WriteSubstring(str, 0, 1)
   196  		res := sb.String()
   197  		if res != asciiString("a") {
   198  			t.Fatal(res)
   199  		}
   200  	})
   201  
   202  	t.Run("substringASCIIPure", func(t *testing.T) {
   203  		t.Parallel()
   204  		var sb StringBuilder
   205  		str := newStringValue("ab")
   206  		sb.WriteSubstring(str, 0, 1)
   207  		res := sb.String()
   208  		if res != asciiString("a") {
   209  			t.Fatal(res)
   210  		}
   211  	})
   212  
   213  	t.Run("substringUnicode", func(t *testing.T) {
   214  		t.Parallel()
   215  		var sb StringBuilder
   216  		str := newStringValue("a\U00010000b")
   217  		sb.WriteSubstring(str, 1, 3)
   218  		res := sb.String()
   219  		if !res.SameAs(unicodeStringFromRunes([]rune{0x10000})) {
   220  			t.Fatal(res)
   221  		}
   222  	})
   223  
   224  	t.Run("substringASCIIUnicode", func(t *testing.T) {
   225  		t.Parallel()
   226  		var sb StringBuilder
   227  		str := newStringValue("a\U00010000b")
   228  		sb.WriteSubstring(str, 0, 2)
   229  		res := sb.String()
   230  		if !res.SameAs(unicodeStringFromRunes([]rune{'a', 0xD800})) {
   231  			t.Fatal(res)
   232  		}
   233  	})
   234  
   235  	t.Run("substringUnicodeASCII", func(t *testing.T) {
   236  		t.Parallel()
   237  		var sb StringBuilder
   238  		str := newStringValue("a\U00010000b")
   239  		sb.WriteSubstring(str, 2, 4)
   240  		res := sb.String()
   241  		if !res.SameAs(unicodeStringFromRunes([]rune{0xDC00, 'b'})) {
   242  			t.Fatal(res)
   243  		}
   244  	})
   245  
   246  	t.Run("concatSubstringUnicodeASCII", func(t *testing.T) {
   247  		t.Parallel()
   248  		var sb StringBuilder
   249  		sb.WriteString(newStringValue("юникод"))
   250  		sb.WriteSubstring(asciiString(" ascii"), 0, 6)
   251  		if res := sb.String(); !res.SameAs(newStringValue("юникод ascii")) {
   252  			t.Fatal(res)
   253  		}
   254  	})
   255  
   256  	t.Run("concat_ASCII_importedASCII", func(t *testing.T) {
   257  		t.Parallel()
   258  		var sb StringBuilder
   259  		sb.WriteString(asciiString("ascii"))
   260  		sb.WriteString(&importedString{s: " imported_ascii1234567890"})
   261  		s := sb.String()
   262  		if res, ok := s.(asciiString); !ok || res != "ascii imported_ascii1234567890" {
   263  			t.Fatal(s)
   264  		}
   265  	})
   266  
   267  	t.Run("concat_ASCII_importedUnicode", func(t *testing.T) {
   268  		t.Parallel()
   269  		var sb StringBuilder
   270  		sb.WriteString(asciiString("ascii"))
   271  		sb.WriteString(&importedString{s: " imported_юникод"})
   272  		s := sb.String()
   273  		if res, ok := s.(unicodeString); !ok || !res.SameAs(newStringValue("ascii imported_юникод")) {
   274  			t.Fatal(s)
   275  		}
   276  	})
   277  
   278  }