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
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
27 static HRESULT
Object_toString(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
35 /* Keep in sync with jsclass_t enum */
36 static const WCHAR
*names
[] = {
59 if(is_undefined(vthis
) || is_null(vthis
)) {
60 if(ctx
->version
< SCRIPTLANGUAGEVERSION_ES5
)
61 str
= L
"[object Object]";
63 str
= is_null(vthis
) ? L
"[object Null]" : L
"[object Undefined]";
67 hres
= to_object(ctx
, vthis
, &disp
);
71 jsdisp
= to_jsdisp(disp
);
73 str
= L
"[object Object]";
74 }else if(names
[jsdisp
->builtin_info
->class]) {
75 str
= names
[jsdisp
->builtin_info
->class];
77 assert(jsdisp
->builtin_info
->class != JSCLASS_NONE
);
78 FIXME("jsdisp->builtin_info->class = %d\n", jsdisp
->builtin_info
->class);
81 IDispatch_Release(disp
);
88 ret
= jsstr_alloc(str
);
91 *r
= jsval_string(ret
);
97 static HRESULT
Object_toLocaleString(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
106 hres
= to_object(ctx
, vthis
, &disp
);
110 if(!(jsdisp
= to_jsdisp(disp
))) {
111 FIXME("Host object this\n");
116 hres
= jsdisp_call_name(jsdisp
, L
"toString", DISPATCH_METHOD
, 0, NULL
, r
);
118 IDispatch_Release(disp
);
122 static HRESULT
Object_valueOf(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
130 if(is_null_disp(vthis
)) {
131 if(r
) *r
= jsval_null_disp();
135 hres
= to_object(ctx
, vthis
, &disp
);
140 *r
= jsval_disp(disp
);
142 IDispatch_Release(disp
);
146 static HRESULT
Object_hasOwnProperty(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
159 hres
= to_object(ctx
, vthis
, &disp
);
165 *r
= jsval_bool(FALSE
);
169 hres
= to_string(ctx
, argv
[0], &name
);
173 if((jsdisp
= to_jsdisp(disp
))) {
174 property_desc_t prop_desc
;
175 const WCHAR
*name_str
;
177 name_str
= jsstr_flatten(name
);
180 hres
= E_OUTOFMEMORY
;
184 hres
= jsdisp_get_own_property(jsdisp
, name_str
, TRUE
, &prop_desc
);
186 if(FAILED(hres
) && hres
!= DISP_E_UNKNOWNNAME
)
189 if(r
) *r
= jsval_bool(hres
== S_OK
);
195 bstr
= SysAllocStringLen(NULL
, jsstr_length(name
));
197 jsstr_flush(name
, bstr
);
200 hres
= E_OUTOFMEMORY
;
204 hres
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
205 if(SUCCEEDED(hres
)) {
206 hres
= IDispatchEx_GetDispID(dispex
, bstr
, make_grfdex(ctx
, fdexNameCaseSensitive
), &id
);
207 IDispatchEx_Release(dispex
);
209 hres
= IDispatch_GetIDsOfNames(disp
, &IID_NULL
, &bstr
, 1, ctx
->lcid
, &id
);
213 *r
= jsval_bool(SUCCEEDED(hres
));
216 IDispatch_Release(disp
);
220 static HRESULT
Object_propertyIsEnumerable(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
223 property_desc_t prop_desc
;
232 hres
= to_object(ctx
, vthis
, &disp
);
237 FIXME("argc %d not supported\n", argc
);
242 if(!(jsdisp
= to_jsdisp(disp
))) {
243 FIXME("Host object this\n");
248 hres
= to_flat_string(ctx
, argv
[0], &name_str
, &name
);
252 hres
= jsdisp_get_own_property(jsdisp
, name
, TRUE
, &prop_desc
);
253 jsstr_release(name_str
);
254 if(FAILED(hres
) && hres
!= DISP_E_UNKNOWNNAME
)
258 *r
= jsval_bool(hres
== S_OK
&& (prop_desc
.flags
& PROPF_ENUMERABLE
) != 0);
261 IDispatch_Release(disp
);
265 static HRESULT
Object_isPrototypeOf(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
268 jsdisp_t
*jsthis
, *jsdisp
;
273 hres
= to_object(ctx
, vthis
, &disp
);
280 if(argc
&& (jsthis
= to_jsdisp(disp
)) && is_object_instance(argv
[0]) &&
281 (jsdisp
= to_jsdisp(get_object(argv
[0])))) {
282 while(jsdisp
->prototype
) {
283 if(jsdisp
->prototype
== jsthis
) {
287 jsdisp
= jsdisp
->prototype
;
291 *r
= jsval_bool(ret
);
293 IDispatch_Release(disp
);
297 static HRESULT
Object_defineGetter(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
299 property_desc_t desc
;
307 if(!is_object_instance(vthis
) || !(jsthis
= to_jsdisp(get_object(vthis
))))
310 if(argc
< 2 || !is_object_instance(argv
[1]))
311 return JS_E_FUNCTION_EXPECTED
;
313 desc
.getter
= to_jsdisp(get_object(argv
[1]));
315 FIXME("getter is not JS object\n");
318 /* FIXME: Check IsCallable */
320 hres
= to_flat_string(ctx
, argv
[0], &name_str
, &name
);
324 desc
.flags
= desc
.mask
= PROPF_CONFIGURABLE
| PROPF_ENUMERABLE
;
325 desc
.explicit_getter
= TRUE
;
326 desc
.explicit_setter
= FALSE
;
327 desc
.explicit_value
= FALSE
;
329 hres
= jsdisp_define_property(jsthis
, name
, &desc
);
331 jsstr_release(name_str
);
336 *r
= jsval_undefined();
340 static HRESULT
Object_defineSetter(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
342 property_desc_t desc
;
350 if(!is_object_instance(vthis
) || !(jsthis
= to_jsdisp(get_object(vthis
))))
353 if(argc
< 2 || !is_object_instance(argv
[1]))
354 return JS_E_FUNCTION_EXPECTED
;
356 desc
.setter
= to_jsdisp(get_object(argv
[1]));
358 FIXME("setter is not JS object\n");
361 /* FIXME: Check IsCallable */
363 hres
= to_flat_string(ctx
, argv
[0], &name_str
, &name
);
367 desc
.flags
= desc
.mask
= PROPF_CONFIGURABLE
| PROPF_ENUMERABLE
;
368 desc
.explicit_getter
= FALSE
;
369 desc
.explicit_setter
= TRUE
;
370 desc
.explicit_value
= FALSE
;
372 hres
= jsdisp_define_property(jsthis
, name
, &desc
);
374 jsstr_release(name_str
);
379 *r
= jsval_undefined();
383 HRESULT
Object_get_proto_(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
389 TRACE("%s\n", debugstr_jsval(vthis
));
391 hres
= to_object(ctx
, vthis
, &disp
);
398 if(!(jsthis
= to_jsdisp(disp
))) {
399 FIXME("Host object this\n");
404 *r
= jsthis
->prototype
405 ? jsval_obj(jsdisp_addref(jsthis
->prototype
))
408 IDispatch_Release(disp
);
412 HRESULT
Object_set_proto_(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
414 jsdisp_t
*jsthis
, *proto
;
417 TRACE("%s\n", debugstr_jsval(vthis
));
419 if(is_undefined(vthis
) || is_null(vthis
))
420 return JS_E_OBJECT_EXPECTED
;
423 *r
= jsval_undefined();
426 if(!is_object_instance(vthis
) || !(jsthis
= to_jsdisp(get_object(vthis
))))
429 if(is_null(argv
[0])) {
431 }else if(is_object_instance(argv
[0])) {
432 proto
= to_jsdisp(get_object(argv
[0]));
434 FIXME("Host object value\n");
440 hres
= jsdisp_change_prototype(jsthis
, proto
);
445 return r
? jsval_copy(argv
[0], r
) : S_OK
;
448 static void Object_destructor(jsdisp_t
*dispex
)
453 static const builtin_prop_t Object_props
[] = {
454 {L
"__defineGetter__", Object_defineGetter
, PROPF_METHOD
|PROPF_ES6
|2},
455 {L
"__defineSetter__", Object_defineSetter
, PROPF_METHOD
|PROPF_ES6
|2},
456 {L
"hasOwnProperty", Object_hasOwnProperty
, PROPF_METHOD
|1},
457 {L
"isPrototypeOf", Object_isPrototypeOf
, PROPF_METHOD
|1},
458 {L
"propertyIsEnumerable", Object_propertyIsEnumerable
, PROPF_METHOD
|1},
459 {L
"toLocaleString", Object_toLocaleString
, PROPF_METHOD
},
460 {L
"toString", Object_toString
, PROPF_METHOD
},
461 {L
"valueOf", Object_valueOf
, PROPF_METHOD
}
464 static const builtin_info_t Object_info
= {
467 ARRAY_SIZE(Object_props
),
473 static const builtin_info_t ObjectInst_info
= {
481 static void release_property_descriptor(property_desc_t
*desc
)
483 if(desc
->explicit_value
)
484 jsval_release(desc
->value
);
486 jsdisp_release(desc
->getter
);
488 jsdisp_release(desc
->setter
);
491 static HRESULT
to_property_descriptor(script_ctx_t
*ctx
, jsdisp_t
*attr_obj
, property_desc_t
*desc
)
498 memset(desc
, 0, sizeof(*desc
));
499 desc
->value
= jsval_undefined();
501 hres
= jsdisp_get_id(attr_obj
, L
"enumerable", 0, &id
);
502 if(SUCCEEDED(hres
)) {
503 desc
->mask
|= PROPF_ENUMERABLE
;
504 hres
= jsdisp_propget(attr_obj
, id
, &v
);
507 hres
= to_boolean(v
, &b
);
512 desc
->flags
|= PROPF_ENUMERABLE
;
513 }else if(hres
!= DISP_E_UNKNOWNNAME
) {
517 hres
= jsdisp_get_id(attr_obj
, L
"configurable", 0, &id
);
518 if(SUCCEEDED(hres
)) {
519 desc
->mask
|= PROPF_CONFIGURABLE
;
520 hres
= jsdisp_propget(attr_obj
, id
, &v
);
523 hres
= to_boolean(v
, &b
);
528 desc
->flags
|= PROPF_CONFIGURABLE
;
529 }else if(hres
!= DISP_E_UNKNOWNNAME
) {
533 hres
= jsdisp_get_id(attr_obj
, L
"value", 0, &id
);
534 if(SUCCEEDED(hres
)) {
535 hres
= jsdisp_propget(attr_obj
, id
, &desc
->value
);
538 desc
->explicit_value
= TRUE
;
539 }else if(hres
!= DISP_E_UNKNOWNNAME
) {
543 hres
= jsdisp_get_id(attr_obj
, L
"writable", 0, &id
);
544 if(SUCCEEDED(hres
)) {
545 desc
->mask
|= PROPF_WRITABLE
;
546 hres
= jsdisp_propget(attr_obj
, id
, &v
);
547 if(SUCCEEDED(hres
)) {
548 hres
= to_boolean(v
, &b
);
550 if(SUCCEEDED(hres
) && b
)
551 desc
->flags
|= PROPF_WRITABLE
;
553 }else if(hres
== DISP_E_UNKNOWNNAME
) {
557 release_property_descriptor(desc
);
561 hres
= jsdisp_get_id(attr_obj
, L
"get", 0, &id
);
562 if(SUCCEEDED(hres
)) {
563 desc
->explicit_getter
= TRUE
;
564 hres
= jsdisp_propget(attr_obj
, id
, &v
);
565 if(SUCCEEDED(hres
) && !is_undefined(v
)) {
566 if(!is_object_instance(v
)) {
567 FIXME("getter is not an object\n");
571 /* FIXME: Check IsCallable */
572 desc
->getter
= to_jsdisp(get_object(v
));
574 FIXME("getter is not JS object\n");
577 }else if(hres
== DISP_E_UNKNOWNNAME
) {
581 release_property_descriptor(desc
);
585 hres
= jsdisp_get_id(attr_obj
, L
"set", 0, &id
);
586 if(SUCCEEDED(hres
)) {
587 desc
->explicit_setter
= TRUE
;
588 hres
= jsdisp_propget(attr_obj
, id
, &v
);
589 if(SUCCEEDED(hres
) && !is_undefined(v
)) {
590 if(!is_object_instance(v
)) {
591 FIXME("setter is not an object\n");
595 /* FIXME: Check IsCallable */
596 desc
->setter
= to_jsdisp(get_object(v
));
598 FIXME("setter is not JS object\n");
601 }else if(hres
== DISP_E_UNKNOWNNAME
) {
605 release_property_descriptor(desc
);
609 if(desc
->explicit_getter
|| desc
->explicit_setter
) {
610 if(desc
->explicit_value
)
611 hres
= JS_E_PROP_DESC_MISMATCH
;
612 else if(desc
->mask
& PROPF_WRITABLE
)
613 hres
= JS_E_INVALID_WRITABLE_PROP_DESC
;
617 release_property_descriptor(desc
);
621 static HRESULT
jsdisp_define_properties(script_ctx_t
*ctx
, jsdisp_t
*obj
, jsval_t list_val
)
623 DISPID id
= DISPID_STARTENUM
;
624 property_desc_t prop_desc
;
625 IDispatch
*list_disp
;
626 jsdisp_t
*list_obj
, *desc_obj
;
631 hres
= to_object(ctx
, list_val
, &list_disp
);
635 if(!(list_obj
= to_jsdisp(list_disp
))) {
636 FIXME("non-JS list obj\n");
637 IDispatch_Release(list_disp
);
642 hres
= jsdisp_next_prop(list_obj
, id
, JSDISP_ENUM_OWN_ENUMERABLE
, &id
);
646 hres
= jsdisp_propget(list_obj
, id
, &desc_val
);
650 if(!is_object_instance(desc_val
) || !(desc_obj
= to_jsdisp(get_object(desc_val
)))) {
651 jsval_release(desc_val
);
655 hres
= to_property_descriptor(ctx
, desc_obj
, &prop_desc
);
656 jsdisp_release(desc_obj
);
660 hres
= IDispatchEx_GetMemberName(&list_obj
->IDispatchEx_iface
, id
, &name
);
662 hres
= jsdisp_define_property(obj
, name
, &prop_desc
);
663 release_property_descriptor(&prop_desc
);
668 jsdisp_release(list_obj
);
669 return FAILED(hres
) ? hres
: S_OK
;
672 static HRESULT
Object_defineProperty(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
,
673 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
675 property_desc_t prop_desc
;
676 jsdisp_t
*obj
, *attr_obj
;
683 if(argc
< 1 || !is_object_instance(argv
[0]))
684 return JS_E_OBJECT_EXPECTED
;
685 obj
= to_jsdisp(get_object(argv
[0]));
687 FIXME("not implemented non-JS object\n");
691 hres
= to_flat_string(ctx
, argc
>= 2 ? argv
[1] : jsval_undefined(), &name_str
, &name
);
695 if(argc
>= 3 && is_object_instance(argv
[2])) {
696 attr_obj
= to_jsdisp(get_object(argv
[2]));
698 hres
= to_property_descriptor(ctx
, attr_obj
, &prop_desc
);
700 FIXME("not implemented non-JS object\n");
704 hres
= JS_E_OBJECT_EXPECTED
;
709 jsstr_release(name_str
);
713 hres
= jsdisp_define_property(obj
, name
, &prop_desc
);
714 jsstr_release(name_str
);
715 release_property_descriptor(&prop_desc
);
716 if(SUCCEEDED(hres
) && r
)
717 *r
= jsval_obj(jsdisp_addref(obj
));
721 static HRESULT
Object_defineProperties(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
,
722 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
727 if(argc
< 1 || !is_object_instance(argv
[0]) || !(obj
= to_jsdisp(get_object(argv
[0])))) {
728 FIXME("not an object\n");
734 hres
= jsdisp_define_properties(ctx
, obj
, argc
>= 2 ? argv
[1] : jsval_undefined());
735 if(SUCCEEDED(hres
) && r
)
736 *r
= jsval_obj(jsdisp_addref(obj
));
740 static HRESULT
Object_getOwnPropertyDescriptor(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
,
741 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
743 property_desc_t prop_desc
;
744 jsdisp_t
*obj
, *desc_obj
;
751 if(argc
< 1 || !is_object_instance(argv
[0]))
752 return JS_E_OBJECT_EXPECTED
;
753 obj
= to_jsdisp(get_object(argv
[0]));
755 FIXME("not implemented non-JS object\n");
759 hres
= to_flat_string(ctx
, argc
>= 2 ? argv
[1] : jsval_undefined(), &name_str
, &name
);
763 hres
= jsdisp_get_own_property(obj
, name
, FALSE
, &prop_desc
);
764 jsstr_release(name_str
);
765 if(hres
== DISP_E_UNKNOWNNAME
) {
766 if(r
) *r
= jsval_undefined();
772 hres
= create_object(ctx
, NULL
, &desc_obj
);
776 if(prop_desc
.explicit_getter
|| prop_desc
.explicit_setter
) {
777 hres
= jsdisp_define_data_property(desc_obj
, L
"get", PROPF_ALL
,
778 prop_desc
.getter
? jsval_obj(prop_desc
.getter
) : jsval_undefined());
780 hres
= jsdisp_define_data_property(desc_obj
, L
"set", PROPF_ALL
,
781 prop_desc
.setter
? jsval_obj(prop_desc
.setter
) : jsval_undefined());
783 hres
= jsdisp_propput_name(desc_obj
, L
"value", prop_desc
.value
);
785 hres
= jsdisp_define_data_property(desc_obj
, L
"writable", PROPF_ALL
,
786 jsval_bool(!!(prop_desc
.flags
& PROPF_WRITABLE
)));
789 hres
= jsdisp_define_data_property(desc_obj
, L
"enumerable", PROPF_ALL
,
790 jsval_bool(!!(prop_desc
.flags
& PROPF_ENUMERABLE
)));
792 hres
= jsdisp_define_data_property(desc_obj
, L
"configurable", PROPF_ALL
,
793 jsval_bool(!!(prop_desc
.flags
& PROPF_CONFIGURABLE
)));
795 release_property_descriptor(&prop_desc
);
796 if(SUCCEEDED(hres
) && r
)
797 *r
= jsval_obj(desc_obj
);
799 jsdisp_release(desc_obj
);
803 static HRESULT
Object_create(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
,
804 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
806 jsdisp_t
*proto
= NULL
, *obj
;
809 if(!argc
|| (!is_object_instance(argv
[0]) && !is_null(argv
[0]))) {
810 FIXME("Invalid arg\n");
814 TRACE("(%s)\n", debugstr_jsval(argv
[0]));
816 if(argc
&& is_object_instance(argv
[0])) {
817 if(get_object(argv
[0]))
818 proto
= to_jsdisp(get_object(argv
[0]));
820 FIXME("Non-JS prototype\n");
823 }else if(!is_null(argv
[0])) {
824 FIXME("Invalid arg %s\n", debugstr_jsval(argc
? argv
[0] : jsval_undefined()));
828 hres
= create_dispex(ctx
, &ObjectInst_info
, proto
, &obj
);
832 if(argc
>= 2 && !is_undefined(argv
[1]))
833 hres
= jsdisp_define_properties(ctx
, obj
, argv
[1]);
835 if(SUCCEEDED(hres
) && r
)
842 static HRESULT
Object_getPrototypeOf(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
,
843 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
847 if(!argc
|| !is_object_instance(argv
[0]))
848 return JS_E_OBJECT_EXPECTED
;
850 TRACE("(%s)\n", debugstr_jsval(argv
[0]));
852 obj
= to_jsdisp(get_object(argv
[0]));
854 *r
= obj
&& obj
->prototype
855 ? jsval_obj(jsdisp_addref(obj
->prototype
))
860 static HRESULT
object_keys(script_ctx_t
*ctx
, jsval_t arg
, enum jsdisp_enum_type enum_type
, jsval_t
*r
)
862 DISPID id
= DISPID_STARTENUM
;
863 jsdisp_t
*obj
, *array
;
868 if(!is_object_instance(arg
))
869 return JS_E_OBJECT_EXPECTED
;
871 obj
= to_jsdisp(get_object(arg
));
873 FIXME("Non-JS object\n");
877 hres
= create_array(ctx
, 0, &array
);
882 hres
= jsdisp_next_prop(obj
, id
, enum_type
, &id
);
886 hres
= jsdisp_get_prop_name(obj
, id
, &key
);
890 hres
= jsdisp_propput_idx(array
, i
++, jsval_string(key
));
892 } while(hres
== S_OK
);
894 if(SUCCEEDED(hres
) && r
)
895 *r
= jsval_obj(array
);
897 jsdisp_release(array
);
901 static HRESULT
Object_keys(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
,
902 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
904 jsval_t arg
= argc
? argv
[0] : jsval_undefined();
906 TRACE("(%s)\n", debugstr_jsval(arg
));
908 return object_keys(ctx
, arg
, JSDISP_ENUM_OWN_ENUMERABLE
, r
);
911 static HRESULT
Object_getOwnPropertyNames(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
,
912 unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
914 jsval_t arg
= argc
? argv
[0] : jsval_undefined();
916 TRACE("(%s)\n", debugstr_jsval(arg
));
918 return object_keys(ctx
, arg
, JSDISP_ENUM_OWN
, r
);
921 static HRESULT
Object_preventExtensions(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
925 if(!argc
|| !is_object_instance(argv
[0]))
926 return JS_E_OBJECT_EXPECTED
;
928 TRACE("(%s)\n", debugstr_jsval(argv
[0]));
930 obj
= to_jsdisp(get_object(argv
[0]));
932 FIXME("Non-JS object\n");
936 obj
->extensible
= FALSE
;
937 if(r
) *r
= jsval_obj(jsdisp_addref(obj
));
941 static HRESULT
Object_freeze(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
,
942 jsval_t
*argv
, jsval_t
*r
)
946 if(!argc
|| !is_object_instance(argv
[0])) {
947 WARN("argument is not an object\n");
948 return JS_E_OBJECT_EXPECTED
;
951 TRACE("(%s)\n", debugstr_jsval(argv
[0]));
953 obj
= to_jsdisp(get_object(argv
[0]));
955 FIXME("Non-JS object\n");
959 jsdisp_freeze(obj
, FALSE
);
960 if(r
) *r
= jsval_obj(jsdisp_addref(obj
));
964 static HRESULT
Object_seal(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
,
965 jsval_t
*argv
, jsval_t
*r
)
969 if(!argc
|| !is_object_instance(argv
[0])) {
970 WARN("argument is not an object\n");
971 return JS_E_OBJECT_EXPECTED
;
974 TRACE("(%s)\n", debugstr_jsval(argv
[0]));
976 obj
= to_jsdisp(get_object(argv
[0]));
978 FIXME("Non-JS object\n");
982 jsdisp_freeze(obj
, TRUE
);
983 if(r
) *r
= jsval_obj(jsdisp_addref(obj
));
987 static HRESULT
Object_isExtensible(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
, jsval_t
*r
)
991 if(!argc
|| !is_object_instance(argv
[0])) {
992 WARN("argument is not an object\n");
993 return JS_E_OBJECT_EXPECTED
;
996 TRACE("(%s)\n", debugstr_jsval(argv
[0]));
998 obj
= to_jsdisp(get_object(argv
[0]));
1000 FIXME("Non-JS object\n");
1004 if(r
) *r
= jsval_bool(obj
->extensible
);
1008 static HRESULT
Object_isFrozen(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
,
1009 jsval_t
*argv
, jsval_t
*r
)
1013 if(!argc
|| !is_object_instance(argv
[0])) {
1014 WARN("argument is not an object\n");
1015 return JS_E_OBJECT_EXPECTED
;
1018 TRACE("(%s)\n", debugstr_jsval(argv
[0]));
1020 obj
= to_jsdisp(get_object(argv
[0]));
1022 FIXME("Non-JS object\n");
1026 if(r
) *r
= jsval_bool(jsdisp_is_frozen(obj
, FALSE
));
1030 static HRESULT
Object_isSealed(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
,
1031 jsval_t
*argv
, jsval_t
*r
)
1035 if(!argc
|| !is_object_instance(argv
[0])) {
1036 WARN("argument is not an object\n");
1037 return JS_E_OBJECT_EXPECTED
;
1040 TRACE("(%s)\n", debugstr_jsval(argv
[0]));
1042 obj
= to_jsdisp(get_object(argv
[0]));
1044 FIXME("Non-JS object\n");
1048 if(r
) *r
= jsval_bool(jsdisp_is_frozen(obj
, TRUE
));
1052 static const builtin_prop_t ObjectConstr_props
[] = {
1053 {L
"create", Object_create
, PROPF_ES5
|PROPF_METHOD
|2},
1054 {L
"defineProperties", Object_defineProperties
, PROPF_ES5
|PROPF_METHOD
|2},
1055 {L
"defineProperty", Object_defineProperty
, PROPF_ES5
|PROPF_METHOD
|2},
1056 {L
"freeze", Object_freeze
, PROPF_ES5
|PROPF_METHOD
|1},
1057 {L
"getOwnPropertyDescriptor", Object_getOwnPropertyDescriptor
, PROPF_ES5
|PROPF_METHOD
|2},
1058 {L
"getOwnPropertyNames", Object_getOwnPropertyNames
, PROPF_ES5
|PROPF_METHOD
|1},
1059 {L
"getPrototypeOf", Object_getPrototypeOf
, PROPF_ES5
|PROPF_METHOD
|1},
1060 {L
"isExtensible", Object_isExtensible
, PROPF_ES5
|PROPF_METHOD
|1},
1061 {L
"isFrozen", Object_isFrozen
, PROPF_ES5
|PROPF_METHOD
|1},
1062 {L
"isSealed", Object_isSealed
, PROPF_ES5
|PROPF_METHOD
|1},
1063 {L
"keys", Object_keys
, PROPF_ES5
|PROPF_METHOD
|1},
1064 {L
"preventExtensions", Object_preventExtensions
, PROPF_ES5
|PROPF_METHOD
|1},
1065 {L
"seal", Object_seal
, PROPF_ES5
|PROPF_METHOD
|1},
1068 static const builtin_info_t ObjectConstr_info
= {
1071 ARRAY_SIZE(ObjectConstr_props
),
1077 static HRESULT
ObjectConstr_value(script_ctx_t
*ctx
, jsval_t vthis
, WORD flags
, unsigned argc
, jsval_t
*argv
,
1085 case DISPATCH_METHOD
:
1086 case DISPATCH_CONSTRUCT
: {
1090 if(!is_undefined(argv
[0]) && !is_null(argv
[0])) {
1093 hres
= to_object(ctx
, argv
[0], &disp
);
1098 *r
= jsval_disp(disp
);
1100 IDispatch_Release(disp
);
1105 hres
= create_object(ctx
, NULL
, &obj
);
1110 *r
= jsval_obj(obj
);
1112 jsdisp_release(obj
);
1117 FIXME("unimplemented flags: %x\n", flags
);
1124 HRESULT
create_object_constr(script_ctx_t
*ctx
, jsdisp_t
*object_prototype
, jsdisp_t
**ret
)
1126 return create_builtin_constructor(ctx
, ObjectConstr_value
, L
"Object", &ObjectConstr_info
, PROPF_CONSTR
,
1127 object_prototype
, ret
);
1130 HRESULT
create_object_prototype(script_ctx_t
*ctx
, jsdisp_t
**ret
)
1132 return create_dispex(ctx
, &Object_info
, NULL
, ret
);
1135 HRESULT
create_object(script_ctx_t
*ctx
, jsdisp_t
*constr
, jsdisp_t
**ret
)
1140 object
= heap_alloc_zero(sizeof(jsdisp_t
));
1142 return E_OUTOFMEMORY
;
1144 hres
= init_dispex_from_constr(object
, ctx
, &ObjectInst_info
, constr
? constr
: ctx
->object_constr
);