https://bugs.webkit.org/show_bug.cgi?id=68676
Patch by Filip Pizlo <fpizlo@apple.com> on 2011-09-22
Reviewed by Oliver Hunt.
Added GetScopedVar value profiling and predictin propagation.
Added GetScopeChain to CSE.
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::predict):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasPrediction):
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::getScopeChainLoadElimination):
(JSC::DFG::Propagator::performNodeCSE):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_scoped_var):
LayoutTests: [Qt] Unreviewed gardening, update expected file after r95745.
Patch by Csaba Osztrogonác <ossy@webkit.org> on 2011-09-22
* platform/qt/editing/deleting/merge-whitespace-pre-expected.png:
* platform/qt/editing/deleting/merge-whitespace-pre-expected.txt:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95787
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
2011-09-22 Gavin Barraclough <barraclough@apple.com>
+ Incorrect this value passed to callbacks.
+ https://bugs.webkit.org/show_bug.cgi?id=68668
+
+ Reviewed by Oliver Hunt.
+
+ From Array/String prototype function. Should be undefined, but
+ global object is passed instead (this is visible for strict callbacks).
+
+ * fast/js/array-prototype-properties-expected.txt:
+ * fast/js/script-tests/strict-callback-this.js: Added.
+ (strictThrowThisString):
+ (nonstrictThrowThisString):
+ (testArrayPrototypeSort):
+ (testArrayPrototypeFilter):
+ (testArrayPrototypeMap):
+ (testArrayPrototypeEvery):
+ (testArrayPrototypeForEach):
+ (testArrayPrototypeSome):
+ (testStringPrototypeReplace):
+ * fast/js/strict-callback-this-expected.txt: Added.
+ * fast/js/strict-callback-this.html: Added.
+ * ietestcenter/Javascript/15.3.4.5-0-2-expected.txt:
+
+2011-09-22 Gavin Barraclough <barraclough@apple.com>
+
Function.prototype.bind.length shoudl be 1.
Rubber stamped by Olier Hunt.
FAIL Array.prototype.filter.call(undefined, toString) should throw an exception. Was [object Object].
FAIL Array.prototype.reduce.call(undefined, toString) should throw an exception. Was [object Object].
FAIL Array.prototype.reduceRight.call(undefined, toString) should throw an exception. Was [object Object].
-FAIL Array.prototype.map.call(undefined, toString) should throw an exception. Was [object DOMWindow].
+FAIL Array.prototype.map.call(undefined, toString) should throw an exception. Was [object Undefined].
PASS successfullyParsed is true
TEST COMPLETE
--- /dev/null
+description(
+"This tests that a call to array/string prototype methods pass the correct this value (undefined) to strict callees."
+);
+
+var undefinedString = String(undefined);
+var globalObjectString = String(this);
+
+function strictThrowThisString()
+{
+ "use strict";
+ throw String(this);
+}
+
+function nonstrictThrowThisString()
+{
+ throw String(this);
+}
+
+function testArrayPrototypeSort(callback)
+{
+ try {
+ [1,2].sort(callback);
+ } catch (e) {
+ return e;
+ }
+ return "FAILED";
+}
+
+function testArrayPrototypeFilter(callback)
+{
+ try {
+ [1,2].filter(callback);
+ } catch (e) {
+ return e;
+ }
+ return "FAILED";
+}
+
+function testArrayPrototypeMap(callback)
+{
+ try {
+ [1,2].map(callback);
+ } catch (e) {
+ return e;
+ }
+ return "FAILED";
+}
+
+function testArrayPrototypeEvery(callback)
+{
+ try {
+ [1,2].every(callback);
+ } catch (e) {
+ return e;
+ }
+ return "FAILED";
+}
+
+function testArrayPrototypeForEach(callback)
+{
+ try {
+ [1,2].forEach(callback);
+ } catch (e) {
+ return e;
+ }
+ return "FAILED";
+}
+
+function testArrayPrototypeSome(callback)
+{
+ try {
+ [1,2].some(callback);
+ } catch (e) {
+ return e;
+ }
+ return "FAILED";
+}
+
+function testStringPrototypeReplace(callback)
+{
+ try {
+ "1,2".replace('1', callback);
+ } catch (e) {
+ return e;
+ }
+ return "FAILED";
+}
+
+shouldBe('testArrayPrototypeSort(strictThrowThisString)', 'undefinedString');
+shouldBe('testArrayPrototypeFilter(strictThrowThisString)', 'undefinedString');
+shouldBe('testArrayPrototypeMap(strictThrowThisString)', 'undefinedString');
+shouldBe('testArrayPrototypeEvery(strictThrowThisString)', 'undefinedString');
+shouldBe('testArrayPrototypeForEach(strictThrowThisString)', 'undefinedString');
+shouldBe('testArrayPrototypeSome(strictThrowThisString)', 'undefinedString');
+shouldBe('testStringPrototypeReplace(strictThrowThisString)', 'undefinedString');
+
+shouldBe('testArrayPrototypeSort(nonstrictThrowThisString)', 'globalObjectString');
+shouldBe('testArrayPrototypeFilter(nonstrictThrowThisString)', 'globalObjectString');
+shouldBe('testArrayPrototypeMap(nonstrictThrowThisString)', 'globalObjectString');
+shouldBe('testArrayPrototypeEvery(nonstrictThrowThisString)', 'globalObjectString');
+shouldBe('testArrayPrototypeForEach(nonstrictThrowThisString)', 'globalObjectString');
+shouldBe('testArrayPrototypeSome(nonstrictThrowThisString)', 'globalObjectString');
+shouldBe('testStringPrototypeReplace(nonstrictThrowThisString)', 'globalObjectString');
+
+var successfullyParsed = true;
--- /dev/null
+This tests that a call to array/string prototype methods pass the correct this value (undefined) to strict callees.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS testArrayPrototypeSort(strictThrowThisString) is undefinedString
+PASS testArrayPrototypeFilter(strictThrowThisString) is undefinedString
+PASS testArrayPrototypeMap(strictThrowThisString) is undefinedString
+PASS testArrayPrototypeEvery(strictThrowThisString) is undefinedString
+PASS testArrayPrototypeForEach(strictThrowThisString) is undefinedString
+PASS testArrayPrototypeSome(strictThrowThisString) is undefinedString
+PASS testStringPrototypeReplace(strictThrowThisString) is undefinedString
+PASS testArrayPrototypeSort(nonstrictThrowThisString) is globalObjectString
+PASS testArrayPrototypeFilter(nonstrictThrowThisString) is globalObjectString
+PASS testArrayPrototypeMap(nonstrictThrowThisString) is globalObjectString
+PASS testArrayPrototypeEvery(nonstrictThrowThisString) is globalObjectString
+PASS testArrayPrototypeForEach(nonstrictThrowThisString) is globalObjectString
+PASS testArrayPrototypeSome(nonstrictThrowThisString) is globalObjectString
+PASS testStringPrototypeReplace(nonstrictThrowThisString) is globalObjectString
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/strict-callback-this.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
2011-09-22 Gavin Barraclough <barraclough@apple.com>
+ Incorrect this value passed to callbacks.
+ https://bugs.webkit.org/show_bug.cgi?id=68668
+
+ Reviewed by Oliver Hunt.
+
+ From Array/String prototype function. Should be undefined, but
+ global object is passed instead (this is visible for strict callbacks).
+
+ * runtime/ArrayPrototype.cpp:
+ (JSC::arrayProtoFuncSort):
+ (JSC::arrayProtoFuncFilter):
+ (JSC::arrayProtoFuncMap):
+ (JSC::arrayProtoFuncEvery):
+ (JSC::arrayProtoFuncForEach):
+ (JSC::arrayProtoFuncSome):
+ * runtime/JSArray.cpp:
+ (JSC::AVLTreeAbstractorForArrayCompare::compare_key_key):
+ (JSC::JSArray::sort):
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncReplace):
+
+2011-09-22 Gavin Barraclough <barraclough@apple.com>
+
Function.prototype.bind.length shoudl be 1.
Rubber stamped by Olier Hunt.
MarkedArgumentBuffer l;
l.append(jObj);
l.append(minObj);
- compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l).toNumber(exec);
+ compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec);
} else
compareResult = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1;
if (callType == CallTypeNone)
return throwVMTypeError(exec);
- JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+ JSValue applyThis = exec->argument(1);
JSArray* resultArray = constructEmptyArray(exec);
unsigned filterIndex = 0;
if (callType == CallTypeNone)
return throwVMTypeError(exec);
- JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+ JSValue applyThis = exec->argument(1);
JSArray* resultArray = constructEmptyArray(exec, length);
unsigned k = 0;
if (callType == CallTypeNone)
return throwVMTypeError(exec);
- JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+ JSValue applyThis = exec->argument(1);
JSValue result = jsBoolean(true);
if (callType == CallTypeNone)
return throwVMTypeError(exec);
- JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+ JSValue applyThis = exec->argument(1);
unsigned k = 0;
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
if (callType == CallTypeNone)
return throwVMTypeError(exec);
- JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+ JSValue applyThis = exec->argument(1);
JSValue result = jsBoolean(false);
JSValue m_compareFunction;
CallType m_compareCallType;
const CallData* m_compareCallData;
- JSValue m_globalThisValue;
OwnPtr<CachedCall> m_cachedCall;
handle get_less(handle h) { return m_nodes[h].lt & 0x7FFFFFFF; }
double compareResult;
if (m_cachedCall) {
- m_cachedCall->setThis(m_globalThisValue);
+ m_cachedCall->setThis(jsUndefined());
m_cachedCall->setArgument(0, va);
m_cachedCall->setArgument(1, vb);
compareResult = m_cachedCall->call().toNumber(m_cachedCall->newCallFrame(m_exec));
MarkedArgumentBuffer arguments;
arguments.append(va);
arguments.append(vb);
- compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, m_globalThisValue, arguments).toNumber(m_exec);
+ compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, jsUndefined(), arguments).toNumber(m_exec);
}
return (compareResult < 0) ? -1 : 1; // Not passing equality through, because we need to store all values, even if equivalent.
}
tree.abstractor().m_compareFunction = compareFunction;
tree.abstractor().m_compareCallType = callType;
tree.abstractor().m_compareCallData = &callData;
- tree.abstractor().m_globalThisValue = exec->globalThisValue();
tree.abstractor().m_nodes.grow(nodeCount);
if (callType == CallTypeJS)
cachedCall.setArgument(i++, jsNumber(completeMatchStart));
cachedCall.setArgument(i++, sourceVal);
- cachedCall.setThis(exec->globalThisValue());
+ cachedCall.setThis(jsUndefined());
JSValue result = cachedCall.call();
if (LIKELY(result.isString()))
replacements.append(asString(result)->value(exec));
args.append(jsNumber(completeMatchStart));
args.append(sourceVal);
- replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec));
+ replacements.append(call(exec, replacement, callType, callData, jsUndefined(), args).toString(exec));
if (exec->hadException())
break;
} else {
args.append(jsNumber(matchPos));
args.append(sourceVal);
- replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec);
+ replacementString = call(exec, replacement, callType, callData, jsUndefined(), args).toString(exec);
}
size_t matchEnd = matchPos + matchLen;