Support for property getter / setter functions in IE

132 views
Skip to first unread message

Frank

unread,
Aug 12, 2010, 3:12:53 PM8/12/10
to Jangaroo Users
Let's continue the getter / setter discussion here!

Status of the discussion:

In ActionScript, getters and setters are normal functions, however,
they are called by property notation. For example, the expression o.x
results in a function call, if o is of Type T and T defines a getter
function for x. If the same expression occurs on the left hand side of
an assignment and T defines a setter function for x, this setter is
called with the right hand side of the assignment as the parameter.

Unlike all other modern browsers, Internet Explorer does not yet
support JavaScript getters and setters. (IE9 supports them, but is not
yet released). Thus, if we want Jangaroo to support this ActionScript
language feature, we have to simulate getters and setters (at least)
for IE.

The complicated part about simulating getters and setters is
determining when to use function calls, and when to use ordinary
property access. Syntactically, there is no difference. And
considering runtime performance, we do not want to generate JavaScript
function calls from each and every ActionScript property access. You
can only tell whether a property access is in fact a function call by
looking at the type of the expression before the dot. Since the
Jangaroo compiler did not really care about types before version 0.6,
we postponed the feature. But now, we are in a much better situation
to deduce expression type and determine whether a getter or setter has
to be simulated. So this part is quite straight-forward now.

However, ActionScript is a quite dynamic language. There are untyped
expressions (the "any"-type "*") and dynamic classes, which means that
objects can have any property, and untyped access to properties may
also result in calling getter functions. To cover such cases, we
sometimes need to decide at runtime whether there is a getter/setter
to be called.

Solution Outline
============

Our current approach is to define getter and setter functions using a
naming scheme like the following. Consider a typical property being
defined in AS3 like so:

private var _x:int;

public function get x():int {
return _x;
}

public function set x(newX:int):void {
_x=newX;
}

These function cannot simply be named "x", since a) both would have
the same name, and b) it would not be possible to tell that they are a
getter / setter functions at runtime. Thus, the Jangaroo Runtime
should create functions with special names. Since Jangaroo reserves
the dollar sign ("$") as an identifier prefix for internal usage,
anyway, we propose to use $$get_x and $$set_x (single $ prefix is used
for names of private identifiers). For brevity, we could also use $$gx
and $$sx, but this looks rather unreadable. In case of dynamic
property access, the compiler has to generate code to check whether a
getter or setter (depending on the kind of property access) exists,
and if so, call that function, else, execute the standard property
access:

$$get = function(o, propertyName) {
return '$$get_'+propertyName in o ? o['$$get_'+propertyName]() :
o[propertyName];
};
$$set = function(o,propertyName, val) {
return '$$set_'+propertyName in o ? o['$$set_'+propertyName](val) :
(o[propertyName]=val);
};

In all browsers / JavaScript environments supporting getters and
setters directly, these helper functions would still be needed (so we
don't have to generate browser-dependent code, although of course we
could do so), but their implementation would be trivial (simply always
execute the property access).

Since in ActionScript (and in JavaScript), assignments evaluate to
their right hand side, but setter functions do not return any value
(void), the last thing missing is the compiler "cheating" a return
statement into the generated setter function code:

"public function set x", function $$set_x(newX/*:int*/)/*:void*/ {
this._x=newX; return newX;
},

Or we might even exploit the most common case of a single assignment
to generate even more concise code:

“public function set x”, function $$set_x(newX/*:int*/)/*:void*/ {
return this._x=newX;
},

If m1 and m2 are setters and m3 is a getter, the result of compiling
the statement

o1.m1 = o2.m2 = o3.m3 + o3[f(x)];

would then be

o1.$$set_m1(o2.$$set_m2(o3.$$get_m3() + $$get(o3, f(x))))

If o1 / o2 / o3 are untyped (*) or of a "dynamic" type and m1, m2 and
m3 are "expando properties", the result would look like so:

$$set(o1,'m1', $$set(o2,'m2', $$get(o3,'m3') + $$get(o3,f(x))));

In any case, there should be a compiler switch that tells Jangaroo
whether you want to have IE-compatible getter/setter code or not,
since if you don't, you surely don't want the runtime performance
penalty that comes with the additional function call.

James Ward

unread,
Aug 16, 2010, 10:14:33 AM8/16/10
to Jangaroo Users
Thanks Frank for the detailed explanation of that. I think the solution
you outline is good. The one area that would be good to explore further
is the compiler flag. It would be cool to be able to specify some
minimum level browser requirement. If the lowest level is specified (IE
6) then code could be generated that would work everywhere (possibly
with browser detection to send optimized versions). If the highest
level is specified then the compiler would just create the most
optimized versions for the most modern browsers. For instance I'm
targeting modern mobile devices and don't want to incur a performance
hit to support IE.

Thanks again.

-James

Reply all
Reply to author
Forward
0 new messages