getter / setters

# Irakli Gozalishvili (15 years ago)

Sorry if my question is stupid or does not really belongs here. I will be thankful to get some clarification on es specs since I just discovered that my interpretation of how getter / setters are supposed to behave appears to be different from the behavior in observed in modern browsers.

var foo = Object.create({}, { bar: { get: function() { return this._foo; }, set: function(value) { return this._foo = 'Hello ' + value; } } });

var bar = foo.bar = 'setter'; if (foo.bar !== bar) throw new Error('Unexpected');

The code will throw an error cause bar will be 'setter' while foo.bar will be 'Hello setter'. I was expecting that `bar' would've get value returned by a setter (or at least getter of foo). And this is not the case nor with FF nor with Safari implementations. Behavior is the same if getters and setters are used instead. Is it expected behavior ? If answer is yes, is there any point of returning anything from setter ?

I am also afraid that this might break some of the frameworks in rare cases like in this example above. (a = b = c is commonly used syntax)

Thanks a lot!

Irakli Gozalishvili Web: www.jeditoolkit.com Phone: +31 614 205275 Address: Taksteeg 3 - 4, 1012PB Amsterdam, Netherlands

# Oliver Hunt (15 years ago)

On May 20, 2010, at 11:37 AM, Irakli Gozalishvili wrote:

Hi,

Sorry if my question is stupid or does not really belongs here. I will be thankful to get some clarification on es specs since I just discovered that my interpretation of how getter / setters are supposed to behave appears to be different from the behavior in observed in modern browsers.

var foo = Object.create({}, { bar: { get: function() { return this._foo; }, set: function(value) { return this._foo = 'Hello ' + value; } } });

var bar = foo.bar = 'setter'; if (foo.bar !== bar) throw new Error('Unexpected');

The code will throw an error cause bar will be 'setter' while foo.bar will be 'Hello setter'. I was expecting that `bar' would've get value returned by a setter (or at least getter of foo). And this is not the case nor with FF nor with Safari implementations. Behavior is the same if getters and setters are used instead. Is it expected behavior ? If answer is yes, is there any point of returning anything from setter ?

There is no point in returning anything from a setter.

This is due to the semantics of the assignment operator, not setters -- the result value of an assignment is the righthand side of the expression.

eg. for any expression <some lvalue> = someObject.property = <expr>

the behaviour is equivalent to

temp = <expr>

someObject.property = temp <some lvalue> = temp

(ignoring the need to resolve the destinations in the correct order)

I am also afraid that this might break some of the frameworks in rare cases like in this example above. (a = b = c is commonly used syntax)

This has always been the behaviour of assignment.

# Mike Samuel (15 years ago)

The relevant portion seems to be

11.13.1 Simple Assignment ( = ) The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:

  1. Let lref be the result of evaluating LeftHandSideExpression.
  2. Let rref be the result of evaluating AssignmentExpression.
  3. Let rval be GetValue(rref).
  4. Throw a SyntaxError exception if the following conditions are all true:  Type(lref) is Reference is true  IsStrictReference(lref) is true  Type(GetBase(lref)) is Enviroment Record  GetReferencedName(lref) is "eval"
  5. Call PutValue(lref, rval).
  6. Return rval.

which returns rval. The value returned by the setter is not used, and looking at step 7 of 8.12.5 no value is returned even if step 5 finds that a setter is defined.

So for a non host object o, o.x = o.x - 1 should yield a number regardless of the details of any setter for x on o, assuming o is not frozen and said setter returns normally.

2010/5/20 Irakli Gozalishvili <rfobic at gmail.com>:

# Brendan Eich (15 years ago)

On May 20, 2010, at 11:37 AM, Irakli Gozalishvili wrote:

Hi,

Sorry if my question is stupid or does not really belongs here. I
will be thankful to get some clarification on es specs since I just
discovered that my interpretation of how getter / setters are
supposed to behave appears to be different from the behavior in
observed in modern browsers.

var foo = Object.create({}, { bar: { get: function() { return this._foo; }, set: function(value) { return this._foo = 'Hello ' + value; } } });

var bar = foo.bar = 'setter'; if (foo.bar !== bar) throw new Error('Unexpected');

SpiderMonkey used to do what you want, since the dawn of time (1995,
the first JS runtime, "Mocha"). The result of evaluating an assignment
expression was the return value of the setter, not the result of
evaluating the right-hand-side expression. We changed to track
ECMA-262 (IIRC Acid3 actually tested this and dinged us).

The code will throw an error cause bar will be 'setter' while
foo.bar will be 'Hello setter'. I was expecting that `bar' would've
get value returned by a setter (or at least getter of foo). And this
is not the case nor with FF nor with Safari implementations.
Behavior is the same if getters and setters are used instead.

I'm not sure what you mean -- do you mean Firefox and Safari ignore
the setter's return value? That's what my testing with Firefox 3.6.x
and Safari 4 show, on this HTML source:

<script>

var foo = { get bar() { return this._foo; }, set bar(value) { return this._foo = 'Hello ' + value; } };

var bar = foo.bar = 'setter'; alert('bar ' + bar + ', foo.bar ' + foo.bar); </script>

Is it expected behavior ? If answer is yes, is there any point of
returning anything from setter ?

No point now.

I am also afraid that this might break some of the frameworks in
rare cases like in this example above. (a = b = c is commonly used
syntax)

No browser does what we used to do, so any framework counting on
setters filtering

# Oliver Hunt (15 years ago)

So for a non host object o, o.x = o.x - 1 should yield a number regardless of the details of any setter for x on o, assuming o is not frozen and said setter returns normally.

The assignment operator is defined in the language fairly clearly in a way that means that the behaviour is unaffected by the type of object being assigned to -- eg. being a host object or not is (mercifully) not relevant :D

# Brendan Eich (15 years ago)

On May 20, 2010, at 11:47 AM, Brendan Eich wrote:

I am also afraid that this might break some of the frameworks in
rare cases like in this example above. (a = b = c is commonly used
syntax)

No browser does what we used to do, so any framework counting on
setters filtering_______________________________________________ es-discuss mailing list es-discuss at mozilla.org, mail.mozilla.org/listinfo/es-discuss

Whoops, a select-cut accident -- I meant to say that any framework
counting on SpiderMonkey's old behavior, which you seem to want (where
the setter return value is the result of the assignment expression) is
broken on all uprev browsers these days. Even before we fixed
SpiderMonkey, all get/set-supporting browsers but Firefox and other
Mozilla-based browsers would have worked per-spec and such a framework
would have been broken on them.

# Mike Samuel (15 years ago)

2010/5/20 Oliver Hunt <oliver at apple.com>:

So for a non host object o,  o.x = o.x - 1 should yield a number regardless of the details of any setter for x on o, assuming o is not frozen and said setter returns normally.

The assignment operator is defined in the language fairly clearly in a way that means that the behaviour is unaffected by the type of object being assigned to -- eg. being a host object or not is (mercifully) not relevant :D

Quite right. Sorry for being confusing. I ran into a corner case for IE6 and IE7 where postfix ++ does not always yield a number, e.g. when applied to some host objects. The comment at line 80 of code.google.com/p/google-caja/source/browse/trunk/tests/com/google/caja/browser-expectations.html is my best recollection.

# Irakli Gozalishvili (15 years ago)

Thanks to everyone for a good explanation, as I was assuming my expectations were wrong, guess partially, because of the SpiderMonkey's behavior in past (Thanks Brendan for clearing this up, I was pretty sure that was the behavior in xulrunner, apparently it's in past now :).

-- Irakli Gozalishvili Web: www.jeditoolkit.com Phone: +31 614 205275 Address: Taksteeg 3 - 4, 1012PB Amsterdam, Netherlands