Skip to content

Commit 6e773cb

Browse files
author
Bradley Meck
committed
foreach callback and little more on the readme
1 parent bfd2d23 commit 6e773cb

File tree

2 files changed

+153
-52
lines changed

2 files changed

+153
-52
lines changed

README.TXT

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
#node-watchable
22

33
##exports
4-
* Watchable(onGet,onSet)
4+
* Watchable(onGet,onSet,onForeach)
5+
6+
Supplies getter and setter callbacks across all the properties along with a for(x in y) callback that returns the list
7+
Callback's can use the _this_ object in order to act normally without reinvoking themselves.
8+
9+
** Value onGet(String propertyName, Value value, hadAlready)
10+
11+
Returns the value at a specific index
12+
** Value onSet(String propertyName, Value oldValue, Value value, hadAlready)
13+
14+
Returns the value to save at a specific index
15+
** Array onForeach()
16+
17+
Returns an array containing all the index keys for this object
18+
519

6-
Supplies getter and setter callbacks across all the properties
7-
Currently both callbacks are required
820

921
##example
1022
Code
@@ -32,4 +44,6 @@ Output
3244

3345
##uses
3446
1. Debugging - Show what is being accessed / set
35-
2. False natives - refuse to allow properties to be set / got beyond a specified few
47+
2. False natives - refuse to allow properties to be set / got beyond a specified few
48+
3. Dynamic programming - Fib[3] could compute Fib[1] and Fib[2]
49+
4. Index based getters / setters - Fib[0] cannot have a getter set normally because it is a number not string based index (all non-number non-undefined values become string based).

overload.cc

