https://bugs.webkit.org/show_bug.cgi?id=170872
Patch by Joseph Pecoraro <pecoraro@apple.com> on 2017-04-15
Reviewed by Saam Barati.
JSTests:
* stress/async-arrow-functions-lexical-new.target-binding.js:
(shouldThrowAsync): Deleted.
(shouldThrowAsync.async): Deleted.
This code should have thrown a SyntaxError. Instead it was throwing
a ReferenceError for the internal @newTargetLocal variable.
* stress/new-target-syntax-errors.js:
Cover the arrow function in global code cases.
* ChakraCore.yaml:
* ChakraCore/test/es6/globalLambdaNewTargetSyntaxError.baseline-jsc:
We now pass with an expected SyntaxError. Our error message is different.
* test262.yaml:
Source/JavaScriptCore:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::Parser):
Mark the global code scope.
(JSC::Parser<LexerType>::parseMemberExpression):
If new.target is detected in an arrow function defined in global scope
throw a SyntaxError.
* parser/Parser.h:
(JSC::Scope::Scope):
(JSC::Scope::setIsGlobalCodeScope):
(JSC::Scope::isGlobalCodeScope):
Marker for a global code scope.
* parser/ParserModes.h:
(JSC::isModuleParseMode):
(JSC::isProgramParseMode):
(JSC::isProgramOrModuleParseMode):
Helper for detecting global code based on parse mode.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@215395
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
# On line 254, JSC throws error during parsing while Chakra throws at runtime.
cmd: runChakra :skip, "NoException", "", ["../UnitTestFramework/UnitTestFramework.js"]
- path: ChakraCore/test/es6/globalLambdaNewTargetSyntaxError.js
- cmd: runChakra :baseline, "ReferenceError", "globalLambdaNewTargetSyntaxError.baseline-jsc", []
+ cmd: runChakra :baseline, "SyntaxError", "globalLambdaNewTargetSyntaxError.baseline-jsc", []
- path: ChakraCore/test/es6/globalNewTargetSyntaxError.js
cmd: runChakra :baseline, "SyntaxError", "globalNewTargetSyntaxError.baseline-jsc", []
- path: ChakraCore/test/es6/globalCatchNewTargetSyntaxError.js
-Exception: ReferenceError: Can't find private variable: @newTargetLocal
-f@globalLambdaNewTargetSyntaxError.js:6:9
-global code@globalLambdaNewTargetSyntaxError.js:7:2
+Exception: SyntaxError: new.target is not valid inside arrow functions in global code.
+at globalLambdaNewTargetSyntaxError.js:6
+2017-04-15 Joseph Pecoraro <pecoraro@apple.com>
+
+ test262: test262/test/language/global-code/new.target-arrow.js
+ https://bugs.webkit.org/show_bug.cgi?id=170872
+
+ Reviewed by Saam Barati.
+
+ * stress/async-arrow-functions-lexical-new.target-binding.js:
+ (shouldThrowAsync): Deleted.
+ (shouldThrowAsync.async): Deleted.
+ This code should have thrown a SyntaxError. Instead it was throwing
+ a ReferenceError for the internal @newTargetLocal variable.
+
+ * stress/new-target-syntax-errors.js:
+ Cover the arrow function in global code cases.
+
+ * ChakraCore.yaml:
+ * ChakraCore/test/es6/globalLambdaNewTargetSyntaxError.baseline-jsc:
+ We now pass with an expected SyntaxError. Our error message is different.
+
+ * test262.yaml:
+
2017-04-14 Saam Barati <sbarati@apple.com>
ParseInt intrinsic in DFG backend doesn't properly flush its operands
shouldBe(expected, actual, msg);
}
-function shouldThrowAsync(run, errorType, message) {
- let actual;
- var hadError = false;
- run().then(function(value) { actual = value; },
- function(error) { hadError = true; actual = error; });
- drainMicrotasks();
-
- if (!hadError)
- throw new Error("Expected " + run + "() to throw " + errorType.name + ", but did not throw.");
- if (!(actual instanceof errorType))
- throw new Error("Expected " + run + "() to throw " + errorType.name + ", but threw '" + actual + "'");
- if (message !== void 0 && actual.message !== message)
- throw new Error("Expected " + run + "() to throw '" + message + "', but threw '" + actual.message + "'");
-}
-
function C1() {
return async () => await new.target;
}
shouldBeAsync(undefined, C2());
shouldBeAsync(C2WithAwait, new C2WithAwait());
shouldBeAsync(undefined, C2WithAwait());
-
-shouldThrowAsync(async () => await new.target, ReferenceError);
-shouldThrowAsync(async () => { return await new.target; }, ReferenceError);
+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion")
+}
+
function shouldBeSyntaxError(str) {
let failed = true;
try {
}
shouldBeSyntaxError(`({foo: new.target} = {foo:20})`);
+
+// Scripts - 15.1.1 Static Semantics: Early Errors
+// https://tc39.github.io/ecma262/#sec-scripts-static-semantics-early-errors
+//
+// Modules - 15.2.1.1 Static Semantics: Early Errors
+// https://tc39.github.io/ecma262/#sec-module-semantics-static-semantics-early-errors
+//
+// new.target is not allowed in arrow functions in global scope.
+
+let sawSyntaxError;
+
+sawSyntaxError = false;
+try {
+ eval(`() => new.target`);
+} catch(e) {
+ sawSyntaxError = e instanceof SyntaxError;
+}
+assert(sawSyntaxError);
+
+sawSyntaxError = false;
+try {
+ eval(`() => { new.target }`);
+} catch(e) {
+ sawSyntaxError = e instanceof SyntaxError;
+}
+assert(sawSyntaxError);
+
+sawSyntaxError = false;
+try {
+ eval(`async () => new.target`);
+} catch(e) {
+ sawSyntaxError = e instanceof SyntaxError;
+}
+assert(sawSyntaxError);
+
+sawSyntaxError = false;
+try {
+ eval(`async () => { new.target }`);
+} catch(e) {
+ sawSyntaxError = e instanceof SyntaxError;
+}
+assert(sawSyntaxError);
+
+sawSyntaxError = false;
+try {
+ eval(`async () => await new.target`);
+} catch(e) {
+ sawSyntaxError = e instanceof SyntaxError;
+}
+assert(sawSyntaxError);
+
+sawSyntaxError = false;
+try {
+ eval(`async () => { await new.target }`);
+} catch(e) {
+ sawSyntaxError = e instanceof SyntaxError;
+}
+assert(sawSyntaxError);
+
+let sawError = false;
+try {
+ new Function(`() => new.target`);
+ new Function(`() => { new.target }`);
+ new Function(`async () => new.target`);
+ new Function(`async () => { new.target }`);
+ new Function(`async () => await new.target`);
+ new Function(`async () => { await new.target }`);
+
+ function f() { () => new.target };
+ function f() { () => { new.target } };
+ function f() { async () => new.target };
+ function f() { async () => { new.target } };
+ function f() { async () => await new.target };
+ function f() { async () => { await new.target } };
+
+ (function() { eval(`() => new.target`) })();
+ (function() { eval(`() => { new.target }`) })();
+ (function() { eval(`async () => new.target`) })();
+ (function() { eval(`async () => { new.target }`) })();
+ (function() { eval(`async () => await new.target`) })();
+ (function() { eval(`async () => { await new.target }`) })();
+} catch (e) {
+ sawError = true;
+}
+assert(!sawError);
- path: test262/test/language/global-code/import.js
cmd: runTest262 :normal, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:strict]
- path: test262/test/language/global-code/new.target-arrow.js
- cmd: runTest262 :fail, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], []
- path: test262/test/language/global-code/new.target-arrow.js
- cmd: runTest262 :fail, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:strict]
- path: test262/test/language/global-code/new.target.js
cmd: runTest262 :normal, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], []
- path: test262/test/language/global-code/new.target.js
+2017-04-15 Joseph Pecoraro <pecoraro@apple.com>
+
+ test262: test262/test/language/global-code/new.target-arrow.js
+ https://bugs.webkit.org/show_bug.cgi?id=170872
+
+ Reviewed by Saam Barati.
+
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::Parser):
+ Mark the global code scope.
+
+ (JSC::Parser<LexerType>::parseMemberExpression):
+ If new.target is detected in an arrow function defined in global scope
+ throw a SyntaxError.
+
+ * parser/Parser.h:
+ (JSC::Scope::Scope):
+ (JSC::Scope::setIsGlobalCodeScope):
+ (JSC::Scope::isGlobalCodeScope):
+ Marker for a global code scope.
+
+ * parser/ParserModes.h:
+ (JSC::isModuleParseMode):
+ (JSC::isProgramParseMode):
+ (JSC::isProgramOrModuleParseMode):
+ Helper for detecting global code based on parse mode.
+
2017-04-14 Nikita Vasilyev <nvasilyev@apple.com>
Web Inspector: WebSockets: messages with non-latin letters are displayed incorrectly
if (strictMode == JSParserStrictMode::Strict)
scope->setStrictMode();
- if (parseMode == SourceParseMode::ModuleAnalyzeMode || parseMode == SourceParseMode::ModuleEvaluateMode)
+ if (isModuleParseMode(parseMode))
m_moduleScopeData = ModuleScopeData::create();
+ if (isProgramOrModuleParseMode(parseMode))
+ scope->setIsGlobalCodeScope();
+
next();
}
if (match(IDENT)) {
const Identifier* ident = m_token.m_data.ident;
if (m_vm->propertyNames->target == *ident) {
- semanticFailIfFalse(currentScope()->isFunction() || closestParentOrdinaryFunctionNonLexicalScope()->evalContextType() == EvalContextType::FunctionEvalContext, "new.target is only valid inside functions");
+ ScopeRef closestOrdinaryFunctionScope = closestParentOrdinaryFunctionNonLexicalScope();
+ semanticFailIfFalse(currentScope()->isFunction() || closestOrdinaryFunctionScope->evalContextType() == EvalContextType::FunctionEvalContext, "new.target is only valid inside functions");
baseIsNewTarget = true;
- if (currentScope()->isArrowFunction())
+ if (currentScope()->isArrowFunction()) {
+ semanticFailIfFalse(!closestOrdinaryFunctionScope->isGlobalCodeScope() || closestOrdinaryFunctionScope->evalContextType() == EvalContextType::FunctionEvalContext, "new.target is not valid inside arrow functions in global code");
currentScope()->setInnerArrowFunctionUsesNewTarget();
+ }
base = context.createNewTargetExpr(location);
newCount--;
next();
, m_isAsyncFunction(isAsyncFunction)
, m_isAsyncFunctionBoundary(false)
, m_isLexicalScope(false)
+ , m_isGlobalCodeScope(false)
, m_isFunctionBoundary(false)
, m_isValidStrictMode(true)
, m_hasArguments(false)
, m_isAsyncFunction(other.m_isAsyncFunction)
, m_isAsyncFunctionBoundary(other.m_isAsyncFunctionBoundary)
, m_isLexicalScope(other.m_isLexicalScope)
+ , m_isGlobalCodeScope(other.m_isGlobalCodeScope)
, m_isFunctionBoundary(other.m_isFunctionBoundary)
, m_isValidStrictMode(other.m_isValidStrictMode)
, m_hasArguments(other.m_hasArguments)
bool hasArguments() const { return m_hasArguments; }
+ void setIsGlobalCodeScope() { m_isGlobalCodeScope = true; }
+ bool isGlobalCodeScope() const { return m_isGlobalCodeScope; }
+
void setIsLexicalScope()
{
m_isLexicalScope = true;
bool m_isAsyncFunction;
bool m_isAsyncFunctionBoundary;
bool m_isLexicalScope;
+ bool m_isGlobalCodeScope;
bool m_isFunctionBoundary;
bool m_isValidStrictMode;
bool m_hasArguments;
SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
}
-
ALWAYS_INLINE bool isModuleParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(
SourceParseMode::ModuleAnalyzeMode,
SourceParseMode::ModuleEvaluateMode).contains(parseMode);
-}
+}
ALWAYS_INLINE bool isProgramParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(SourceParseMode::ProgramMode).contains(parseMode);
-}
+}
+
+ALWAYS_INLINE bool isProgramOrModuleParseMode(SourceParseMode parseMode)
+{
+ return SourceParseModeSet(
+ SourceParseMode::ProgramMode,
+ SourceParseMode::ModuleAnalyzeMode,
+ SourceParseMode::ModuleEvaluateMode).contains(parseMode);
+}
ALWAYS_INLINE ConstructAbility constructAbilityForParseMode(SourceParseMode parseMode)
{