Author: dda
Date: 2007-12-11 08:30:08 -0800 (Tue, 11 Dec 2007)
New Revision: 7507

Modified:
   
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
   
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
   
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/ParseTreePrinter.java
   
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
   
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9ParseTreePrinter.java
   openlaszlo/branches/devildog/lps/components/lztest/lztestmanager.lzx
Log:
Change 20071211-dda-Y by [EMAIL PROTECTED] on 2007-12-11 10:58:29 EST
    in /Users/dda/laszlo/src/svn/openlaszlo/branches/devildog
    for http://svn.openlaszlo.org/openlaszlo/branches/devildog

Summary: lztest-node fixes for SWF9

New Features: none

Bugs Fixed: LPP-5234

Technical Reviewer: ptw (pending)
QA Reviewer: (pending)
Doc Reviewer: (pending)

Documentation: none

Release Notes: none

Details:
    This change addresses several issues related to building lztest-node in 
SWF9.

  + lztestmanager was written using 'old style' class definition.
    We could have found a way to make this work, but it seemed much better to
    take advantage of the new capabilities of defining classes via 'class' 
keywords, etc.

  + Many methods reference global variables.  These variables either appear
    as part of the default application class, or become true 'globals'.  In the
    former case, we need to potentially emit 'with (this)' or 'with 
(lzDefaultAppliation)',
    apparently depending on whether the method is within the default 
application or not.
    In the latter case, the users of the global variable are fine, but the 
variable needs
    to be emitted in its own source file.  This seems to be the only way to 
create a standalone
    global variable in SWF9.
       package {
        public var global = null;
       }

  + Normally the JavascriptGenerator remaps local variables to names like $1, 
$2, etc.
    This was even happening for 'class variables' in explicitly declared 
classes:
      class foo {
         var x = 1;
         function bar() {
            x++;
         }
      }
    x would be renamed to $1, and the references to it (from bar) were not 
remapped.
    Even if we could remap all, this would not be appropriate if x were public
    (really only private should be remapped for this case).  In SWF9, we simply
    disable this remapping for now.  Undoubtedly, we'll need this conditionally
    (I left in a TODO) but it's easiest to make progress by deferring this.
    
  + Fixed some small problems related to string manipulation of generated code.
    For SWF9, generated code contains 'annotations', that is line and classname 
information
    embedded in the generated Strings.  These annotations are stripped out when 
writing
    the text to a file, but is also used to build line number tables and direct 
output
    to the proper filename.  When making simple manipulations, like 'remove a 
semicolon
    from the last character of a string', care must be taken to not remove any 
part of
    the annotation.  Fortunately, very little string manipulation occurs after 
code
    is generated.

Tests:



Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
 2007-12-11 16:28:47 UTC (rev 7506)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/Compiler.java
 2007-12-11 16:30:08 UTC (rev 7507)
@@ -345,6 +345,7 @@
         }
         cg.setOptions(options);
         SimpleNode translated = cg.translate(program);
+        (new FileSaver()).emit("/tmp/lzsrc.txt", 
source).emit("/tmp/lzprog.txt", program);
         List tunits = cg.makeTranslationUnits(translated, compress, obfuscate);
         bytes = cg.postProcess(tunits);
 

Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
      2007-12-11 16:28:47 UTC (rev 7506)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
      2007-12-11 16:30:08 UTC (rev 7507)
@@ -1095,10 +1095,12 @@
     int stmtsIndex;
     ASTIdentifier functionNameIdentifier = null;
     if (children.length == 3) {
-      functionNameIdentifier = (ASTIdentifier)children[0];
+      if (children[0] instanceof ASTIdentifier) {
+        functionNameIdentifier = (ASTIdentifier)children[0];
+        functionName = functionNameIdentifier.getName();
+      }
       params = children[1];
       stmts = children[stmtsIndex = 2];
-      functionName = functionNameIdentifier.getName();
     } else {
       params = children[0];
       stmts = children[stmtsIndex = 1];
@@ -1294,7 +1296,7 @@
     // Look for #pragma
     boolean scriptElement = options.getBoolean(Compiler.SCRIPT_ELEMENT);
     Map registerMap = new HashMap();
-    if (! scriptElement) {
+    if (remapLocals()) {
       // All parameters and locals are remapped to 'registers' of the
       // form `$n`.  This prevents them from colliding with member
       // slots due to implicit `with (this)` added below, and also makes
@@ -1707,6 +1709,19 @@
 
     return new JavascriptReference(this, node, referenceCount);
   }
+
+  /**
+   * Returns true if local variables and parameters
+   * should have remapped names (like $1, $2, ...) to prevent
+   * them from colliding with member names that may be exposed
+   * by implicit insertion of with(this).
+   *
+   * This method can be overridden when subclassed.
+   */
+  public boolean remapLocals() {
+    boolean scriptElement = options.getBoolean(Compiler.SCRIPT_ELEMENT);
+    return !scriptElement;
+  }
 }
 
 /**

Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/ParseTreePrinter.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/ParseTreePrinter.java
 2007-12-11 16:28:47 UTC (rev 7506)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/ParseTreePrinter.java
 2007-12-11 16:30:08 UTC (rev 7507)
@@ -102,8 +102,10 @@
   }
   
   public String delimit(String phrase, boolean force) {
-    if (phrase.length() > 0) {
-      return ((('(' != phrase.charAt(0)) && force)?" ":SPACE) + phrase;
+    // Strip the phrase of annotations so we can look at the first char
+    String plain = unannotate(phrase);
+    if (plain.length() > 0) {
+      return ((('(' != plain.charAt(0)) && force)?" ":SPACE) + phrase;
     }
     return phrase;
   }
@@ -113,8 +115,11 @@
   }
   
   public String elideSemi(String phrase) {
-    if (phrase.endsWith(SEMI)) {
-      return phrase.substring(0, phrase.length() - SEMI.length());
+    // Strip the phrase of annotations so we can look at the ending
+    if (unannotate(phrase).endsWith(SEMI)) {
+      // We don't want to lose the annotations, none will contain SEMI though.
+      int semipos = phrase.lastIndexOf(SEMI);
+      return phrase.substring(0, semipos) + phrase.substring(semipos + 
SEMI.length());
     }
     return phrase;
   }
@@ -871,7 +876,7 @@
         endann = annotated.indexOf(ANNOTATE_MARKER, startann+2);
         if (endann < 0) {
           // unbalanced annotations
-          throw new IllegalArgumentException("bad line number annotations");
+          throw new IllegalArgumentException("bad line number annotations:");
         }
         sb.append(notify(op, annotated.substring(startann+2, endann)));
         startann = annotated.indexOf(ANNOTATE_MARKER, endann+1);

Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
    2007-12-11 16:28:47 UTC (rev 7506)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9Generator.java
    2007-12-11 16:30:08 UTC (rev 7507)
@@ -32,11 +32,32 @@
  */
 public class SWF9Generator extends JavascriptGenerator {
 
+  Map programVars = new HashMap();
+
+  // this is set when we are visiting class definitions.
+  // The 'default' class is implicit and will encompass everything else.
+  //
+  // Use of this variable to save state during 'visit' calls means that
+  // visit methods are not reentrant.  This is not really
+  // a new concern in the generators, as compiler options are often
+  // twiddled as we parse.
+  //
+  boolean inNonDefaultClass = false;
+
+  // override superclass version - we don't want to remap names
+  // of class variables
+
+  public boolean remapLocals() {
+    // TODO: [2007-12-11 dda] maybe remap selectively - anything that is
+    // private may be remapped.
+    return false;
+  }
+
   // override superclass method.
   // For SWF9, we need to preserve
   // the class definition, rather than converting it to
   // a function call to dynamically create the class.
-  //
+
   public SimpleNode visitClassDefinition(SimpleNode node, SimpleNode[] 
children) {
     ASTIdentifier classortrait = (ASTIdentifier)children[0];
     ASTIdentifier classname = (ASTIdentifier)children[1];
@@ -59,7 +80,7 @@
     }
 
     /*
-     * TODO: [2007-11-20 ptw]  some code below borrowed from superclass
+     * TODO: [2007-11-20 dda]  some code below borrowed from superclass
      * that is currently unused, but may translate to something we need
      * to output or track.  In particular, we'll want to do something
      * with props/classProps, there may be some extra directives
@@ -85,11 +106,37 @@
     node.setChildren(newch);
     */
 
-    visitChildren(node);
+    boolean savedInNonDefault = inNonDefaultClass;
+    inNonDefaultClass = true;
+    try {
+      visitChildren(node);
+    }
+    finally {
+      inNonDefaultClass = savedInNonDefault;
+    }
 
     return node;
   }
 
+  /**
+   * Intercept JavascriptGenerator version.
+   * We keep track of variables that are implicitly global.
+   */
+  public SimpleNode visitVariableDeclaration(SimpleNode node, SimpleNode[] 
children) {
+    if (options.getBoolean(Compiler.SCRIPT_ELEMENT)) {
+      if (children.length > 1) {
+        String idname = ((ASTIdentifier)children[0]).getName();
+        programVars.put(idname, idname);
+      }
+    }
+    return super.visitVariableDeclaration(node, children);
+  }
+
+  /**
+   * Intercept JavascriptGenerator version.
+   * We insert a with (this) or with (defaultApplication)
+   * as appropriate.
+   */
   public SimpleNode translateFunction(SimpleNode node, boolean isReferenced, 
SimpleNode[] children) {
     int stmtPos = children.length - 1;
     SimpleNode stmts = children[stmtPos];
@@ -108,11 +155,18 @@
         break;
       }
     }
+
+    // TODO: [2007-12-11 dda] always reference the app?  rethink this.
+    // needsApp is set unconditionally for now to get through some
+    // test cases
+    needsApp = true;
     if (needsApp) {
+      String withVariable = (inNonDefaultClass ? "lzApplicationInstance" : 
"this");
+
       Map map = new HashMap();
       map.put("_1", new Compiler.Splice(stmts.getChildren()));
       //      SimpleNode newNode = (new 
Compiler.Parser()).substitute("(function () { with (lzApplicationInstance) { _1 
}})()", map);
-      SimpleNode newNode = (new Compiler.Parser()).substituteStmt("with 
(lzApplicationInstance) { _1 }", map);
+      SimpleNode newNode = (new Compiler.Parser()).substituteStmt("with (" + 
withVariable + ") { _1 }", map);
       children[stmtPos] = visitStatement(newNode);
     }
     return super.translateFunction(node, isReferenced, children);
@@ -574,7 +628,8 @@
     boolean hasErrors = false;
     String apptype = null;
 
-    TranslationUnit instDecl = null;
+    TranslationUnit globalVar = null;
+    List globalVars = new ArrayList();
 
     for (Iterator iter = tunits.iterator(); iter.hasNext(); ) {
       TranslationUnit tunit = (TranslationUnit)iter.next();
@@ -597,16 +652,28 @@
 
         epilog = "\n}" + epilog;
 
-        instDecl = new TranslationUnit();
-        instDecl.setName("lzApplicationInstance");
-        instDecl.addText("public var lzApplicationInstance:" + name + " = 
null;");
+        globalVar = new TranslationUnit();
+        globalVar.setName("lzApplicationInstance");
+        globalVar.addText("public var lzApplicationInstance:" + name + " = 
null;");
+        globalVars.add(globalVar);
+        
+        for (Iterator variter = programVars.keySet().iterator(); 
variter.hasNext(); ) {
+          String varname = (String)variter.next();
+          globalVar = new TranslationUnit();
+          globalVar.setName(varname);
+          globalVar.addText("public var " + varname + " = null;");
+          globalVars.add(globalVar);
+        }
+        programVars = new HashMap();
+
       }
       writeOutputFile(name, preamble, tunit.getContents(), epilog);
     }
-    if (instDecl != null) {
-      writeOutputFile(instDecl.getName(), DEFAULT_FILE_PREAMBLE,
-                      instDecl.getContents(), DEFAULT_FILE_EPILOG);
-      tunits.add(instDecl);
+    for (Iterator iter = globalVars.iterator(); iter.hasNext(); ) {
+      TranslationUnit tunit = (TranslationUnit)iter.next();
+      writeOutputFile(tunit.getName(), DEFAULT_FILE_PREAMBLE,
+                      tunit.getContents(), DEFAULT_FILE_EPILOG);
+      tunits.add(tunit);
     }
 
     try {

Modified: 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9ParseTreePrinter.java
===================================================================
--- 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9ParseTreePrinter.java
     2007-12-11 16:28:47 UTC (rev 7506)
+++ 
openlaszlo/branches/devildog/WEB-INF/lps/server/src/org/openlaszlo/sc/SWF9ParseTreePrinter.java
     2007-12-11 16:30:08 UTC (rev 7507)
@@ -53,11 +53,11 @@
     String classnm = unannotate(children[1]);
     StringBuffer sb = new StringBuffer();
     sb.append("public class" + SPACE + classnm + SPACE);
-    if (children[2].length() > 0)
+    if (unannotate(children[2]).length() > 0)
       sb.append("extends" + SPACE + children[2] + SPACE);
 
     // TODO: [2007-11-20 dda] handle 'with' or inherits clause
-    // if (children[3].length() > 0) ....
+    // if (unannotate(children[3]).length() > 0) ....
 
     sb.append("{\n");
     for (int i=4; i<children.length; i++) {

Modified: openlaszlo/branches/devildog/lps/components/lztest/lztestmanager.lzx
===================================================================
--- openlaszlo/branches/devildog/lps/components/lztest/lztestmanager.lzx        
2007-12-11 16:28:47 UTC (rev 7506)
+++ openlaszlo/branches/devildog/lps/components/lztest/lztestmanager.lzx        
2007-12-11 16:30:08 UTC (rev 7507)
@@ -7,17 +7,6 @@
 
 <script><![CDATA[
 
-var LzTestManager = {
-    totalsuites: 0,
-    passedsuites: 0,
-    failedsuites: 0,
-    suites: [],
-    cursuite: 0,
-    results: [],
-    global: this,
-    logfile: "lztest.log",
-    resultstring: ""
-}; 
 
 var LzTestSuite = function ( nm ) {
     this.name = nm; 
@@ -50,21 +39,30 @@
     }
 }
 
-LzTestManager.findTestSuites = function() {
+class LzTestManager {
+public var totalsuites = 0;
+public var passedsuites = 0;
+public var failedsuites = 0;
+public var suites = [];
+public var cursuite = 0;
+public var results = [];
+public var global = this;
+public var logfile = "lztest.log";
+public var resultstring = "";
+
+function findTestSuites() {
     // Debug.write("findTests..."); 
     for (var n in global) {
         var ts = global[n];
         if (ts && ts instanceof LzTestSuite) {
             // Debug.write("found test suite: ", n, " and it's really ", ts); 
-            LzTestManager.suites.push(ts); 
-            LzTestManager.totalsuites += 1;             
+            this.suites.push(ts); 
+            this.totalsuites += 1;             
         }
     }
 }       
 
-
-
-LzTestManager.setupServerLogging = function () {
+function setupServerLogging() {
     var lzurl = LzBrowser.getLoadURLAsLzURL();
     // strip initial "/legals/" from path, to make it relative to LPS servlet 
base
     if (lzurl.path) {
@@ -77,7 +75,7 @@
     //this.resultstring = "start testsuite: "+this.testpath +"\n";
 }
 
-LzTestManager.sendLogData = function (logfile, msg) {
+function sendLogData(logfile, msg) {
     if (!this.loggingEnabled) {
         return;
     }
@@ -95,7 +93,7 @@
     tloader.send (/* content */ null)        
 }
 
-LzTestManager.printSummary = function () {
+function printSummary () {
     var failedsuitenames = [];
     var passedsuitenames = [];
     var countedfailedsuites = 0; 
@@ -140,7 +138,7 @@
     this.sendLogData(this.logfile, this.resultstring);
 }
 
-LzTestManager.runTestSuites = function() {
+function runTestSuites() {
     this.setupServerLogging();
     for (var suite in this.suites) {
         this.results[suite] = "pre"; 
@@ -172,7 +170,7 @@
 }
 
 
-LzTestManager.failAssertion = function( msg ) {    
+function failAssertion ( msg ) {    
     var ste = this.suites[this.cursuite]; 
     if (ste) {
         var tst = ste.curtest;     
@@ -186,7 +184,7 @@
     }
 }
 
-LzTestManager.assertTrue = function(condition, assertion) {
+function assertTrue (condition, assertion) {
     if (!condition)  {
         var errmsg = "FAIL: assertTrue('" + condition + "') failed"
                     + (assertion ? ': ' + assertion : '');      
@@ -195,7 +193,7 @@
 }
 
 
-LzTestManager.assertFalse = function(condition, assertion) {
+function assertFalse (condition, assertion) {
     if (condition)  {
         var errmsg = "FAIL: assertFalse('" + condition + "') failed"
                     + (assertion ? ': ' + assertion : '');      
@@ -203,26 +201,26 @@
     }
 }
 
-LzTestManager.assertEquals = function(expected, actual, message) {
+function assertEquals (expected, actual, message) {
     if (! (expected == actual)) {
         var errmsg = "FAIL: " + message + "Equals expected " + expected + ", 
got " + actual; 
         LzTestManager.failAssertion(errmsg); 
     }
 }
 
-LzTestManager.assertNull = function(object, message) {
+function assertNull (object, message) {
     if (object !== null) {
        LzTestManager.failAssertion(message + " Null " + null + object);
     }
 }
 
-LzTestManager.assertNotNull = function(object, message) {
+function assertNotNull (object, message) {
     if (object === null) {
        LzTestManager.failAssertion(message + " NotNull " + "non-null value: " 
+ object);
     }
 }
 
-LzTestManager.assertSame = function(expected, actual, message) {
+function assertSame (expected, actual, message) {
     if (typeof(expected) == "undefined" && typeof(actual) == "undefined") {
         return;
     }
@@ -232,26 +230,26 @@
     }
 }
 
-LzTestManager.assertNotSame = function(expected, actual, message) {
+function assertNotSame (expected, actual, message) {
     if (expected === actual) {
         var msg = "NotSame " + msg + " expected anything but " + expected + ", 
got ", actual; 
         LzTestManager.failAssertion(msg);
     }
 }
 
-LzTestManager.assertUndefined = function(object, message) {
+function assertUndefined (object, message) {
     if (typeof(object) != "undefined") {
        LzTestManager.failAssertion(message + " undefined value  " + object);
     }
 }
 
-LzTestManager.assertNotUndefined = function(object, message) {
+function assertNotUndefined (object, message) {
     if (typeof(object) == "undefined") {
         LzTestManager.failAssertion(message + " undefined value  " + object); 
// 
     }
 }
 
-LzTestManager.assertWithin = function(expected, actual, delta, message) {
+function assertWithin (expected, actual, delta, message) {
     // handle infinite expected
     if (expected == actual) return;
 
@@ -261,16 +259,20 @@
         LzTestManager.failAssertion(message + "Within" + "" + expected + 
"\u00B1" + delta + " " + actual);
     }
 }
+}
+var LzTestManager:LzTestManager = new LzTestManager();
 
 var startTestsDelegate = new LzDelegate(canvas, "startTests");
 startTestsDelegate.register(canvas, "oninit"); 
 
 canvas.startTests = function() {
+  with (this) {
     // Debug.info("LzTestManager is starting tests from canvas.oninit");
     LzTestManager.findTestSuites(); 
     LzTestManager.runTestSuites();     
     LzTestManager.printSummary(); 
     // Debug.info("LzTestManager is done with tests from canvas.oninit");
+  }
 }
 
 


_______________________________________________
Laszlo-checkins mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-checkins

Reply via email to