Return-Path: X-Original-To: apmail-flex-commits-archive@www.apache.org Delivered-To: apmail-flex-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id AD67E18088 for ; Tue, 24 Nov 2015 16:42:38 +0000 (UTC) Received: (qmail 96931 invoked by uid 500); 24 Nov 2015 16:42:38 -0000 Delivered-To: apmail-flex-commits-archive@flex.apache.org Received: (qmail 96836 invoked by uid 500); 24 Nov 2015 16:42:38 -0000 Mailing-List: contact commits-help@flex.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@flex.apache.org Delivered-To: mailing list commits@flex.apache.org Received: (qmail 96745 invoked by uid 99); 24 Nov 2015 16:42:38 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 24 Nov 2015 16:42:38 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 41E9BE0511; Tue, 24 Nov 2015 16:42:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: aharui@apache.org To: commits@flex.apache.org Date: Tue, 24 Nov 2015 16:42:42 -0000 Message-Id: <9837a3a2df074bc1b466dfcd7c7baade@git.apache.org> In-Reply-To: <45c1bc42260a445db12d2173ecb4530d@git.apache.org> References: <45c1bc42260a445db12d2173ecb4530d@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [5/5] git commit: [flex-falcon] [refs/heads/develop] - es5 strict required local functions declared before code es5 strict required local functions declared before code Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/f0ebbf0c Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/f0ebbf0c Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/f0ebbf0c Branch: refs/heads/develop Commit: f0ebbf0ca473a6938cb05f86b40d7053abab3014 Parents: 47ed21a Author: Alex Harui Authored: Tue Nov 24 08:42:09 2015 -0800 Committer: Alex Harui Committed: Tue Nov 24 08:42:09 2015 -0800 ---------------------------------------------------------------------- .../codegen/js/flexjs/TestFlexJSClass.java | 4 +- .../js/flexjs/TestFlexJSExpressions.java | 99 +++++++++++++++----- .../flexjs/files/LocalFunction_result.js | 3 +- .../codegen/js/flexjs/JSFlexJSEmitter.java | 65 +++++++++++++ .../codegen/js/jx/IdentifierEmitter.java | 8 +- .../codegen/js/jx/SelfReferenceEmitter.java | 2 +- .../compiler/internal/tree/as/FunctionNode.java | 40 ++++++-- .../internal/tree/as/FunctionObjectNode.java | 4 - .../flex/compiler/tree/as/IFunctionNode.java | 28 +++++- 9 files changed, 209 insertions(+), 44 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/f0ebbf0c/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java index 801b9f6..db12f5b 100644 --- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java +++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java @@ -243,7 +243,7 @@ public class TestFlexJSClass extends TestGoogClass + "public function foo2():Object{function bar2(param1:Object):Object {return null;}; return bar2('foo');}" + "}"); asBlockWalker.visitClass(node); - assertOut("/**\n * @constructor\n */\norg.apache.flex.B = function() {\n};\n\n\n/**\n * @export\n * @return {Object}\n */\norg.apache.flex.B.prototype.foo1 = function() {\n function bar1() {\n return null;\n };\n return org.apache.flex.utils.Language.closure(bar1, this, 'bar1')();\n};\n\n\n/**\n * @export\n * @return {Object}\n */\norg.apache.flex.B.prototype.foo2 = function() {\n function bar2(param1) {\n return null;\n };\n return org.apache.flex.utils.Language.closure(bar2, this, 'bar2')('foo');\n};"); + assertOut("/**\n * @constructor\n */\norg.apache.flex.B = function() {\n};\n\n\n/**\n * @export\n * @return {Object}\n */\norg.apache.flex.B.prototype.foo1 = function() {\n var self = this;\n function bar1() {\n return null;\n };\n return bar1();\n};\n\n\n/**\n * @export\n * @return {Object}\n */\norg.apache.flex.B.prototype.foo2 = function() {\n var self = this;\n function bar2(param1) {\n return null;\n };\n return bar2('foo');\n};"); } @Test @@ -255,7 +255,7 @@ public class TestFlexJSClass extends TestGoogClass + "public function foo2():String{function bar2(param1:String):String {return param1 + baz1;}; return bar2('foo');}" + "}"); asBlockWalker.visitClass(node); - assertOut("/**\n * @constructor\n */\norg.apache.flex.B = function() {\n};\n\n\n/**\n * @export\n * @type {string}\n */\norg.apache.flex.B.prototype.baz1;\n\n\n/**\n * @export\n * @return {string}\n */\norg.apache.flex.B.prototype.foo1 = function() {\n function bar1() {\n return this.baz1;\n };\n return org.apache.flex.utils.Language.closure(bar1, this, 'bar1')();\n};\n\n\n/**\n * @export\n * @return {string}\n */\norg.apache.flex.B.prototype.foo2 = function() {\n function bar2(param1) {\n return param1 + this.baz1;\n };\n return org.apache.flex.utils.Language.closure(bar2, this, 'bar2')('foo');\n};"); + assertOut("/**\n * @constructor\n */\norg.apache.flex.B = function() {\n};\n\n\n/**\n * @export\n * @type {string}\n */\norg.apache.flex.B.prototype.baz1;\n\n\n/**\n * @export\n * @return {string}\n */\norg.apache.flex.B.prototype.foo1 = function() {\n var self = this;\n function bar1() {\n return this.baz1;\n };\n return bar1();\n};\n\n\n/**\n * @export\n * @return {string}\n */\norg.apache.flex.B.prototype.foo2 = function() {\n var self = this;\n function bar2(param1) {\n return param1 + this.baz1;\n };\n return bar2('foo');\n};"); } @Test http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/f0ebbf0c/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java index fdb40ec..76d48dc 100644 --- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java +++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java @@ -552,7 +552,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function c(f:Function):void {}; function d():void {}; c(d); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n function c(f) {\n };\n function d() {\n };\n org.apache.flex.utils.Language.closure(c, this, 'c')(org.apache.flex.utils.Language.closure(d, this, 'd'));\n}"); + assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n function d() {\n };\n c(org.apache.flex.utils.Language.closure(d, this, 'd'));\n}"); } @Test @@ -562,7 +562,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function c(s:String, f:Function):void {}; function d():void {}; c('foo', d); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n function c(s, f) {\n };\n function d() {\n };\n org.apache.flex.utils.Language.closure(c, this, 'c')('foo', org.apache.flex.utils.Language.closure(d, this, 'd'));\n}"); + assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(s, f) {\n };\n function d() {\n };\n c('foo', org.apache.flex.utils.Language.closure(d, this, 'd'));\n}"); } @Test @@ -572,7 +572,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { c('foo', d); function c(s:String, f:Function):void {}; function d():void {};}}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n org.apache.flex.utils.Language.closure(c, this, 'c')('foo', org.apache.flex.utils.Language.closure(d, this, 'd'));\n function c(s, f) {\n };\n function d() {\n };\n}"); + assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(s, f) {\n };\n function d() {\n };\n c('foo', org.apache.flex.utils.Language.closure(d, this, 'd'));\n \n}"); } @Test @@ -582,7 +582,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function d():void {}; c('foo', d); } public function c(s:String, f:Function):void {};}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n function d() {\n };\n this.c('foo', org.apache.flex.utils.Language.closure(d, this, 'd'));\n}"); + assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function d() {\n };\n this.c('foo', org.apache.flex.utils.Language.closure(d, this, 'd'));\n}"); } @Test @@ -592,7 +592,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function c(f:Function):void {}; c(b); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n function c(f) {\n };\n org.apache.flex.utils.Language.closure(c, this, 'c')(org.apache.flex.utils.Language.closure(this.b, this, 'b'));\n}"); + assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n c(org.apache.flex.utils.Language.closure(this.b, this, 'b'));\n}"); } @Test @@ -602,7 +602,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {static public function b() { function c(f:Function):void {}; c(b); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nfoo.bar.B.b = function() {\n function c(f) {\n };\n org.apache.flex.utils.Language.closure(c, this, 'c')(foo.bar.B.b);\n}"); + assertOut("/**\n * @export\n */\nfoo.bar.B.b = function() {\n function c(f) {\n };\n c(foo.bar.B.b);\n}"); } @Test @@ -612,7 +612,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function c(f:Function):void {}; var f:Function = b; c(f); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n function c(f) {\n };\n var /** @type {Function} */ f = org.apache.flex.utils.Language.closure(this.b, this, 'b');\n org.apache.flex.utils.Language.closure(c, this, 'c')(f);\n}"); + assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Function} */ f = org.apache.flex.utils.Language.closure(this.b, this, 'b');\n c(f);\n}"); } @Test @@ -622,7 +622,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {static public function b() { function c(f:Function):void {}; var f:Function = b; c(f); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nfoo.bar.B.b = function() {\n function c(f) {\n };\n var /** @type {Function} */ f = foo.bar.B.b;\n org.apache.flex.utils.Language.closure(c, this, 'c')(f);\n}"); + assertOut("/**\n * @export\n */\nfoo.bar.B.b = function() {\n function c(f) {\n };\n var /** @type {Function} */ f = foo.bar.B.b;\n c(f);\n}"); } @Test @@ -632,7 +632,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function c(f:Function):void {}; var f:Function; f = b; c(f); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n function c(f) {\n };\n var /** @type {Function} */ f;\n f = org.apache.flex.utils.Language.closure(this.b, this, 'b');\n org.apache.flex.utils.Language.closure(c, this, 'c')(f);\n}"); + assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Function} */ f;\n f = org.apache.flex.utils.Language.closure(this.b, this, 'b');\n c(f);\n}"); } @Test @@ -642,7 +642,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {static public function b() { function c(f:Function):void {}; var f:Function; f = b; c(f); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nfoo.bar.B.b = function() {\n function c(f) {\n };\n var /** @type {Function} */ f;\n f = foo.bar.B.b;\n org.apache.flex.utils.Language.closure(c, this, 'c')(f);\n}"); + assertOut("/**\n * @export\n */\nfoo.bar.B.b = function() {\n function c(f) {\n };\n var /** @type {Function} */ f;\n f = foo.bar.B.b;\n c(f);\n}"); } @Test @@ -652,7 +652,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function c(f:Function):void {}; var f:Array = [b]; c(f[0]); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n function c(f) {\n };\n var /** @type {Array} */ f = [org.apache.flex.utils.Language.closure(this.b, this, 'b')];\n org.apache.flex.utils.Language.closure(c, this, 'c')(f[0]);\n}"); + assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Array} */ f = [org.apache.flex.utils.Language.closure(this.b, this, 'b')];\n c(f[0]);\n}"); } @Test @@ -662,7 +662,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {static public function b() { function c(f:Function):void {}; var f:Array = [b]; c(f); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nfoo.bar.B.b = function() {\n function c(f) {\n };\n var /** @type {Array} */ f = [foo.bar.B.b];\n org.apache.flex.utils.Language.closure(c, this, 'c')(f);\n}"); + assertOut("/**\n * @export\n */\nfoo.bar.B.b = function() {\n function c(f) {\n };\n var /** @type {Array} */ f = [foo.bar.B.b];\n c(f);\n}"); } @Test @@ -672,7 +672,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function c(f:Function):void {}; c(this.b); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n function c(f) {\n };\n org.apache.flex.utils.Language.closure(c, this, 'c')(org.apache.flex.utils.Language.closure(this.b, this, 'b'));\n}"); + assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n c(org.apache.flex.utils.Language.closure(this.b, this, 'b'));\n}"); } @Test @@ -735,26 +735,83 @@ public class TestFlexJSExpressions extends TestGoogExpressions @Override @Test + public void testAnonymousFunction() + { + IFunctionNode node = (IFunctionNode) getNode("var a = function(){};", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("FalconTest_A.prototype.falconTest_a = function() {\n" + + " var self = this;\n" + + " var /** @type {Function} */ __localFn0__ = function() {\n" + + " }\n" + + " var /** @type {*} */ a = __localFn0__;\n" + + "}"); + } + + @Override + @Test public void testAnonymousFunctionWithParamsReturn() { - IVariableNode node = (IVariableNode) getNode( + IFunctionNode node = (IFunctionNode) getNode( "var a:Object = function(foo:int, bar:String = 'goo'):int{return -1;};", - IVariableNode.class); - asBlockWalker.visitVariable(node); - assertOut("var /** @type {Object} */ a = function(foo, bar) {\n bar = typeof bar !== 'undefined' ? bar : 'goo';\n return -1;\n}"); + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("FalconTest_A.prototype.falconTest_a = function() {\n" + + " var self = this;\n" + + " var /** @type {Function} */ __localFn0__ = function(foo, bar) {\n" + + " bar = typeof bar !== 'undefined' ? bar : 'goo';\n" + + " return -1;\n" + + " }\n" + + " var /** @type {Object} */ a = __localFn0__;\n" + + "}"); } @Override @Test public void testAnonymousFunctionAsArgument() { - IFunctionCallNode node = (IFunctionCallNode) getNode( + IFunctionNode node = (IFunctionNode) getNode( "addListener('foo', function(event:Object):void{doit();})", - IFunctionCallNode.class); - asBlockWalker.visitFunctionCall(node); - assertOut("addListener('foo', function(event) {\n doit();\n})"); + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("FalconTest_A.prototype.falconTest_a = function() {\n" + + " var self = this;\n" + + " var /** @type {Function} */ __localFn0__ = function(event) {\n" + + " doit();\n" + + " }\n" + + " addListener('foo', __localFn0__);\n" + + "}"); } + @Test + public void testES5StrictAnonymousFunctions() + { + IFunctionNode node = (IFunctionNode) getNode( + "var a:Object = {}; var b:Function = function(foo:Object) { foo.bar = 10 }; var c:Object = b(a);", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("FalconTest_A.prototype.falconTest_a = function() {\n" + + " var self = this;\n" + + " var /** @type {Function} */ __localFn0__ = function(foo) {\n foo.bar = 10;\n }\n" + + " var /** @type {Object} */ a = {};\n" + + " var /** @type {Function} */ b = __localFn0__;\n" + + " var /** @type {Object} */ c = b(a);\n}"); + } + + @Test + public void testES5StrictNamedLocalFunctions() + { + IFunctionNode node = (IFunctionNode) getNode( + "var a:Object = {}; function b(foo:Object) { foo.bar = 10 }; var c:Object = b(a);", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("FalconTest_A.prototype.falconTest_a = function() {\n" + + " var self = this;\n" + + " function b(foo) {\n foo.bar = 10;\n };\n" + + " var /** @type {Object} */ a = {};\n" + + " var /** @type {Object} */ c = b(a);\n}"); + } + @Override @Test public void testVisitAs() http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/f0ebbf0c/compiler.jx.tests/test-files/flexjs/files/LocalFunction_result.js ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/test-files/flexjs/files/LocalFunction_result.js b/compiler.jx.tests/test-files/flexjs/files/LocalFunction_result.js index 9d51bc3..09f3245 100644 --- a/compiler.jx.tests/test-files/flexjs/files/LocalFunction_result.js +++ b/compiler.jx.tests/test-files/flexjs/files/LocalFunction_result.js @@ -42,10 +42,11 @@ LocalFunction.prototype.myMemberProperty = "got it: "; * @param {number} value */ LocalFunction.prototype.myMemberMethod = function(value) { + var self = this; function myLocalFunction(value) { return this.myMemberProperty + value; }; - org.apache.flex.utils.Language.trace("WOW! :: " + org.apache.flex.utils.Language.closure(myLocalFunction, this, 'myLocalFunction')(value + 42)); + org.apache.flex.utils.Language.trace("WOW! :: " + myLocalFunction(value + 42)); }; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/f0ebbf0c/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java index 57eb309..8903c25 100644 --- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java @@ -20,6 +20,7 @@ package org.apache.flex.compiler.internal.codegen.js.flexjs; import java.io.FilterWriter; +import java.util.List; import org.apache.flex.compiler.codegen.js.flexjs.IJSFlexJSEmitter; import org.apache.flex.compiler.codegen.js.goog.IJSGoogDocEmitter; @@ -53,6 +54,7 @@ import org.apache.flex.compiler.internal.projects.FlexJSProject; import org.apache.flex.compiler.internal.tree.as.BinaryOperatorAsNode; import org.apache.flex.compiler.internal.tree.as.DynamicAccessNode; import org.apache.flex.compiler.internal.tree.as.FunctionCallNode; +import org.apache.flex.compiler.internal.tree.as.FunctionNode; import org.apache.flex.compiler.internal.tree.as.IdentifierNode; import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode; import org.apache.flex.compiler.internal.tree.as.TernaryOperatorNode; @@ -68,6 +70,7 @@ import org.apache.flex.compiler.tree.as.IFileNode; import org.apache.flex.compiler.tree.as.IForLoopNode; import org.apache.flex.compiler.tree.as.IFunctionCallNode; import org.apache.flex.compiler.tree.as.IFunctionNode; +import org.apache.flex.compiler.tree.as.IFunctionObjectNode; import org.apache.flex.compiler.tree.as.IGetterNode; import org.apache.flex.compiler.tree.as.IIdentifierNode; import org.apache.flex.compiler.tree.as.IInterfaceNode; @@ -202,8 +205,19 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter } @Override + public void emitLocalNamedFunction(IFunctionNode node) + { + IFunctionNode fnNode = (IFunctionNode)node.getAncestorOfType(IFunctionNode.class); + if (fnNode.getEmittingLocalFunctions()) + { + super.emitLocalNamedFunction(node); + } + } + + @Override public void emitFunctionBlockHeader(IFunctionNode node) { + node.setEmittingLocalFunctions(true); super.emitFunctionBlockHeader(node); if (node.isConstructor()) { @@ -211,6 +225,46 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter .getAncestorOfType(IClassNode.class); emitComplexInitializers(cnode); } + if (node.containsLocalFunctions()) + { + List anonFns = node.getLocalFunctions(); + int n = anonFns.size(); + for (int i = 0; i < n; i++) + { + IFunctionNode anonFn = anonFns.get(i); + if (anonFn.getParent().getNodeID() == ASTNodeID.AnonymousFunctionID) + { + write(" var /** @type {Function} */ __localFn" + Integer.toString(i) + "__ = "); + getWalker().walk(anonFn.getParent()); + } + else + { + getWalker().walk(anonFn); + write(ASEmitterTokens.SEMICOLON); + } + this.writeNewline(); + } + } + node.setEmittingLocalFunctions(false); + } + + @Override + public void emitFunctionObject(IFunctionObjectNode node) + { + IFunctionNode fnNode = (IFunctionNode)node.getAncestorOfType(IFunctionNode.class); + if (fnNode.getEmittingLocalFunctions()) + { + super.emitFunctionObject(node); + } + else + { + List anonFns = fnNode.getLocalFunctions(); + int i = anonFns.indexOf(node.getFunctionNode()); + if (i < 0) + System.out.println("missing index for " + node.toString()); + else + write("__localFn" + Integer.toString(i) + "__"); + } } @Override @@ -486,6 +540,17 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter write(ASEmitterTokens.PAREN_CLOSE); } + @Override + public void emitStatement(IASNode node) + { + // don't emit named local functions as statements + // they are emitted as part of the function block header + if (node.getNodeID() == ASTNodeID.FunctionID) + { + return; + } + super.emitStatement(node); + } private void writeChainName(IASNode node) { while (node.getNodeID() == ASTNodeID.MemberAccessExpressionID) http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/f0ebbf0c/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/IdentifierEmitter.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/IdentifierEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/IdentifierEmitter.java index 704b77d..a21cd63 100644 --- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/IdentifierEmitter.java +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/IdentifierEmitter.java @@ -73,11 +73,9 @@ public class IdentifierEmitter extends JSSubEmitter implements { FunctionClassification fc = ((FunctionDefinition)nodeDef).getFunctionClassification(); identifierIsLocalOrInstanceFunctionAsValue = - fc == FunctionClassification.LOCAL || - (fc == FunctionClassification.CLASS_MEMBER && - // not a value if parent is a function call or member access expression - (!(parentNodeId == ASTNodeID.MemberAccessExpressionID || - parentNodeId == ASTNodeID.FunctionCallID))); + (fc == FunctionClassification.LOCAL || fc == FunctionClassification.CLASS_MEMBER) && + // not a value if parent is a function call or member access expression + (!(parentNodeId == ASTNodeID.MemberAccessExpressionID || parentNodeId == ASTNodeID.FunctionCallID)); } // an instance method as a parameter or http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/f0ebbf0c/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/SelfReferenceEmitter.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/SelfReferenceEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/SelfReferenceEmitter.java index 0d7849c..6e662ce 100644 --- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/SelfReferenceEmitter.java +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/SelfReferenceEmitter.java @@ -40,7 +40,7 @@ public class SelfReferenceEmitter extends JSSubEmitter implements { // we don't want 'var self = this;' in FlexJS // unless there are anonymous functions - if (node.containsAnonymousFunctions()) + if (node.containsLocalFunctions()) { writeToken(ASEmitterTokens.VAR); writeToken(JSGoogEmitterTokens.SELF); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/f0ebbf0c/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionNode.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionNode.java b/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionNode.java index af63395..5eb3621 100644 --- a/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionNode.java +++ b/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionNode.java @@ -68,6 +68,7 @@ import org.apache.flex.compiler.tree.as.IContainerNode; import org.apache.flex.compiler.tree.as.IDefinitionNode; import org.apache.flex.compiler.tree.as.IExpressionNode; import org.apache.flex.compiler.tree.as.IFunctionNode; +import org.apache.flex.compiler.tree.as.IFunctionObjectNode; import org.apache.flex.compiler.tree.as.INamespaceDecorationNode; import org.apache.flex.compiler.tree.as.IParameterNode; import org.apache.flex.compiler.tree.as.IScopedNode; @@ -209,6 +210,10 @@ public class FunctionNode extends BaseTypedDefinitionNode implements IFunctionNo { if (set.contains(PostProcessStep.POPULATE_SCOPE)) { + final IFunctionNode parentFunctionNode = (IFunctionNode)getAncestorOfType(IFunctionNode.class); + if (parentFunctionNode != null) + parentFunctionNode.rememberLocalFunction(this); + FunctionDefinition definition = buildDefinition(); setDefinition(definition); @@ -933,7 +938,7 @@ public class FunctionNode extends BaseTypedDefinitionNode implements IFunctionNo */ public final void discardFunctionBody() { - if (!isBodyDeferred) + if (!isBodyDeferred || containsLocalFunctions()) return; deferredBodyParsingLock.lock(); @@ -1015,17 +1020,40 @@ public class FunctionNode extends BaseTypedDefinitionNode implements IFunctionNo this.functionBodyText = bodyCache.toString(); } + private ArrayList localFunctions; + @Override - public boolean containsAnonymousFunctions() + public List getLocalFunctions() { - return hasAnonymousFunctions; + return localFunctions; } - @Override - public void setAnonymousFunctionsFlag(boolean value) + public boolean containsLocalFunctions() { - hasAnonymousFunctions = value; + return localFunctions != null; } + @Override + public void rememberLocalFunction(IFunctionNode value) + { + if (localFunctions == null) + localFunctions = new ArrayList(); + + localFunctions.add(value); + } + + private boolean emitLocalFunctions; + + @Override + public boolean getEmittingLocalFunctions() + { + return emitLocalFunctions; + } + + @Override + public void setEmittingLocalFunctions(boolean emit) + { + emitLocalFunctions = emit; + } } http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/f0ebbf0c/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionObjectNode.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionObjectNode.java b/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionObjectNode.java index 4750272..4b6b268 100644 --- a/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionObjectNode.java +++ b/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionObjectNode.java @@ -93,10 +93,6 @@ public class FunctionObjectNode extends ExpressionNodeBase implements IFunctionO @Override protected void analyze(EnumSet set, ASScope scope, Collection problems) { - final IFunctionNode parentFunctionNode = (IFunctionNode)getAncestorOfType(IFunctionNode.class); - if (parentFunctionNode != null) - parentFunctionNode.setAnonymousFunctionsFlag(true); - EnumSet stepsToRunOnChildren; if (set.contains(PostProcessStep.RECONNECT_DEFINITIONS)) { http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/f0ebbf0c/compiler/src/org/apache/flex/compiler/tree/as/IFunctionNode.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/tree/as/IFunctionNode.java b/compiler/src/org/apache/flex/compiler/tree/as/IFunctionNode.java index a7e5ee6..361ae5d 100644 --- a/compiler/src/org/apache/flex/compiler/tree/as/IFunctionNode.java +++ b/compiler/src/org/apache/flex/compiler/tree/as/IFunctionNode.java @@ -19,6 +19,8 @@ package org.apache.flex.compiler.tree.as; +import java.util.List; + import org.apache.flex.compiler.definitions.IFunctionDefinition; import org.apache.flex.compiler.definitions.IFunctionDefinition.FunctionClassification; @@ -156,12 +158,30 @@ public interface IFunctionNode extends IScopedDefinitionNode, IDocumentableDefin boolean hasBody(); /** - * Does this function have a anonymous functions within + * Does this function have a local functions within + */ + boolean containsLocalFunctions(); + + /** + * Get local functions within + */ + List getLocalFunctions(); + + /** + * Remember local Functions in this function node(). + * JS codegen needs to know about them. + */ + void rememberLocalFunction(IFunctionNode localFunction); + + /** + * flag to determine whether to emit the local function + * or a reference to it */ - boolean containsAnonymousFunctions(); + boolean getEmittingLocalFunctions(); /** - * Set containsAnonymousFunction() + * flag to determine whether to emit the local function + * or a reference to it */ - void setAnonymousFunctionsFlag(boolean value); + void setEmittingLocalFunctions(boolean emit); }