Personal tools

Runtime Differences

From OpenLaszlo

This is a starter page to collect user-visible differences in how the LZX applications behave in the various runtime targets. In addition, it provides information about any changes required to update applications for OpenLaszlo 4.1.x and 4.2.x. Further updates coming.

Contents

Upgrading to OpenLaszlo 4.2.x and higher

General Steps for Upgrading Your OpenLaszlo 4.0.x Application to OpenLaszlo 4.2

As of OpenLaszlo 4.1.1, all global classes and services have been moved to the lz namespace. For example, LzTimer should now be referred to as lz.Timer. There are several ways to proceed depending on your goal.

For SWF8/DHTML Applications

To get your OpenLaszlo 4.0.x SWF8 and DHTML applications running quickly in OpenLaszlo 4.2, with no intent to move to SWF9, do the following:

1. Add the 4.2 compatibility include file to your application. This adds top-level globals for 4.0-style services, e.g., LzTimer=lz.timer. You will see lots of warnings at the INFO level. You can set Debug.messageLevel="WARNING" and you won't see them. This is only recommended as a transitional step in porting your application to 4.2 for SWF8 and DHTML. This will not work for SWF9. See the #4.2 compatibility include section.

For SWF9 Applications

To get your OpenLaszlo 4.0.x SWF8 and DHTML application running in SWF9, do as follows:

1. Run the convert_required.pl script and remove the compatibility include (if you did that previously). Once again, you will see lots of warnings at the INFO level, which you can suppress by setting debug.messageLevel="WARNING". See the #4.2 Migration Script section.

2. Complete the port of your application by running the Attribute Setters conversion script: convert_setters.pl as described below in #Attribute Setter Migration Script. This will eliminate a majority of the warnings.

3. Run convert_laszlo.pl as a final cleanup pass to mitigate the remaining errors. It can be found here: http://svn.openlaszlo.org/openlaszlo/trunk/WEB-INF/lps/server/bin/convert_laszlo.pl.

4.2 compatibility include

This compatibility include is designed to make 4.0.x applications run in 4.2 in SWF8 and DHTML only, to assist you in porting your code to OpenLaszlo 4.2. It adds top-level globals for 4.0-style services, e.g. LzTimer=lz.timer. This is only recommended as a transitional step in porting your application to 4.2 for SWF8 and DHTML. This will not work for SWF9.

To take advantage of SWF9 performance gains, you must run the 4.2 migration script: convert_required.pl script to migrate your code (as written above). Once you've run the 4.2 migration script, the compatibility include is no longer needed.

Here's a simple example of the include in action:

 <canvas debug="true" height="200">
   <include href="utils/4.1.x_compatibility.lzx"/>
   <script>
     // no runtime errors in 4.2
     var foo = LzKeys.keyCodes;
     var bar = LzTimer.timerList;
   </script>
 </canvas>


4.2 migration script

We have provided a simple perl conversion script (convert_required.pl) to help eliminate the majority of these warnings. This requires Perl 5 or greater.

NOTE: use this in small increments and review the changes to avoid unanticipated side effects. We recommended using version that ships with your OpenLaszlo distribution if available - see WEB-INF/lps/server/bin/convert_required.pl. You can view the perl script, even without an OpenLaszlo installation, here: http://svn.openlaszlo.org/openlaszlo/trunk/WEB-INF/lps/server/bin/convert_required.pl.

To run the script, type:

   perl /path_to_script/convert_required.pl  where path_to_script is the path to your OpenLaszlo installation


Usage:

   perl convert_required.pl [ options ] filename...

Options:

  -d debuglevel
          get debugging info for development
  -g graphical-difftool
          for each file changed, invoke the graphical difftool,
          and prompt the user to keep or not keep the changes
  -t
          create output for simple tests in /tmp/convtest
  -v
          show version number and exit

For each file, a backup file is made (filename.bak) and the file will be converted, with the result put into filename.

Examples:

 # Convert all the lzx files in the directory, doing all conversions.
 $ perl convert_required.pl *.lzs

Attribute setters defined with <setter/>

Use the new <setter/> tag to declare or override attribute setter methods. For example, this 4.1.x code:

 <method name="setY" args="y" > 
   super.setY( Math.max(parent.arrowbuttonheight-1 , Math.min( y , parent.height - (parent.thumbheight + parent.arrowbuttonheight)))); 
 </method> 

