/* ECMA-262 3rd Edition 15.4.4.5 */ static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; DWORD length; HRESULT hres; TRACE("\n"); hres = get_length(ctx, vthis, &jsthis, &length); if(FAILED(hres)) return hres; if(argc) { const WCHAR *sep; jsstr_t *sep_str; hres = to_flat_string(ctx, argv[0], &sep_str, &sep); if(FAILED(hres)) return hres; hres = array_join(ctx, jsthis, length, sep, r); jsstr_release(sep_str); }else { hres = array_join(ctx, jsthis, length, default_separatorW, r); } return hres; }
static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *search_jsstr, *jsstr; const WCHAR *search_str, *str; int length, pos = 0; INT ret = -1; HRESULT hres; TRACE("\n"); hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); if(FAILED(hres)) return hres; length = jsstr_length(jsstr); if(!argc) { if(r) *r = jsval_number(-1); jsstr_release(jsstr); return S_OK; } hres = to_flat_string(ctx, argv[0], &search_jsstr, &search_str); if(FAILED(hres)) { jsstr_release(jsstr); return hres; } if(argc >= 2) { double d; hres = to_integer(ctx, argv[1], &d); if(SUCCEEDED(hres) && d > 0.0) pos = is_int32(d) ? min(length, d) : length; } if(SUCCEEDED(hres)) { const WCHAR *ptr; ptr = strstrW(str+pos, search_str); if(ptr) ret = ptr - str; else ret = -1; } jsstr_release(search_jsstr); jsstr_release(jsstr); if(FAILED(hres)) return hres; if(r) *r = jsval_number(ret); return S_OK; }
static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, jsstr_t **input, match_state_t **result, BOOL *ret) { RegExpInstance *regexp; match_state_t *match; DWORD last_index = 0; const WCHAR *string; jsstr_t *jsstr; HRESULT hres; if(!is_vclass(jsthis, JSCLASS_REGEXP)) { FIXME("Not a RegExp\n"); return E_NOTIMPL; } regexp = regexp_from_vdisp(jsthis); hres = to_flat_string(ctx, arg, &jsstr, &string); if(FAILED(hres)) return hres; if(regexp->jsregexp->flags & REG_GLOB) { if(regexp->last_index < 0) { jsstr_release(jsstr); set_last_index(regexp, 0); *ret = FALSE; if(input) *input = jsstr_empty(); return S_OK; } last_index = regexp->last_index; } match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, string+last_index); if(!match) { jsstr_release(jsstr); return E_OUTOFMEMORY; } hres = regexp_match_next(ctx, ®exp->dispex, REM_RESET_INDEX, jsstr, &match); if(FAILED(hres)) { jsstr_release(jsstr); return hres; } *result = match; *ret = hres == S_OK; if(input) *input = jsstr; else jsstr_release(jsstr); return S_OK; }
static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *ret_str, *str; const WCHAR *ptr, *buf; DWORD len = 0; WCHAR *ret; HRESULT hres; TRACE("\n"); if(!argc) { if(r) *r = jsval_string(jsstr_undefined()); return S_OK; } hres = to_flat_string(ctx, argv[0], &str, &buf); if(FAILED(hres)) return hres; for(ptr = buf; *ptr; ptr++) { if(*ptr > 0xff) len += 6; else if(is_ecma_nonblank(*ptr)) len++; else len += 3; } ret = jsstr_alloc_buf(len, &ret_str); if(!ret) { jsstr_release(str); return E_OUTOFMEMORY; } len = 0; for(ptr = buf; *ptr; ptr++) { if(*ptr > 0xff) { ret[len++] = '%'; ret[len++] = 'u'; ret[len++] = int_to_char(*ptr >> 12); ret[len++] = int_to_char((*ptr >> 8) & 0xf); ret[len++] = int_to_char((*ptr >> 4) & 0xf); ret[len++] = int_to_char(*ptr & 0xf); } else if(is_ecma_nonblank(*ptr))
static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t * progid_str; const WCHAR *progid; IDispatch *disp; IUnknown *obj; HRESULT hres; TRACE("\n"); if(flags != DISPATCH_CONSTRUCT) { FIXME("unsupported flags %x\n", flags); return E_NOTIMPL; } if(ctx->safeopt != (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER) && ctx->safeopt != INTERFACE_USES_DISPEX) { FIXME("Unsupported safeopt %x\n", ctx->safeopt); return E_NOTIMPL; } if(argc != 1) { FIXME("unsupported argc %d\n", argc); return E_NOTIMPL; } hres = to_flat_string(ctx, argv[0], &progid_str, &progid); if(FAILED(hres)) return hres; obj = create_activex_object(ctx, progid); jsstr_release(progid_str); if(!obj) return throw_generic_error(ctx, JS_E_CANNOT_CREATE_OBJ, NULL); hres = IUnknown_QueryInterface(obj, &IID_IDispatch, (void**)&disp); IUnknown_Release(obj); if(FAILED(hres)) { FIXME("Object does not support IDispatch\n"); return E_NOTIMPL; } *r = jsval_disp(disp); return S_OK; }
/* ECMA-262 5.1 Edition 15.12.2 */ static HRESULT JSON_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { json_parse_ctx_t parse_ctx; const WCHAR *buf; jsstr_t *str; jsval_t ret; HRESULT hres; if(argc != 1) { FIXME("Unsupported args\n"); return E_INVALIDARG; } hres = to_flat_string(ctx, argv[0], &str, &buf); if(FAILED(hres)) return hres; TRACE("%s\n", debugstr_w(buf)); parse_ctx.ptr = buf; parse_ctx.end = buf + jsstr_length(str); parse_ctx.ctx = ctx; hres = parse_json_value(&parse_ctx, &ret); jsstr_release(str); if(FAILED(hres)) return hres; if(skip_spaces(&parse_ctx)) { FIXME("syntax error\n"); jsval_release(ret); return E_FAIL; } if(r) *r = ret; else jsval_release(ret); return S_OK; }
/* ECMA-262 3rd Edition 15.5.4.11 */ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { const WCHAR *str, *match_str = NULL, *rep_str = NULL; jsstr_t *rep_jsstr, *match_jsstr, *jsstr; jsdisp_t *rep_func = NULL, *regexp = NULL; match_state_t *match = NULL, last_match = {0}; strbuf_t ret = {NULL,0,0}; DWORD re_flags = REM_NO_CTX_UPDATE|REM_ALLOC_RESULT; DWORD rep_len=0; HRESULT hres = S_OK; TRACE("\n"); hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); if(FAILED(hres)) return hres; if(!argc) { if(r) *r = jsval_string(jsstr); else jsstr_release(jsstr); return S_OK; } if(is_object_instance(argv[0])) { regexp = iface_to_jsdisp(get_object(argv[0])); if(regexp && !is_class(regexp, JSCLASS_REGEXP)) { jsdisp_release(regexp); regexp = NULL; } } if(!regexp) { hres = to_flat_string(ctx, argv[0], &match_jsstr, &match_str); if(FAILED(hres)) { jsstr_release(jsstr); return hres; } } if(argc >= 2) { if(is_object_instance(argv[1])) { rep_func = iface_to_jsdisp(get_object(argv[1])); if(rep_func && !is_class(rep_func, JSCLASS_FUNCTION)) { jsdisp_release(rep_func); rep_func = NULL; } } if(!rep_func) { hres = to_flat_string(ctx, argv[1], &rep_jsstr, &rep_str); if(SUCCEEDED(hres)) rep_len = jsstr_length(rep_jsstr); } } if(SUCCEEDED(hres)) { const WCHAR *ecp = str; while(1) { if(regexp) { hres = regexp_match_next(ctx, regexp, re_flags, jsstr, &match); re_flags = (re_flags | REM_CHECK_GLOBAL) & (~REM_ALLOC_RESULT); if(hres == S_FALSE) { hres = S_OK; break; } if(FAILED(hres)) break; last_match.cp = match->cp; last_match.match_len = match->match_len; } else { if(re_flags & REM_ALLOC_RESULT) { re_flags &= ~REM_ALLOC_RESULT; match = &last_match; match->cp = str; } match->cp = strstrW(match->cp, match_str); if(!match->cp) break; match->match_len = jsstr_length(match_jsstr); match->cp += match->match_len; } hres = strbuf_append(&ret, ecp, match->cp-ecp-match->match_len); ecp = match->cp; if(FAILED(hres)) break; if(rep_func) { jsstr_t *cstr; hres = rep_call(ctx, rep_func, jsstr, str, match, &cstr); if(FAILED(hres)) break; hres = strbuf_append_jsstr(&ret, cstr); jsstr_release(cstr); if(FAILED(hres)) break; } else if(rep_str && regexp) { const WCHAR *ptr = rep_str, *ptr2; while((ptr2 = strchrW(ptr, '$'))) { hres = strbuf_append(&ret, ptr, ptr2-ptr); if(FAILED(hres)) break; switch(ptr2[1]) { case '$': hres = strbuf_append(&ret, ptr2, 1); ptr = ptr2+2; break; case '&': hres = strbuf_append(&ret, match->cp-match->match_len, match->match_len); ptr = ptr2+2; break; case '`': hres = strbuf_append(&ret, str, match->cp-str-match->match_len); ptr = ptr2+2; break; case '\'': hres = strbuf_append(&ret, ecp, (str+jsstr_length(jsstr))-ecp); ptr = ptr2+2; break; default: { DWORD idx; if(!isdigitW(ptr2[1])) { hres = strbuf_append(&ret, ptr2, 1); ptr = ptr2+1; break; } idx = ptr2[1] - '0'; if(isdigitW(ptr2[2]) && idx*10 + (ptr2[2]-'0') <= match->paren_count) { idx = idx*10 + (ptr[2]-'0'); ptr = ptr2+3; } else if(idx && idx <= match->paren_count) { ptr = ptr2+2; } else { hres = strbuf_append(&ret, ptr2, 1); ptr = ptr2+1; break; } if(match->parens[idx-1].index != -1) hres = strbuf_append(&ret, str+match->parens[idx-1].index, match->parens[idx-1].length); } } if(FAILED(hres)) break; } if(SUCCEEDED(hres)) hres = strbuf_append(&ret, ptr, (rep_str+rep_len)-ptr); if(FAILED(hres)) break; } else if(rep_str) { hres = strbuf_append(&ret, rep_str, rep_len); if(FAILED(hres)) break; } else { static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d'}; hres = strbuf_append(&ret, undefinedW, sizeof(undefinedW)/sizeof(WCHAR)); if(FAILED(hres)) break; } if(!regexp) break; else if(!match->match_len) match->cp++; } if(SUCCEEDED(hres)) hres = strbuf_append(&ret, ecp, str+jsstr_length(jsstr)-ecp); } if(rep_func) jsdisp_release(rep_func); if(rep_str) jsstr_release(rep_jsstr); if(match_str) jsstr_release(match_jsstr); if(regexp) heap_free(match); if(SUCCEEDED(hres) && last_match.cp && regexp) { jsstr_release(ctx->last_match); ctx->last_match = jsstr_addref(jsstr); ctx->last_match_index = last_match.cp-str-last_match.match_len; ctx->last_match_length = last_match.match_len; } if(regexp) jsdisp_release(regexp); jsstr_release(jsstr); if(SUCCEEDED(hres) && r) { jsstr_t *ret_str; ret_str = jsstr_alloc_len(ret.buf, ret.len); if(!ret_str) return E_OUTOFMEMORY; TRACE("= %s\n", debugstr_jsstr(ret_str)); *r = jsval_string(ret_str); } heap_free(ret.buf); return hres; }
/* ECMA-262 3rd Edition 15.5.4.8 */ static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { unsigned pos = 0, search_len, length; jsstr_t *search_jsstr, *jsstr; const WCHAR *search_str, *str; INT ret = -1; HRESULT hres; TRACE("\n"); hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); if(FAILED(hres)) return hres; if(!argc) { if(r) *r = jsval_number(-1); jsstr_release(jsstr); return S_OK; } hres = to_flat_string(ctx, argv[0], &search_jsstr, &search_str); if(FAILED(hres)) { jsstr_release(jsstr); return hres; } search_len = jsstr_length(search_jsstr); length = jsstr_length(jsstr); if(argc >= 2) { double d; hres = to_integer(ctx, argv[1], &d); if(SUCCEEDED(hres) && d > 0) pos = is_int32(d) ? min(length, d) : length; } else { pos = length; } if(SUCCEEDED(hres) && length >= search_len) { const WCHAR *ptr; for(ptr = str+min(pos, length-search_len); ptr >= str; ptr--) { if(!memcmp(ptr, search_str, search_len*sizeof(WCHAR))) { ret = ptr-str; break; } } } jsstr_release(search_jsstr); jsstr_release(jsstr); if(FAILED(hres)) return hres; if(r) *r = jsval_number(ret); return S_OK; }
static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { match_state_t match_result, *match_ptr = &match_result; DWORD length, i, match_len = 0; const WCHAR *ptr, *ptr2, *str, *match_str = NULL; unsigned limit = ~0u; jsdisp_t *array, *regexp = NULL; jsstr_t *jsstr, *match_jsstr, *tmp_str; HRESULT hres; TRACE("\n"); if(argc != 1 && argc != 2) { FIXME("unsupported argc %u\n", argc); return E_NOTIMPL; } hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); if(FAILED(hres)) return hres; length = jsstr_length(jsstr); if(argc > 1 && !is_undefined(argv[1])) { hres = to_uint32(ctx, argv[1], &limit); if(FAILED(hres)) { jsstr_release(jsstr); return hres; } } if(is_object_instance(argv[0])) { regexp = iface_to_jsdisp(get_object(argv[0])); if(regexp) { if(!is_class(regexp, JSCLASS_REGEXP)) { jsdisp_release(regexp); regexp = NULL; } } } if(!regexp) { hres = to_flat_string(ctx, argv[0], &match_jsstr, &match_str); if(FAILED(hres)) { jsstr_release(jsstr); return hres; } match_len = jsstr_length(match_jsstr); if(!match_len) { jsstr_release(match_jsstr); match_str = NULL; } } hres = create_array(ctx, 0, &array); if(SUCCEEDED(hres)) { ptr = str; match_result.cp = str; for(i=0; i<limit; i++) { if(regexp) { hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, jsstr, &match_ptr); if(hres != S_OK) break; ptr2 = match_result.cp - match_result.match_len; } else if(match_str) { ptr2 = strstrW(ptr, match_str); if(!ptr2) break; } else { if(!*ptr) break; ptr2 = ptr+1; } tmp_str = jsstr_alloc_len(ptr, ptr2-ptr); if(!tmp_str) { hres = E_OUTOFMEMORY; break; } hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str)); jsstr_release(tmp_str); if(FAILED(hres)) break; if(regexp) ptr = match_result.cp; else if(match_str) ptr = ptr2 + match_len; else ptr++; } } if(SUCCEEDED(hres) && (match_str || regexp) && i<limit) { DWORD len = (str+length) - ptr; if(len || match_str) { tmp_str = jsstr_alloc_len(ptr, len); if(tmp_str) { hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str)); jsstr_release(tmp_str); } else { hres = E_OUTOFMEMORY; } } } if(regexp) jsdisp_release(regexp); if(match_str) jsstr_release(match_jsstr); jsstr_release(jsstr); if(SUCCEEDED(hres) && r) *r = jsval_obj(array); else jsdisp_release(array); return hres; }