Closed Bug 1168257 Opened 9 years ago Closed 9 years ago

String.prototype.replace fails with frozen RegExp param


(Core :: JavaScript Engine, defect)

38 Branch
Not set





(Reporter: adamsmith, Unassigned)




(1 file)

User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36

Steps to reproduce:

The steps to reproduce this bug are simple:
1) Write a script that creates a RegExp, freezes it, and runs string.replace(frozenRegExp, string).
2) Open Firefox (34, 38, 41, ...) any way you desire.
3) Run the script written for step 1.
Note: The attached files will quickly reproduce the error without any difficulty. Plus it contains much greater detail of the problem than provided here.

Actual results:

TypeError: string.replace(...) is read-only

Expected results:

returned new string with replacements
It doesn't work after bug 501739. I'd say it's an issue in your code.
Blocks: 501739
Component: Untriaged → JavaScript Engine
Product: Firefox → Core
The testcase is basically this:

  var regex = /0/g;
  var str = "abc000";
  str.replace(regex, "o");

Per spec this calls which then gets @@replace from the regex and calls that method.

That means that we're calling which in step 10 sees that the global flag on the regex is true and hence does step 10c, which attempts to set the lastIndex property of the regex to 0.  It does so by invoking with the "Throw" argument set to true.  The call to [[Set]] in step 4 there returns false (because the property is readonly), so Set() throws an exception.  This is then propagated out.

So the observed behavior is correct: an exception should be thrown here.
Closed: 9 years ago
Resolution: --- → INVALID
I filed on Chrome here.

Also filed and bug 1168416 on a somewhat related testcase that both SpiderMonkey and V8 get wrong (in slightly different ways).

Step 4.

Since lastIndex is being set to the exactly the same value no error is thrown.
Ever confirmed: true
Resolution: INVALID → ---
Flags: needinfo?(jwalden+bmo)
(In reply to Erik Arvidsson from comment #4)
> validateandapplypropertydescriptor
> Step 4.
> Since lastIndex is being set to the exactly the same value no error is
> thrown. RegExp.prototype [ @@replace ], step 10.c calls [[Set]] (through the Set() abstract operation). And [[Set]], step 5.a returns false which will then lead to Set() throwing the TypeError.
Yes, exactly.  This is not ending up in ValidateAndApplyPropertyDescriptor at all, nor even ending up in DefineOwnProperty.  It bails out directly from [[Set]].
Closed: 9 years ago9 years ago
Flags: needinfo?(jwalden+bmo)
Resolution: --- → INVALID
This is just something that is unfortunately **** in the standard.  The problem is understandable when the regular expression has the global flag set, but unfortunately basically all RegExp operations throw on match failure regardless of the flags due to a mistake in " Runtime Semantics: RegExpBuiltinExec" step 12.a.i which always sets lastIndex to 0 with a throw on failure if the regular expression doesn't successfully match before the end of the string.

The RegExpBuiltinExec step is pointless because if the RegExp is non-global/non-sticky the lastIndex can never have a non-0 value.  In fact that step is one of the only places where lastIndex is touched without gating by global or sticky.  The only other place is in " RegExp.prototype [ @@search ]" where it blindly saves and restores the lastIndex around a call to RegExpBuiltinExec (also pointless if non-global/non-sticky and so should be gated).
Please send spec feedback to
You need to log in before you can comment on or make changes to this bug.