Changes to:

 <setter name="y" args="y" >
   super.setAttribute('y', Math.max(parent.arrowbuttonheight-1 , Math.min( y , parent.height - (parent.thumbheight + parent.arrowbuttonheight))));
 </setter>


Here's another example:

 <text x="${Math.round((parent.width-this.width)/2)}" font="vera_super_bold" fgcolor="0x4d4d4d" datapath="@username" resize="true">
   <method name="setText">
     if (typeof(this.datapath.data) != 'undefined') {
       super.setText(this.datapath.data + "'s information");
     }
   </method>
 </text>

This changes to:

 <text x="${Math.round((parent.width-this.width)/2)}" font="vera_super_bold" fgcolor="0x4d4d4d" datapath="@username" resize="true">
   <setter name="text">
     if (typeof(this.datapath.data) != 'undefined') {
       super.setAttribute('text', this.datapath.data + "'s information");
     }
   </setter>
 </text>


LFC setter methods like setWidth(), setHeight(), setBGColor() are now deprecated. They continue to work but if you use them, a warning message is displayed in the debugging console.

More Details about Attribute Setters

It used to be that if a user class wanted to override a setter for an LFC class, it had to know the name of the method that the LFC class had secretly installed as the setter. Yes, we tried to be regular about it and call the setter for `foo` `setFoo`, but there was nothing enforcing that. We have now deprecated _all_ those secret methods in the LFC, and we give you a deprecation warning if you call one, telling you to use `setAttribute('foo', ...` instead.

User classes have always been able to define their own setter methods by saying:

 <attribute name="foo" setter="..." />

where ... could be anything. Unfortunately, if you wanted to do a lot in a setter method, you usually ended up saying:

 <attribute name="foo" setter="setFoo(foo)" />
 <method name="setFoo" args="newFoo">
   ...
 </method>

which was inefficient, because your setter was actually having to call another method. The new way lets you say:

 <attribute name="foo" />
 <setter name="foo" args="newFoo">
   ...
 </setter>

This has two benefits: 1) it's efficient, there is only a single method, 2) it automatically overrides any inherited setter, without you having to know a magic name, because the name of the setter is _exactly_ the name of the attribute it is the setter for -- it's not a loosely-enforced convention that it is usually called 'set' + captialize(attribute-name).

Also, if you want to just wrap some of your own functionality around a setter, and still invoke the superclass's setter, you used to do it by calling the superclass method whose name you just "knew". No longer. Now you simply say:

 <setter name="foo" args="newFoo">
   ...
   super.setAttribute('foo', newFoo);
   ...
 </setter>

One more thing:

A probably little-known feature of writing your own setter is that you _have_ to send the event associated with the attribute yourself. The original designer of the language thought that it would be useful to expose this in custom setters, so you could decide when to send the event, etc. BUT, people often forget to do this. In a simple setter, where you might say:

 <attribute name="foo" setter="if ($debug) Debug.write('new foo:', foo); this.foo=foo" />

it's really easy to forget that you also need to say:

 onFoo.sendEvent(foo);

or any constraints that involve `foo` won't work.

