/* ECMA-262 3rd Edition 15.4.4.13 */ static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; WCHAR buf[14], *buf_end, *str; DWORD i, length; jsval_t val; DISPID id; HRESULT hres; TRACE("\n"); hres = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres)) return hres; if(argc) { buf_end = buf + sizeof(buf)/sizeof(WCHAR)-1; *buf_end-- = 0; i = length; while(i--) { str = idx_to_str(i, buf_end); hres = jsdisp_get_id(jsthis, str, 0, &id); if(SUCCEEDED(hres)) { hres = jsdisp_propget(jsthis, id, &val); if(FAILED(hres)) return hres; hres = jsdisp_propput_idx(jsthis, i+argc, val); jsval_release(val); }else if(hres == DISP_E_UNKNOWNNAME) { hres = IDispatchEx_DeleteMemberByDispID(vthis->u.dispex, id); } } if(FAILED(hres)) return hres; } for(i=0; i<argc; i++) { hres = jsdisp_propput_idx(jsthis, i, argv[i]); if(FAILED(hres)) return hres; } if(argc) { length += argc; hres = set_length(jsthis, length); if(FAILED(hres)) return hres; } if(r) *r = ctx->version < 2 ? jsval_undefined() : jsval_number(length); return S_OK; }
static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) { DispatchEx *This = DISPATCHEX_THIS(iface); TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid); if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit)) { FIXME("Unsupported grfdex %x\n", grfdex); return E_NOTIMPL; } return jsdisp_get_id(This, bstrName, grfdex, pid); }
/* ECMA-262 5.1 Edition 15.12.3 (abstract operation Str) */ static HRESULT stringify(stringify_ctx_t *ctx, jsval_t val) { jsval_t value; HRESULT hres; if(is_object_instance(val) && get_object(val)) { jsdisp_t *obj; DISPID id; obj = iface_to_jsdisp((IUnknown*)get_object(val)); if(!obj) return S_FALSE; hres = jsdisp_get_id(obj, toJSONW, 0, &id); jsdisp_release(obj); if(hres == S_OK) FIXME("Use toJSON.\n"); } /* FIXME: Support replacer replacer. */ hres = maybe_to_primitive(ctx->ctx, val, &value); if(FAILED(hres)) return hres; switch(jsval_type(value)) { case JSV_NULL: if(!append_string(ctx, nullW)) hres = E_OUTOFMEMORY; break; case JSV_BOOL: if(!append_string(ctx, get_bool(value) ? trueW : falseW)) hres = E_OUTOFMEMORY; break; case JSV_STRING: { jsstr_t *str = get_string(value); const WCHAR *ptr = jsstr_flatten(str); if(ptr) hres = json_quote(ctx, ptr, jsstr_length(str)); else hres = E_OUTOFMEMORY; break; } case JSV_NUMBER: { double n = get_number(value); if(is_finite(n)) { const WCHAR *ptr; jsstr_t *str; /* FIXME: Optimize. There is no need for jsstr_t here. */ hres = double_to_string(n, &str); if(FAILED(hres)) break; ptr = jsstr_flatten(str); assert(ptr != NULL); hres = ptr && !append_string_len(ctx, ptr, jsstr_length(str)) ? E_OUTOFMEMORY : S_OK; jsstr_release(str); }else { if(!append_string(ctx, nullW)) hres = E_OUTOFMEMORY; } break; } case JSV_OBJECT: { jsdisp_t *obj; obj = iface_to_jsdisp((IUnknown*)get_object(value)); if(!obj) { hres = S_FALSE; break; } if(!is_callable(obj)) hres = is_class(obj, JSCLASS_ARRAY) ? stringify_array(ctx, obj) : stringify_object(ctx, obj); else hres = S_FALSE; jsdisp_release(obj); break; } case JSV_UNDEFINED: hres = S_FALSE; break; case JSV_VARIANT: FIXME("VARIANT\n"); hres = E_NOTIMPL; break; } jsval_release(value); return hres; }
/* ECMA-262 3rd Edition 15.4.4.13 */ static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) { jsdisp_t *jsthis; WCHAR buf[14], *buf_end, *str; DWORD argc, i, length; VARIANT var; DISPID id; HRESULT hres; TRACE("\n"); hres = get_length(ctx, vthis, ei, &jsthis, &length); if(FAILED(hres)) return hres; argc = arg_cnt(dp); if(argc) { buf_end = buf + sizeof(buf)/sizeof(WCHAR)-1; *buf_end-- = 0; i = length; while(i--) { str = idx_to_str(i, buf_end); hres = jsdisp_get_id(jsthis, str, 0, &id); if(SUCCEEDED(hres)) { hres = jsdisp_propget(jsthis, id, &var, ei); if(FAILED(hres)) return hres; hres = jsdisp_propput_idx(jsthis, i+argc, &var, ei); VariantClear(&var); }else if(hres == DISP_E_UNKNOWNNAME) { hres = IDispatchEx_DeleteMemberByDispID(vthis->u.dispex, id); } } if(FAILED(hres)) return hres; } for(i=0; i<argc; i++) { hres = jsdisp_propput_idx(jsthis, i, get_arg(dp,i), ei); if(FAILED(hres)) return hres; } if(argc) { length += argc; hres = set_length(jsthis, ei, length); if(FAILED(hres)) return hres; } if(retv) { if(ctx->version < 2) { V_VT(retv) = VT_EMPTY; }else { V_VT(retv) = VT_I4; V_I4(retv) = length; } } return S_OK; }
/* ECMA-262 3rd Edition 9.1 */ HRESULT to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *ret, hint_t hint) { if(is_object_instance(val)) { jsdisp_t *jsdisp; jsval_t prim; DISPID id; HRESULT hres; static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0}; if(!get_object(val)) { *ret = jsval_null(); return S_OK; } jsdisp = iface_to_jsdisp((IUnknown*)get_object(val)); if(!jsdisp) return disp_propget(ctx, get_object(val), DISPID_VALUE, ret); if(hint == NO_HINT) hint = is_class(jsdisp, JSCLASS_DATE) ? HINT_STRING : HINT_NUMBER; /* Native implementation doesn't throw TypeErrors, returns strange values */ hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? toStringW : valueOfW, 0, &id); if(SUCCEEDED(hres)) { hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, 0, NULL, &prim); if(FAILED(hres)) { WARN("call error - forwarding exception\n"); jsdisp_release(jsdisp); return hres; }else if(!is_object_instance(prim)) { jsdisp_release(jsdisp); *ret = prim; return S_OK; }else { IDispatch_Release(get_object(prim)); } } hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? valueOfW : toStringW, 0, &id); if(SUCCEEDED(hres)) { hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, 0, NULL, &prim); if(FAILED(hres)) { WARN("call error - forwarding exception\n"); jsdisp_release(jsdisp); return hres; }else if(!is_object_instance(prim)) { jsdisp_release(jsdisp); *ret = prim; return S_OK; }else { IDispatch_Release(get_object(prim)); } } jsdisp_release(jsdisp); WARN("failed\n"); return throw_type_error(ctx, JS_E_TO_PRIMITIVE, NULL); } return jsval_copy(val, ret); }