Return-Path: X-Original-To: apmail-incubator-flex-dev-archive@minotaur.apache.org Delivered-To: apmail-incubator-flex-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 49BE4DB54 for ; Thu, 20 Dec 2012 17:30:36 +0000 (UTC) Received: (qmail 64199 invoked by uid 500); 20 Dec 2012 17:30:35 -0000 Delivered-To: apmail-incubator-flex-dev-archive@incubator.apache.org Received: (qmail 64177 invoked by uid 500); 20 Dec 2012 17:30:35 -0000 Mailing-List: contact flex-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: flex-dev@incubator.apache.org Delivered-To: mailing list flex-dev@incubator.apache.org Received: (qmail 64169 invoked by uid 99); 20 Dec 2012 17:30:35 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 20 Dec 2012 17:30:35 +0000 X-ASF-Spam-Status: No, hits=2.2 required=5.0 tests=HTML_MESSAGE,RCVD_IN_DNSWL_LOW,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [209.85.216.54] (HELO mail-qa0-f54.google.com) (209.85.216.54) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 20 Dec 2012 17:30:29 +0000 Received: by mail-qa0-f54.google.com with SMTP id j15so2736597qaq.6 for ; Thu, 20 Dec 2012 09:30:08 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type :x-gm-message-state; bh=44d1vXrL1TvLoh4KXbLPXX6UDA6tqTBJancwiYV2uRY=; b=lChaNUqrHrZHe8GA6oZR0sgMd/5eR6LKGVvju0yQQsBFumemARmrtwLj650GY9Jy3N ++EO4mEZTxmWeG1n+xDWFQAzEhOUpCY9/BrfCovnN1iWY5xwEJimCapf/ZKDd2hiQ11g fF9nswEE4qklE+CYGWaN24wwnoRmICADJSsl7oZViz1HHtiBzWmMQ27UHjWcohrni27i Qn1PwTvOqDnYlnb4N0wNU8ZYRHAv2R5hoNwpGG8K6jy2ay/tS2B5mSGq6qKIqmgd8OFs TvIZqgzKR7BPQ2h/ATdZp72KVOwIRB/Xdxg+CA/FcndTQZfC1KJRByz80ph4qTEg1qNe XCrA== MIME-Version: 1.0 Received: by 10.49.132.199 with SMTP id ow7mr5825699qeb.56.1356024607938; Thu, 20 Dec 2012 09:30:07 -0800 (PST) Received: by 10.49.2.131 with HTTP; Thu, 20 Dec 2012 09:30:07 -0800 (PST) Date: Thu, 20 Dec 2012 18:30:07 +0100 Message-ID: Subject: [FalconJx] New JavaScript runtime format prototype From: Frank Wienberg To: flex-dev@incubator.apache.org Content-Type: multipart/alternative; boundary=047d7bf164ae1017b504d14c1520 X-Gm-Message-State: ALoCoQlv01fiDPwCRWYXbNn1K5nmTeNsY43ZSYOAtW9EN7AU51aixFOm8lLQK1VFYfjnFV9mFu0H X-Virus-Checked: Checked by ClamAV on apache.org --047d7bf164ae1017b504d14c1520 Content-Type: text/plain; charset=ISO-8859-1 Hi folks, as mentioned in another thread, I have been working on a new JavaScript "runtime", which is what I call the way the generated JavaScript code looks and works like. While this thread's title has [FalconJx] in it, there is no reason the proposal could not be used for FalconJS, too, but I understood that for now, using Google Closure is a given. I had the following design goals: - Support ActionScript 3's "differentiator" features: private members, interfaces + is/as, lazy class initialization, method binding, getter/setter functions - work in IE < 9 (except for getter/setter functions) - Produce debuggable JavaScript code that can also be optimized for deployment. The debuggable code should be very similar to the original ActionScript source code for every line containing executable code - Dependency management: load/bundle only the needed classes. Every compilation unit to debug should load as a separate request - Minimal to no runtime overhead, even in debug mode - Support trace() I took the following design decisions: - For private members, a mix of JavaScript lexical scope and field renaming like in Jangaroo is used - To implement an efficient "is" operator, all interfaces a class implements are determined once for the class. I use a prototype chain to inherit the interfaces implemented by the super class - Lazy class initialization uses a very efficient technique refined by Olaf Kummer: Wherever a constructor or non-private static member is called, the "self-destructing" class initialization function is checked for existence and, if still existing, called ("guarded" call) - Method binding is again borrowed from the Jangaroo Runtime: the bound function is "cached" at the object under a different but unique name so that it keeps its identity. This is important e.g. to be able to remove event listeners - Getter/setter functions map to Object.defineProperty("...", { get: ..., set: ...}), thus no support in IE < 9 - To make everything else work in IE < 9, I use polyfills for ECMAScript 5 Object, Array and Function API - For keeping generated code in separate JS files, expressing dependencies between these files, loading them separately at runtime and linking them statically into a single JavaScript file, I chose to use Asynchronous Module Definitions (AMD) and RequireJS (version 2.1.2) as the concrete implementation of AMD. AMD is preferred over CommonJS because it better fits web applications, as e.g. argued here: http://blog.millermedeiros.com/amd-is-better-for-the-web-than-commonjs-modules/To link and optimize the application, RequireJS provides an optimizer tool simply called "r.js". - To conditionally load polyfills (for IE < 9), I use the "shim" RequireJS plugin - To achieve minimal runtime overhead, I only use helper functions to define the class structure once (defineClass and defineInterface). As soon as the complete application structure is set up, all code executed is inlined - Since all modern browsers seem to support a "console" object with a "log" method, trace() is simply implemented to check for the existence of console.log() by trial-and-error (try... catch). It then String-converts and concatenates all its arguments like its ActionScript sibling *About the Example* To specify how I think FalconJx-generated JavaScript output should look like, I created an ActionScript example, consisting of two classes and three interfaces. Every language feature supported by the new runtime format gives an appearance in the code (well, I didn't add a private static method, because it works like a private method, only simpler). The whole thing is a public GitHub project at https://github.com/fwienber/as-js-runtime-prototype. To download all files in one go as a zip or tar.gz, please use the tag page: https://github.com/fwienber/as-js-runtime-prototype/tags. A live demo is available on the corresponding GitHub pages at http://fwienber.github.com/as-js-runtime-prototype/index.html >From there, you can reach all ActionScript example sources and the proposed JavaScript equivalent (so far, hand-coded :-)). To see the example in action, use the three bottom links which start the same application in three flavors: - debug: Each JS file corresponding to an AS class or interface and the main bootstrap file is loaded with a single request. This gives you a nice 1:1 mapping of source to output in the JavaScript debugger. Additionally, there are some "infrastructure" files: require.js itself, the RequireJS plugin "shim" (shim.js, shims.js), my AS3 runtime helpers defineClass.js and defineInterface.js, and a couple of built-in AS3 functions (bind, as, is, trace). If loading in IE < 9, the shim plugin loads several ES5 polyfills. - linked: The whole application is merged into one JS file using the RequireJS optimizer "r.js" without optimizations. Thus you only have two requests: require.js and hello-worls-all.js are loaded. In IE < 9, the polyfills are still loaded one-by-one (I didn't bother to optimize this case, but of course, it can be done). - minified: Same as "linked", only that require.js and hellow-world-all.js are minified by Uglify2. This can easily be achieved using "r.js" with the parameter optimize=uglify2. For the demo, I redirected trace() from the JavaScript console (backed-up in trace-console.js) to the DOM, so that you can see the log messages directly. Just look into the code and observe how it works in Firebug or any other JavaScript debugger of your choice, and let me know if anything is unclear, missing or if you need more reasoning for the design decisions taken. I know there are still several issues to be fleshed out (e.g. interaction with "native" JavaScript or package-scope variables, just to name two), but I think the current state is a solid core of how a modern, efficient, self-contained, extensive and still concise JavaScript runtime format for Apache Flex could look like. Please tell me what you think! Have fun, -Frank- --047d7bf164ae1017b504d14c1520--