Diff
Modified: trunk/LayoutTests/ChangeLog (196260 => 196261)
--- trunk/LayoutTests/ChangeLog 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/LayoutTests/ChangeLog 2016-02-08 19:29:24 UTC (rev 196261)
@@ -1,3 +1,17 @@
+2016-02-08 Skachkov Oleksandr <gskach...@gmail.com>
+
+ [ES6] Arrow function syntax. Using 'super' in arrow function that declared out of the class should lead to Syntax error
+ https://bugs.webkit.org/show_bug.cgi?id=150893
+
+ Reviewed by Saam Barati.
+
+ Adding tests for using of the 'super' inside of the arrow function
+
+ * js/arrowfunction-superproperty-expected.txt:
+ * js/arrowfunction-syntax-errors-expected.txt:
+ * js/script-tests/arrowfunction-superproperty.js:
+ * js/script-tests/arrowfunction-syntax-errors.js:
+
2016-02-08 Adrien Plazas <apla...@igalia.com>
Timeouts in tests because of non implemented UIScriptController::singleTapAtPoint()
Modified: trunk/LayoutTests/js/arrowfunction-superproperty-expected.txt (196260 => 196261)
--- trunk/LayoutTests/js/arrowfunction-superproperty-expected.txt 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/LayoutTests/js/arrowfunction-superproperty-expected.txt 2016-02-08 19:29:24 UTC (rev 196261)
@@ -9,7 +9,6 @@
PASS f.prop is expectedValue + "-" + expectedValue
PASS f.prop is expectedValue + "-" + "new-value"
PASS (new F()).getParentValue() is expectedValue
-PASS (new F()).getParentValueWithError()() threw exception TypeError: undefined is not an object (evaluating 'super.getValue').
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/js/arrowfunction-syntax-errors-expected.txt (196260 => 196261)
--- trunk/LayoutTests/js/arrowfunction-syntax-errors-expected.txt 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/LayoutTests/js/arrowfunction-syntax-errors-expected.txt 2016-02-08 19:29:24 UTC (rev 196261)
@@ -131,6 +131,19 @@
PASS var arr2 = {a, b} => a + b; threw exception SyntaxError: Unexpected token '=>'. Expected ';' after variable declaration..
PASS var arr3 = {c:a,d:b} => a + b; threw exception SyntaxError: Unexpected token '=>'. Expected ';' after variable declaration..
PASS var arr3 = {c:b,d:a} => a + b; threw exception SyntaxError: Unexpected token '=>'. Expected ';' after variable declaration..
+PASS var arr4 = () => { super(); }; threw exception SyntaxError: Cannot call super() outside of a class constructor..
+PASS var arr4 = () => { super; }; threw exception SyntaxError: Cannot reference super..
+PASS var arr5 = () => { super.getValue(); }; threw exception SyntaxError: super can only be used in a method of a derived class..
+PASS var arr6 = () => super(); threw exception SyntaxError: Cannot call super() outside of a class constructor..
+PASS var arr7 = () => super; threw exception SyntaxError: Cannot reference super..
+PASS var arr8 = () => super.getValue(); threw exception SyntaxError: super can only be used in a method of a derived class..
+PASS class A { constructor() { function a () { return () => { super(); };}} threw exception SyntaxError: Cannot call super() outside of a class constructor..
+PASS class B { constructor() { function b () { return () => { super; }; }; }} threw exception SyntaxError: Cannot reference super..
+PASS class C { constructor() { function c () { return () => { super.getValue(); };}} threw exception SyntaxError: super can only be used in a method of a derived class..
+PASS class D { constructor() { function a () { return () => super(); }} threw exception SyntaxError: Cannot call super() outside of a class constructor..
+PASS class E { constructor() { function b () { return () => super; }; }} threw exception SyntaxError: Cannot reference super..
+PASS class F { constructor() { function c () { return () => super.getValue(); }} threw exception SyntaxError: super can only be used in a method of a derived class..
+PASS class G {}; class G2 extends G { getValue() { function c () { return () => super.getValue(); }} threw exception SyntaxError: super can only be used in a method of a derived class..
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/js/script-tests/arrowfunction-superproperty.js (196260 => 196261)
--- trunk/LayoutTests/js/script-tests/arrowfunction-superproperty.js 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/LayoutTests/js/script-tests/arrowfunction-superproperty.js 2016-02-08 19:29:24 UTC (rev 196261)
@@ -63,12 +63,6 @@
let arrow = () => () => super.getValue();
return arrow()();
}
- getParentValueWithError() {
- var f = function () {
- return () => super.getValue();
- };
- return f();
- }
};
shouldBe('(new B()).getValueParentFunction()', 'expectedValue');
@@ -90,6 +84,4 @@
shouldBe('(new F()).getParentValue()', 'expectedValue');
-shouldThrow('(new F()).getParentValueWithError()()');
-
var successfullyParsed = true;
Modified: trunk/LayoutTests/js/script-tests/arrowfunction-syntax-errors.js (196260 => 196261)
--- trunk/LayoutTests/js/script-tests/arrowfunction-syntax-errors.js 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/LayoutTests/js/script-tests/arrowfunction-syntax-errors.js 2016-02-08 19:29:24 UTC (rev 196261)
@@ -48,4 +48,21 @@
shouldThrow('var arr3 = {c:a,d:b} => a + b;');
shouldThrow('var arr3 = {c:b,d:a} => a + b;');
+shouldThrow('var arr4 = () => { super(); };', '"SyntaxError: Cannot call super() outside of a class constructor."');
+shouldThrow('var arr4 = () => { super; };', '"SyntaxError: Cannot reference super."');
+shouldThrow('var arr5 = () => { super.getValue(); };', '"SyntaxError: super can only be used in a method of a derived class."');
+
+shouldThrow('var arr6 = () => super();', '"SyntaxError: Cannot call super() outside of a class constructor."');
+shouldThrow('var arr7 = () => super;', '"SyntaxError: Cannot reference super."');
+shouldThrow('var arr8 = () => super.getValue();', '"SyntaxError: super can only be used in a method of a derived class."');
+
+shouldThrow('class A { constructor() { function a () { return () => { super(); };}}', '"SyntaxError: Cannot call super() outside of a class constructor."');
+shouldThrow('class B { constructor() { function b () { return () => { super; }; }; }}', '"SyntaxError: Cannot reference super."');
+shouldThrow('class C { constructor() { function c () { return () => { super.getValue(); };}}', '"SyntaxError: super can only be used in a method of a derived class."');
+
+shouldThrow('class D { constructor() { function a () { return () => super(); }}', '"SyntaxError: Cannot call super() outside of a class constructor."');
+shouldThrow('class E { constructor() { function b () { return () => super; }; }}', '"SyntaxError: Cannot reference super."');
+shouldThrow('class F { constructor() { function c () { return () => super.getValue(); }}', '"SyntaxError: super can only be used in a method of a derived class."');
+shouldThrow('class G {}; class G2 extends G { getValue() { function c () { return () => super.getValue(); }}', '"SyntaxError: super can only be used in a method of a derived class."');
+
var successfullyParsed = true;
Modified: trunk/Source/_javascript_Core/ChangeLog (196260 => 196261)
--- trunk/Source/_javascript_Core/ChangeLog 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-02-08 19:29:24 UTC (rev 196261)
@@ -1,3 +1,37 @@
+2016-02-08 Skachkov Oleksandr <gskach...@gmail.com>
+
+ [ES6] Arrow function syntax. Using 'super' in arrow function that declared out of the class should lead to Syntax error
+ https://bugs.webkit.org/show_bug.cgi?id=150893
+
+ Reviewed by Saam Barati.
+
+ 'super' and 'super()' inside of the arrow function should lead to syntax error if they are used
+ out of the class context or they wrapped by ordinary function. Now JSC returns ReferenceError but
+ should return SyntaxError according to the following specs:
+ http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions-static-semantics-early-errors
+ and http://www.ecma-international.org/ecma-262/6.0/#sec-arrow-function-definitions-runtime-semantics-evaluation
+ Curren patch implemented only one case when super/super() are used inside of the arrow function
+ Case when super/super() are used within the eval:
+ class A {}
+ class B extends A {
+ costructor() { eval("super()");}
+ }
+ is not part of this patch and will be implemented in this issue https://bugs.webkit.org/show_bug.cgi?id=153864.
+ The same for case when eval with super/super() is invoked in arrow function will be
+ implemented in issue https://bugs.webkit.org/show_bug.cgi?id=153977.
+
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseFunctionInfo):
+ * parser/Parser.h:
+ (JSC::Scope::Scope):
+ (JSC::Scope::setExpectedSuperBinding):
+ (JSC::Scope::expectedSuperBinding):
+ (JSC::Scope::setConstructorKind):
+ (JSC::Scope::constructorKind):
+ (JSC::Parser::closestParentNonArrowFunctionNonLexicalScope):
+ * tests/stress/arrowfunction-lexical-bind-supercall-4.js:
+ * tests/stress/arrowfunction-lexical-bind-superproperty.js:
+
2016-02-08 Filip Pizlo <fpi...@apple.com>
Parser should detect error before calls to parseAssignmentExpression()
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (196260 => 196261)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2016-02-08 19:29:24 UTC (rev 196261)
@@ -1976,8 +1976,9 @@
functionBodyType = StandardFunctionBodyBlock;
}
- bool isClassConstructor = constructorKind != ConstructorKind::None;
-
+ functionScope->setConstructorKind(constructorKind);
+ functionScope->setExpectedSuperBinding(expectedSuperBinding);
+
functionInfo.bodyStartColumn = startColumn;
// If we know about this function already, we can use the cached info and skip the parser to the end of the function.
@@ -2066,12 +2067,24 @@
semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
}
- if (functionScope->hasDirectSuper() && functionBodyType == StandardFunctionBodyBlock) {
- semanticFailIfTrue(!isClassConstructor, "Cannot call super() outside of a class constructor");
- semanticFailIfTrue(constructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
+ // It unncecessary to check of using super during reparsing one more time. Also it can lead to syntax error
+ // in case of arrow function becuase during reparsing we don't know that parse arrow function
+ // inside of the constructor or method
+ if (!m_lexer->isReparsingFunction()) {
+ if (functionScope->hasDirectSuper()) {
+ ConstructorKind functionConstructorKind = functionBodyType == StandardFunctionBodyBlock
+ ? constructorKind
+ : closestParentNonArrowFunctionNonLexicalScope()->constructorKind();
+ semanticFailIfTrue(functionConstructorKind == ConstructorKind::None, "Cannot call super() outside of a class constructor");
+ semanticFailIfTrue(functionConstructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
+ }
+ if (functionScope->needsSuperBinding()) {
+ SuperBinding functionSuperBinding = functionBodyType == StandardFunctionBodyBlock
+ ? expectedSuperBinding
+ : closestParentNonArrowFunctionNonLexicalScope()->expectedSuperBinding();
+ semanticFailIfTrue(functionSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
+ }
}
- if (functionScope->needsSuperBinding() && functionBodyType == StandardFunctionBodyBlock)
- semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
JSTokenLocation location = JSTokenLocation(m_token.m_location);
functionInfo.endOffset = m_token.m_data.offset;
@@ -2083,7 +2096,9 @@
// Cache the tokenizer state and the function scope the first time the function is parsed.
// Any future reparsing can then skip the function.
- static const int minimumFunctionLengthToCache = 16;
+ // For arrow function is 8 = x=>x + 4 symbols;
+ // For ordinary function is 16 = function(){} + 4 symbols
+ const int minimumFunctionLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
std::unique_ptr<SourceProviderCacheItem> newInfo;
int functionLength = functionInfo.endOffset - functionInfo.startOffset;
if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
Modified: trunk/Source/_javascript_Core/parser/Parser.h (196260 => 196261)
--- trunk/Source/_javascript_Core/parser/Parser.h 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/Source/_javascript_Core/parser/Parser.h 2016-02-08 19:29:24 UTC (rev 196261)
@@ -175,6 +175,8 @@
, m_isFunctionBoundary(false)
, m_isValidStrictMode(true)
, m_hasArguments(false)
+ , m_constructorKind(static_cast<unsigned>(ConstructorKind::None))
+ , m_expectedSuperBinding(static_cast<unsigned>(SuperBinding::NotNeeded))
, m_loopDepth(0)
, m_switchDepth(0)
{
@@ -197,6 +199,8 @@
, m_isFunctionBoundary(rhs.m_isFunctionBoundary)
, m_isValidStrictMode(rhs.m_isValidStrictMode)
, m_hasArguments(rhs.m_hasArguments)
+ , m_constructorKind(rhs.m_constructorKind)
+ , m_expectedSuperBinding(rhs.m_expectedSuperBinding)
, m_loopDepth(rhs.m_loopDepth)
, m_switchDepth(rhs.m_switchDepth)
, m_moduleScopeData(rhs.m_moduleScopeData)
@@ -458,6 +462,11 @@
bool needsSuperBinding() { return m_needsSuperBinding; }
void setNeedsSuperBinding() { m_needsSuperBinding = true; }
+
+ void setExpectedSuperBinding(SuperBinding superBinding) { m_expectedSuperBinding = static_cast<unsigned>(superBinding); }
+ SuperBinding expectedSuperBinding() const { return static_cast<SuperBinding>(m_expectedSuperBinding); }
+ void setConstructorKind(ConstructorKind constructorKind) { m_constructorKind = static_cast<unsigned>(constructorKind); }
+ ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
{
@@ -614,6 +623,8 @@
bool m_isFunctionBoundary : 1;
bool m_isValidStrictMode : 1;
bool m_hasArguments : 1;
+ unsigned m_constructorKind : 2;
+ unsigned m_expectedSuperBinding : 2;
int m_loopDepth;
int m_switchDepth;
@@ -866,6 +877,15 @@
return ScopeRef(&m_scopeStack, i);
}
+ ScopeRef closestParentNonArrowFunctionNonLexicalScope()
+ {
+ unsigned i = m_scopeStack.size() - 1;
+ ASSERT(i < m_scopeStack.size() && m_scopeStack.size());
+ while (i && (!m_scopeStack[i].isFunctionBoundary() || m_scopeStack[i].isArrowFunction()))
+ i--;
+ // When reaching the top level scope (it can be non function scope), we return it.
+ return ScopeRef(&m_scopeStack, i);
+ }
ScopeRef pushScope()
{
Modified: trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-supercall-4.js (196260 => 196261)
--- trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-supercall-4.js 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-supercall-4.js 2016-02-08 19:29:24 UTC (rev 196261)
@@ -51,6 +51,9 @@
}
};
+// FIXME: Arrow function does not support using of eval with super/super()
+// https://bugs.webkit.org/show_bug.cgi?id=153977
+/*
for (var i=0; i < 1000; i++) {
new B(true);
var c = new C();
@@ -60,6 +63,7 @@
var e = new E();
testCase(e.id, 'new-value', 'Error during set value in eval #3');
}
+*/
var testException = function (value, index) {
var exception;
Modified: trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-superproperty.js (196260 => 196261)
--- trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-superproperty.js 2016-02-08 19:27:01 UTC (rev 196260)
+++ trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-superproperty.js 2016-02-08 19:29:24 UTC (rev 196261)
@@ -123,12 +123,6 @@
getParentValue() {
return super.getValue();
}
- getParentValueWithError() {
- var f = function () {
- return () => super.getValue();
- };
- return f();
- }
};
var g = new G();
@@ -149,20 +143,6 @@
testCase(getValue(), 'new-value', 'Error: Some problem with using arrow and "super" inside of the method that retun arrow function');
}
-var g2 = new G();
-for (var i = 0; i < 10000; i++) {
- let error = false;
- try {
- g2.getParentValueWithError()();
- } catch(e) {
- // FIXME: should by check if e instanceof SyntaxError
- // https://bugs.webkit.org/show_bug.cgi?id=150893
- error = true;
- }
- testCase(error, true, 'Error: using "super" should lead to error');
-}
-
-
var H = class H extends A {
constructor() {
var arrow = () => () => super.getValue();