Bug 1083476 - Add console warnings for JS1.7 legacy generators. r=arai

MozReview-Commit-ID: LnctQK4EEOM

--HG--
extra : rebase_source : a3598ce5a91ffb87e698c88604c32937306baf53
This commit is contained in:
Masatoshi Kimura 2017-08-06 18:48:39 +09:00
parent 7d55aeeced
commit 990481538b
7 changed files with 78 additions and 29 deletions

View File

@ -6800,6 +6800,8 @@ Parser<ParseHandler, CharT>::yieldExpression(InHandling inHandling)
pc->functionBox()->setGeneratorKind(LegacyGenerator);
addTelemetry(DeprecatedLanguageExtension::LegacyGenerator);
if (!warnOnceAboutLegacyGenerator())
return null();
MOZ_FALLTHROUGH;
@ -10441,6 +10443,20 @@ ParserBase::warnOnceAboutForEach()
return true;
}
bool
ParserBase::warnOnceAboutLegacyGenerator()
{
if (context->helperThread())
return true;
if (!context->compartment()->warnedAboutLegacyGenerator) {
if (!warning(JSMSG_DEPRECATED_LEGACY_GENERATOR))
return false;
context->compartment()->warnedAboutLegacyGenerator = true;
}
return true;
}
template class Parser<FullParseHandler, char16_t>;
template class Parser<SyntaxParseHandler, char16_t>;

View File

@ -251,6 +251,7 @@ class ParserBase : public StrictModeGetter
bool warnOnceAboutExprClosure();
bool warnOnceAboutForEach();
bool warnOnceAboutLegacyGenerator();
bool allowsForEachIn() {
#if !JS_HAS_FOR_EACH_IN

View File

@ -0,0 +1,55 @@
// Legacy generators should be warned once and only once.
version(170);
function testWarn(code) {
enableLastWarning();
var g = newGlobal();
g.code = code;
g.eval('eval(code)');
var warning = getLastWarning();
assertEq(warning !== null, true, "warning should be caught for " + code);
assertEq(warning.name, "Warning");
clearLastWarning();
g.eval('eval(code)');
warning = getLastWarning();
assertEq(warning, null, "warning should not be caught for 2nd ocurrence");
clearLastWarning();
g = newGlobal();
g.code = code;
g.eval('Reflect.parse(code);');
warning = getLastWarning();
assertEq(warning !== null, true, "warning should be caught for " + code);
assertEq(warning.name, "Warning");
clearLastWarning();
g.eval('Reflect.parse(code);');
warning = getLastWarning();
assertEq(warning, null, "warning should not be caught for 2nd ocurrence");
disableLastWarning();
}
function testPass(code) {
enableLastWarning();
var g = newGlobal();
g.code = code;
g.eval('eval(code)');
var warning = getLastWarning();
assertEq(warning, null, "warning should not be caught for " + code);
clearLastWarning();
g = newGlobal();
g.code = code;
g.eval('Reflect.parse(code);');
warning = getLastWarning();
assertEq(warning, null, "warning should not be caught for " + code);
disableLastWarning();
}
testWarn("(function() { yield; })");
testWarn("function a() { yield; }");
testPass("(function*() { yield; })");
testPass("function* a() { yield; }");

View File

@ -1,26 +0,0 @@
// yield without an operand is fine and dandy.
load(libdir + "asserts.js");
assertNoWarning(() => Function("yield"), SyntaxError,
"yield followed by EOF is fine");
assertNoWarning(() => Function("yield;"), SyntaxError,
"yield followed by semicolon is fine");
assertNoWarning(() => Function("yield\n"), SyntaxError,
"yield followed by newline is fine");
assertNoWarning(() => Function("yield\n print('ok');"), SyntaxError,
"yield followed by newline and statement is fine");
assertNoWarning(() => Function("yield\n /x/;"), SyntaxError,
"yield followed by newline and regexp is fine");
assertThrowsInstanceOf(() => Function("yield\n /"), SyntaxError,
"yield followed by newline and slash is fine");
assertNoWarning(() => eval("(function () { yield; })"), SyntaxError,
"yield followed by semicolon in eval code is fine");
assertNoWarning(() => eval("(function () { yield })"), SyntaxError,
"yield followed by } in eval code is fine");
assertNoWarning(() => Function("yield 0;"),
"yield with an operand should be fine");
assertNoWarning(() => Function("yield 0"),
"yield with an operand should be fine, even without a semicolon");

View File

@ -251,6 +251,7 @@ MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT,0, JSEXN_SYNTAXERR, "missing declaration
MSG_DEF(JSMSG_DEPRECATED_DELETE_OPERAND, 0, JSEXN_SYNTAXERR, "applying the 'delete' operator to an unqualified name is deprecated")
MSG_DEF(JSMSG_DEPRECATED_EXPR_CLOSURE, 0, JSEXN_WARN, "expression closures are deprecated")
MSG_DEF(JSMSG_DEPRECATED_FOR_EACH, 0, JSEXN_WARN, "JavaScript 1.6's for-each-in loops are deprecated; consider using ES6 for-of instead")
MSG_DEF(JSMSG_DEPRECATED_LEGACY_GENERATOR, 0, JSEXN_WARN, "JavaScript 1.7's legacy generators are deprecated; consider using ES6 generators instead. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function* for details.")
MSG_DEF(JSMSG_DEPRECATED_OCTAL, 0, JSEXN_SYNTAXERR, "\"0\"-prefixed octal literals and octal escape sequences are deprecated; for octal literals use the \"0o\" prefix instead")
MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_WARN, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead")
MSG_DEF(JSMSG_DEPRECATED_BLOCK_SCOPE_FUN_REDECL, 1, JSEXN_WARN, "redeclaration of block-scoped function `{0}' is deprecated")

View File

@ -59,6 +59,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
warnedAboutDateToLocaleFormat(false),
warnedAboutExprClosure(false),
warnedAboutForEach(false),
warnedAboutLegacyGenerator(false),
warnedAboutStringGenericsMethods(0),
#ifdef DEBUG
firedOnNewGlobalObject(false),

View File

@ -621,9 +621,10 @@ struct JSCompartment
public:
bool isSelfHosting;
bool marked;
bool warnedAboutDateToLocaleFormat;
bool warnedAboutExprClosure;
bool warnedAboutForEach;
bool warnedAboutDateToLocaleFormat : 1;
bool warnedAboutExprClosure : 1;
bool warnedAboutForEach : 1;
bool warnedAboutLegacyGenerator : 1;
uint32_t warnedAboutStringGenericsMethods;
#ifdef DEBUG