Commit 1c4a32c9 authored by fpizlo@apple.com's avatar fpizlo@apple.com

If a prototype has indexed setters and its instances have indexed storage,...

If a prototype has indexed setters and its instances have indexed storage, then all put_by_val's should have a bad time
https://bugs.webkit.org/show_bug.cgi?id=96596

Reviewed by Gavin Barraclough.

Source/JavaScriptCore: 

Added comprehensive support for accessors and read-only indexed properties on the
prototype chain. This is done without any performance regression on benchmarks that
we're aware of, by having the entire VM's strategy with respect to arrays tilted
heavily in favor of:
        
- The prototype chain of JSArrays never having any accessors or read-only indexed
  properties. If that changes, you're going to have a bad time.
        
- Prototypes of non-JSArray objects either having no indexed accessors or read-only
  indexed properties, or, having those indexed accessor thingies inserted before
  any instance object (i.e. object with that prototype as its prototype) is created.
  If you add indexed accessors or read-only indexed properties to an object that is
  already used as a prototype, you're going to have a bad time.
        
See below for the exact definition of having a bad time.
        
Put another way, "fair" uses of indexed accessors and read-only indexed properties
are:
        
- Put indexed accessors and read-only indexed properties on an object that is never
  used as a prototype. This will slow down accesses to that object, but will not
  have any effect on any other object.
        
- Put those indexed accessor thingies on an object before it is used as a prototype
  and then start instantiating objects that claim that object as their prototype.
  This will slightly slow down indexed stores to the instance objects, and greatly
  slow down all indexed accesses to the prototype, but will have no other effect.
        
In short, "fair" uses only affect the object itself and any instance objects. But
if you start using indexed accessors in more eclectic ways, you're going to have
a bad time.
        
Specifically, if an object that may be used as a prototype has an indexed accessor
added, the VM performs a whole-heap scan to find all objects that belong to the
same global object as the prototype you modified. If any of those objects has
indexed storage, their indexed storage is put into slow-put mode, just as if their
prototype chain had indexed accessors. This will happen even for objects that do
not currently have indexed accessors in their prototype chain. As well, all JSArray
allocations are caused to create arrays with slow-put storage, and all future
allocations of indexed storage for non-JSArray objects are also flipped to slow-put
mode. Note there are two aspects to having a bad time: (i) the whole-heap scan and
(ii) the poisoning of all indexed storage in the entire global object. (i) is
necessary for correctness. If we detect that an object that may be used as a
prototype has had an indexed accessor or indexed read-only property inserted into
it, then we need to ensure that henceforth all instances of that object inspect
the prototype chain whenever an indexed hole is stored to. But by default, indexed
stores do no such checking because doing so would be unnecessarily slow. So, we must
find all instances of the affected object and flip them into a different array
storage mode that omits all hole optimizations. Since prototypes never keep a list
of instance objects, the only way to find those objects is a whole-heap scan. But
(i) alone would be a potential disaster, if a program frequently allocated an
object without indexed accessors, then allocated a bunch of objects that used that
one as their prototype, and then added indexed accessors to the prototype. So, to
prevent massive heap scan storms in such awkward programs, having a bad time also
implies (ii): henceforth *all* objects belonging to that global object will use
slow put indexed storage, so that we don't ever have to scan the heap again. Note
that here we are using the global object as just an approximation of a program
module; it may be worth investigating in the future if other approximations can be
used instead.