[I'm wondering if we should amend the language so that in the simple case, where you write your setter in the <attribute> tag as a property, we should send the event for you.]

Attribute Setters for Component Developers

Some LFC components mimic text objects. For example, <edittext> is similar to <inputtext> but it does not extend a text object.

This is what the text attribute used to look like in edittext:

       <attribute name="text" type="text" setter="setText(text)"/>
       ...
       <method name="setText" args="t">
           this.text = t;
           if (this._initcomplete) {
               this.setValue(t, true);
               this.field.setAttribute('text', this.value);
               if (this['ontext']) this.ontext.sendEvent();
           } else {
               this._initialtext = t;
           }
       </method>

As you can see, this allows setting the text object via setAttribute('text',...) and setText(). To make this code run a little faster (by removing a call to setText from the setter), and follow how the LFC does it, this was rewritten to use the <setter> tag,

       <attribute name="text" type="text"/>
       ...
       <method name="setText" args="t">
           Debug.warn("edittext.setText is deprecated. Use setAttribute instead");
           this.setAttribute('text', t);
       </method>
       
       <setter name="text" args="t">
           this.text = t;
           if (this._initcomplete) {
               this.setValue(t, true);
               this.field.setAttribute('text', this.value);
               if (this['ontext']) this.ontext.sendEvent();
           } else {
               this._initialtext = t;
           }
       </setter>


Attribute Setter Migration Script

We have provided a simple perl conversion script (convert_setters.pl) to help eliminate the majority of these warnings. This requires Perl 5 or greater. You will find this version in the OpenLaszlo distribution at WEB-INF/lps/server/bin/convert_setters.pl. Unfortunately, Openlaszlo 4.2 didn't ship with a copy of this script - you can get it here: http://svn.openlaszlo.org/openlaszlo/branches/4.2/WEB-INF/lps/server/bin/convert_setters.pl

To run the script, type:

   perl /path_to_script/convert_setters.pl  where path_to_script is the path to your OpenLaszlo installation


Usage:

   perl convert_setters.pl [ options ] filename...

Options:

  -d debuglevel
          get debugging info for development
  -g graphical-difftool
          for each file changed, invoke the graphical difftool,
          and prompt the user to keep or not keep the changes
  -q
          Run in quiet mode. Output will be generated only for files that were changed, or must be manually inspected.
  -t
          create output for simple tests in /tmp/convtest
  -v
          show version number and exit

For each file, a backup file is made (filename.bak) and the file will be converted, with the result put into filename. The script will warn of changes it cannot make. For example, if the script sees a reserved method name that normally would be modified (ex: setBGColor()), all references to setBGColor() in the file will not be converted to setAttribute. For example, this code,

           <view id="testcolor" width="22" height="22"
               bgcolor="${setBGColor(canvas.defaultstyle, canvas.defaultstyle.basecolor)}" >
               <method name="setBGColor">
                    super.setBGColor(canvas.defaultstyle.basecolor);
               </method>
           </view>

will not be modified by convert_setters.pl, and any call to setBGColor() in the file will not be converted to setAttribute. The warning message displayed is,

 WARNING. Possible Conflict: The method 'setBGColor' in ./lz/most_styles.lzx will not be converted
 by this script because of a possible name collision. Calls to 'setBGColor' are normally converted
 to setAttribute by this script. Please check this file manually.


Examples:

 # Convert all the lzx files in the directory, doing all conversions.
 $ perl convert_setters.pl -q *.lzx
 # Convert all files from the currently directory and recurse into subdirectories
 $ find . -name '*.lzx' -exec /path_to_script/convert_setters.pl -q {} \;

Swf9 issues

This section lists issues encountered when updating 4.1.x-style LZX for swf9.

Argument signatures on overridden methods must match the superclass definition

When overriding a method on a superclass, swf9 requires the method signature (all arguments, type specifications and default values) to match.

Consider the following code:

 <canvas debug="true" height="400">
   <class name="aaa" extends="layout">
     <method name="update" args="ignore">
        Debug.write('here goes the method');
     </method>
   </class>
 </canvas>

Compiling for swf9 gives the compiler error:

 org.openlaszlo.sc.CompilerError: case.lzx: 8: Error: Incompatible override, in line: static var tagname = "aaa";static var attributes = new LzInheritedHash(LzLayout.attributes);override function update ($1_ignore) {

(Filed http://jira.openlaszlo.org/jira/browse/LPP-6950 to improve the error message)

In this case, the definition of the superclass requires the default argument to have a default value of null - from http://svn.openlaszlo.org/openlaszlo/trunk/WEB-INF/lps/lfc/controllers/LaszloLayout.lzs :

 function update(e=null) {
 }

The method override needs to be updated to match the superclass method's argument signature:

     <method name="update" args="ignore=null">
         Debug.write('here goes the method');
     </method>

Here's another example:

 <canvas debug="true" height="400">
   <class name="aaa" extends="view">
     <method name="updateWidth"
         Debug.write('here goes the method');
     </method>
     <method name="updateHeight">
         Debug.write('here goes the method');
     </method>
   </class>
 </canvas>

Compiling for swf9 gives the compiler error:

 org.openlaszlo.sc.CompilerError: case.lzx: 8: Error: Incompatible override, in line: static var tagname = "aaa";static var attributes = new LzInheritedHash(LzView.attributes);override function updateWidth () {

case.lzx: 15: Error: Incompatible override, in line: override function updateHeight () {

See http://svn.openlaszlo.org/openlaszlo/trunk/WEB-INF/lps/lfc/views/LaszloView.lzs :

 function updateWidth ( newsize ){
   ...

Updated to match the superclass method's argument signature:

     <method name="updateWidth" args="newsize">
         Debug.write('here goes the method');
     </method>
     <method name="updateHeight" args="newsize">
         Debug.write('here goes the method');
     </method>

Global variable declarations require the var keyword

Swf9 requires global variable declarations to use the var keyword. For example, the following code works with swf8 but not swf9:

 <canvas>
   <script>
     a = 20;
   </script>
 </canvas>

To fix this, add a var keyword at the beginning of the declaration:

 <canvas>
   <script>
     var a = 20;
   </script>
 </canvas>

Upgrading to OpenLaszlo 4.1 SWF/DHTML Release

User classes can no longer be defined in the global namespace

Anyplace your code says:

<class name="foo" .../>
new foo(...)

will have to be changed to:

new lz.foo(...)

Also, any references to "ConstructorMap" must be changed to "lz"

This is part of our campaign to reduce global namespace pollution so we interact better with other frameworks. It also prevents component names from conflicting with built-in browser objects, e.g. window.

Sebastian Wagner has posted an eclipse plugin to help with this issue - see http://code.google.com/p/laszlo4converter/

You can also use this perl script, if you prefer, to automatically update dynamic instantiations user of user classes.

Image:Convert instantiation.pl

Warnings may appear for deprecated language features

OpenLaszlo 4.1 warns you about deprecated syntax in use in your application. We have provided a simple perl conversion script (convert_laszlo.pl)to help eliminate the majority of these warnings. This requires Perl 5 or greater.

NOTE: use this in small increments and review the changes to avoid unanticipated side effects. We recommended using version that ships with your OpenLaszlo distribution if available - see WEB-INF/lps/server/bin/convert_laszlo.pl. You can view the perl script, even without an OpenLaszlo installation, here: http://svn.openlaszlo.org/openlaszlo/trunk/WEB-INF/lps/server/bin/convert_laszlo.pl

To run the script, type:

   perl /path_to_script/convert_laszlo.pl  where path_to_script is the path to your OpenLaszlo installation


Usage:

   perl convert_laszlo.pl [ options ] filename...

Options:

   -d debuglevel  get debugging info for development
   -t             create output for simple tests in /tmp/convtest
   -x exceptlist  exceptlist is a comma separated list of transforms
                  to NOT apply.  These are chosen from:
               method        - <method ...> transforms
               setattribute  - setVisible -> setAttribute('visible', ...) etc.
               widthheight   - getWidth(),getHeight() to width,height
               tagname       - constructor.classname to constructor.tagname
               states        - apply=" -> applied=", state.apply()/remove() -> setAttribute('applied', true|false)

  -v              show version number and exit

For each file, a backup file is made (filename.bak) and the file will be converted, with the result put into filename.

Examples:

 # Convert all the lzx files in the directory, doing all conversions.
 perl convert_laszlo.pl *.lzx

 # Convert just myfile.lzx, do not apply two of the conversions.
 perl convert_laszlo.pl -x setattribute,tagname  myfile.lzx

HTML embedding APIs changed

Lz.swfEmbed is now lz.swf.embed(), Lz.dhtmlEmbed() is now lz.dhtml.embed(), and Lz.dhtmlEmbedLFC() is now lz.embed.lfc(). For the most up-to-date information on embedding, click the 'Deploy: [Server]' button on the developer's console for any application, e.g. http://labs.openlaszlo.org/trunk-nightly/my-apps/copy-of-hello.lzx?lzr=swf8&lzt=deployment

WEB-INF/web.xml has changed

A number of changes were made to the default WEB-INF/web.xml in LPS 4.1. If you have a custom web.xml for your application, you may need to merge it with the version web.xml for LPS 4.1 - see http://svn.openlaszlo.org/openlaszlo/trunk/WEB-INF/web.xml for a current version.

Names, IDs and method arguments must use valid JS2 names

You may receive compiler errors if you use reserved words such as "private" "public" or "is". JS2 names can contain letters, numbers and underscores but must nut begin with a number.

Methods called by delegates/events must have a single argument

Where a delegate calls a method, you will see warnings if the method had no arguments. Adding an argument to these methods e.g. <method args="ignore"> will silence the warnings and get your code ready for the upcoming Flash 9 release.

<method event="eventname"> is deprecated

The syntax <method event="eventname"> is now deprecated and will trigger a compiler warning. You should update your code to use <handler name="eventname">. In the case where the method is named (<method event="eventname" name="methodname">) you will have to split the declaration into a handler (<handler name="eventname" method="methodname" />) and a method (<method name="methodname">).

This syntax allows subclasses to override the method that will be handling the event. See the documentation (http://www.openlaszlo.org/documentation) of handler for further details and examples.

Duplicate attributes now cause compiler warnings

In previous versions of LZX, you could potentially create a duplicate attribute with no warning from the compiler. For example:

   <class name="zot">
   <attribute name="name" value="${'bar'}" />
   </class>

In the above example, the attribute named `name` is defined both in the open tag of the class and as an attribute. This is illegal and could lead to ambiguous or unpredictable results. The compiler will now warn that you have a duplicated attribute. You will have to rename one of the duplicate cases to ensure that your code works as expected.

Other API changes

LzDataNode.stringToLzData() has been moved to to LzDataElement.stringToLzData()

<datasource> is no longer supported in 4.1

<script/> includes

<script/> includes may need the when="immediate" attribute added to ensure they are compiled early enough to be ready to use in the application. This generally only applies to classes.

States no longer support super() calls in methods

The workaround is to move the super() call to a method that's can be called from the state

Swf resources compiled for earlier versions of Flash don't support playback control in Flash 9

In Flash 9, properties and methods are not accessible in swf files compiled for previous versions of the player. This is a restriction in Flash 9 - see http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000011.html for more details.

DHTML limitations

Rotation

Rotation is currently only supported in recent builds of Safari.

Stretching nested subviews

Stretching only works for views that don't have subviews, or nested children.

<font/> includes

DHTML does not support font inclusion. If <font> tags are used, the compiler will give warnings for DHTML. Note that it is possible to specify a list of font names which will be used in the order available. This allows font includes to work in supported runtimes such as Flash, and fall back to a suitable system font in DHTML.

Persistent Connections

Persistent connections are not supported in DHTML and are deprecated in Flash.

Keyboard events

In DHTML, control, shift and alt are treated as 'modifier' keys. As a result, they are only sent when another key is pressed or a mouse event occurs.

Creating Dates

You can no longer use new Date(millis) but must instead use var d = new Date(); d.setTime(millis).

<splash/> tags

It's difficult to get meaningful load progress information in DHTML, so this feature was deprecated to provide a more consistent experience for developers and users. LPS 4.1 has a new mechanism - essentially, an event is now sent when the app finishes loading, and arbitrary javascript can execute. By default, the HTML for DHTML applications contains a div with a progress animation that is hidden when the application finishes loading. Run see any app with lzr=dhtml&lzt=html for an example. The <splash/> tag will continue to work in Flash as-is. The Reference Manual documentation for the <splash> tag has been updated with this information. Also see http://www.openlaszlo.org/jira/browse/LPP-5280 for more details.

However, all versions of Flash support a browser Javascript onloadstatus event which can be used to update the appearance of the surrounding page as it loads, e.g.

                <script type="text/javascript">
                  lz.embed.swf({url: 'copy-of-hello.lzx?lzt=swf&lzr=swf10', allowfullscreen: 'false', bgcolor: '#ffffff', width: '100%', height: '100%', id: 'lzapp', accessible: 'false'});

                  lz.embed.lzapp.onloadstatus = function loadstatus(p) {
                    // called with a percentage (0-100) indicating load progress
                  }

                  lz.embed.lzapp.onload = function loaded() {
                    // called when this application is done loading
                  }
                </script>

XML data in SOLO apps

The Flash player is generally more lenient than browser JavaScript parsers.

For DHTML apps running in SOLO mode, the web browser's XML parser is very picky about the data source. The server delivering the data must mark the HTTP content type header as text/xml and it doesn't hurt to have an <?xml ... ?> declaration either, and no white space between the start of the file, the <?xml...?> declaration, and the start of the data.

Safari 2 and popup blockers

In Safari 2.0.4 DHTML, the popup blocker will prevent windows from opening if not called directly from an onclick event. The workaround is to change the LZX source so the window is opened directly from the onclick event handler - see http://www.openlaszlo.org/jira/browse/LPP-3333?page=all.

Internet Explorer and opacity

Internet Explorer 6 and 7 have a number of limitations with the way they handle opacity. We've worked hard to work around these limitations where possible. Unfortunately, some limitations require minor changes to the structure of your LZX to work properly in IE:

Javascript substr method behaves differently

In firefox the substr method always returns an empty string for lengths of 0 or less. In flash it appears that negative lengths work. It is recommended to convert all substr calls into an equivalent substring call.