taskease.js - Tasks: task #13054, Pre-ES5 method patching

 
 

You are not allowed to post comments on this tracker with your current authentication level.

task #13054: Pre-ES5 method patching

Submitter:  Mike Gerwitz <mikegerwitz>
Submitted:  Wed 22 Jan 2014 06:06:56 AM UTC
   
 
Should Start On:  Wed 22 Jan 2014 05:00:00 AM UTC Should be Finished on:  Sat 01 Mar 2014 05:00:00 AM UTC
Category:  Core Priority:  5 - Normal
Item Group:  Development Status:  Cancelled
Privacy:  Public Assigned to:  mikegerwitz
Percent Complete:  0% Open/Closed:  Open
Planned Release:  None
Keywords:  patching, fallback, pre-es5, traits, constants, private members

Wed 20 Jul 2016 04:53:29 PM UTC, comment #3: 

Will not do.

ES3 is largely no longer in use.  While easejs will continue to support it, this type of development will not occur.

Mike Gerwitz <mikegerwitz>
Group administrator
Thu 23 Jan 2014 05:02:18 AM UTC, comment #2: 
[Additional Information]

See recent comments in #12102; while this feature is desirable, it should not be immediately necessary for a fairly complete trait implementation.

Mike Gerwitz <mikegerwitz>
Group administrator
Wed 22 Jan 2014 06:15:42 PM UTC, comment #1: 
[Additional Information]

To perform patching with any reasonable level of confidence, a basic lexer is needed to generate, at least partially, an AST/CST from the function body. I stress basic because this lexer will be used, at least for the time being, only in pre-ES5 environments, which will also happen to be the slowest (older) environments.

  • All private members must be accessed using `this'.
  • However, `this' can (and is quite often) assigned to other variables; we must track those assignments reliably.
    • Further, we must track assignments of specific private members to variables.
  • We must recognize when we enter the scope of another function in which `this' is bound differently. We must also recognize when `this' is passed as the context to that function (via `call' or `apply').
  • We must recognize both dot and array syntax.
    • We must recognize when a variable using the private member name is used with array syntax on any variable containing `this', or `this' itself.
    • We will not parse array-syntax accesses that are generated at runtime that could possibly result in private member access; that is not worth the time when pre-ES5 is increasingly less common; developers will be made aware of the restriction. Perhaps we will provide a warning when this situation is encountered.
  • We must not alter non-private references.
  • We must not alter strings that look like private member references.


It is clear from the above that we are interested in only a very small subset of the AST---indeed, we're interested only in the names of the private members that are actually causing conflicts, so if none of those private member names are even seen in a function body via any of the above methods, then nothing needs to be done. Despite this, however, there are still some challenges.

The other consideration, once this concept is applied to traits, is that we do not know at the time the trait is defined whether there will be a private member conflict. To make matters worse, we cannot perform the patching after a trait has been defined, because it may have already been used and there may be references to the old (unpatched) name. Introducing the overhead of patching all private member references upon trait definition is not acceptable; it may therefore be necessary to, upon introduction of a conflict on mixin, clone the trait and use the cloned object (but ease.js would consider them to be one and the same for purposes of public-facing APIs).

But all of this work could end up being useful outside of pre-ES5 environments. Indeed, this throws a wrench in the idea of forced feature degredation for production, because it might introduce more overhead than desired. We could, however, use this method to introduce a simple compiler that could prepare ease.js classes for production; it could be added to the pipeline before minification.

It is unlikely that I will use an existing JS AST library, beacuse I need only a very small subset of features and the additional features those libraries provide would have negative effects on both performance and the size of ease.js.

Mike Gerwitz <mikegerwitz>
Group administrator
Wed 22 Jan 2014 06:06:56 AM UTC, original submission:  

Up until this point, I had avoided the concept of patching methods at runtime (that is, new Function( func.toString().replace( ... ) )) because of issues it may introduce with, mainly, debugging. I'm not concerned with performance, as the patched function would remain in memory and would not need to be touched again.

However, this would be a very useful feature to have for the private member implementation (and possibly constants). The issue and current implementation for each of these are discussed in the manual:

  - http://www.gnu.org/software/easejs/manual/Pre_002dES5-Fallback.html
  - http://www.gnu.org/software/easejs/manual/Static-Implementation.html

My focus at the moment is the private member fallback, as this is a much greater issue with traits---they each need their own private scope and, since a number of traits can be mixed into a single class, there is a much greater chance for conflict then subtyping. Further, subtypes can be designed with knowledge of their supertype private members so that they can avoid conflicts; trait developers cannot possibly take into account issues with traits that they may be mixed in with.

Importantly, as mentioned in the first link above, note that we currently throw an error for such conflicts---this means that we are detecting it. This detection is only to avoid inconcistencies in pre-ES5 environments; it is not a problem when proxying is available. As such, right off the bat, patching is not even needed for newer environments. Further, we know that patching is only needed when we encounter this error. In that case, rather than erroring out, we can do this:

  - Rename the private member that is causing the conflict
  - Patch all methods in the definition object that reference that private member so that they now reference the new name
  - Update the definition object, replacing the functions in memory

This does cause debugging issues, but the solution to that problem is simple---debug in an up-to-date browser/environment.

This will help to prevent ease.js from being bogged down by pre-ES5 environments, which are being slowly phased out, and allow it to think ahead toward more powerful features and a more enjoyable development experience. And it will save my ass with traits.

(This can also help eliminate the terrible this.__self.$('CONSTANT') syntax by patching pre-ES5 environments to use that, allowing developers to simply write this.CONSTANT. Indeed, I rarely use constants because they are so verbose and, quite frankly, embarassing.)

Mike Gerwitz <mikegerwitz>
Group administrator

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by mikegerwitz (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

     

    Follow 8 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2016-07-20 mikegerwitz StatusNone Cancelled
    2014-01-23 mikegerwitz Priority7 - High 5 - Normal
        StatusIn Progress None
        Planned Release0.2.0 None
    2014-01-22 mikegerwitz DependenciesRemoved dependency from task #12102 -
    2014-01-22 mikegerwitz Dependencies- task #12102 is dependent
    2014-01-22 mikegerwitz StatusNone In Progress
        Planned ReleaseNone 0.2.0

    Back to the top

    Powered by Savane 3.13-4448.
    Corresponding source code