wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / jscript / object.c
blobb957ea58bdf57be1cc343be527113cc4d1c78091
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 TRACE("(%s)\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 obj->extensible = FALSE;
692 if(r) *r = jsval_obj(jsdisp_addref(obj));
693 return S_OK;
696 static HRESULT Object_freeze(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc,
697 jsval_t *argv, jsval_t *r)
699 jsdisp_t *obj;
701 if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
702 WARN("argument is not an object\n");
703 return JS_E_OBJECT_EXPECTED;
706 TRACE("(%s)\n", debugstr_jsval(argv[0]));
708 obj = to_jsdisp(get_object(argv[0]));
709 if(!obj) {
710 FIXME("Non-JS object\n");
711 return E_NOTIMPL;
714 jsdisp_freeze(obj, FALSE);
715 if(r) *r = jsval_obj(jsdisp_addref(obj));
716 return S_OK;
719 static HRESULT Object_seal(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc,
720 jsval_t *argv, jsval_t *r)
722 jsdisp_t *obj;
724 if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
725 WARN("argument is not an object\n");
726 return JS_E_OBJECT_EXPECTED;
729 TRACE("(%s)\n", debugstr_jsval(argv[0]));
731 obj = to_jsdisp(get_object(argv[0]));
732 if(!obj) {
733 FIXME("Non-JS object\n");
734 return E_NOTIMPL;
737 jsdisp_freeze(obj, TRUE);
738 if(r) *r = jsval_obj(jsdisp_addref(obj));
739 return S_OK;
742 static HRESULT Object_isExtensible(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
744 jsdisp_t *obj;
746 if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
747 WARN("argument is not an object\n");
748 return JS_E_OBJECT_EXPECTED;
751 TRACE("(%s)\n", debugstr_jsval(argv[0]));
753 obj = to_jsdisp(get_object(argv[0]));
754 if(!obj) {
755 FIXME("Non-JS object\n");
756 return E_NOTIMPL;
759 if(r) *r = jsval_bool(obj->extensible);
760 return S_OK;
763 static HRESULT Object_isFrozen(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc,
764 jsval_t *argv, jsval_t *r)
766 jsdisp_t *obj;
768 if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
769 WARN("argument is not an object\n");
770 return JS_E_OBJECT_EXPECTED;
773 TRACE("(%s)\n", debugstr_jsval(argv[0]));
775 obj = to_jsdisp(get_object(argv[0]));
776 if(!obj) {
777 FIXME("Non-JS object\n");
778 return E_NOTIMPL;
781 if(r) *r = jsval_bool(jsdisp_is_frozen(obj, FALSE));
782 return S_OK;
785 static HRESULT Object_isSealed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc,
786 jsval_t *argv, jsval_t *r)
788 jsdisp_t *obj;
790 if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
791 WARN("argument is not an object\n");
792 return JS_E_OBJECT_EXPECTED;
795 TRACE("(%s)\n", debugstr_jsval(argv[0]));
797 obj = to_jsdisp(get_object(argv[0]));
798 if(!obj) {
799 FIXME("Non-JS object\n");
800 return E_NOTIMPL;
803 if(r) *r = jsval_bool(jsdisp_is_frozen(obj, TRUE));
804 return S_OK;
807 static const builtin_prop_t ObjectConstr_props[] = {
808 {L"create", Object_create, PROPF_ES5|PROPF_METHOD|2},
809 {L"defineProperties", Object_defineProperties, PROPF_ES5|PROPF_METHOD|2},
810 {L"defineProperty", Object_defineProperty, PROPF_ES5|PROPF_METHOD|2},
811 {L"freeze", Object_freeze, PROPF_ES5|PROPF_METHOD|1},
812 {L"getOwnPropertyDescriptor", Object_getOwnPropertyDescriptor, PROPF_ES5|PROPF_METHOD|2},
813 {L"getPrototypeOf", Object_getPrototypeOf, PROPF_ES5|PROPF_METHOD|1},
814 {L"isExtensible", Object_isExtensible, PROPF_ES5|PROPF_METHOD|1},
815 {L"isFrozen", Object_isFrozen, PROPF_ES5|PROPF_METHOD|1},
816 {L"isSealed", Object_isSealed, PROPF_ES5|PROPF_METHOD|1},
817 {L"keys", Object_keys, PROPF_ES5|PROPF_METHOD|1},
818 {L"preventExtensions", Object_preventExtensions, PROPF_ES5|PROPF_METHOD|1},
819 {L"seal", Object_seal, PROPF_ES5|PROPF_METHOD|1},
822 static const builtin_info_t ObjectConstr_info = {
823 JSCLASS_FUNCTION,
824 DEFAULT_FUNCTION_VALUE,
825 ARRAY_SIZE(ObjectConstr_props),
826 ObjectConstr_props,
827 NULL,
828 NULL
831 static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
832 jsval_t *r)
834 HRESULT hres;
836 TRACE("\n");
838 switch(flags) {
839 case DISPATCH_METHOD:
840 case DISPATCH_CONSTRUCT: {
841 jsdisp_t *obj;
843 if(argc) {
844 if(!is_undefined(argv[0]) && !is_null(argv[0]) && (!is_object_instance(argv[0]) || get_object(argv[0]))) {
845 IDispatch *disp;
847 hres = to_object(ctx, argv[0], &disp);
848 if(FAILED(hres))
849 return hres;
851 if(r)
852 *r = jsval_disp(disp);
853 else
854 IDispatch_Release(disp);
855 return S_OK;
859 hres = create_object(ctx, NULL, &obj);
860 if(FAILED(hres))
861 return hres;
863 if(r)
864 *r = jsval_obj(obj);
865 else
866 jsdisp_release(obj);
867 break;
870 default:
871 FIXME("unimplemented flags: %x\n", flags);
872 return E_NOTIMPL;
875 return S_OK;
878 HRESULT create_object_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
880 return create_builtin_constructor(ctx, ObjectConstr_value, L"Object", &ObjectConstr_info, PROPF_CONSTR,
881 object_prototype, ret);
884 HRESULT create_object_prototype(script_ctx_t *ctx, jsdisp_t **ret)
886 return create_dispex(ctx, &Object_info, NULL, ret);
889 HRESULT create_object(script_ctx_t *ctx, jsdisp_t *constr, jsdisp_t **ret)
891 jsdisp_t *object;
892 HRESULT hres;
894 object = heap_alloc_zero(sizeof(jsdisp_t));
895 if(!object)
896 return E_OUTOFMEMORY;
898 hres = init_dispex_from_constr(object, ctx, &ObjectInst_info, constr ? constr : ctx->object_constr);
899 if(FAILED(hres)) {
900 heap_free(object);
901 return hres;
904 *ret = object;
905 return S_OK;