/* ECMA-262 5.1 Edition 15.4.3.2 */ static HRESULT ArrayConstr_isArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *obj; TRACE("\n"); if(!argc || !is_object_instance(argv[0])) { if(r) *r = jsval_bool(FALSE); return S_OK; } obj = iface_to_jsdisp(get_object(argv[0])); if(r) *r = jsval_bool(obj && is_class(obj, JSCLASS_ARRAY)); if(obj) jsdisp_release(obj); return S_OK; }
static HRESULT maybe_to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *r) { jsdisp_t *obj; HRESULT hres; if(!is_object_instance(val) || !get_object(val) || !(obj = iface_to_jsdisp((IUnknown*)get_object(val)))) return jsval_copy(val, r); if(is_class(obj, JSCLASS_NUMBER)) { double n; hres = to_number(ctx, val, &n); jsdisp_release(obj); if(SUCCEEDED(hres)) *r = jsval_number(n); return hres; } if(is_class(obj, JSCLASS_STRING)) { jsstr_t *str; hres = to_string(ctx, val, &str); jsdisp_release(obj); if(SUCCEEDED(hres)) *r = jsval_string(str); return hres; } if(is_class(obj, JSCLASS_BOOLEAN)) { *r = jsval_bool(bool_obj_value(obj)); jsdisp_release(obj); return S_OK; } *r = jsval_obj(obj); return S_OK; }
HRESULT variant_to_jsval(VARIANT *var, jsval_t *r) { switch(V_VT(var)) { case VT_EMPTY: *r = jsval_undefined(); return S_OK; case VT_NULL: *r = jsval_null(); return S_OK; case VT_BOOL: *r = jsval_bool(V_BOOL(var)); return S_OK; case VT_I4: *r = jsval_number(V_I4(var)); return S_OK; case VT_R8: *r = jsval_number(V_R8(var)); return S_OK; case VT_BSTR: { jsstr_t *str; str = jsstr_alloc_len(V_BSTR(var), SysStringLen(V_BSTR(var))); if(!str) return E_OUTOFMEMORY; if(!V_BSTR(var)) str->length_flags |= JSSTR_FLAG_NULLBSTR; *r = jsval_string(str); return S_OK; } case VT_DISPATCH: { if(V_DISPATCH(var)) IDispatch_AddRef(V_DISPATCH(var)); *r = jsval_disp(V_DISPATCH(var)); return S_OK; } case VT_I2: *r = jsval_number(V_I2(var)); return S_OK; case VT_INT: *r = jsval_number(V_INT(var)); return S_OK; case VT_UNKNOWN: if(V_UNKNOWN(var)) { IDispatch *disp; HRESULT hres; hres = IUnknown_QueryInterface(V_UNKNOWN(var), &IID_IDispatch, (void**)&disp); if(SUCCEEDED(hres)) { *r = jsval_disp(disp); return S_OK; } } /* fall through */ default: return jsval_variant(r, var); } }
static HRESULT Enumerator_atEnd(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { EnumeratorInstance *This; if (!(This = enumerator_this(jsthis))) return throw_type_error(ctx, JS_E_ENUMERATOR_EXPECTED, NULL); TRACE("%d\n", This->atend); if (r) *r = jsval_bool(This->atend); return S_OK; }
static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { match_state_t *match; jsstr_t *undef_str; heap_pool_t *mark; BOOL b; HRESULT hres; TRACE("\n"); mark = heap_pool_mark(&ctx->tmp_heap); hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(undef_str = jsstr_undefined()), NULL, &match, &b); heap_pool_clear(mark); if(!argc) jsstr_release(undef_str); if(FAILED(hres)) return hres; if(r) *r = jsval_bool(b); return S_OK; }
/* ECMA-262 5.1 Edition 15.12.1.2 */ static HRESULT parse_json_value(json_parse_ctx_t *ctx, jsval_t *r) { HRESULT hres; switch(skip_spaces(ctx)) { /* JSONNullLiteral */ case 'n': if(!is_keyword(ctx, nullW)) break; *r = jsval_null(); return S_OK; /* JSONBooleanLiteral */ case 't': if(!is_keyword(ctx, trueW)) break; *r = jsval_bool(TRUE); return S_OK; case 'f': if(!is_keyword(ctx, falseW)) break; *r = jsval_bool(FALSE); return S_OK; /* JSONObject */ case '{': { WCHAR *prop_name; jsdisp_t *obj; jsval_t val; hres = create_object(ctx->ctx, NULL, &obj); if(FAILED(hres)) return hres; ctx->ptr++; if(skip_spaces(ctx) == '}') { ctx->ptr++; *r = jsval_obj(obj); return S_OK; } while(1) { if(*ctx->ptr != '"') break; hres = parse_json_string(ctx, &prop_name); if(FAILED(hres)) break; if(skip_spaces(ctx) != ':') { FIXME("missing ':'\n"); heap_free(prop_name); break; } ctx->ptr++; hres = parse_json_value(ctx, &val); if(SUCCEEDED(hres)) { hres = jsdisp_propput_name(obj, prop_name, val); jsval_release(val); } heap_free(prop_name); if(FAILED(hres)) break; if(skip_spaces(ctx) == '}') { ctx->ptr++; *r = jsval_obj(obj); return S_OK; } if(*ctx->ptr++ != ',') { FIXME("expected ','\n"); break; } skip_spaces(ctx); } jsdisp_release(obj); break; } /* JSONString */ case '"': { WCHAR *string; jsstr_t *str; hres = parse_json_string(ctx, &string); if(FAILED(hres)) return hres; /* FIXME: avoid reallocation */ str = jsstr_alloc(string); heap_free(string); if(!str) return E_OUTOFMEMORY; *r = jsval_string(str); return S_OK; } /* JSONArray */ case '[': { jsdisp_t *array; unsigned i = 0; jsval_t val; hres = create_array(ctx->ctx, 0, &array); if(FAILED(hres)) return hres; ctx->ptr++; if(skip_spaces(ctx) == ']') { ctx->ptr++; *r = jsval_obj(array); return S_OK; } while(1) { hres = parse_json_value(ctx, &val); if(FAILED(hres)) break; hres = jsdisp_propput_idx(array, i, val); jsval_release(val); if(FAILED(hres)) break; if(skip_spaces(ctx) == ']') { ctx->ptr++; *r = jsval_obj(array); return S_OK; } if(*ctx->ptr != ',') { FIXME("expected ','\n"); break; } ctx->ptr++; i++; } jsdisp_release(array); break; } /* JSONNumber */ default: { int sign = 1; double n; if(*ctx->ptr == '-') { sign = -1; ctx->ptr++; skip_spaces(ctx); } if(!isdigitW(*ctx->ptr)) break; if(*ctx->ptr == '0') { ctx->ptr++; n = 0; if(is_identifier_char(*ctx->ptr)) break; }else { hres = parse_decimal(&ctx->ptr, ctx->end, &n); if(FAILED(hres)) return hres; } *r = jsval_number(sign*n); return S_OK; } } FIXME("Syntax error at %s\n", debugstr_w(ctx->ptr)); return E_FAIL; }
HRESULT variant_to_jsval(VARIANT *var, jsval_t *r) { if(V_VT(var) == (VT_VARIANT|VT_BYREF)) var = V_VARIANTREF(var); switch(V_VT(var)) { case VT_EMPTY: *r = jsval_undefined(); return S_OK; case VT_NULL: *r = jsval_null(); return S_OK; case VT_BOOL: *r = jsval_bool(V_BOOL(var)); return S_OK; case VT_I4: *r = jsval_number(V_I4(var)); return S_OK; case VT_R8: *r = jsval_number(V_R8(var)); return S_OK; case VT_BSTR: { jsstr_t *str; if(V_BSTR(var)) { str = jsstr_alloc_len(V_BSTR(var), SysStringLen(V_BSTR(var))); if(!str) return E_OUTOFMEMORY; }else { str = jsstr_null_bstr(); } *r = jsval_string(str); return S_OK; } case VT_DISPATCH: { if(V_DISPATCH(var)) IDispatch_AddRef(V_DISPATCH(var)); *r = jsval_disp(V_DISPATCH(var)); return S_OK; } case VT_I2: *r = jsval_number(V_I2(var)); return S_OK; case VT_UI2: *r = jsval_number(V_UI2(var)); return S_OK; case VT_INT: *r = jsval_number(V_INT(var)); return S_OK; case VT_UI4: *r = jsval_number(V_UI4(var)); return S_OK; case VT_UI8: /* * Native doesn't support VT_UI8 here, but it's needed for IE9+ APIs * (native IE9 doesn't use jscript.dll for JavaScript). */ *r = jsval_number(V_UI8(var)); return S_OK; case VT_R4: *r = jsval_number(V_R4(var)); return S_OK; case VT_UNKNOWN: if(V_UNKNOWN(var)) { IDispatch *disp; HRESULT hres; hres = IUnknown_QueryInterface(V_UNKNOWN(var), &IID_IDispatch, (void**)&disp); if(SUCCEEDED(hres)) { *r = jsval_disp(disp); return S_OK; } }else { *r = jsval_disp(NULL); return S_OK; } /* fall through */ default: return jsval_variant(r, var); } }