Skip to content
This repository has been archived by the owner on Jan 14, 2021. It is now read-only.

__{define,lookup}{Get,Set}ter__ don't work as they do in impls #18

Closed
gsnedders opened this issue Feb 19, 2014 · 4 comments
Closed

__{define,lookup}{Get,Set}ter__ don't work as they do in impls #18

gsnedders opened this issue Feb 19, 2014 · 4 comments

Comments

@gsnedders
Copy link

Consider the following:

var x = {};
Object.defineProperty(x, "foo", {get: function(){return 1}});
print(x.__lookupGetter__("foo"));

Per the current spec, this should print undefined. Per every implementation, this should print the get property of the foo property descriptor on x (i.e., the function).

As far as I can tell, __lookupGetter__ (with __lookupSetter__ being a very slight variation on this with .get replaced by .set) should be:

Object.prototype.__lookupGetter__ = function(propertyName) {
  var obj = this;
  do {
    var desc = Object.getOwnPropertyDescriptor(obj, propertyName);
    if (desc !== undefined)
      return desc.get;
  } while((obj = Object.getPrototypeOf(obj)) !== null);
}

…where all the built-ins have their initial values (i.e., Object.prototype, Object.getOwnPropertyDescriptor, Object.getPrototypeOf, and undefined).

Now, to look at the define variants:

Set the internal [[Enumerable]] property of obj’s prop property to true.

What if obj doesn't have a prop property? In a case like var x = {}; x.__defineGetter__("foo", function(){return 1}); there is no foo property on x, as where would it come from?

Whenever a property with the name of prop is accessed on the obj object, call function with the this binding set to obj, and return the result.

What does this even mean? What should the following do:

var x = {};
x.__defineGetter__("foo", function(){return 1});
print(Object.getOwnPropertyDescriptor("foo"));
print(Object.getOwnPropertyDescriptor("foo").get);

Is this accessing the property? What on earth should the object that Object.getOwnPropertyDescriptor look like? You've not created a property descriptor for foo, you've just magically defined its behaviour!

As far as I can tell, the actual behaviour is the following (again, assuming all built-ins have their initial value, and the setter variant just being the set property and not the get property):

Object.prototype.__defineGetter__ = function(propertyName, func) {
  if (typeof func !== "function")
    throw TypeError("not a function");
  Object.defineProperty(this, propertyName, {get: func, enumerable: true});
}

As it is now, it is pretty much totally undefined how these functions relate to the ES object model (just some handwaving about "whenever a property with name of prop is accessed on the obj object").

@gsnedders
Copy link
Author

(i.e., these operations should be defined in terms of [[Get]] and [[Put]], not black-box magic)

@anba
Copy link

anba commented Feb 21, 2014

Which alternative do you prefer? 😄

@anba
Copy link

anba commented Feb 22, 2014

Adding @bterlson, because he volunteered to write an initial spec draft for ES7.

@gsnedders
Copy link
Author

Nice fix. :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

2 participants