Skip to content

Commit 4681ea8

Browse files
committed
[JSC] DFG should not turn a call to RegExp into NewRegExpUntyped
https://bugs.webkit.org/show_bug.cgi?id=327458 rdar://189954203 Reviewed by Dan Hecht. ByteCodeParser::handleConstantFunction lowered RegExp to NewRegExpUntyped without checking whether the site is a construct. For a call, argument 0 is `this`, so `RegExp.call(RegExp, re, undefined)` passed the new.target == callee check and allocated a fresh RegExp. Called as a function, RegExp returns the pattern itself when it is a RegExp, the flags are undefined, and pattern.constructor is RegExp. This patch restricts the lowering to construct sites. Test: JSTests/stress/regexp-constructor-call-is-not-construct.js * JSTests/stress/regexp-constructor-call-is-not-construct.js: Added. (shouldBe): (callWithCalleeAsThis): (construct): * Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleConstantFunction): Canonical link: https://commits.webkit.org/323678@main
1 parent 9f54364 commit 4681ea8

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
function shouldBe(actual, expected, what) {
2+
if (actual !== expected)
3+
throw new Error(what + ": bad value " + actual + ", expected " + expected);
4+
}
5+
6+
function callWithCalleeAsThis(R, pattern, flags) { return R.call(R, pattern, flags); }
7+
noInline(callWithCalleeAsThis);
8+
9+
function construct(R, pattern, flags) { return new R(pattern, flags); }
10+
noInline(construct);
11+
12+
var re = /a/g;
13+
for (var i = 0; i < testLoopCount; ++i) {
14+
shouldBe(callWithCalleeAsThis(RegExp, re, undefined), re, "RegExp(re, undefined)");
15+
16+
var copy = construct(RegExp, re, undefined);
17+
shouldBe(copy !== re, true, "new RegExp(re, undefined) returns a new object");
18+
shouldBe(copy.source, "a", "new RegExp(re, undefined).source");
19+
shouldBe(copy.flags, "g", "new RegExp(re, undefined).flags");
20+
}

‎Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6741,7 +6741,7 @@ bool ByteCodeParser::handleConstantFunction(
67416741
return true;
67426742
}
67436743

6744-
if (function->classInfo() == RegExpConstructor::info()) {
6744+
if (function->classInfo() == RegExpConstructor::info() && kind == CodeSpecializationKind::CodeForConstruct) {
67456745
Node* newTargetNode = get(virtualRegisterForArgumentIncludingThis(0, registerOffset));
67466746
// We cannot handle the case where new.target != callee (i.e. a construct from a super call) because we
67476747
// don't know what the prototype of the constructed object will be.

0 commit comments

Comments
 (0)