* bytecode/ArrayProfile.h:
(JSC):
(JSC::arrayModeFromStructure):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGArrayMode.cpp:
(JSC::DFG::fromObserved):
(JSC::DFG::modeAlreadyChecked):
(JSC::DFG::modeToString):
* dfg/DFGArrayMode.h:
(DFG):
(JSC::DFG::isSlowPutAccess):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::checkArray):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/JIT.h:
* jit/JITInlineMethods.h:
(JSC::JIT::emitAllocateJSArray):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_new_array):
* runtime/ArrayPrototype.cpp:
(JSC::ArrayPrototype::finishCreation):
(JSC::arrayProtoFuncSort):
* runtime/IndexingType.h:
(JSC):
(JSC::hasIndexedProperties):
(JSC::hasIndexingHeader):
(JSC::hasArrayStorage):
(JSC::shouldUseSlowPut):
* runtime/JSArray.cpp:
(JSC::JSArray::pop):
(JSC::JSArray::push):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToArguments):
* runtime/JSArray.h:
(JSC::JSArray::createStructure):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::JSGlobalObject):
(JSC::JSGlobalObject::reset):
(JSC):
(JSC::JSGlobalObject::haveABadTime):
* runtime/JSGlobalObject.h:
(JSGlobalObject):
(JSC::JSGlobalObject::addressOfArrayStructure):
(JSC::JSGlobalObject::havingABadTimeWatchpoint):
(JSC::JSGlobalObject::isHavingABadTime):
* runtime/JSObject.cpp:
(JSC::JSObject::visitButterfly):
(JSC::JSObject::getOwnPropertySlotByIndex):
(JSC::JSObject::put):
(JSC::JSObject::putByIndex):
(JSC::JSObject::enterDictionaryIndexingMode):
(JSC::JSObject::notifyPresenceOfIndexedAccessors):
(JSC):
(JSC::JSObject::createArrayStorage):
(JSC::JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode):
(JSC::JSObject::switchToSlowPutArrayStorage):
(JSC::JSObject::setPrototype):
(JSC::JSObject::resetInheritorID):
(JSC::JSObject::inheritorID):
(JSC::JSObject::allowsAccessFrom):
(JSC::JSObject::deletePropertyByIndex):
(JSC::JSObject::getOwnPropertyNames):
(JSC::JSObject::unwrappedGlobalObject):
(JSC::JSObject::notifyUsedAsPrototype):
(JSC::JSObject::createInheritorID):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::attemptToInterceptPutByIndexOnHoleForPrototype):
(JSC::JSObject::attemptToInterceptPutByIndexOnHole):
(JSC::JSObject::putByIndexBeyondVectorLength):
(JSC::JSObject::putDirectIndexBeyondVectorLength):
(JSC::JSObject::getNewVectorLength):
(JSC::JSObject::getOwnPropertyDescriptor):
* runtime/JSObject.h:
(JSC::JSObject::mayBeUsedAsPrototype):
(JSObject):
(JSC::JSObject::mayInterceptIndexedAccesses):
(JSC::JSObject::getArrayLength):
(JSC::JSObject::getVectorLength):
(JSC::JSObject::canGetIndexQuickly):
(JSC::JSObject::getIndexQuickly):
(JSC::JSObject::canSetIndexQuickly):
(JSC::JSObject::setIndexQuickly):
(JSC::JSObject::initializeIndex):
(JSC::JSObject::completeInitialization):
(JSC::JSObject::inSparseIndexingMode):
(JSC::JSObject::arrayStorage):
(JSC::JSObject::arrayStorageOrNull):
(JSC::JSObject::ensureArrayStorage):
(JSC):
(JSC::JSValue::putByIndex):
* runtime/JSValue.cpp:
(JSC::JSValue::putToPrimitive):
(JSC::JSValue::putToPrimitiveByIndex):
(JSC):
* runtime/JSValue.h:
(JSValue):
* runtime/ObjectPrototype.cpp:
(JSC::ObjectPrototype::finishCreation):
* runtime/SparseArrayValueMap.cpp:
(JSC::SparseArrayValueMap::putEntry):
(JSC::SparseArrayEntry::put):
(JSC):
* runtime/SparseArrayValueMap.h:
(JSC):
(SparseArrayEntry):
* runtime/Structure.cpp:
(JSC::Structure::anyObjectInChainMayInterceptIndexedAccesses):
(JSC):
(JSC::Structure::suggestedIndexingTransition):
* runtime/Structure.h:
(Structure):
(JSC::Structure::mayInterceptIndexedAccesses):
* runtime/StructureTransitionTable.h:
(JSC::newIndexingType):

LayoutTests: 

Removed failing expectation for primitive-property-access-edge-cases, and
added more tests to cover the numerical-setter-on-prototype cases.

