Pārlūkot izejas kodu

Skip new regexp allocation for standard regexes in split(). See #201

Dmitry Panov 5 gadi atpakaļ
vecāks
revīzija
ac41584057
2 mainītis faili ar 36 papildinājumiem un 13 dzēšanām
  1. 16 13
      builtin_regexp.go
  2. 20 0
      regexp_test.go

+ 16 - 13
builtin_regexp.go

@@ -852,21 +852,24 @@ func advanceStringIndex(s valueString, pos int, unicode bool) int {
 
 
 func (r *Runtime) regexpproto_stdSplitter(call FunctionCall) Value {
 func (r *Runtime) regexpproto_stdSplitter(call FunctionCall) Value {
 	rxObj := r.toObject(call.This)
 	rxObj := r.toObject(call.This)
-	c := r.speciesConstructor(rxObj, r.global.RegExp)
-	flags := nilSafe(rxObj.self.getStr("flags", nil)).toString()
-	flagsStr := flags.String()
-
-	// Add 'y' flag if missing
-	if !strings.Contains(flagsStr, "y") {
-		flags = newStringValue(flagsStr + "y")
-	}
-	splitter := c([]Value{rxObj, flags}, nil)
-
 	s := call.Argument(0).toString()
 	s := call.Argument(0).toString()
 	limitValue := call.Argument(1)
 	limitValue := call.Argument(1)
-	search := r.checkStdRegexp(splitter)
-	if search == nil {
-		return r.regexpproto_stdSplitterGeneric(splitter, s, limitValue, strings.Contains(flagsStr, "u"))
+	var splitter *Object
+	search := r.checkStdRegexp(rxObj)
+	c := r.speciesConstructorObj(rxObj, r.global.RegExp)
+	if search == nil || c != r.global.RegExp {
+		flags := nilSafe(rxObj.self.getStr("flags", nil)).toString()
+		flagsStr := flags.String()
+
+		// Add 'y' flag if missing
+		if !strings.Contains(flagsStr, "y") {
+			flags = flags.concat(asciiString("y"))
+		}
+		splitter = r.toConstructor(c)([]Value{rxObj, flags}, nil)
+		search = r.checkStdRegexp(splitter)
+		if search == nil {
+			return r.regexpproto_stdSplitterGeneric(splitter, s, limitValue, strings.Contains(flagsStr, "u"))
+		}
 	}
 	}
 
 
 	limit := -1
 	limit := -1

+ 20 - 0
regexp_test.go

@@ -458,6 +458,26 @@ func TestRegexpConsecutiveMatchCache(t *testing.T) {
 
 
 }
 }
 
 
+func TestRegexpOverrideSpecies(t *testing.T) {
+	const SCRIPT = `
+	Object.defineProperty(RegExp, Symbol.species, {
+		configurable: true,
+		value: function() {
+			throw "passed";
+		}
+	});
+	try {
+		"ab".split(/a/);
+		throw new Error("Expected error");
+	} catch(e) {
+		if (e !== "passed") {
+			throw e;
+		}
+	}
+	`
+	testScript1(SCRIPT, _undefined, t)
+}
+
 func BenchmarkRegexpSplitWithBackRef(b *testing.B) {
 func BenchmarkRegexpSplitWithBackRef(b *testing.B) {
 	const SCRIPT = `
 	const SCRIPT = `
 	"aaaaaaaaaaaaaaaaaaaaaaaaa++bbbbbbbbbbbbbbbbbbbbbb+-ccccccccccccccccccccccc".split(/([+-])\1/)
 	"aaaaaaaaaaaaaaaaaaaaaaaaa++bbbbbbbbbbbbbbbbbbbbbb+-ccccccccccccccccccccccc".split(/([+-])\1/)