widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / jscript / object.c
blob1e94f1634464af6969f139ce17fba1e454a10ba4
1 /*
2 * Copyright 2008 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <assert.h>
21 #include "jscript.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
27 static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
28 jsval_t *r)
30 jsdisp_t *jsdisp;
31 const WCHAR *str;
33 /* Keep in sync with jsclass_t enum */
34 static const WCHAR *names[] = {
35 NULL,
36 L"[object Array]",
37 L"[object Boolean]",
38 L"[object Date]",
39 L"[object Object]",
40 L"[object Error]",
41 L"[object Function]",
42 NULL,
43 L"[object Math]",
44 L"[object Number]",
45 L"[object Object]",
46 L"[object RegExp]",
47 L"[object String]",
48 L"[object Object]",
49 L"[object Object]",
50 L"[object Object]"
53 TRACE("\n");
55 jsdisp = get_jsdisp(jsthis);
56 if(!jsdisp) {
57 str = L"[object Object]";
58 }else if(names[jsdisp->builtin_info->class]) {
59 str = names[jsdisp->builtin_info->class];
60 }else {
61 assert(jsdisp->builtin_info->class != JSCLASS_NONE);
62 FIXME("jsdisp->builtin_info->class = %d\n", jsdisp->builtin_info->class);
63 return E_FAIL;
66 if(r) {
67 jsstr_t *ret;
68 ret = jsstr_alloc(str);
69 if(!ret)
70 return E_OUTOFMEMORY;
71 *r = jsval_string(ret);
74 return S_OK;
77 static HRESULT Object_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
78 jsval_t *r)
80 TRACE("\n");
82 if(!is_jsdisp(jsthis)) {
83 FIXME("Host object this\n");
84 return E_FAIL;
87 return jsdisp_call_name(jsthis->u.jsdisp, L"toString", DISPATCH_METHOD, 0, NULL, r);
90 static HRESULT Object_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
91 jsval_t *r)
93 TRACE("\n");
95 if(r) {
96 IDispatch_AddRef(jsthis->u.disp);
97 *r = jsval_disp(jsthis->u.disp);
99 return S_OK;
102 static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
103 jsval_t *r)
105 jsstr_t *name;
106 DISPID id;
107 BSTR bstr;
108 HRESULT hres;
110 TRACE("\n");
112 if(!argc) {
113 if(r)
114 *r = jsval_bool(FALSE);
115 return S_OK;
118 hres = to_string(ctx, argv[0], &name);
119 if(FAILED(hres))
120 return hres;
122 if(is_jsdisp(jsthis)) {
123 property_desc_t prop_desc;
124 const WCHAR *name_str;
126 name_str = jsstr_flatten(name);
127 if(!name_str) {
128 jsstr_release(name);
129 return E_OUTOFMEMORY;
132 hres = jsdisp_get_own_property(jsthis->u.jsdisp, name_str, TRUE, &prop_desc);
133 jsstr_release(name);
134 if(FAILED(hres) && hres != DISP_E_UNKNOWNNAME)
135 return hres;
137 if(r) *r = jsval_bool(hres == S_OK);
138 return S_OK;
142 bstr = SysAllocStringLen(NULL, jsstr_length(name));
143 if(bstr)
144 jsstr_flush(name, bstr);
145 jsstr_release(name);
146 if(!bstr)
147 return E_OUTOFMEMORY;
149 if(is_dispex(jsthis))
150 hres = IDispatchEx_GetDispID(jsthis->u.dispex, bstr, make_grfdex(ctx, fdexNameCaseSensitive), &id);
151 else
152 hres = IDispatch_GetIDsOfNames(jsthis->u.disp, &IID_NULL, &bstr, 1, ctx->lcid, &id);
154 SysFreeString(bstr);
155 if(r)
156 *r = jsval_bool(SUCCEEDED(hres));
157 return S_OK;
160 static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
161 jsval_t *r)
163 property_desc_t prop_desc;
164 const WCHAR *name;
165 jsstr_t *name_str;
166 HRESULT hres;
168 TRACE("\n");
170 if(argc != 1) {
171 FIXME("argc %d not supported\n", argc);
172 return E_NOTIMPL;
175 if(!is_jsdisp(jsthis)) {
176 FIXME("Host object this\n");
177 return E_FAIL;
180 hres = to_flat_string(ctx, argv[0], &name_str, &name);
181 if(FAILED(hres))
182 return hres;
184 hres = jsdisp_get_own_property(jsthis->u.jsdisp, name, TRUE, &prop_desc);
185 jsstr_release(name_str);
186 if(FAILED(hres) && hres != DISP_E_UNKNOWNNAME)
187 return hres;
189 if(r)
190 *r = jsval_bool(hres == S_OK && (prop_desc.flags & PROPF_ENUMERABLE) != 0);
191 return S_OK;
194 static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
195 jsval_t *r)
197 FIXME("\n");
198 return E_NOTIMPL;
201 static HRESULT Object_get_value(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
203 jsstr_t *ret;
205 TRACE("\n");
207 ret = jsstr_alloc(L"[object Object]");
208 if(!ret)
209 return E_OUTOFMEMORY;
211 *r = jsval_string(ret);
212 return S_OK;
215 static void Object_destructor(jsdisp_t *dispex)
217 heap_free(dispex);
220 static const builtin_prop_t Object_props[] = {
221 {L"hasOwnProperty", Object_hasOwnProperty, PROPF_METHOD|1},
222 {L"isPrototypeOf", Object_isPrototypeOf, PROPF_METHOD|1},
223 {L"propertyIsEnumerable", Object_propertyIsEnumerable, PROPF_METHOD|1},
224 {L"toLocaleString", Object_toLocaleString, PROPF_METHOD},
225 {L"toString", Object_toString, PROPF_METHOD},
226 {L"valueOf", Object_valueOf, PROPF_METHOD}
229 static const builtin_info_t Object_info = {
230 JSCLASS_OBJECT,
231 {NULL, NULL,0, Object_get_value},
232 ARRAY_SIZE(Object_props),
233 Object_props,
234 Object_destructor,
235 NULL
238 static const builtin_info_t ObjectInst_info = {
239 JSCLASS_OBJECT,
240 {NULL, NULL,0, Object_get_value},
241 0, NULL,
242 Object_destructor,
243 NULL
246 static void release_property_descriptor(property_desc_t *desc)
248 if(desc->explicit_value)
249 jsval_release(desc->value);
250 if(desc->getter)
251 jsdisp_release(desc->getter);
252 if(desc->setter)
253 jsdisp_release(desc->setter);
256 static HRESULT to_property_descriptor(script_ctx_t *ctx, jsdisp_t *attr_obj, property_desc_t *desc)
258 DISPID id;
259 jsval_t v;
260 BOOL b;
261 HRESULT hres;
263 memset(desc, 0, sizeof(*desc));
264 desc->value = jsval_undefined();
266 hres = jsdisp_get_id(attr_obj, L"enumerable", 0, &id);
267 if(SUCCEEDED(hres)) {
268 desc->mask |= PROPF_ENUMERABLE;
269 hres = jsdisp_propget(attr_obj, id, &v);
270 if(FAILED(hres))
271 return hres;
272 hres = to_boolean(v, &b);
273 jsval_release(v);
274 if(FAILED(hres))
275 return hres;
276 if(b)
277 desc->flags |= PROPF_ENUMERABLE;
278 }else if(hres != DISP_E_UNKNOWNNAME) {
279 return hres;
282 hres = jsdisp_get_id(attr_obj, L"configurable", 0, &id);
283 if(SUCCEEDED(hres)) {
284 desc->mask |= PROPF_CONFIGURABLE;
285 hres = jsdisp_propget(attr_obj, id, &v);
286 if(FAILED(hres))
287 return hres;
288 hres = to_boolean(v, &b);
289 jsval_release(v);
290 if(FAILED(hres))
291 return hres;
292 if(b)
293 desc->flags |= PROPF_CONFIGURABLE;
294 }else if(hres != DISP_E_UNKNOWNNAME) {
295 return hres;
298 hres = jsdisp_get_id(attr_obj, L"value", 0, &id);
299 if(SUCCEEDED(hres)) {
300 hres = jsdisp_propget(attr_obj, id, &desc->value);
301 if(FAILED(hres))
302 return hres;
303 desc->explicit_value = TRUE;
304 }else if(hres != DISP_E_UNKNOWNNAME) {
305 return hres;
308 hres = jsdisp_get_id(attr_obj, L"writable", 0, &id);
309 if(SUCCEEDED(hres)) {
310 desc->mask |= PROPF_WRITABLE;
311 hres = jsdisp_propget(attr_obj, id, &v);
312 if(SUCCEEDED(hres)) {
313 hres = to_boolean(v, &b);
314 jsval_release(v);
315 if(SUCCEEDED(hres) && b)
316 desc->flags |= PROPF_WRITABLE;
318 }else if(hres == DISP_E_UNKNOWNNAME) {
319 hres = S_OK;
321 if(FAILED(hres)) {
322 release_property_descriptor(desc);
323 return hres;
326 hres = jsdisp_get_id(attr_obj, L"get", 0, &id);
327 if(SUCCEEDED(hres)) {
328 desc->explicit_getter = TRUE;
329 hres = jsdisp_propget(attr_obj, id, &v);
330 if(SUCCEEDED(hres) && !is_undefined(v)) {
331 if(!is_object_instance(v)) {
332 FIXME("getter is not an object\n");
333 jsval_release(v);
334 hres = E_FAIL;
335 }else {
336 /* FIXME: Check IsCallable */
337 desc->getter = to_jsdisp(get_object(v));
338 if(!desc->getter)
339 FIXME("getter is not JS object\n");
342 }else if(hres == DISP_E_UNKNOWNNAME) {
343 hres = S_OK;
345 if(FAILED(hres)) {
346 release_property_descriptor(desc);
347 return hres;
350 hres = jsdisp_get_id(attr_obj, L"set", 0, &id);
351 if(SUCCEEDED(hres)) {
352 desc->explicit_setter = TRUE;
353 hres = jsdisp_propget(attr_obj, id, &v);
354 if(SUCCEEDED(hres) && !is_undefined(v)) {
355 if(!is_object_instance(v)) {
356 FIXME("setter is not an object\n");
357 jsval_release(v);
358 hres = E_FAIL;
359 }else {
360 /* FIXME: Check IsCallable */
361 desc->setter = to_jsdisp(get_object(v));
362 if(!desc->setter)
363 FIXME("setter is not JS object\n");
366 }else if(hres == DISP_E_UNKNOWNNAME) {
367 hres = S_OK;
369 if(FAILED(hres)) {
370 release_property_descriptor(desc);
371 return hres;
374 if(desc->explicit_getter || desc->explicit_setter) {
375 if(desc->explicit_value)
376 hres = JS_E_PROP_DESC_MISMATCH;
377 else if(desc->mask & PROPF_WRITABLE)
378 hres = JS_E_INVALID_WRITABLE_PROP_DESC;
381 if(FAILED(hres))
382 release_property_descriptor(desc);
383 return hres;
386 static HRESULT jsdisp_define_properties(script_ctx_t *ctx, jsdisp_t *obj, jsval_t list_val)
388 DISPID id = DISPID_STARTENUM;
389 property_desc_t prop_desc;
390 IDispatch *list_disp;
391 jsdisp_t *list_obj, *desc_obj;
392 jsval_t desc_val;
393 BSTR name;
394 HRESULT hres;
396 hres = to_object(ctx, list_val, &list_disp);
397 if(FAILED(hres))
398 return hres;
400 if(!(list_obj = to_jsdisp(list_disp))) {
401 FIXME("non-JS list obj\n");
402 IDispatch_Release(list_disp);
403 return E_NOTIMPL;
406 while(1) {
407 hres = jsdisp_next_prop(list_obj, id, TRUE, &id);
408 if(hres != S_OK)
409 break;
411 hres = jsdisp_propget(list_obj, id, &desc_val);
412 if(FAILED(hres))
413 break;
415 if(!is_object_instance(desc_val) || !get_object(desc_val) || !(desc_obj = to_jsdisp(get_object(desc_val)))) {
416 jsval_release(desc_val);
417 break;
420 hres = to_property_descriptor(ctx, desc_obj, &prop_desc);
421 jsdisp_release(desc_obj);
422 if(FAILED(hres))
423 break;
425 hres = IDispatchEx_GetMemberName(&list_obj->IDispatchEx_iface, id, &name);
426 if(SUCCEEDED(hres))
427 hres = jsdisp_define_property(obj, name, &prop_desc);
428 release_property_descriptor(&prop_desc);
429 if(FAILED(hres))
430 break;
433 jsdisp_release(list_obj);
434 return FAILED(hres) ? hres : S_OK;
437 static HRESULT Object_defineProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
438 unsigned argc, jsval_t *argv, jsval_t *r)
440 property_desc_t prop_desc;
441 jsdisp_t *obj, *attr_obj;
442 const WCHAR *name;
443 jsstr_t *name_str;
444 HRESULT hres;
446 TRACE("\n");
448 if(argc < 1 || !is_object_instance(argv[0]))
449 return JS_E_OBJECT_EXPECTED;
450 obj = to_jsdisp(get_object(argv[0]));
451 if(!obj) {
452 FIXME("not implemented non-JS object\n");
453 return E_NOTIMPL;
456 hres = to_flat_string(ctx, argc >= 2 ? argv[1] : jsval_undefined(), &name_str, &name);
457 if(FAILED(hres))
458 return hres;
460 if(argc >= 3 && is_object_instance(argv[2])) {
461 attr_obj = to_jsdisp(get_object(argv[2]));
462 if(attr_obj) {
463 hres = to_property_descriptor(ctx, attr_obj, &prop_desc);
464 }else {
465 FIXME("not implemented non-JS object\n");
466 hres = E_NOTIMPL;
468 }else {
469 hres = JS_E_OBJECT_EXPECTED;
471 jsstr_release(name_str);
472 if(FAILED(hres))
473 return hres;
475 hres = jsdisp_define_property(obj, name, &prop_desc);
476 release_property_descriptor(&prop_desc);
477 if(SUCCEEDED(hres) && r)
478 *r = jsval_obj(jsdisp_addref(obj));
479 return hres;
482 static HRESULT Object_defineProperties(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
483 unsigned argc, jsval_t *argv, jsval_t *r)
485 jsdisp_t *obj;
486 HRESULT hres;
488 if(argc < 1 || !is_object_instance(argv[0]) || !get_object(argv[0]) || !(obj = to_jsdisp(get_object(argv[0])))) {
489 FIXME("not an object\n");
490 return E_NOTIMPL;
493 TRACE("%p\n", obj);
495 hres = jsdisp_define_properties(ctx, obj, argc >= 2 ? argv[1] : jsval_undefined());
496 if(SUCCEEDED(hres) && r)
497 *r = jsval_obj(jsdisp_addref(obj));
498 return hres;
501 static HRESULT Object_getOwnPropertyDescriptor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
502 unsigned argc, jsval_t *argv, jsval_t *r)
504 property_desc_t prop_desc;
505 jsdisp_t *obj, *desc_obj;
506 const WCHAR *name;
507 jsstr_t *name_str;
508 HRESULT hres;
510 TRACE("\n");
512 if(argc < 1 || !is_object_instance(argv[0]))
513 return JS_E_OBJECT_EXPECTED;
514 obj = to_jsdisp(get_object(argv[0]));
515 if(!obj) {
516 FIXME("not implemented non-JS object\n");
517 return E_NOTIMPL;
520 hres = to_flat_string(ctx, argc >= 2 ? argv[1] : jsval_undefined(), &name_str, &name);
521 if(FAILED(hres))
522 return hres;
524 hres = jsdisp_get_own_property(obj, name, FALSE, &prop_desc);
525 jsstr_release(name_str);
526 if(hres == DISP_E_UNKNOWNNAME) {
527 if(r) *r = jsval_undefined();
528 return S_OK;
530 if(FAILED(hres))
531 return hres;
533 hres = create_object(ctx, NULL, &desc_obj);
534 if(FAILED(hres))
535 return hres;
537 if(prop_desc.explicit_getter || prop_desc.explicit_setter) {
538 hres = jsdisp_define_data_property(desc_obj, L"get", PROPF_ALL,
539 prop_desc.getter ? jsval_obj(prop_desc.getter) : jsval_undefined());
540 if(SUCCEEDED(hres))
541 hres = jsdisp_define_data_property(desc_obj, L"set", PROPF_ALL,
542 prop_desc.setter ? jsval_obj(prop_desc.setter) : jsval_undefined());
543 }else {
544 hres = jsdisp_propput_name(desc_obj, L"value", prop_desc.value);
545 if(SUCCEEDED(hres))
546 hres = jsdisp_define_data_property(desc_obj, L"writable", PROPF_ALL,
547 jsval_bool(!!(prop_desc.flags & PROPF_WRITABLE)));
549 if(SUCCEEDED(hres))
550 hres = jsdisp_define_data_property(desc_obj, L"enumerable", PROPF_ALL,
551 jsval_bool(!!(prop_desc.flags & PROPF_ENUMERABLE)));
552 if(SUCCEEDED(hres))
553 hres = jsdisp_define_data_property(desc_obj, L"configurable", PROPF_ALL,
554 jsval_bool(!!(prop_desc.flags & PROPF_CONFIGURABLE)));
556 release_property_descriptor(&prop_desc);
557 if(SUCCEEDED(hres) && r)
558 *r = jsval_obj(desc_obj);
559 else
560 jsdisp_release(desc_obj);
561 return hres;
564 static HRESULT Object_create(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
565 unsigned argc, jsval_t *argv, jsval_t *r)
567 jsdisp_t *proto = NULL, *obj;
568 HRESULT hres;
570 if(!argc || (!is_object_instance(argv[0]) && !is_null(argv[0]))) {
571 FIXME("Invalid arg\n");
572 return E_INVALIDARG;
575 TRACE("(%s)\n", debugstr_jsval(argv[0]));
577 if(argc && is_object_instance(argv[0])) {
578 if(get_object(argv[0]))
579 proto = to_jsdisp(get_object(argv[0]));
580 if(!proto) {
581 FIXME("Non-JS prototype\n");
582 return E_NOTIMPL;
584 }else if(!is_null(argv[0])) {
585 FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined()));
586 return E_INVALIDARG;
589 hres = create_dispex(ctx, &ObjectInst_info, proto, &obj);
590 if(FAILED(hres))
591 return hres;
593 if(argc >= 2 && !is_undefined(argv[1]))
594 hres = jsdisp_define_properties(ctx, obj, argv[1]);
596 if(SUCCEEDED(hres) && r)
597 *r = jsval_obj(obj);
598 else
599 jsdisp_release(obj);
600 return hres;
603 static HRESULT Object_getPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
604 unsigned argc, jsval_t *argv, jsval_t *r)
606 jsdisp_t *obj;
608 if(!argc || !is_object_instance(argv[0])) {
609 FIXME("invalid arguments\n");
610 return E_NOTIMPL;
613 TRACE("(%s)\n", debugstr_jsval(argv[0]));
615 obj = to_jsdisp(get_object(argv[0]));
616 if(!obj) {
617 FIXME("Non-JS object\n");
618 return E_NOTIMPL;
621 if(r)
622 *r = obj->prototype
623 ? jsval_obj(jsdisp_addref(obj->prototype))
624 : jsval_null();
625 return S_OK;
628 static HRESULT Object_keys(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
629 unsigned argc, jsval_t *argv, jsval_t *r)
631 DISPID id = DISPID_STARTENUM;
632 jsdisp_t *obj, *array;
633 unsigned i = 0;
634 jsstr_t *key;
635 HRESULT hres;
637 if(!argc || !is_object_instance(argv[0])) {
638 FIXME("invalid arguments %s\n", debugstr_jsval(argv[0]));
639 return E_NOTIMPL;
642 TRACE("(%s)\n", debugstr_jsval(argv[0]));
644 obj = to_jsdisp(get_object(argv[0]));
645 if(!obj) {
646 FIXME("Non-JS object\n");
647 return E_NOTIMPL;
650 hres = create_array(ctx, 0, &array);
651 if(FAILED(hres))
652 return hres;
654 do {
655 hres = jsdisp_next_prop(obj, id, TRUE, &id);
656 if(hres != S_OK)
657 break;
659 hres = jsdisp_get_prop_name(obj, id, &key);
660 if(FAILED(hres))
661 break;
663 hres = jsdisp_propput_idx(array, i++, jsval_string(key));
664 jsstr_release(key);
665 } while(hres == S_OK);
667 if(SUCCEEDED(hres) && r)
668 *r = jsval_obj(array);
669 else
670 jsdisp_release(array);
671 return hres;
674 static HRESULT Object_preventExtensions(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
676 jsdisp_t *obj;
678 if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
679 FIXME("invalid arguments\n");
680 return E_NOTIMPL;
683 FIXME("(%s) semi-stub\n", debugstr_jsval(argv[0]));
685 obj = to_jsdisp(get_object(argv[0]));
686 if(!obj) {
687 FIXME("Non-JS object\n");
688 return E_NOTIMPL;
691 if(r) *r = jsval_obj(jsdisp_addref(obj));
692 return S_OK;
695 static const builtin_prop_t ObjectConstr_props[] = {
696 {L"create", Object_create, PROPF_ES5|PROPF_METHOD|2},
697 {L"defineProperties", Object_defineProperties, PROPF_ES5|PROPF_METHOD|2},
698 {L"defineProperty", Object_defineProperty, PROPF_ES5|PROPF_METHOD|2},
699 {L"getOwnPropertyDescriptor", Object_getOwnPropertyDescriptor, PROPF_ES5|PROPF_METHOD|2},
700 {L"getPrototypeOf", Object_getPrototypeOf, PROPF_ES5|PROPF_METHOD|1},
701 {L"keys", Object_keys, PROPF_ES5|PROPF_METHOD|1},
702 {L"preventExtensions", Object_preventExtensions, PROPF_ES5|PROPF_METHOD|1},
705 static const builtin_info_t ObjectConstr_info = {
706 JSCLASS_FUNCTION,
707 DEFAULT_FUNCTION_VALUE,
708 ARRAY_SIZE(ObjectConstr_props),
709 ObjectConstr_props,
710 NULL,
711 NULL
714 static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
715 jsval_t *r)
717 HRESULT hres;
719 TRACE("\n");
721 switch(flags) {
722 case DISPATCH_METHOD:
723 case DISPATCH_CONSTRUCT: {
724 jsdisp_t *obj;
726 if(argc) {
727 if(!is_undefined(argv[0]) && !is_null(argv[0]) && (!is_object_instance(argv[0]) || get_object(argv[0]))) {
728 IDispatch *disp;
730 hres = to_object(ctx, argv[0], &disp);
731 if(FAILED(hres))
732 return hres;
734 if(r)
735 *r = jsval_disp(disp);
736 else
737 IDispatch_Release(disp);
738 return S_OK;
742 hres = create_object(ctx, NULL, &obj);
743 if(FAILED(hres))
744 return hres;
746 if(r)
747 *r = jsval_obj(obj);
748 else
749 jsdisp_release(obj);
750 break;
753 default:
754 FIXME("unimplemented flags: %x\n", flags);
755 return E_NOTIMPL;
758 return S_OK;
761 HRESULT create_object_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
763 return create_builtin_constructor(ctx, ObjectConstr_value, L"Object", &ObjectConstr_info, PROPF_CONSTR,
764 object_prototype, ret);
767 HRESULT create_object_prototype(script_ctx_t *ctx, jsdisp_t **ret)
769 return create_dispex(ctx, &Object_info, NULL, ret);
772 HRESULT create_object(script_ctx_t *ctx, jsdisp_t *constr, jsdisp_t **ret)
774 jsdisp_t *object;
775 HRESULT hres;
777 object = heap_alloc_zero(sizeof(jsdisp_t));
778 if(!object)
779 return E_OUTOFMEMORY;
781 hres = init_dispex_from_constr(object, ctx, &ObjectInst_info, constr ? constr : ctx->object_constr);
782 if(FAILED(hres)) {
783 heap_free(object);
784 return hres;
787 *ret = object;
788 return S_OK;