Commit 46406a91 authored by barraclough@apple.com's avatar barraclough@apple.com

RegExp lastIndex should behave as a regular property

https://bugs.webkit.org/show_bug.cgi?id=79446

Reviewed by Sam Weinig.

lastIndex should be a regular data descriptor, with the attributes configurable:false,
enumerable:false, writable:true. As such, it should be possible to reconfigure writable
as false. If the lastIndex property is reconfigured to be read-only, we should respect
this correctly.

Source/JavaScriptCore: 

* runtime/CommonIdentifiers.h:
    - Removed some unused identifiers, added lastIndex.
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::getOwnPropertySlot):
    - lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::getOwnPropertyDescriptor):
    - lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::deleteProperty):
    - lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::getOwnPropertyNames):
    - lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::getPropertyNames):
    - lastIndex is no longer a static value, provided specific handling.
(JSC::reject):
    - helper function for defineOwnProperty.
(JSC::RegExpObject::defineOwnProperty):
    - lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::put):
    - lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::match):
    - Pass setLastIndex an ExecState, so it can throw if read-only.
* runtime/RegExpObject.h:
(JSC::RegExpObject::setLastIndex):
    - Pass setLastIndex an ExecState, so it can throw if read-only.
(RegExpObjectData):
    - Added lastIndexIsWritable.
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncCompile):
    - Pass setLastIndex an ExecState, so it can throw if read-only.

LayoutTests: 

* fast/regex/lastIndex-expected.txt: Added.
* fast/regex/lastIndex.html: Added.
* fast/regex/script-tests/lastIndex.js: Added.
    - Added test cases for correct handling of lastIndex.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@109008 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent a6bdfc82
