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

     1  package goja
     2  
     3  import (
     4  	"testing"
     5  )
     6  
     7  func TestRegexp1(t *testing.T) {
     8  	const SCRIPT = `
     9  	var r = new RegExp("(['\"])(.*?)\\1");
    10  	var m = r.exec("'test'");
    11  	m !== null && m.length == 3 && m[2] === "test";
    12  	`
    13  
    14  	testScript(SCRIPT, valueTrue, t)
    15  }
    16  
    17  func TestRegexp2(t *testing.T) {
    18  	const SCRIPT = `
    19  	var r = new RegExp("(['\"])(.*?)['\"]");
    20  	var m = r.exec("'test'");
    21  	m !== null && m.length == 3 && m[2] === "test";
    22  	`
    23  
    24  	testScript(SCRIPT, valueTrue, t)
    25  }
    26  
    27  func TestRegexpLiteral(t *testing.T) {
    28  	const SCRIPT = `
    29  	var r = /(['\"])(.*?)\1/;
    30  	var m = r.exec("'test'");
    31  	m !== null && m.length == 3 && m[2] === "test";
    32  	`
    33  
    34  	testScript(SCRIPT, valueTrue, t)
    35  }
    36  
    37  func TestRegexpRe2Unicode(t *testing.T) {
    38  	const SCRIPT = `
    39  	var r = /(тест)/i;
    40  	var m = r.exec("'Тест'");
    41  	m !== null && m.length == 2 && m[1] === "Тест";
    42  	`
    43  
    44  	testScript(SCRIPT, valueTrue, t)
    45  }
    46  
    47  func TestRegexpRe2UnicodeTarget(t *testing.T) {
    48  	const SCRIPT = `
    49  	var r = /(['\"])(.*?)['\"]/i;
    50  	var m = r.exec("'Тест'");
    51  	m !== null && m.length == 3 && m[2] === "Тест";
    52  	`
    53  
    54  	testScript(SCRIPT, valueTrue, t)
    55  }
    56  
    57  func TestRegexpRegexp2Unicode(t *testing.T) {
    58  	const SCRIPT = `
    59  	var r = /(['\"])(тест)\1/i;
    60  	var m = r.exec("'Тест'");
    61  	m !== null && m.length == 3 && m[2] === "Тест";
    62  	`
    63  
    64  	testScript(SCRIPT, valueTrue, t)
    65  }
    66  
    67  func TestRegexpRegexp2UnicodeTarget(t *testing.T) {
    68  	const SCRIPT = `
    69  	var r = /(['\"])(.*?)\1/;
    70  	var m = r.exec("'Тест'");
    71  	m !== null && m.length == 3 && m[2] === "Тест";
    72  	`
    73  
    74  	testScript(SCRIPT, valueTrue, t)
    75  }
    76  
    77  func TestRegexpRe2Whitespace(t *testing.T) {
    78  	const SCRIPT = `
    79  	"\u2000\u2001\u2002\u200b".replace(/\s+/g, "") === "\u200b";
    80  	`
    81  
    82  	testScript(SCRIPT, valueTrue, t)
    83  }
    84  
    85  func TestRegexpRegexp2Whitespace(t *testing.T) {
    86  	const SCRIPT = `
    87  	"A\u2000\u2001\u2002A\u200b".replace(/(A)\s+\1/g, "") === "\u200b"
    88  	`
    89  	testScript(SCRIPT, valueTrue, t)
    90  }
    91  
    92  func TestEmptyCharClassRe2(t *testing.T) {
    93  	const SCRIPT = `
    94  	/[]/.test("\u0000");
    95  	`
    96  
    97  	testScript(SCRIPT, valueFalse, t)
    98  }
    99  
   100  func TestNegatedEmptyCharClassRe2(t *testing.T) {
   101  	const SCRIPT = `
   102  	/[^]/.test("\u0000");
   103  	`
   104  
   105  	testScript(SCRIPT, valueTrue, t)
   106  }
   107  
   108  func TestEmptyCharClassRegexp2(t *testing.T) {
   109  	const SCRIPT = `
   110  	/([])\1/.test("\u0000\u0000");
   111  	`
   112  
   113  	testScript(SCRIPT, valueFalse, t)
   114  }
   115  
   116  func TestRegexp2Negate(t *testing.T) {
   117  	const SCRIPT = `
   118  	/([\D1])\1/.test("aa");
   119  	`
   120  
   121  	testScript(SCRIPT, valueTrue, t)
   122  }
   123  
   124  func TestAlternativeRe2(t *testing.T) {
   125  	const SCRIPT = `
   126  	/()|/.exec("") !== null;
   127  	`
   128  
   129  	testScript(SCRIPT, valueTrue, t)
   130  }
   131  
   132  func TestRegexpReplaceGlobal(t *testing.T) {
   133  	const SCRIPT = `
   134  	"QBZPbage\ny_cynprubyqre".replace(/^\s*|\s*$/g, '')
   135  	`
   136  
   137  	testScript(SCRIPT, asciiString("QBZPbage\ny_cynprubyqre"), t)
   138  }
   139  
   140  func TestRegexpNumCaptures(t *testing.T) {
   141  	const SCRIPT = `
   142  	"Fubpxjnir Synfu 9.0  e115".replace(/([a-zA-Z]|\s)+/, '')
   143  	`
   144  	testScript(SCRIPT, asciiString("9.0  e115"), t)
   145  }
   146  
   147  func TestRegexpNumCaptures1(t *testing.T) {
   148  	const SCRIPT = `
   149  	"Fubpxjnir Sy\tfu 9.0  e115".replace(/^.*\s+(\S+\s+\S+$)/, '')
   150  	`
   151  	testScript(SCRIPT, asciiString(""), t)
   152  }
   153  
   154  func TestRegexpSInClass(t *testing.T) {
   155  	const SCRIPT = `
   156  	/[\S]/.test("\u2028");
   157  	`
   158  	testScript(SCRIPT, valueFalse, t)
   159  }
   160  
   161  func TestRegexpDotMatchCR(t *testing.T) {
   162  	const SCRIPT = `
   163  	/./.test("\r");
   164  	`
   165  
   166  	testScript(SCRIPT, valueFalse, t)
   167  }
   168  
   169  func TestRegexpDotMatchCRInGroup(t *testing.T) {
   170  	const SCRIPT = `
   171  	/(.)/.test("\r");
   172  	`
   173  
   174  	testScript(SCRIPT, valueFalse, t)
   175  }
   176  
   177  func TestRegexpDotMatchLF(t *testing.T) {
   178  	const SCRIPT = `
   179  	/./.test("\n");
   180  	`
   181  
   182  	testScript(SCRIPT, valueFalse, t)
   183  }
   184  
   185  func TestRegexpSplitWithBackRef(t *testing.T) {
   186  	const SCRIPT = `
   187  	"a++b+-c".split(/([+-])\1/).join(" $$ ")
   188  	`
   189  
   190  	testScript(SCRIPT, asciiString("a $$ + $$ b+-c"), t)
   191  }
   192  
   193  func TestEscapeNonASCII(t *testing.T) {
   194  	const SCRIPT = `
   195  	/\⩓/.test("⩓")
   196  	`
   197  
   198  	testScript(SCRIPT, valueTrue, t)
   199  }
   200  
   201  func TestRegexpUTF16(t *testing.T) {
   202  	const SCRIPT = `
   203  	var str = "\uD800\uDC00";
   204  
   205  	assert(/\uD800/g.test(str), "#1");
   206  	assert(/\uD800/.test(str), "#2");
   207  	assert(/𐀀/.test(str), "#3");
   208  
   209  	var re = /\uD800/;
   210  
   211  	assert(compareArray(str.replace(re, "X"), ["X", "\uDC00"]), "#4");
   212  	assert(compareArray(str.split(re), ["", "\uDC00"]), "#5");
   213  	assert(compareArray("a\uD800\uDC00b".split(/\uD800/g), ["a", "\uDC00b"]), "#6");
   214  	assert(compareArray("a\uD800\uDC00b".split(/(?:)/g), ["a", "\uD800", "\uDC00", "b"]), "#7");
   215  	assert(compareArray("0\x80".split(/(0){0}/g), ["0", undefined, "\x80"]), "#7+");
   216  
   217  	re = /(?=)a/; // a hack to use regexp2
   218  	assert.sameValue(re.exec('\ud83d\ude02a').index, 2, "#8");
   219  
   220  	assert.sameValue(/./.exec('\ud83d\ude02')[0], '\ud83d', "#9");
   221  
   222  	assert(RegExp("\uD800").test("\uD800"), "#10");
   223  
   224  	var cu = 0xD800;
   225  	var xx = "a\\" + String.fromCharCode(cu);
   226  	var pattern = eval("/" + xx + "/");
   227  	assert.sameValue(pattern.source, "a\\\\\\ud800", "Code unit: " + cu.toString(16), "#11");
   228  	assert(pattern.test("a\\\uD800"), "#12");
   229  	`
   230  
   231  	testScriptWithTestLib(SCRIPT, _undefined, t)
   232  }
   233  
   234  func TestRegexpUnicode(t *testing.T) {
   235  	const SCRIPT = `
   236  
   237  	assert(!/\uD800/u.test("\uD800\uDC00"), "#1");
   238  	assert(!/\uFFFD/u.test("\uD800\uDC00"), "#2");
   239  
   240  	assert(/\uD800\uDC00/u.test("\uD800\uDC00"), "#3");
   241  
   242  	assert(/\uD800/u.test("\uD800"), "#4");
   243  
   244  	assert(compareArray("a\uD800\uDC00b".split(/\uD800/gu), ["a\uD800\uDC00b"]), "#5");
   245  
   246  	assert(compareArray("a\uD800\uDC00b".split(/(?:)/gu), ["a", "𐀀", "b"]), "#6");
   247  
   248  	assert(compareArray("0\x80".split(/(0){0}/gu), ["0", undefined, "\x80"]), "#7");
   249  
   250  	var re = eval('/' + /\ud834\udf06/u.source + '/u');
   251  	assert(re.test('\ud834\udf06'), "#9");
   252  
   253  	/*re = RegExp("\\p{L}", "u");
   254  	if (!re.test("A")) {
   255  		throw new Error("Test 9 failed");
   256  	}*/
   257  	`
   258  
   259  	testScriptWithTestLib(SCRIPT, _undefined, t)
   260  }
   261  
   262  func TestConvertRegexpToUnicode(t *testing.T) {
   263  	if s := convertRegexpToUnicode(`test\uD800\u0C00passed`); s != `test\uD800\u0C00passed` {
   264  		t.Fatal(s)
   265  	}
   266  	if s := convertRegexpToUnicode(`test\uD800\uDC00passed`); s != `test𐀀passed` {
   267  		t.Fatal(s)
   268  	}
   269  	if s := convertRegexpToUnicode(`test\u0023passed`); s != `test\u0023passed` {
   270  		t.Fatal(s)
   271  	}
   272  	if s := convertRegexpToUnicode(`test\u0passed`); s != `test\u0passed` {
   273  		t.Fatal(s)
   274  	}
   275  	if s := convertRegexpToUnicode(`test\uD800passed`); s != `test\uD800passed` {
   276  		t.Fatal(s)
   277  	}
   278  	if s := convertRegexpToUnicode(`test\uD800`); s != `test\uD800` {
   279  		t.Fatal(s)
   280  	}
   281  	if s := convertRegexpToUnicode(`test\uD80`); s != `test\uD80` {
   282  		t.Fatal(s)
   283  	}
   284  	if s := convertRegexpToUnicode(`\\uD800\uDC00passed`); s != `\\uD800\uDC00passed` {
   285  		t.Fatal(s)
   286  	}
   287  	if s := convertRegexpToUnicode(`testpassed`); s != `testpassed` {
   288  		t.Fatal(s)
   289  	}
   290  }
   291  
   292  func TestConvertRegexpToUtf16(t *testing.T) {
   293  	if s := convertRegexpToUtf16(`𐀀`); s != `\ud800\udc00` {
   294  		t.Fatal(s)
   295  	}
   296  	if s := convertRegexpToUtf16(`\𐀀`); s != `\\\ud800\udc00` {
   297  		t.Fatal(s)
   298  	}
   299  }
   300  
   301  func TestEscapeInvalidUtf16(t *testing.T) {
   302  	if s := escapeInvalidUtf16(asciiString("test")); s != "test" {
   303  		t.Fatal(s)
   304  	}
   305  	if s := escapeInvalidUtf16(newStringValue("test\U00010000")); s != "test\U00010000" {
   306  		t.Fatal(s)
   307  	}
   308  	if s := escapeInvalidUtf16(unicodeStringFromRunes([]rune{'t', 0xD800})); s != "t\\ud800" {
   309  		t.Fatal(s)
   310  	}
   311  	if s := escapeInvalidUtf16(unicodeStringFromRunes([]rune{'t', 0xD800, 'p'})); s != "t\\ud800p" {
   312  		t.Fatal(s)
   313  	}
   314  	if s := escapeInvalidUtf16(unicodeStringFromRunes([]rune{0xD800, 'p'})); s != "\\ud800p" {
   315  		t.Fatal(s)
   316  	}
   317  	if s := escapeInvalidUtf16(unicodeStringFromRunes([]rune{'t', '\\', 0xD800, 'p'})); s != `t\\\ud800p` {
   318  		t.Fatal(s)
   319  	}
   320  }
   321  
   322  func TestRegexpAssertion(t *testing.T) {
   323  	const SCRIPT = `
   324  	var res = 'aaa'.match(/^a/g);
   325  	res.length === 1 || res[0] === 'a';
   326  	`
   327  	testScript(SCRIPT, valueTrue, t)
   328  }
   329  
   330  func TestRegexpUnicodeAdvanceStringIndex(t *testing.T) {
   331  	const SCRIPT = `
   332  	// deoptimise RegExp
   333  	var origExec = RegExp.prototype.exec;
   334  	RegExp.prototype.exec = function(s) {
   335  		return origExec.call(this, s);
   336  	};
   337  
   338  	var re = /(?:)/gu;
   339  	var str = "a\uD800\uDC00b";
   340  	assert(compareArray(str.split(re), ["a", "𐀀", "b"]), "#1");
   341  
   342  	re.lastIndex = 3;
   343  	assert.sameValue(re.exec(str).index, 3, "#2");
   344  
   345  	re.lastIndex = 2;
   346  	assert.sameValue(re.exec(str).index, 1, "#3");
   347  
   348  	re.lastIndex = 4;
   349  	assert.sameValue(re.exec(str).index, 4, "#4");
   350  
   351  	re.lastIndex = 5;
   352  	assert.sameValue(re.exec(str), null, "#5");
   353  
   354  	var iterator = str.matchAll(re); // regexp is copied by matchAll, but resets lastIndex
   355  	var matches = [];
   356  	for (var v of iterator) {matches.push(v);}
   357  	assert.sameValue(matches.length, 4, "#6");
   358  	assert.sameValue(matches[0].index, 0, "#7 index");
   359  	assert.sameValue(matches[0][0], "", "#7 value");
   360  	assert.sameValue(matches[1].index, 1, "#8 index");
   361  	assert.sameValue(matches[1][0], "", "#8 value");
   362  	assert.sameValue(matches[2].index, 3, "#9 index");
   363  	assert.sameValue(matches[2][0], "", "#9 value");
   364  	assert.sameValue(matches[3].index, 4, "#10 index");
   365  	assert.sameValue(matches[3][0], "", "#10 value");
   366  	`
   367  	testScriptWithTestLib(SCRIPT, _undefined, t)
   368  }
   369  
   370  func TestRegexpInit(t *testing.T) {
   371  	const SCRIPT = `
   372  	RegExp(".").lastIndex;
   373  	`
   374  	testScript(SCRIPT, intToValue(0), t)
   375  }
   376  
   377  func TestRegexpToString(t *testing.T) {
   378  	const SCRIPT = `
   379  	RegExp.prototype.toString.call({
   380  	source: 'foo',
   381      flags: 'bar'});
   382  	`
   383  	testScript(SCRIPT, asciiString("/foo/bar"), t)
   384  }
   385  
   386  func TestRegexpEscapeSource(t *testing.T) {
   387  	const SCRIPT = `
   388  	/href="(.+?)(\/.*\/\S+?)\/"/.source;
   389  	`
   390  	testScript(SCRIPT, asciiString(`href="(.+?)(\/.*\/\S+?)\/"`), t)
   391  }
   392  
   393  func TestRegexpConsecutiveMatchCache(t *testing.T) {
   394  	const SCRIPT = `
   395  	(function test(unicode) {
   396  		var regex = new RegExp('t(e)(st(\\d?))', unicode?'gu':'g');
   397  		var string = 'test1test2';
   398  		var match;
   399  		var matches = [];
   400  		while (match = regex.exec(string)) {
   401  			matches.push(match);
   402  		}
   403  		var expectedMatches = [
   404  		  [
   405  			'test1',
   406  			'e',
   407  			'st1',
   408  			'1'
   409  		  ],
   410  		  [
   411  			'test2',
   412  			'e',
   413  			'st2',
   414  			'2'
   415  		  ]
   416  		];
   417  		expectedMatches[0].index = 0;
   418  		expectedMatches[0].input = 'test1test2';
   419  		expectedMatches[1].index = 5;
   420  		expectedMatches[1].input = 'test1test2';
   421  
   422  		assert(deepEqual(matches, expectedMatches), "#1");
   423  
   424  		// try the same regexp with a different string
   425  		regex.lastIndex = 0;
   426  		match = regex.exec(' test5');
   427  		var expectedMatch = [
   428  		  'test5',
   429  		  'e',
   430  		  'st5',
   431  		  '5'
   432  		];
   433  		expectedMatch.index = 1;
   434  		expectedMatch.input = ' test5';
   435  		assert(deepEqual(match, expectedMatch), "#2");
   436  		assert.sameValue(regex.lastIndex, 6, "#3");
   437  
   438  		// continue matching with a different string
   439  		match = regex.exec(' test5test6');
   440  		expectedMatch = [
   441  		  'test6',
   442  		  'e',
   443  		  'st6',
   444  		  '6'
   445  		];
   446  		expectedMatch.index = 6;
   447  		expectedMatch.input = ' test5test6';
   448  		assert(deepEqual(match, expectedMatch), "#4");
   449  		assert.sameValue(regex.lastIndex, 11, "#5");
   450  
   451  		match = regex.exec(' test5test6');
   452  		assert.sameValue(match, null, "#6");
   453  		return regex;
   454  	});
   455  	`
   456  	vm := New()
   457  	_, _ = vm.RunProgram(testLib())
   458  	_, _ = vm.RunProgram(testLibX())
   459  	v, err := vm.RunString(SCRIPT)
   460  	if err != nil {
   461  		t.Fatal(err)
   462  	}
   463  	var f func(bool) (*Object, error)
   464  	err = vm.ExportTo(v, &f)
   465  	if err != nil {
   466  		t.Fatal(err)
   467  	}
   468  
   469  	regex, err := f(false)
   470  	if err != nil {
   471  		t.Fatal(err)
   472  	}
   473  	if regex.self.(*regexpObject).pattern.regexp2Wrapper.cache != nil {
   474  		t.Fatal("Cache is not nil (non-unicode)")
   475  	}
   476  
   477  	regex, err = f(true)
   478  	if err != nil {
   479  		t.Fatal(err)
   480  	}
   481  	if regex.self.(*regexpObject).pattern.regexp2Wrapper.cache != nil {
   482  		t.Fatal("Cache is not nil (unicode)")
   483  	}
   484  }
   485  
   486  func TestRegexpMatchAll(t *testing.T) {
   487  	const SCRIPT = `
   488  	(function test(unicode) {
   489  		var regex = new RegExp('t(e)(st(\\d?))', unicode?'gu':'g');
   490  		var string = 'test1test2';
   491  		var matches = [];
   492  		for (var match of string.matchAll(regex)) {
   493  			matches.push(match);
   494  		}
   495  		var expectedMatches = [
   496  		  [
   497  			'test1',
   498  			'e',
   499  			'st1',
   500  			'1'
   501  		  ],
   502  		  [
   503  			'test2',
   504  			'e',
   505  			'st2',
   506  			'2'
   507  		  ]
   508  		];
   509  		expectedMatches[0].index = 0;
   510  		expectedMatches[0].input = 'test1test2';
   511  		expectedMatches[1].index = 5;
   512  		expectedMatches[1].input = 'test1test2';
   513  
   514  		assert(deepEqual(matches, expectedMatches), "#1");
   515  		assert.sameValue(regex.lastIndex, 0, "#1 lastIndex");
   516  
   517  		// try the same regexp with a different string
   518  		string = ' test5';
   519  		matches = [];
   520  		for (var match of string.matchAll(regex)) {
   521  			matches.push(match);
   522  		}
   523  		expectedMatches = [
   524  			[
   525  			  'test5',
   526  			  'e',
   527  			  'st5',
   528  			  '5'
   529  			]
   530  		];
   531  		expectedMatches[0].index = 1;
   532  		expectedMatches[0].input = ' test5';
   533  		assert(deepEqual(matches, expectedMatches), "#2");
   534  		assert.sameValue(regex.lastIndex, 0, "#2 lastIndex");
   535  
   536  		// continue matching with a different string
   537  		string = ' test5test6';
   538  		matches = [];
   539  		for (var match of string.matchAll(regex)) {
   540  			matches.push(match);
   541  		}
   542  		var expectedMatches = [
   543  		  [
   544  			'test5',
   545  			'e',
   546  			'st5',
   547  			'5'
   548  		  ],
   549  		  [
   550  			'test6',
   551  			'e',
   552  			'st6',
   553  			'6'
   554  		  ]
   555  		];
   556  		expectedMatches[0].index = 1;
   557  		expectedMatches[0].input = ' test5test6';
   558  		expectedMatches[1].index = 6;
   559  		expectedMatches[1].input = ' test5test6';
   560  		assert(deepEqual(matches, expectedMatches), "#3");
   561  		assert.sameValue(regex.lastIndex, 0, "#3 lastindex");
   562  	});
   563  	`
   564  	vm := New()
   565  	_, _ = vm.RunProgram(testLib())
   566  	_, _ = vm.RunProgram(testLibX())
   567  	v, err := vm.RunString(SCRIPT)
   568  	if err != nil {
   569  		t.Fatal(err)
   570  	}
   571  	var f func(bool) (*Object, error)
   572  	err = vm.ExportTo(v, &f)
   573  	if err != nil {
   574  		t.Fatal(err)
   575  	}
   576  
   577  	_, err = f(false)
   578  	if err != nil {
   579  		t.Fatal(err)
   580  	}
   581  
   582  	_, err = f(true)
   583  	if err != nil {
   584  		t.Fatal(err)
   585  	}
   586  }
   587  
   588  func TestRegexpOverrideSpecies(t *testing.T) {
   589  	const SCRIPT = `
   590  	Object.defineProperty(RegExp, Symbol.species, {
   591  		configurable: true,
   592  		value: function() {
   593  			throw "passed";
   594  		}
   595  	});
   596  	try {
   597  		"ab".split(/a/);
   598  		throw new Error("Expected error");
   599  	} catch(e) {
   600  		if (e !== "passed") {
   601  			throw e;
   602  		}
   603  	}
   604  	`
   605  	testScript(SCRIPT, _undefined, t)
   606  }
   607  
   608  func TestRegexpSymbolMatchAllCallsIsRegexp(t *testing.T) {
   609  	// This is tc39's test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-this-throws.js
   610  	const SCRIPT = `
   611  	var a = new Object();
   612  	Object.defineProperty(a, Symbol.match, {
   613  		get: function() {
   614  			throw "passed";
   615  		}
   616  	});
   617  	try {
   618  		RegExp.prototype[Symbol.matchAll].call(a, '');
   619  		throw new Error("Expected error");
   620  	} catch(e) {
   621  		if (e !== "passed") {
   622  			throw e;
   623  		}
   624  	}
   625  	`
   626  	testScript(SCRIPT, _undefined, t)
   627  }
   628  
   629  func TestRegexpMatchAllConstructor(t *testing.T) {
   630  	// This is tc39's test/built-ins/RegExp/prototype/Symbol.matchAll/species-constuctor.js
   631  	const SCRIPT = `
   632  	var callCount = 0;
   633  	var callArgs;
   634  	var regexp = /\d/u;
   635  	var obj = {}
   636  	Object.defineProperty(obj, Symbol.species, {
   637  		value: function() {
   638  		  callCount++;
   639  		  callArgs = arguments;
   640  		  return /\w/g;
   641  		}
   642  	});
   643  	regexp.constructor = obj;
   644  	var str = 'a*b';
   645  	var iter = regexp[Symbol.matchAll](str);
   646  
   647  	assert.sameValue(callCount, 1);
   648  	assert.sameValue(callArgs.length, 2);
   649  	assert.sameValue(callArgs[0], regexp);
   650  	assert.sameValue(callArgs[1], 'u');
   651  
   652  	var first = iter.next()
   653  	assert.sameValue(first.done, false);
   654  	assert.sameValue(first.value.length, 1);
   655  	assert.sameValue(first.value[0], "a");
   656  	var second = iter.next()
   657  	assert.sameValue(second.done, true);
   658  	`
   659  	testScriptWithTestLib(SCRIPT, _undefined, t)
   660  }
   661  
   662  func TestRegexp2InvalidEscape(t *testing.T) {
   663  	testScript(`/(?=)\x0/.test("x0")`, valueTrue, t)
   664  }
   665  
   666  func TestRegexpUnicodeEmptyMatch(t *testing.T) {
   667  	testScript(`/(0)0|/gu.exec("0\xef").length === 2`, valueTrue, t)
   668  }
   669  
   670  func TestRegexpInvalidGroup(t *testing.T) {
   671  	const SCRIPT = `
   672  	["?", "(?)"].forEach(function(s) {
   673  		assert.throws(SyntaxError, function() {new RegExp(s)}, s);
   674  	});
   675  	`
   676  	testScriptWithTestLib(SCRIPT, _undefined, t)
   677  }
   678  
   679  func TestRegexpLookbehindAssertion(t *testing.T) {
   680  	const SCRIPT = `
   681  	var re = /(?<=Jack|Tom)Sprat/;
   682  	assert(re.test("JackSprat"), "#1");
   683  	assert(!re.test("JohnSprat"), "#2");
   684  
   685  	re = /(?<!-)\d+/;
   686  	assert(re.test("3"), "#3");
   687  	assert(!re.test("-3"), "#4");
   688  	`
   689  	testScriptWithTestLib(SCRIPT, _undefined, t)
   690  }
   691  
   692  func TestRegexpInvalidUTF8(t *testing.T) {
   693  	vm := New()
   694  	// Note that normally vm.ToValue() would replace invalid UTF-8 sequences with RuneError
   695  	_, err := vm.New(vm.Get("RegExp"), asciiString([]byte{0xAD}))
   696  	if err == nil {
   697  		t.Fatal("Expected error")
   698  	}
   699  }
   700  
   701  // this should not cause data races when run with -race
   702  func TestRegexpConcurrentLiterals(t *testing.T) {
   703  	prg := MustCompile("test.js", `var r = /(?<!-)\d+/; r.test("");`, false)
   704  	go func() {
   705  		vm := New()
   706  		_, err := vm.RunProgram(prg)
   707  		if err != nil {
   708  			panic(err)
   709  		}
   710  	}()
   711  	vm := New()
   712  	_, _ = vm.RunProgram(prg)
   713  }
   714  
   715  func BenchmarkRegexpSplitWithBackRef(b *testing.B) {
   716  	const SCRIPT = `
   717  	"aaaaaaaaaaaaaaaaaaaaaaaaa++bbbbbbbbbbbbbbbbbbbbbb+-ccccccccccccccccccccccc".split(/([+-])\1/)
   718  	`
   719  	b.StopTimer()
   720  	prg, err := Compile("test.js", SCRIPT, false)
   721  	if err != nil {
   722  		b.Fatal(err)
   723  	}
   724  	vm := New()
   725  	b.StartTimer()
   726  	for i := 0; i < b.N; i++ {
   727  		vm.RunProgram(prg)
   728  	}
   729  }
   730  
   731  func BenchmarkRegexpMatch(b *testing.B) {
   732  	const SCRIPT = `
   733          "a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   734           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   735           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   736           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   737           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   738           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   739           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   740           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   741           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   742           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   743          ".match(/[^\r\n]+/g)
   744          `
   745  	b.StopTimer()
   746  	prg, err := Compile("test.js", SCRIPT, false)
   747  	if err != nil {
   748  		b.Fatal(err)
   749  	}
   750  	vm := New()
   751  	b.StartTimer()
   752  	for i := 0; i < b.N; i++ {
   753  		vm.RunProgram(prg)
   754  	}
   755  }
   756  
   757  func BenchmarkRegexpMatchCache(b *testing.B) {
   758  	const SCRIPT = `
   759  	(function() {
   760  		var s = "a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   761           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   762           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   763           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   764           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   765           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   766           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   767           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   768           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   769           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   770           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   771           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   772           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   773           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   774           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   775           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   776           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   777           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   778           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   779           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   780           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   781           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   782           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   783           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   784           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   785           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   786           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   787           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   788           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   789           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   790           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   791           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   792           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   793           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   794           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   795           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   796           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   797          "
   798  		var r = /[^\r\n]+/g
   799  		while(r.exec(s)) {};
   800  	});
   801  	`
   802  	vm := New()
   803  	v, err := vm.RunString(SCRIPT)
   804  	if err != nil {
   805  		b.Fatal(err)
   806  	}
   807  	if fn, ok := AssertFunction(v); ok {
   808  		b.ResetTimer()
   809  		b.ReportAllocs()
   810  		for i := 0; i < b.N; i++ {
   811  			fn(_undefined)
   812  		}
   813  	} else {
   814  		b.Fatal("not a function")
   815  	}
   816  }
   817  
   818  func BenchmarkRegexpMatchAll(b *testing.B) {
   819  	const SCRIPT = `
   820  	(function() {
   821  		var s = "a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   822           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   823           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   824           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   825           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   826           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   827           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   828           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   829           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   830           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   831           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   832           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   833           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   834           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   835           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   836           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   837           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   838           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   839           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   840           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   841           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   842           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   843           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   844           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   845           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   846           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   847           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   848           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   849           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   850           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   851           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   852           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   853           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   854           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   855           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   856           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   857           a\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\ra\nb\r\c\nd\r\e\n\f\rg\nh\r\
   858          "
   859  		var r = /[^\r\n]+/g
   860  		for (var v of s.matchAll(r)) {}
   861  	});
   862  	`
   863  	vm := New()
   864  	v, err := vm.RunString(SCRIPT)
   865  	if err != nil {
   866  		b.Fatal(err)
   867  	}
   868  	if fn, ok := AssertFunction(v); ok {
   869  		b.ResetTimer()
   870  		b.ReportAllocs()
   871  		for i := 0; i < b.N; i++ {
   872  			fn(_undefined)
   873  		}
   874  	} else {
   875  		b.Fatal("not a function")
   876  	}
   877  }
   878  
   879  func BenchmarkRegexpSingleExec(b *testing.B) {
   880  	vm := New()
   881  	regexp := vm.Get("RegExp")
   882  	f := func(reStr, str string, b *testing.B) {
   883  		r, err := vm.New(regexp, vm.ToValue(reStr))
   884  		if err != nil {
   885  			b.Fatal(err)
   886  		}
   887  		exec, ok := AssertFunction(r.Get("exec"))
   888  		if !ok {
   889  			b.Fatal("RegExp.exec is not a function")
   890  		}
   891  		arg := vm.ToValue(str)
   892  		b.ResetTimer()
   893  		b.ReportAllocs()
   894  		for i := 0; i < b.N; i++ {
   895  			_, err := exec(r, arg)
   896  			if err != nil {
   897  				b.Fatal(err)
   898  			}
   899  		}
   900  	}
   901  
   902  	b.Run("Re-ASCII", func(b *testing.B) {
   903  		f("test", "aaaaaaaaaaaaaaaaaaaaaaaaa testing", b)
   904  	})
   905  
   906  	b.Run("Re2-ASCII", func(b *testing.B) {
   907  		f("(?=)test", "aaaaaaaaaaaaaaaaaaaaaaaaa testing", b)
   908  	})
   909  
   910  	b.Run("Re-Unicode", func(b *testing.B) {
   911  		f("test", "aaaaaaaaaaaaaaaaaaaaaaaaa testing 😀", b)
   912  	})
   913  
   914  	b.Run("Re2-Unicode", func(b *testing.B) {
   915  		f("(?=)test", "aaaaaaaaaaaaaaaaaaaaaaaaa testing 😀", b)
   916  	})
   917  
   918  }