static HRESULT create_arguments(script_ctx_t *ctx, FunctionInstance *calee, jsdisp_t *var_obj, unsigned argc, jsval_t *argv, jsdisp_t **ret) { ArgumentsInstance *args; unsigned i; HRESULT hres; static const WCHAR caleeW[] = {'c','a','l','l','e','e',0}; args = heap_alloc_zero(sizeof(*args)); if(!args) return E_OUTOFMEMORY; hres = init_dispex_from_constr(&args->jsdisp, ctx, &Arguments_info, ctx->object_constr); if(FAILED(hres)) { heap_free(args); return hres; } jsdisp_addref(&calee->dispex); args->function = calee; args->var_obj = jsdisp_addref(var_obj); /* Store unnamed arguments directly in arguments object */ for(i = calee->length; i < argc; i++) { WCHAR buf[12]; static const WCHAR formatW[] = {'%','d',0}; sprintfW(buf, formatW, i); hres = jsdisp_propput_dontenum(&args->jsdisp, buf, argv[i]); if(FAILED(hres)) break; } if(SUCCEEDED(hres)) { hres = jsdisp_propput_dontenum(&args->jsdisp, lengthW, jsval_number(argc)); if(SUCCEEDED(hres)) hres = jsdisp_propput_dontenum(&args->jsdisp, caleeW, jsval_disp(to_disp(&calee->dispex))); } if(FAILED(hres)) { jsdisp_release(&args->jsdisp); return hres; } *ret = &args->jsdisp; return S_OK; }
static HRESULT Function_arguments(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { FunctionInstance *function = (FunctionInstance*)jsthis->u.jsdisp; HRESULT hres = S_OK; TRACE("\n"); switch(flags) { case DISPATCH_PROPERTYGET: { if(function->arguments) { jsdisp_addref(function->arguments); var_set_jsdisp(retv, function->arguments); }else { V_VT(retv) = VT_NULL; } break; } case DISPATCH_PROPERTYPUT: break; default: FIXME("unimplemented flags %x\n", flags); hres = E_NOTIMPL; } return hres; }
static HRESULT constructor_call(jsdisp_t *constr, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { if(flags != DISPATCH_PROPERTYGET) return jsdisp_call_value(constr, NULL, flags, argc, argv, r); *r = jsval_obj(jsdisp_addref(constr)); return S_OK; }
static HRESULT Function_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { FunctionInstance *function = function_from_jsdisp(jsthis); TRACE("\n"); *r = function->arguments ? jsval_obj(jsdisp_addref(function->arguments)) : jsval_null(); return S_OK; }
static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) { jsdisp_t *jsthis; DWORD length, k, l; VARIANT v1, v2; HRESULT hres1, hres2; TRACE("\n"); hres1 = get_length(ctx, vthis, ei, &jsthis, &length); if(FAILED(hres1)) return hres1; for(k=0; k<length/2; k++) { l = length-k-1; hres1 = jsdisp_get_idx(jsthis, k, &v1, ei); if(FAILED(hres1) && hres1!=DISP_E_UNKNOWNNAME) return hres1; hres2 = jsdisp_get_idx(jsthis, l, &v2, ei); if(FAILED(hres2) && hres2!=DISP_E_UNKNOWNNAME) { VariantClear(&v1); return hres2; } if(hres1 == DISP_E_UNKNOWNNAME) hres1 = jsdisp_delete_idx(jsthis, l); else hres1 = jsdisp_propput_idx(jsthis, l, &v1, ei); if(FAILED(hres1)) { VariantClear(&v1); VariantClear(&v2); return hres1; } if(hres2 == DISP_E_UNKNOWNNAME) hres2 = jsdisp_delete_idx(jsthis, k); else hres2 = jsdisp_propput_idx(jsthis, k, &v2, ei); if(FAILED(hres2)) { VariantClear(&v2); return hres2; } } if(retv) { jsdisp_addref(jsthis); var_set_jsdisp(retv, jsthis); } return S_OK; }
static HRESULT constructor_call(jsdisp_t *constr, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) { if(flags != DISPATCH_PROPERTYGET) return jsdisp_call_value(constr, flags, dp, retv, ei); jsdisp_addref(constr); var_set_jsdisp(retv, constr); return S_OK; }
static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; DWORD length, k, l; jsval_t v1, v2; HRESULT hres1, hres2; TRACE("\n"); hres1 = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres1)) return hres1; for(k=0; k<length/2; k++) { l = length-k-1; hres1 = jsdisp_get_idx(jsthis, k, &v1); if(FAILED(hres1) && hres1!=DISP_E_UNKNOWNNAME) return hres1; hres2 = jsdisp_get_idx(jsthis, l, &v2); if(FAILED(hres2) && hres2!=DISP_E_UNKNOWNNAME) { jsval_release(v1); return hres2; } if(hres1 == DISP_E_UNKNOWNNAME) hres1 = jsdisp_delete_idx(jsthis, l); else hres1 = jsdisp_propput_idx(jsthis, l, v1); if(FAILED(hres1)) { jsval_release(v1); jsval_release(v2); return hres1; } if(hres2 == DISP_E_UNKNOWNNAME) hres2 = jsdisp_delete_idx(jsthis, k); else hres2 = jsdisp_propput_idx(jsthis, k, v2); if(FAILED(hres2)) { jsval_release(v2); return hres2; } } if(r) *r = jsval_obj(jsdisp_addref(jsthis)); return S_OK; }
static HRESULT Function_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { FunctionInstance *function = function_from_jsdisp(jsthis); call_frame_t *frame; TRACE("\n"); for(frame = ctx->call_ctx; frame; frame = frame->prev_frame) { if(frame->function_instance == &function->dispex) { *r = jsval_obj(jsdisp_addref(frame->arguments_obj)); return S_OK; } } *r = jsval_null(); return S_OK; }
static HRESULT Function_arguments(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { FunctionInstance *function = (FunctionInstance*)jsthis->u.jsdisp; HRESULT hres = S_OK; TRACE("\n"); switch(flags) { case DISPATCH_PROPERTYGET: { *r = function->arguments ? jsval_obj(jsdisp_addref(function->arguments)) : jsval_null(); break; } case DISPATCH_PROPERTYPUT: break; default: FIXME("unimplemented flags %x\n", flags); hres = E_NOTIMPL; } return hres; }
/* ECMA-262 3rd Edition 15.4.4.11 */ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) { jsdisp_t *jsthis, *cmp_func = NULL; VARIANT *vtab, **sorttab = NULL; DWORD length; DWORD i; HRESULT hres = S_OK; TRACE("\n"); hres = get_length(ctx, vthis, ei, &jsthis, &length); if(FAILED(hres)) return hres; if(arg_cnt(dp) > 1) { WARN("invalid arg_cnt %d\n", arg_cnt(dp)); return E_FAIL; } if(arg_cnt(dp) == 1) { VARIANT *arg = get_arg(dp, 0); if(V_VT(arg) != VT_DISPATCH) { WARN("arg is not dispatch\n"); return E_FAIL; } cmp_func = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg)); if(!cmp_func || !is_class(cmp_func, JSCLASS_FUNCTION)) { WARN("cmp_func is not a function\n"); if(cmp_func) jsdisp_release(cmp_func); return E_FAIL; } } if(!length) { if(cmp_func) jsdisp_release(cmp_func); if(retv) { jsdisp_addref(jsthis); var_set_jsdisp(retv, jsthis); } return S_OK; } vtab = heap_alloc_zero(length * sizeof(VARIANT)); if(vtab) { for(i=0; i<length; i++) { hres = jsdisp_get_idx(jsthis, i, vtab+i, ei); if(hres == DISP_E_UNKNOWNNAME) { V_VT(vtab+i) = VT_EMPTY; hres = S_OK; } else if(FAILED(hres)) { WARN("Could not get elem %d: %08x\n", i, hres); break; } } }else { hres = E_OUTOFMEMORY; } if(SUCCEEDED(hres)) { sorttab = heap_alloc(length*2*sizeof(VARIANT*)); if(!sorttab) hres = E_OUTOFMEMORY; } /* merge-sort */ if(SUCCEEDED(hres)) { VARIANT *tmpv, **tmpbuf; INT cmp; tmpbuf = sorttab + length; for(i=0; i < length; i++) sorttab[i] = vtab+i; for(i=0; i < length/2; i++) { hres = sort_cmp(ctx, cmp_func, sorttab[2*i+1], sorttab[2*i], ei, &cmp); if(FAILED(hres)) break; if(cmp < 0) { tmpv = sorttab[2*i]; sorttab[2*i] = sorttab[2*i+1]; sorttab[2*i+1] = tmpv; } } if(SUCCEEDED(hres)) { DWORD k, a, b, bend; for(k=2; k < length; k *= 2) { for(i=0; i+k < length; i += 2*k) { a = b = 0; if(i+2*k <= length) bend = k; else bend = length - (i+k); memcpy(tmpbuf, sorttab+i, k*sizeof(VARIANT*)); while(a < k && b < bend) { hres = sort_cmp(ctx, cmp_func, tmpbuf[a], sorttab[i+k+b], ei, &cmp); if(FAILED(hres)) break; if(cmp < 0) { sorttab[i+a+b] = tmpbuf[a]; a++; }else { sorttab[i+a+b] = sorttab[i+k+b]; b++; } } if(FAILED(hres)) break; if(a < k) memcpy(sorttab+i+a+b, tmpbuf+a, (k-a)*sizeof(VARIANT*)); } if(FAILED(hres)) break; } } for(i=0; SUCCEEDED(hres) && i < length; i++) hres = jsdisp_propput_idx(jsthis, i, sorttab[i], ei); } if(vtab) { for(i=0; i < length; i++) VariantClear(vtab+i); heap_free(vtab); } heap_free(sorttab); if(cmp_func) jsdisp_release(cmp_func); if(FAILED(hres)) return hres; if(retv) { jsdisp_addref(jsthis); var_set_jsdisp(retv, jsthis); } return S_OK; }
/* ECMA-262 3rd Edition 15.4.4.11 */ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis, *cmp_func = NULL; jsval_t *vtab, **sorttab = NULL; DWORD length; DWORD i; HRESULT hres = S_OK; TRACE("\n"); hres = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres)) return hres; if(argc > 1) { WARN("invalid arg_cnt %d\n", argc); return E_FAIL; } if(argc == 1) { if(!is_object_instance(argv[0])) { WARN("arg is not dispatch\n"); return E_FAIL; } cmp_func = iface_to_jsdisp((IUnknown*)get_object(argv[0])); if(!cmp_func || !is_class(cmp_func, JSCLASS_FUNCTION)) { WARN("cmp_func is not a function\n"); if(cmp_func) jsdisp_release(cmp_func); return E_FAIL; } } if(!length) { if(cmp_func) jsdisp_release(cmp_func); if(r) *r = jsval_obj(jsdisp_addref(jsthis)); return S_OK; } vtab = heap_alloc_zero(length * sizeof(*vtab)); if(vtab) { for(i=0; i<length; i++) { hres = jsdisp_get_idx(jsthis, i, vtab+i); if(hres == DISP_E_UNKNOWNNAME) { vtab[i] = jsval_undefined(); hres = S_OK; } else if(FAILED(hres)) { WARN("Could not get elem %d: %08x\n", i, hres); break; } } }else { hres = E_OUTOFMEMORY; } if(SUCCEEDED(hres)) { sorttab = heap_alloc(length*2*sizeof(*sorttab)); if(!sorttab) hres = E_OUTOFMEMORY; } /* merge-sort */ if(SUCCEEDED(hres)) { jsval_t *tmpv, **tmpbuf; INT cmp; tmpbuf = sorttab + length; for(i=0; i < length; i++) sorttab[i] = vtab+i; for(i=0; i < length/2; i++) { hres = sort_cmp(ctx, cmp_func, *sorttab[2*i+1], *sorttab[2*i], &cmp); if(FAILED(hres)) break; if(cmp < 0) { tmpv = sorttab[2*i]; sorttab[2*i] = sorttab[2*i+1]; sorttab[2*i+1] = tmpv; } } if(SUCCEEDED(hres)) { DWORD k, a, b, bend; for(k=2; k < length; k *= 2) { for(i=0; i+k < length; i += 2*k) { a = b = 0; if(i+2*k <= length) bend = k; else bend = length - (i+k); memcpy(tmpbuf, sorttab+i, k*sizeof(jsval_t*)); while(a < k && b < bend) { hres = sort_cmp(ctx, cmp_func, *tmpbuf[a], *sorttab[i+k+b], &cmp); if(FAILED(hres)) break; if(cmp < 0) { sorttab[i+a+b] = tmpbuf[a]; a++; }else { sorttab[i+a+b] = sorttab[i+k+b]; b++; } } if(FAILED(hres)) break; if(a < k) memcpy(sorttab+i+a+b, tmpbuf+a, (k-a)*sizeof(jsval_t*)); } if(FAILED(hres)) break; } } for(i=0; SUCCEEDED(hres) && i < length; i++) hres = jsdisp_propput_idx(jsthis, i, *sorttab[i]); } if(vtab) { for(i=0; i < length; i++) jsval_release(vtab[i]); heap_free(vtab); } heap_free(sorttab); if(cmp_func) jsdisp_release(cmp_func); if(FAILED(hres)) return hres; if(r) *r = jsval_obj(jsdisp_addref(jsthis)); return S_OK; }