2012-02-27 Gavin Barraclough <barraclough@apple.com>
RegExp lastIndex should behave as a regular property
https://bugs.webkit.org/show_bug.cgi?id=79446
Reviewed by Sam Weinig.
lastIndex should be a regular data descriptor, with the attributes configurable:false,
enumerable:false, writable:true. As such, it should be possible to reconfigure writable
as false. If the lastIndex property is reconfigured to be read-only, we should respect
this correctly.
* fast/regex/lastIndex-expected.txt: Added.
* fast/regex/lastIndex.html: Added.
* fast/regex/script-tests/lastIndex.js: Added.
- Added test cases for correct handling of lastIndex.
2012-02-27 Adrienne Walker <enne@google.com> 2012-02-27 Adrienne Walker <enne@google.com>
[chromium] Unreviewed gardening, mark getPutImageDataPair as slow [chromium] Unreviewed gardening, mark getPutImageDataPair as slow
This page tests that a RegExp object's lastIndex behaves like a regular property.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS delete /x/.lastIndex is false
PASS 'use strict'; delete /x/.lastIndex threw exception TypeError: Unable to delete property..
PASS 'lastIndex' in /x/ is true
PASS for (property in /x/) if (property === 'lastIndex') throw false; true is true
PASS var re = /x/; re.lastIndex = re; re.lastIndex === re is true
PASS Object.defineProperty(/x/, {get:function(){}}) threw exception TypeError: Property description must be an object..
PASS Object.defineProperty(/x/, 'lastIndex', {enumerable:true}); true threw exception TypeError: Attempting to change enumerable attribute of unconfigurable property..
PASS Object.defineProperty(/x/, 'lastIndex', {enumerable:false}); true is true
PASS Object.defineProperty(/x/, 'lastIndex', {configurable:true}); true threw exception TypeError: Attempting to change configurable attribute of unconfigurable property..
PASS Object.defineProperty(/x/, 'lastIndex', {configurable:false}); true is true
PASS var re = Object.defineProperty(/x/, 'lastIndex', {writable:true}); re.lastIndex = 42; re.lastIndex is 42
PASS var re = Object.defineProperty(/x/, 'lastIndex', {writable:false}); re.lastIndex = 42; re.lastIndex is 0
PASS var re = Object.defineProperty(/x/, 'lastIndex', {value:42}); re.lastIndex is 42
PASS Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {writable:true}); true threw exception TypeError: Attempting to change writable attribute of unconfigurable property..
PASS Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {value:42}); true threw exception TypeError: Attempting to change value of a readonly property..
PASS Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {value:0}); true is true
PASS Object.defineProperty(/x/, 'lastIndex', {writable:false}).exec('') is null
PASS Object.defineProperty(/x/, 'lastIndex', {writable:false}).exec('x') is ["x"]
PASS Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('') threw exception TypeError: Attempted to assign to readonly property..
PASS Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('x') threw exception TypeError: Attempted to assign to readonly property..
PASS var re = /x/; Object.freeze(re); Object.isFrozen(re); is true
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../js/resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/lastIndex.js"></script>
<script src="../js/resources/js-test-post.js"></script>
</body>
</html>
description(
"This page tests that a RegExp object's lastIndex behaves like a regular property."
);
// lastIndex is not configurable
shouldBeFalse("delete /x/.lastIndex");
shouldThrow("'use strict'; delete /x/.lastIndex");
// lastIndex is not enumerable
shouldBeTrue("'lastIndex' in /x/");
shouldBeTrue("for (property in /x/) if (property === 'lastIndex') throw false; true");
// lastIndex is writable
shouldBeTrue("var re = /x/; re.lastIndex = re; re.lastIndex === re");
// Cannot redefine lastIndex as an accessor
shouldThrow("Object.defineProperty(/x/, {get:function(){}})");
// Cannot redefine lastIndex as enumerable
shouldThrow("Object.defineProperty(/x/, 'lastIndex', {enumerable:true}); true");
shouldBeTrue("Object.defineProperty(/x/, 'lastIndex', {enumerable:false}); true");
// Cannot redefine lastIndex as configurable
shouldThrow("Object.defineProperty(/x/, 'lastIndex', {configurable:true}); true");
shouldBeTrue("Object.defineProperty(/x/, 'lastIndex', {configurable:false}); true");
// Can redefine lastIndex as read-only
shouldBe("var re = Object.defineProperty(/x/, 'lastIndex', {writable:true}); re.lastIndex = 42; re.lastIndex", '42');
shouldBe("var re = Object.defineProperty(/x/, 'lastIndex', {writable:false}); re.lastIndex = 42; re.lastIndex", '0');
// Can redefine the value
shouldBe("var re = Object.defineProperty(/x/, 'lastIndex', {value:42}); re.lastIndex", '42');
// Cannot redefine read-only lastIndex as writable
shouldThrow("Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {writable:true}); true");
// Can only redefine the value of a read-only lastIndex as the current value
shouldThrow("Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {value:42}); true");
shouldBeTrue("Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {value:0}); true");
// Trying to run a global regular expression should throw, if lastIndex is read-only
shouldBe("Object.defineProperty(/x/, 'lastIndex', {writable:false}).exec('')", 'null');
shouldBe("Object.defineProperty(/x/, 'lastIndex', {writable:false}).exec('x')", '["x"]');
shouldThrow("Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('')");
shouldThrow("Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('x')");
// Should be able to freeze a regular expression object.
shouldBeTrue("var re = /x/; Object.freeze(re); Object.isFrozen(re);");
2012-02-27 Gavin Barraclough <barraclough@apple.com>
RegExp lastIndex should behave as a regular property
https://bugs.webkit.org/show_bug.cgi?id=79446
Reviewed by Sam Weinig.
lastIndex should be a regular data descriptor, with the attributes configurable:false,
enumerable:false, writable:true. As such, it should be possible to reconfigure writable
as false. If the lastIndex property is reconfigured to be read-only, we should respect
this correctly.
* runtime/CommonIdentifiers.h:
- Removed some unused identifiers, added lastIndex.
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::getOwnPropertySlot):
- lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::getOwnPropertyDescriptor):
- lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::deleteProperty):
- lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::getOwnPropertyNames):
- lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::getPropertyNames):
- lastIndex is no longer a static value, provided specific handling.
(JSC::reject):
- helper function for defineOwnProperty.
(JSC::RegExpObject::defineOwnProperty):
- lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::put):
- lastIndex is no longer a static value, provided specific handling.
(JSC::RegExpObject::match):
- Pass setLastIndex an ExecState, so it can throw if read-only.
* runtime/RegExpObject.h:
(JSC::RegExpObject::setLastIndex):
- Pass setLastIndex an ExecState, so it can throw if read-only.
(RegExpObjectData):
- Added lastIndexIsWritable.
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncCompile):
- Pass setLastIndex an ExecState, so it can throw if read-only.
2012-02-27 Gavin Barraclough <barraclough@apple.com> 2012-02-27 Gavin Barraclough <barraclough@apple.com>
Implement support for op_negate and op_bitnot in the DFG JIT Implement support for op_negate and op_bitnot in the DFG JIT
...@@ -27,10 +27,6 @@ ...@@ -27,10 +27,6 @@
// MarkedArgumentBuffer of property names, passed to a macro so we can do set them up various // MarkedArgumentBuffer of property names, passed to a macro so we can do set them up various
// ways without repeating the list. // ways without repeating the list.
#define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \ #define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
macro(__defineGetter__) \
macro(__defineSetter__) \
macro(__lookupGetter__) \
macro(__lookupSetter__) \
macro(apply) \ macro(apply) \
macro(arguments) \ macro(arguments) \
macro(bind) \ macro(bind) \
...@@ -52,6 +48,7 @@ ...@@ -52,6 +48,7 @@
macro(input) \ macro(input) \
macro(isArray) \ macro(isArray) \
macro(isPrototypeOf) \ macro(isPrototypeOf) \
macro(lastIndex) \
macro(length) \ macro(length) \
macro(message) \ macro(message) \
macro(multiline) \ macro(multiline) \
......
...@@ -40,8 +40,6 @@ static JSValue regExpObjectGlobal(ExecState*, JSValue, const Identifier&); ...@@ -40,8 +40,6 @@ static JSValue regExpObjectGlobal(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectIgnoreCase(ExecState*, JSValue, const Identifier&); static JSValue regExpObjectIgnoreCase(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectMultiline(ExecState*, JSValue, const Identifier&); static JSValue regExpObjectMultiline(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectSource(ExecState*, JSValue, const Identifier&); static JSValue regExpObjectSource(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectLastIndex(ExecState*, JSValue, const Identifier&);
static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue);
} // namespace JSC } // namespace JSC
...@@ -59,7 +57,6 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &JSNonFinalObject::s_info, 0, ...@@ -59,7 +57,6 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &JSNonFinalObject::s_info, 0,
ignoreCase regExpObjectIgnoreCase DontDelete|ReadOnly|DontEnum ignoreCase regExpObjectIgnoreCase DontDelete|ReadOnly|DontEnum
multiline regExpObjectMultiline DontDelete|ReadOnly|DontEnum multiline regExpObjectMultiline DontDelete|ReadOnly|DontEnum
source regExpObjectSource DontDelete|ReadOnly|DontEnum source regExpObjectSource DontDelete|ReadOnly|DontEnum
lastIndex regExpObjectLastIndex DontDelete|DontEnum
@end @end
*/ */
...@@ -95,14 +92,79 @@ void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor) ...@@ -95,14 +92,79 @@ void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
bool RegExpObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) bool RegExpObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{ {
if (propertyName == exec->propertyNames().lastIndex) {
RegExpObject* regExp = asRegExpObject(cell);
slot.setValue(regExp, regExp->getLastIndex());
return true;
}
return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), propertyName, slot); return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), propertyName, slot);
} }
bool RegExpObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) bool RegExpObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{ {
if (propertyName == exec->propertyNames().lastIndex) {
RegExpObject* regExp = asRegExpObject(object);
descriptor.setDescriptor(regExp->getLastIndex(), regExp->d->lastIndexIsWritable ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly);
return true;
}
return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(object), propertyName, descriptor); return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(object), propertyName, descriptor);
} }
bool RegExpObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
{
if (propertyName == exec->propertyNames().lastIndex)
return false;
return Base::deleteProperty(cell, exec, propertyName);
}
void RegExpObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
if (mode == IncludeDontEnumProperties)
propertyNames.add(exec->propertyNames().lastIndex);
Base::getOwnPropertyNames(object, exec, propertyNames, mode);
}
void RegExpObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
if (mode == IncludeDontEnumProperties)
propertyNames.add(exec->propertyNames().lastIndex);
Base::getPropertyNames(object, exec, propertyNames, mode);
}
static bool reject(ExecState* exec, bool throwException, const char* message)
{
if (throwException)
throwTypeError(exec, message);
return false;
}
bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
{
if (propertyName == exec->propertyNames().lastIndex) {
RegExpObject* regExp = asRegExpObject(object);
if (descriptor.configurablePresent() && descriptor.configurable())
return reject(exec, shouldThrow, "Attempting to change configurable attribute of unconfigurable property.");
if (descriptor.enumerablePresent() && descriptor.enumerable())
return reject(exec, shouldThrow, "Attempting to change enumerable attribute of unconfigurable property.");
if (descriptor.isAccessorDescriptor())
return reject(exec, shouldThrow, "Attempting to change access mechanism for an unconfigurable property.");
if (!regExp->d->lastIndexIsWritable) {
if (descriptor.writablePresent() && descriptor.writable())
return reject(exec, shouldThrow, "Attempting to change writable attribute of unconfigurable property.");
if (!sameValue(exec, regExp->getLastIndex(), descriptor.value()))
return reject(exec, shouldThrow, "Attempting to change value of a readonly property.");
return true;
}
if (descriptor.writablePresent() && !descriptor.writable())
regExp->d->lastIndexIsWritable = false;
if (descriptor.value())
regExp->setLastIndex(exec, descriptor.value(), false);
return true;
}
return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
}
JSValue regExpObjectGlobal(ExecState*, JSValue slotBase, const Identifier&) JSValue regExpObjectGlobal(ExecState*, JSValue slotBase, const Identifier&)
{ {
return jsBoolean(asRegExpObject(slotBase)->regExp()->global()); return jsBoolean(asRegExpObject(slotBase)->regExp()->global());
...@@ -200,21 +262,15 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&) ...@@ -200,21 +262,15 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
return jsString(exec, result.toUString()); return jsString(exec, result.toUString());
} }
JSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&)
{
return asRegExpObject(slotBase)->getLastIndex();
}
void RegExpObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) void RegExpObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{ {
if (propertyName == exec->propertyNames().lastIndex) {
asRegExpObject(cell)->setLastIndex(exec, value, slot.isStrictMode());
return;
}
lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), slot); lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), slot);
} }
void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value)
{
asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value);
}
JSValue RegExpObject::test(ExecState* exec) JSValue RegExpObject::test(ExecState* exec)
{ {
return jsBoolean(match(exec)); return jsBoolean(match(exec));
...@@ -245,13 +301,13 @@ bool RegExpObject::match(ExecState* exec) ...@@ -245,13 +301,13 @@ bool RegExpObject::match(ExecState* exec)
if (LIKELY(jsLastIndex.isUInt32())) { if (LIKELY(jsLastIndex.isUInt32())) {
lastIndex = jsLastIndex.asUInt32(); lastIndex = jsLastIndex.asUInt32();
if (lastIndex > input.length()) { if (lastIndex > input.length()) {
setLastIndex(0); setLastIndex(exec, 0);
return false; return false;
} }
} else { } else {
double doubleLastIndex = jsLastIndex.toInteger(exec); double doubleLastIndex = jsLastIndex.toInteger(exec);
if (doubleLastIndex < 0 || doubleLastIndex > input.length()) { if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
setLastIndex(0); setLastIndex(exec, 0);
return false; return false;
} }
lastIndex = static_cast<unsigned>(doubleLastIndex); lastIndex = static_cast<unsigned>(doubleLastIndex);
...@@ -261,11 +317,11 @@ bool RegExpObject::match(ExecState* exec) ...@@ -261,11 +317,11 @@ bool RegExpObject::match(ExecState* exec)
int length = 0; int length = 0;
regExpConstructor->performMatch(*globalData, d->regExp.get(), input, lastIndex, position, length); regExpConstructor->performMatch(*globalData, d->regExp.get(), input, lastIndex, position, length);
if (position < 0) { if (position < 0) {
setLastIndex(0); setLastIndex(exec, 0);
return false; return false;
} }
setLastIndex(position + length); setLastIndex(exec, position + length);
return true; return true;
} }
......
...@@ -47,13 +47,20 @@ namespace JSC { ...@@ -47,13 +47,20 @@ namespace JSC {
void setRegExp(JSGlobalData& globalData, RegExp* r) { d->regExp.set(globalData, this, r); } void setRegExp(JSGlobalData& globalData, RegExp* r) { d->regExp.set(globalData, this, r); }
RegExp* regExp() const { return d->regExp.get(); } RegExp* regExp() const { return d->regExp.get(); }
void setLastIndex(size_t lastIndex) void setLastIndex(ExecState* exec, size_t lastIndex)
{ {
d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex)); d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
if (LIKELY(d->lastIndexIsWritable))
d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
else
throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
} }
void setLastIndex(JSGlobalData& globalData, JSValue lastIndex) void setLastIndex(ExecState* exec, JSValue lastIndex, bool shouldThrow)
{ {
d->lastIndex.set(globalData, this, lastIndex); if (LIKELY(d->lastIndexIsWritable))
d->lastIndex.set(exec->globalData(), this, lastIndex);
else if (shouldThrow)
throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
} }
JSValue getLastIndex() const JSValue getLastIndex() const
{ {
...@@ -83,6 +90,11 @@ namespace JSC { ...@@ -83,6 +90,11 @@ namespace JSC {
static void visitChildren(JSCell*, SlotVisitor&); static void visitChildren(JSCell*, SlotVisitor&);
JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
private: private:
bool match(ExecState*); bool match(ExecState*);
...@@ -91,12 +103,14 @@ namespace JSC { ...@@ -91,12 +103,14 @@ namespace JSC {
public: public:
RegExpObjectData(JSGlobalData& globalData, RegExpObject* owner, RegExp* regExp) RegExpObjectData(JSGlobalData& globalData, RegExpObject* owner, RegExp* regExp)
: regExp(globalData, owner, regExp) : regExp(globalData, owner, regExp)
, lastIndexIsWritable(true)
{ {
lastIndex.setWithoutWriteBarrier(jsNumber(0)); lastIndex.setWithoutWriteBarrier(jsNumber(0));
} }
WriteBarrier<RegExp> regExp; WriteBarrier<RegExp> regExp;
WriteBarrier<Unknown> lastIndex; WriteBarrier<Unknown> lastIndex;
bool lastIndexIsWritable;
}; };
#if COMPILER(MSVC) #if COMPILER(MSVC)
friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*); friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*);
......
...@@ -129,7 +129,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) ...@@ -129,7 +129,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage())); return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
asRegExpObject(thisValue)->setRegExp(exec->globalData(), regExp); asRegExpObject(thisValue)->setRegExp(exec->globalData(), regExp);
asRegExpObject(thisValue)->setLastIndex(0); asRegExpObject(thisValue)->setLastIndex(exec, 0);
return JSValue::encode(jsUndefined()); return JSValue::encode(jsUndefined());
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment