Print this page
XXX review feedback from keith
XXX rework to avoid changing api
XXX well, it works now...
Split |
Close |
Expand all |
Collapse all |
--- old/./v8plus_objectwrap.cc
+++ new/./v8plus_objectwrap.cc
1 1 /*
2 2 * Copyright (c) 2012 Joyent, Inc. All rights reserved.
3 3 */
4 4
5 5 #include <sys/types.h>
6 6 #include <string.h>
7 7 #include <new>
8 8 #include <unordered_map>
9 9 #include <stdlib.h>
10 10 #include <node.h>
11 11 #include "v8plus_impl.h"
12 12 #include "v8plus_glue.h"
13 13
14 14 #define METHOD_NAME_FMT "__v8plus_%s_%s"
15 15
16 16 v8::Persistent<v8::Function> v8plus::ObjectWrap::_constructor;
17 17 v8plus_method_descr_t *v8plus::ObjectWrap::_mtbl;
18 18 v8plus_static_descr_t *v8plus::ObjectWrap::_stbl;
19 19 std::unordered_map<void *, v8plus::ObjectWrap *> v8plus::ObjectWrap::_objhash;
20 20
21 21 static char *
22 22 function_name(const char *lambda)
23 23 {
24 24 char *fn;
25 25 size_t len;
26 26
27 27 len = snprintf(NULL, 0, METHOD_NAME_FMT,
28 28 v8plus_js_class_name, lambda);
29 29 if ((fn = (char *)malloc(len + 1)) == NULL)
30 30 v8plus_panic("out of memory for function name for %s", lambda);
31 31
32 32 (void) snprintf(fn, len + 1, METHOD_NAME_FMT,
33 33 v8plus_js_class_name, lambda);
34 34
35 35 return (fn);
36 36 }
37 37
38 38 void
39 39 v8plus::ObjectWrap::init(v8::Handle<v8::Object> target)
40 40 {
41 41 uint_t i;
42 42
43 43 if (v8plus_static_method_count > 0) {
44 44 const v8plus_static_descr_t *sdp;
45 45
46 46 _stbl = new (std::nothrow)
47 47 v8plus_static_descr_t[v8plus_static_method_count];
48 48 if (_stbl == NULL)
49 49 v8plus_panic("out of memory for static method table");
50 50
51 51 for (i = 0; i < v8plus_static_method_count; i++) {
52 52 v8::Local<v8::FunctionTemplate> fth =
53 53 v8::FunctionTemplate::New(_static_entry);
54 54 v8::Local<v8::Function> fh = fth->GetFunction();
55 55 sdp = &v8plus_static_methods[i];
56 56
57 57 _stbl[i].sd_name = function_name(sdp->sd_name);
58 58 _stbl[i].sd_c_func = sdp->sd_c_func;
59 59
60 60 fh->SetName(v8::String::New(_stbl[i].sd_name));
61 61
62 62 target->Set(v8::String::NewSymbol(sdp->sd_name), fh);
63 63 }
64 64 }
65 65
66 66
67 67 if (v8plus_method_count > 0) {
68 68 v8::Local<v8::FunctionTemplate> tpl =
69 69 v8::FunctionTemplate::New(_new);
70 70 const v8plus_method_descr_t *mdp;
71 71
72 72 _mtbl = new (std::nothrow)
73 73 v8plus_method_descr_t[v8plus_method_count];
74 74 if (_mtbl == NULL)
75 75 v8plus_panic("out of memory for method table");
76 76
77 77 tpl->SetClassName(v8::String::NewSymbol(v8plus_js_class_name));
78 78 tpl->InstanceTemplate()->SetInternalFieldCount(
79 79 v8plus_method_count);
80 80
81 81 for (i = 0; i < v8plus_method_count; i++) {
82 82 v8::Local<v8::FunctionTemplate> fth =
83 83 v8::FunctionTemplate::New(_entry);
84 84 v8::Local<v8::Function> fh = fth->GetFunction();
85 85 mdp = &v8plus_methods[i];
86 86
87 87 _mtbl[i].md_name = function_name(mdp->md_name);
88 88 _mtbl[i].md_c_func = mdp->md_c_func;
89 89
90 90 fh->SetName(v8::String::New(_mtbl[i].md_name));
91 91
92 92 tpl->PrototypeTemplate()->Set(
↓ open down ↓ |
92 lines elided |
↑ open up ↑ |
93 93 v8::String::NewSymbol(mdp->md_name), fh);
94 94 }
95 95
96 96 _constructor =
97 97 v8::Persistent<v8::Function>::New(tpl->GetFunction());
98 98
99 99 target->Set(v8::String::NewSymbol(v8plus_js_factory_name),
100 100 v8::FunctionTemplate::New(
101 101 v8plus::ObjectWrap::cons)->GetFunction());
102 102 }
103 +
104 + v8plus_crossthread_init();
103 105 }
104 106
105 107 v8::Handle<v8::Value>
106 108 v8plus::ObjectWrap::_new(const v8::Arguments &args)
107 109 {
108 110 v8::HandleScope scope;
109 111 v8plus::ObjectWrap *op = new v8plus::ObjectWrap();
110 112 nvlist_t *c_excp;
111 113 nvlist_t *c_args;
112 114
113 115 if ((c_args = v8plus::v8_Arguments_to_nvlist(args)) == NULL)
114 116 return (V8PLUS_THROW_DEFAULT());
115 117
116 118 c_excp = v8plus_ctor(c_args, &op->_c_impl);
117 119 nvlist_free(c_args);
118 120 if (op->_c_impl == NULL) {
119 121 if (c_excp == NULL) {
120 122 return (V8PLUS_THROW_DEFAULT());
121 123 } else {
122 124 return (V8PLUS_THROW_DECORATED(c_excp));
123 125 }
124 126 }
125 127
126 128 _objhash.insert(std::make_pair(op->_c_impl, op));
127 129 op->Wrap(args.This());
128 130
129 131 return (args.This());
130 132 }
131 133
132 134 v8plus::ObjectWrap::~ObjectWrap()
133 135 {
134 136 v8plus_dtor(_c_impl);
135 137 (void) _objhash.erase(_c_impl);
136 138 }
137 139
138 140 v8::Handle<v8::Value>
139 141 v8plus::ObjectWrap::cons(const v8::Arguments &args)
140 142 {
141 143 v8::HandleScope scope;
142 144 const unsigned argc = 1;
143 145 v8::Handle<v8::Value> argv[argc] = { args[0] };
144 146 v8::Local<v8::Object> instance = _constructor->NewInstance(argc, argv);
145 147
146 148 return (scope.Close(instance));
147 149 }
148 150
149 151 v8plus::ObjectWrap *
150 152 v8plus::ObjectWrap::objlookup(const void *cop)
151 153 {
152 154 std::unordered_map<void *, v8plus::ObjectWrap *>::iterator it;
153 155
154 156 if ((it = _objhash.find(const_cast<void *>(cop))) == _objhash.end())
155 157 v8plus_panic("unable to find C++ wrapper for %p\n", cop);
156 158
157 159 return (it->second);
158 160 }
159 161
160 162 /*
161 163 * This is the entry point for all methods. We will start by demultiplexing
162 164 * out the C method from the function name by which we were called. There is
163 165 * probably some mechanism by which overly clever JavaScript code could make
164 166 * this not match the actual name; this will kill your Node process, so don't
165 167 * get cute.
166 168 */
167 169 v8::Handle<v8::Value>
168 170 v8plus::ObjectWrap::_entry(const v8::Arguments &args)
169 171 {
170 172 v8::HandleScope scope;
171 173 v8plus::ObjectWrap *op =
172 174 node::ObjectWrap::Unwrap<v8plus::ObjectWrap>(args.This());
173 175 nvlist_t *c_args;
174 176 nvlist_t *c_out;
175 177 nvlist_t *excp;
176 178 nvpair_t *rpp;
177 179 v8::Local<v8::String> self = args.Callee()->GetName()->ToString();
178 180 v8::String::Utf8Value selfsv(self);
179 181 const char *fn = *selfsv;
180 182 const v8plus_method_descr_t *mdp;
181 183 v8plus_c_method_f c_method = NULL;
182 184 uint_t i;
183 185
184 186 for (i = 0; i < v8plus_method_count; i++) {
185 187 mdp = &_mtbl[i];
186 188 if (strcmp(mdp->md_name, fn) == 0) {
187 189 c_method = mdp->md_c_func;
188 190 break;
189 191 }
190 192 }
191 193
192 194 if (c_method == NULL)
193 195 v8plus_panic("impossible method name %s\n", fn);
194 196
195 197 if ((c_args = v8plus::v8_Arguments_to_nvlist(args)) == NULL)
196 198 return (V8PLUS_THROW_DEFAULT());
197 199
198 200 c_out = c_method(op->_c_impl, c_args);
199 201 nvlist_free(c_args);
200 202
201 203 if (c_out == NULL) {
202 204 if (_v8plus_errno == V8PLUSERR_NOERROR)
203 205 return (scope.Close(v8::Undefined()));
204 206 else
205 207 return (V8PLUS_THROW_DEFAULT());
206 208 } else {
207 209 if (nvlist_lookup_nvlist(c_out, "err", &excp) == 0) {
208 210 v8::Handle<v8::Value> x = V8PLUS_THROW_DECORATED(excp);
209 211 nvlist_free(c_out);
210 212 return (x);
211 213 } else if (nvlist_lookup_nvpair(c_out, "res", &rpp) == 0) {
212 214 v8::Handle<v8::Value> r =
213 215 v8plus::nvpair_to_v8_Value(rpp);
214 216 nvlist_free(c_out);
215 217 return (scope.Close(r));
216 218 } else {
217 219 v8plus_panic("bad encoded object in return");
218 220 }
219 221 }
220 222
221 223 /*NOTREACHED*/
222 224 return (v8::Undefined());
223 225 }
224 226
225 227 v8::Handle<v8::Value>
226 228 v8plus::ObjectWrap::_static_entry(const v8::Arguments &args)
227 229 {
228 230 v8::HandleScope scope;
229 231 nvlist_t *c_args;
230 232 nvlist_t *c_out;
231 233 nvlist_t *excp;
232 234 nvpair_t *rpp;
233 235 v8::Local<v8::String> self = args.Callee()->GetName()->ToString();
234 236 v8::String::Utf8Value selfsv(self);
235 237 const char *fn = *selfsv;
236 238 const v8plus_static_descr_t *sdp;
237 239 v8plus_c_static_f c_static = NULL;
238 240 uint_t i;
239 241
240 242 for (i = 0; i < v8plus_static_method_count; i++) {
241 243 sdp = &_stbl[i];
242 244 if (strcmp(sdp->sd_name, fn) == 0) {
243 245 c_static = sdp->sd_c_func;
244 246 break;
245 247 }
246 248 }
247 249
248 250 if (c_static == NULL)
249 251 v8plus_panic("impossible static method name %s\n", fn);
250 252
251 253 if ((c_args = v8plus::v8_Arguments_to_nvlist(args)) == NULL)
252 254 return (V8PLUS_THROW_DEFAULT());
253 255
254 256 c_out = c_static(c_args);
255 257 nvlist_free(c_args);
256 258
257 259 if (c_out == NULL) {
258 260 if (_v8plus_errno == V8PLUSERR_NOERROR)
259 261 return (scope.Close(v8::Undefined()));
260 262 else
261 263 return (V8PLUS_THROW_DEFAULT());
262 264 } else {
263 265 if (nvlist_lookup_nvlist(c_out, "err", &excp) == 0) {
264 266 v8::Handle<v8::Value> x = V8PLUS_THROW_DECORATED(excp);
265 267 nvlist_free(c_out);
266 268 return (x);
267 269 } else if (nvlist_lookup_nvpair(c_out, "res", &rpp) == 0) {
268 270 v8::Handle<v8::Value> r =
269 271 v8plus::nvpair_to_v8_Value(rpp);
270 272 nvlist_free(c_out);
271 273 return (scope.Close(r));
272 274 } else {
273 275 v8plus_panic("bad encoded object in return");
274 276 }
275 277 }
276 278
277 279 /*NOTREACHED*/
278 280 return (v8::Undefined());
279 281 }
280 282
281 283 v8::Handle<v8::Value>
282 284 v8plus::ObjectWrap::call(const char *name,
283 285 int argc, v8::Handle<v8::Value> argv[])
284 286 {
285 287 v8::Handle<v8::Value> v = v8::Undefined();
286 288 v8::Local<v8::Value> f = handle_->Get(v8::String::NewSymbol(name));
287 289
288 290 /*
289 291 * XXX - we'd like to throw here, but for some reason our TryCatch
290 292 * block doesn't seem to handle the exception.
291 293 */
292 294 if (!f->IsFunction())
293 295 return (v8::Undefined());
294 296
295 297 #ifdef NODE_MAKECALLBACK_RETURN
296 298 v =
297 299 #endif
298 300 node::MakeCallback(handle_, name, argc, argv);
299 301
300 302 return (v);
301 303 }
302 304
303 305 void
304 306 v8plus::ObjectWrap::public_Ref(void)
305 307 {
306 308 this->Ref();
307 309 }
308 310
309 311 void
310 312 v8plus::ObjectWrap::public_Unref(void)
311 313 {
312 314 this->Unref();
313 315 }
314 316
315 317 extern "C" void
316 318 init(v8::Handle<v8::Object> target)
317 319 {
318 320 v8plus::ObjectWrap::init(target);
319 321 }
↓ open down ↓ |
207 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX