Bug 6041 - Support property getters and setters
Summary: Support property getters and setters
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: 420+
Hardware: Mac OS X 10.4
: P2 Normal
Assignee: Anders Carlsson
URL:
Keywords:
Depends on:
Blocks: 6519
  Show dependency treegraph
 
Reported: 2005-12-11 03:23 PST by Anders Carlsson
Modified: 2006-01-12 20:35 PST (History)
0 users

See Also:


Attachments
Implement getters and setters (35.08 KB, patch)
2005-12-11 04:17 PST, Anders Carlsson
andersca: review-
Details | Formatted Diff | Diff
Make params an optional, last argument (1021 bytes, text/plain)
2005-12-11 08:43 PST, Geoffrey Garen
no flags Details
Address comments (99.42 KB, patch)
2005-12-12 15:08 PST, Anders Carlsson
darin: review-
Details | Formatted Diff | Diff
Address more comments (102.96 KB, patch)
2005-12-13 12:29 PST, Anders Carlsson
darin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Anders Carlsson 2005-12-11 03:23:13 PST
Property getters and setters is a Firefox extension. It's described at http://developer.mozilla.org/en/docs/
Core_JavaScript_1.5_Guide:Working_with_Objects#Defining_Getters_and_Setters
Comment 1 Anders Carlsson 2005-12-11 04:17:54 PST
Created attachment 5027 [details]
Implement getters and setters

Note that this does not implement the old deprecated way of defining getters
and setters (which unfortunately is used in the jsc test suite)
Comment 2 Anders Carlsson 2005-12-11 04:22:27 PST
Comment on attachment 5027 [details]
Implement getters and setters

Ah, some tests actually use __defineGetter__ and __defineSetter__ but still
fail, I'll investigate why
Comment 3 Geoffrey Garen 2005-12-11 08:42:37 PST
+    if (params)
+        func = new FuncExprNode(Identifier::null(), params, body);
+    else
+        func = new FuncExprNode(Identifier::null(), body);

This code seemed a little bizarre to me at first read. Since params is an optional argument, why isn't it 
the last argument?

I've attached a manual patch to show you what I mean. (CVS is down for me right now.) It has the added 
advantage of collapsing the above lines to one:

     func = new FuncExprNode(Identifier::null(), body, params);
Comment 4 Geoffrey Garen 2005-12-11 08:43:48 PST
Created attachment 5034 [details]
Make params an optional, last argument
Comment 5 Geoffrey Garen 2005-12-11 08:53:10 PST
+JSValue *GetterSetterImp::toPrimitive(ExecState *, Type) const
+{
+    assert(false);
+    return 0;
+}

+JSObject *GetterSetterImp::toObject(ExecState *exec) const
+{
+    assert(false);
+    return 0;
+}

JavaScriptCore is not tolerant of null pointers, so these return values for deployment builds will almost 
certainly cause a crash if they're ever hit.

I would suggest
     return jsNull().toPrimitive(exec);
and
     return jsNull().toObject(exec);
Comment 6 Geoffrey Garen 2005-12-11 08:55:54 PST
Same comment here:
+JSValue *PropertyNode::evaluate(ExecState *exec)
+{
+  assert(false);
+  return 0;
+}
Comment 7 Anders Carlsson 2005-12-12 15:08:22 PST
Created attachment 5055 [details]
Address comments

Here's a new patch that addresses the comments made, and also passes
getset-00[456].js in the mozilla test suite.

I had to do some changes to PropertySlot which makes the patch big, but Maciej
thought it was the right approach (and so do I)
Comment 8 Darin Adler 2005-12-13 08:20:39 PST
Comment on attachment 5055 [details]
Address comments

In PropertyListNode::evaluate, defineGetter and defineSetter are called on the
value from the assign node without checking that it's a JSObject. That's
dangerous and could crash if the thing is not an object. The code needs a check
if it's an object somewhere rather than just calling JSObject member functions
on a JSValue.

I notice this line in the parser is no longer lined up with the code above it:

+  | '{' PropertyList '}'    { $$ = new ObjectLiteralNode($2); }

I know that Geoff suggested returning jsNull()->toPrimitive(exec, type), but
that's exactly the same as jsNull(), so there's no reason to include the extra
function call. I also think that the logical equivalent of assert(false) is to
call throwError so we get a JavaScript exception in those cases. But since
these values should never get out of properties into expressions, there's very
little reason to worry about exactly what code is there after the assertion,
never to be executed.

Is PropertyNode::streamTo really all that hard to write for getter and setter?

I like to see member functions that are virtual re-declared as virtual, so I'd
like to see that in GetterSetterImp's declaration.

The PropertyListNode::evaluate seems to be a serious one, so marking review-,
otherwise I'd say review+.
Comment 9 Anders Carlsson 2005-12-13 12:29:50 PST
Created attachment 5066 [details]
Address more comments

(In reply to comment #8)
> (From update of attachment 5055 [details] [edit])
> In PropertyListNode::evaluate, defineGetter and defineSetter are called on
the
> value from the assign node without checking that it's a JSObject. That's
> dangerous and could crash if the thing is not an object. The code needs a
check
> if it's an object somewhere rather than just calling JSObject member
functions
> on a JSValue.
> 
The reason I skipped this check is that we know that the node to be evaluated
always is a FuncExprNode which will always be evaluated to a JSObject. Anyway,
I've added an isObject check for both the getter and setter.

> I notice this line in the parser is no longer lined up with the code above
it:
> 
> +  | '{' PropertyList '}'    { $$ = new ObjectLiteralNode($2); }
> 
> I know that Geoff suggested returning jsNull()->toPrimitive(exec, type), but
> that's exactly the same as jsNull(), so there's no reason to include the
extra
> function call. I also think that the logical equivalent of assert(false) is
to
> call throwError so we get a JavaScript exception in those cases. But since
> these values should never get out of properties into expressions, there's
very
> little reason to worry about exactly what code is there after the assertion,
> never to be executed.
> 
Both of these have been fixed.

> Is PropertyNode::streamTo really all that hard to write for getter and
setter?

It's not hard to write, but the end result will look ugly because there will be
newlines everywhere. I added an implementation for this that will generate
ugly, yet syntactically correct, text.
> 
> I like to see member functions that are virtual re-declared as virtual, so
I'd
> like to see that in GetterSetterImp's declaration.
> 
Fixed.

> The PropertyListNode::evaluate seems to be a serious one, so marking review-,

> otherwise I'd say review+. 
>
Comment 10 Anders Carlsson 2005-12-13 12:32:16 PST
Comment on attachment 5066 [details]
Address more comments

I noticed that the JSC ChangeLog is messed up; I've fixed that in my local
copy.
Comment 11 Darin Adler 2005-12-13 13:18:47 PST
Comment on attachment 5066 [details]
Address more comments

As far as PropertyListNode::evaluate is concerned -- if we really do know the
value is an object, then it can be an assert rather than an if.

r=me