From 50068cd4e04a61ac5bb7e8c2149d27145436b832 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 30 Nov 2016 22:48:40 -0500 Subject: [PATCH] Keep directive strings at top of original function. Fixes #248. --- packages/regenerator-transform/package.json | 2 +- packages/regenerator-transform/src/visit.js | 17 +++++++++++++- test/tests.es6.js | 25 +++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/packages/regenerator-transform/package.json b/packages/regenerator-transform/package.json index 3fcf4418e..0e9ae23ca 100644 --- a/packages/regenerator-transform/package.json +++ b/packages/regenerator-transform/package.json @@ -2,7 +2,7 @@ "name": "regenerator-transform", "author": "Ben Newman ", "description": "Explode async and generator functions into a state machine.", - "version": "0.9.6", + "version": "0.9.7", "main": "lib/index.js", "keywords": [ "regenerator", diff --git a/packages/regenerator-transform/src/visit.js b/packages/regenerator-transform/src/visit.js index 8d96f2b40..15f6203dc 100644 --- a/packages/regenerator-transform/src/visit.js +++ b/packages/regenerator-transform/src/visit.js @@ -56,7 +56,15 @@ exports.visitor = { bodyBlockPath.get("body").forEach(function(childPath) { let node = childPath.node; - if (node && node._blockHoist != null) { + if (t.isExpressionStatement(node) && + t.isStringLiteral(node.expression)) { + // Babylon represents directives like "use strict" as elements + // of a bodyBlockPath.node.directives array, but they could just + // as easily be represented (by other parsers) as traditional + // string-literal-valued expression statements, so we need to + // handle that here. (#248) + outerBody.push(node); + } else if (node && node._blockHoist != null) { outerBody.push(node); } else { innerBody.push(node); @@ -117,6 +125,13 @@ exports.visitor = { outerBody.push(t.returnStatement(wrapCall)); node.body = t.blockStatement(outerBody); + const oldDirectives = bodyBlockPath.node.directives; + if (oldDirectives) { + // Babylon represents directives like "use strict" as elements of + // a bodyBlockPath.node.directives array. (#248) + node.body.directives = oldDirectives; + } + let wasGeneratorFunction = node.generator; if (wasGeneratorFunction) { node.generator = false; diff --git a/test/tests.es6.js b/test/tests.es6.js index a5902d303..e4a56c4c0 100644 --- a/test/tests.es6.js +++ b/test/tests.es6.js @@ -1484,6 +1484,31 @@ describe("the arguments object", function() { }); }); +describe("directive strings", function () { + function *strict() { + "use strict"; + yield ! this; + } + + function *sloppy() { + yield ! this; + } + + it("should be kept at top of outer function", function () { + var strictCode = String(strict); + var useStrictIndex = strictCode.indexOf("use strict"); + var thisIndex = strictCode.indexOf("this"); + + assert.notStrictEqual(useStrictIndex, -1); + assert.ok(thisIndex > useStrictIndex); + + assert.strictEqual(String(sloppy).indexOf("use strict"), -1); + + check(strict(), [true]); + check(sloppy(), [false]); + }); +}); + describe("catch parameter shadowing", function() { it("should leave outer variables unmodified", function() { function *gen(x) {