* fast/js/array-bad-time-expected.txt: Added.
* fast/js/array-bad-time.html: Added.
* fast/js/array-slow-put-expected.txt: Added.
* fast/js/array-slow-put.html: Added.
* fast/js/cross-frame-bad-time-expected.txt: Added.
* fast/js/cross-frame-bad-time.html: Added.
* fast/js/jsc-test-list:
* fast/js/object-bad-time-expected.txt: Added.
* fast/js/object-bad-time.html: Added.
* fast/js/object-slow-put-expected.txt: Added.
* fast/js/object-slow-put.html: Added.
* fast/js/script-tests/array-bad-time.js: Added.
* fast/js/script-tests/array-slow-put.js: Added.
(foo):
* fast/js/script-tests/cross-frame-bad-time.js: Added.
(foo):
* fast/js/script-tests/object-bad-time.js: Added.
(Cons):
* fast/js/script-tests/object-slow-put.js: Added.
(Cons):
(foo):
* platform/mac/fast/js/primitive-property-access-edge-cases-expected.txt: Removed.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@128802 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9c82b2de
2012-09-17 Filip Pizlo <fpizlo@apple.com>
If a prototype has indexed setters and its instances have indexed storage, then all put_by_val's should have a bad time
https://bugs.webkit.org/show_bug.cgi?id=96596
Reviewed by Gavin Barraclough.
Removed failing expectation for primitive-property-access-edge-cases, and
added more tests to cover the numerical-setter-on-prototype cases.
* fast/js/array-bad-time-expected.txt: Added.
* fast/js/array-bad-time.html: Added.
* fast/js/array-slow-put-expected.txt: Added.
* fast/js/array-slow-put.html: Added.
* fast/js/cross-frame-bad-time-expected.txt: Added.
* fast/js/cross-frame-bad-time.html: Added.
* fast/js/jsc-test-list:
* fast/js/object-bad-time-expected.txt: Added.
* fast/js/object-bad-time.html: Added.
* fast/js/object-slow-put-expected.txt: Added.
* fast/js/object-slow-put.html: Added.
* fast/js/script-tests/array-bad-time.js: Added.
* fast/js/script-tests/array-slow-put.js: Added.
(foo):
* fast/js/script-tests/cross-frame-bad-time.js: Added.
(foo):
* fast/js/script-tests/object-bad-time.js: Added.
(Cons):
* fast/js/script-tests/object-slow-put.js: Added.
(Cons):
(foo):
* platform/mac/fast/js/primitive-property-access-edge-cases-expected.txt: Removed.
2012-09-17 Tony Chang <tony@chromium.org>
[chromium] Unreviewed, updating some bug numbers in TestExpectations.
This diff is collapsed.
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/array-bad-time.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
Tests that defining a setter on the Array prototype works.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
PASS ouches is 100
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/array-slow-put.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
Tests that having a bad time has correct cross frame behavior.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS Got 100 ouches.
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<iframe id="myframe"></iframe>
<script src="script-tests/cross-frame-bad-time.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
......@@ -2,6 +2,7 @@ fast/js/add-recovery
fast/js/apply-varargs
fast/js/arguments-bad-index
fast/js/arguments
fast/js/array-bad-time
fast/js/array-constructor-host-call
fast/js/array-defineOwnProperty
fast/js/array-enumerators-functions
......@@ -19,6 +20,7 @@ fast/js/array-proto-func-property-getter-except
fast/js/array-reduce
fast/js/array-reduceRight
fast/js/array-reset-large-index
fast/js/array-slow-put
fast/js/array-sort-numericCompare
fast/js/array-sort-reentrance
fast/js/array-splice
......@@ -229,8 +231,10 @@ fast/js/Object-defineProperties
fast/js/Object-defineProperty
fast/js/Object-getOwnPropertyNames
fast/js/Object-keys
fast/js/object-bad-time
fast/js/object-literal-direct-put
fast/js/object-literal-syntax
fast/js/object-slow-put
fast/js/order-of-operations
fast/js/parse-backslash-before-newline
fast/js/parse-nan
......
This diff is collapsed.
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/object-bad-time.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
Tests that defining a setter on the prototype of an object used for indexed storage works.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
Ouch!
PASS "0,1,2,,4" is "0,1,2,,4"
PASS ouches is 100
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/object-slow-put.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
description(
"Tests that defining a setter on the Array prototype works even if it is done after arrays are allocated."
);
var ouches = 0;
function foo(haveABadTime) {
var result = [];
result.length = 5;
for (var i = 0; i < result.length; ++i) {
if (i == haveABadTime) {
debug("Henceforth I will have a bad time.");
Array.prototype.__defineSetter__("3", function() { debug("Ouch!"); ouches++; });
}
result[i] = i;
}
return result;
}
var expected = "\"0,1,2,3,4\"";
for (var i = 0; i < 1000; ++i) {
var haveABadTime;
if (i == 950) {
haveABadTime = 2;
expected = "\"0,1,2,,4\"";
} else
haveABadTime = -1;
shouldBe("\"" + foo(haveABadTime).join(",") + "\"", expected);
}
shouldBe("ouches", "50");
description(
"Tests that defining a setter on the Array prototype works."
);
var ouches = 0;
Array.prototype.__defineSetter__("3", function() { debug("Ouch!"); ouches++; });
function foo() {
var result = [];
result.length = 5;
for (var i = 0; i < result.length; ++i)
result[i] = i;
return result;
}
for (var i = 0; i < 100; ++i)
shouldBe("\"" + foo().join(",") + "\"", "\"0,1,2,,4\"");
shouldBe("ouches", "100");
description(
"Tests that having a bad time has correct cross frame behavior."
);
if (window.testRunner)
testRunner.waitUntilDone();
var ouches = 0;
function foo(array) {
for (var i = 0; i < 100; ++i)
array[0] = true;
if (ouches == 100)
testPassed("Got 100 ouches.");
else
testFailed("Did not get 100 ouches. Got " + ouches + " instead.");
if (testRunner)
testRunner.notifyDone();
}
var frame = document.getElementById("myframe");