Lines changed: 135 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,15 @@ Handle<Value> WatchableNamedPropertyGetter(
2020
) {
2121
HandleScope scope;
2222
//Grab the value of the property
23-
Handle<Object> holder=info.Holder();
23+
Handle<Object> holder = info.Holder();
24+
Handle<Object> map = Handle<Object>::Cast(
25+
holder->GetInternalField(0)
26+
);
27+
//Default
28+
Handle<Value> data = holder->GetInternalField(1);
29+
if(data->IsNull()) {
30+
return scope.Close(map->Get(property));
31+
}
2432
Handle<Value> value;
2533
Handle<Value> had_value;
2634

@@ -37,7 +45,6 @@ Handle<Value> WatchableNamedPropertyGetter(
3745
Handle<Value> values[3] = {property,value,had_value};
3846

3947
//Grab function and call (property,value)
40-
Handle<Value> data = holder->GetInternalField(1);
4148
Handle<Function> callback = Handle<Function>::Cast(data);
4249
Handle<Value> new_value = callback->Call(info.Holder(),3,values);
4350

@@ -52,7 +59,8 @@ Handle<Value> WatchableNamedPropertySetter(
5259
) {
5360
HandleScope scope;
5461
//Grab the value of the property
55-
Handle<Object> holder = Handle<Object>::Cast(
62+
Handle<Object> holder = info.Holder();
63+
Handle<Object> map = Handle<Object>::Cast(
5664
holder->GetInternalField(0)
5765
);
5866
Handle<Value> old_value;
@@ -66,14 +74,21 @@ Handle<Value> WatchableNamedPropertySetter(
6674
old_value = Undefined();
6775
had_value = False();
6876
}
77+
//Default
78+
Handle<Value> data = holder->GetInternalField(2);
79+
if(data->IsNull()) {
80+
return scope.Close(map->Set(property,value)
81+
?value
82+
:old_value
83+
);
84+
}
6985

7086
//Set up arguments
7187
Handle<Value> values[4] = {property,old_value,value,had_value};
7288

7389
//Grab function and call (property,value)
74-
Handle<Value> data = holder->GetInternalField(2);
7590
Handle<Function> callback = Handle<Function>::Cast(data);
76-
Handle<Value> new_value = callback->Call(Holder,4,values);
91+
Handle<Value> new_value = callback->Call(holder,4,values);
7792

7893
holder->ForceSet(property,new_value);
7994

@@ -86,26 +101,32 @@ Handle<Array> WatchableNamedPropertyEnumerator(
86101
) {
87102
HandleScope scope;
88103
//Grab the value of the property
89-
Handle<Object> holder = Handle<Object>::Cast(
104+
Handle<Object> holder = info.Holder();
105+
Handle<Object> map = Handle<Object>::Cast(
90106
holder->GetInternalField(0)
91107
);
108+
//Default
109+
Handle<Value> data = holder->GetInternalField(4);
110+
if(data->IsNull()) {
111+
return scope.Close(map->GetPropertyNames());
112+
}
92113
Handle<Value> old_value;
93114
Handle<Value> had_value;
94115

95-
Handle<Array> names = holder->GetPropertyNames();
96-
97116
//Set up arguments
98-
Handle<Value> values[4] = {property,old_value,value,had_value};
117+
Handle<Value> values[0] = {};
99118

100119
//Grab function and call (property,value)
101-
Handle<Value> data = holder->GetInternalField(2);
102120
Handle<Function> callback = Handle<Function>::Cast(data);
103-
Handle<Value> new_value = callback->Call(holder,4,values);
104-
105-
holder->ForceSet(property,new_value);
121+
Handle<Value> new_value = callback->Call(holder,0,values);
106122

107-
//Return value is the return of the function call
108-
return scope.Close(new_value);
123+
if(new_value->IsArray()) {
124+
return scope.Close(Handle<Array>::Cast(new_value));
125+
}
126+
else {
127+
ThrowException(String::New("Callback must return an Array."));
128+
return scope.Close(Array::New());
129+
}
109130
}
110131

111132
Handle<Value> WatchableIndexedPropertyGetter(
@@ -115,15 +136,21 @@ Handle<Value> WatchableIndexedPropertyGetter(
115136
HandleScope scope;
116137

117138
//Grab the value
118-
Handle<Object> holder = Handle<Object>::Cast(
139+
Handle<Object> holder = info.Holder();
140+
Handle<Object> map = Handle<Object>::Cast(
119141
holder->GetInternalField(0)
120142
);
143+
//Default
144+
Handle<Value> data = holder->GetInternalField(1);
145+
if(data->IsNull()) {
146+
return scope.Close(map->Get(index));
147+
}
121148
Handle<Number> property = Number::New(index);
122149
Handle<Value> value;
123150
Handle<Value> had_value;
124151

125152
if( holder->Has(index) ) {
126-
value = holder->Get(index);
153+
value = map->Get(index);
127154
had_value = True();
128155
}
129156
else {
@@ -134,7 +161,6 @@ Handle<Value> WatchableIndexedPropertyGetter(
134161
Handle<Value> values[3] = {property,value,had_value};
135162

136163
//Grab function and call (property,value)
137-
Handle<Value> data = holder->GetInternalField(1);
138164
Handle<Function> callback = Handle<Function>::Cast(data);
139165
Handle<Value> new_value = callback->Call(holder,3,values);
140166

@@ -148,82 +174,143 @@ Handle<Value> WatchableIndexedPropertySetter(
148174
, const AccessorInfo& info
149175
) {
150176
HandleScope scope;
151-
152177
//Grab the value
153-
Handle<Object> holder = Handle<Object>::Cast(
178+
Handle<Object> holder = info.Holder();
179+
Handle<Object> map = Handle<Object>::Cast(
154180
holder->GetInternalField(0)
155181
);
156182
Handle<Number> property = Number::New(index);
157183
Handle<Value> had_value;
158184

159185
Handle<Value> old_value;
160186
if( holder->Has(index) ) {
161-
old_value = holder->Get(index);
187+
old_value = map->Get(index);
162188
had_value = True();
163189
}
164190
else {
165191
old_value = Undefined();
166192
had_value = False();
167193
}
168-
194+
//Default
195+
Handle<Value> data = holder->GetInternalField(2);
196+
if(data->IsNull()) {
197+
return scope.Close(map->Set(index,value)
198+
?value
199+
:old_value
200+
);
201+
}
169202
//Set up arguments
170203
Handle<Value> values[4] = {property,old_value,value,had_value};
171204

172205
//Grab function and call (property,value)
173-
Handle<Value> data = holder->GetInternalField(2);
174206
Handle<Function> callback = Handle<Function>::Cast(data);
175207
Handle<Value> new_value = callback->Call(holder,4,values);
176208

177-
holder->Set(index,new_value);
209+
map->Set(index,new_value);
178210

179211
//Return value is the return of the function call
180212
return scope.Close(new_value);
181213
}
214+
Handle<Array> WatchableIndexedPropertyEnumerator(
215+
const AccessorInfo& info
216+
) {
217+
HandleScope scope;
218+
//Grab the value
219+
Handle<Object> holder = info.Holder();
220+
Handle<Object> map = Handle<Object>::Cast(
221+
holder->GetInternalField(0)
222+
);
223+
//Default
224+
Handle<Value> data = holder->GetInternalField(2);
225+
if(data->IsNull()) {
226+
return scope.Close(map->GetPropertyNames());
227+
}
228+
//Set up arguments
229+
Handle<Value> values[0];
230+
231+
//Grab function and call (property,value)
232+
Handle<Function> callback = Handle<Function>::Cast(data);
233+
Handle<Value> new_value = callback->Call(holder,0,values);
234+
235+
if(new_value->IsArray()) {
236+
return scope.Close(Handle<Array>::Cast(new_value));
237+
}
238+
else {
239+
ThrowException(String::New("Callback must return an Array."));
240+
return scope.Close(Array::New());
241+
}
242+
}
243+
182244

183-
Local<ObjectTemplate> object_template = ObjectTemplate::New();
184245
Handle<Value> Watchable(const Arguments& args) {
185246
HandleScope scope;
186-
Handle<Value> getter = args[0];
187247
//Check our arguments!
188-
if(getter.IsEmpty() || getter->IsFunction()) {}
248+
Handle<Value> getter = args[0];
249+
if(getter->IsFunction()) {
250+
//Do nothing
251+
}
252+
else if(getter->IsNull() || getter->IsUndefined()) {
253+
getter = Null();
254+
}
189255
else {
190256
return ThrowException(String::New("Getter callback must be a function"));
191257
}
192258
Handle<Value> setter = args[1];
193-
if(setter.IsEmpty() || setter->IsFunction()) {}
259+
if(setter->IsFunction()) {
260+
//Do nothing
261+
}
262+
else if(setter->IsNull() || setter->IsUndefined()) {
263+
setter = Null();
264+
}
194265
else {
195266
return ThrowException(String::New("Getter callback must be a function"));
196267
}
197-
Handle<Object> watchable = object_template->NewInstance();
198-
watchable->SetInternalField(0,Object::New());
199-
watchable->SetInternalField(1,getter);
200-
watchable->SetInternalField(2,setter);
201-
return scope.Close(watchable);
202-
}
203-
204-
extern "C" void init (Handle<Object> target)
205-
{
206-
HandleScope scope;
207-
//Every one with a different callback needs a different template
208-
//0 - Holder object - aka the real one
209-
//1 - Getter
210-
//2 - Setter
211-
//3 - Query
212-
//4 - Deleter
213-
//5 - Enumerator
214-
object_template->SetInternalFieldCount(5);
268+
Handle<Value> enumerator = args[2];
269+
if(enumerator->IsFunction()) {
270+
//Do nothing
271+
}
272+
else if(enumerator->IsNull() || enumerator->IsUndefined()) {
273+
enumerator = Null();
274+
}
275+
else {
276+
return ThrowException(String::New("Getter callback must be a function"));
277+
}
278+
Local<ObjectTemplate> object_template = ObjectTemplate::New();
215279
object_template->SetNamedPropertyHandler(
216280
WatchableNamedPropertyGetter
217-
,WatchableNamedPropertySetter
281+
,WatchableNamedPropertySetter,0,0
218282
// ,WatchableNamedPropertyQuery
219283
// ,WatchableNamedPropertyDeleter
220284
,WatchableNamedPropertyEnumerator
221285
);
222286
object_template->SetIndexedPropertyHandler(
223287
WatchableIndexedPropertyGetter
224288
,WatchableIndexedPropertySetter
225-
,0,0,0
289+
,0,0
290+
//Is this ever used?
291+
//,WatchableIndexedPropertyEnumerator
226292
);
293+
//Every one with a different callback needs a different template
294+
//0 - Holder object - aka the real one
295+
//1 - Getter
296+
//2 - Setter
297+
//3 - Query
298+
//4 - Deleter
299+
//5 - Enumerator
300+
object_template->SetInternalFieldCount(5);
301+
Handle<Object> watchable = object_template->NewInstance();
302+
watchable->SetInternalField(0,Object::New());
303+
watchable->SetInternalField(1,getter);
304+
watchable->SetInternalField(2,setter);
305+
watchable->SetInternalField(4,enumerator);
306+
//printf("watchable created\n");
307+
return scope.Close(watchable);
308+
}
309+
310+
extern "C" void init (Handle<Object> target)
311+
{
312+
HandleScope scope;
313+
//printf("init\n");
227314
Local<FunctionTemplate> watchable_template = FunctionTemplate::New(Watchable);
228315
Local<Function> watchable = watchable_template->GetFunction();
229316
//Export

0 commit comments

Comments
 (0)