static int jsstr_cmp_str(jsstr_t *jsstr, const WCHAR *str, unsigned len) { int ret; switch(jsstr_tag(jsstr)) { case JSSTR_INLINE: ret = memcmp(jsstr_as_inline(jsstr)->buf, str, len*sizeof(WCHAR)); return ret || jsstr_length(jsstr) == len ? ret : 1; case JSSTR_HEAP: ret = memcmp(jsstr_as_heap(jsstr)->buf, str, len*sizeof(WCHAR)); return ret || jsstr_length(jsstr) == len ? ret : 1; case JSSTR_ROPE: { jsstr_rope_t *rope = jsstr_as_rope(jsstr); unsigned left_len = jsstr_length(rope->left); ret = jsstr_cmp_str(rope->left, str, min(len, left_len)); if(ret || len <= left_len) return ret; return jsstr_cmp_str(rope->right, str+left_len, len-left_len); } } assert(0); return 0; }
static int ropes_cmp(jsstr_rope_t *left, jsstr_rope_t *right) { WCHAR left_buf[TMP_BUF_SIZE], right_buf[TMP_BUF_SIZE]; unsigned left_len = jsstr_length(&left->str); unsigned right_len = jsstr_length(&right->str); unsigned cmp_off = 0, cmp_size; int ret; /* FIXME: We can avoid temporary buffers here. */ while(cmp_off < min(left_len, right_len)) { cmp_size = min(left_len, right_len) - cmp_off; if(cmp_size > TMP_BUF_SIZE) cmp_size = TMP_BUF_SIZE; jsstr_rope_extract(left, cmp_off, cmp_size, left_buf); jsstr_rope_extract(right, cmp_off, cmp_size, right_buf); ret = memcmp(left_buf, right_buf, cmp_size); if(ret) return ret; cmp_off += cmp_size; } return left_len - right_len; }
static HRESULT strbuf_append_jsstr(strbuf_t *buf, jsstr_t *str) { if(!strbuf_ensure_size(buf, buf->len+jsstr_length(str))) return E_OUTOFMEMORY; jsstr_flush(str, buf->buf+buf->len); buf->len += jsstr_length(str); return S_OK; }
int jsstr_cmp(jsstr_t *str1, jsstr_t *str2) { int len1 = jsstr_length(str1); int len2 = jsstr_length(str2); int ret; ret = memcmp(str1->str, str2->str, min(len1, len2)*sizeof(WCHAR)); if(!ret) ret = len1 - len2; return ret; }
jsstr_t *jsstr_concat(jsstr_t *str1, jsstr_t *str2) { unsigned len1, len2; jsstr_t *ret; WCHAR *ptr; len1 = jsstr_length(str1); if(!len1) return jsstr_addref(str2); len2 = jsstr_length(str2); if(!len2) return jsstr_addref(str1); if(len1 + len2 >= JSSTR_SHORT_STRING_LENGTH) { unsigned depth, depth2; jsstr_rope_t *rope; depth = jsstr_is_rope(str1) ? jsstr_as_rope(str1)->depth : 0; depth2 = jsstr_is_rope(str2) ? jsstr_as_rope(str2)->depth : 0; if(depth2 > depth) depth = depth2; if(depth++ < JSSTR_MAX_ROPE_DEPTH) { if(len1+len2 > JSSTR_MAX_LENGTH) return NULL; rope = heap_alloc(sizeof(*rope)); if(!rope) return NULL; jsstr_init(&rope->str, len1+len2, JSSTR_ROPE); rope->left = jsstr_addref(str1); rope->right = jsstr_addref(str2); rope->depth = depth; return &rope->str; } } ptr = jsstr_alloc_buf(len1+len2, &ret); if(!ret) return NULL; jsstr_flush(str1, ptr); jsstr_flush(str2, ptr+len1); return ret; }
HRESULT create_regexp(script_ctx_t *ctx, jsstr_t *src, DWORD flags, jsdisp_t **ret) { RegExpInstance *regexp; HRESULT hres; TRACE("%s %x\n", debugstr_jsstr(src), flags); hres = alloc_regexp(ctx, NULL, ®exp); if(FAILED(hres)) return hres; regexp->str = jsstr_addref(src); regexp->last_index_val = jsval_number(0); regexp->jsregexp = regexp_new(ctx, &ctx->tmp_heap, regexp->str->str, jsstr_length(regexp->str), flags, FALSE); if(FAILED(hres)) { WARN("regexp_new failed\n"); jsdisp_release(®exp->dispex); return E_FAIL; } *ret = ®exp->dispex; return S_OK; }
static HRESULT RegExpConstr_rightContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { TRACE("\n"); switch(flags) { case DISPATCH_PROPERTYGET: { jsstr_t *ret; ret = jsstr_substr(ctx->last_match, ctx->last_match_index+ctx->last_match_length, jsstr_length(ctx->last_match) - ctx->last_match_index - ctx->last_match_length); if(!ret) return E_OUTOFMEMORY; *r = jsval_string(ret); break; } case DISPATCH_PROPERTYPUT: break; default: FIXME("unsupported flags\n"); return E_NOTIMPL; } return S_OK; }
/* ECMA-262 5.1 Edition 15.12.3 */ static HRESULT JSON_stringify(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { stringify_ctx_t stringify_ctx = {ctx, NULL,0,0, NULL,0,0, {0}}; HRESULT hres; TRACE("\n"); if(argc >= 2 && is_object_instance(argv[1])) { FIXME("Replacer %s not yet supported\n", debugstr_jsval(argv[1])); return E_NOTIMPL; } if(argc >= 3) { jsval_t space_val; hres = maybe_to_primitive(ctx, argv[2], &space_val); if(FAILED(hres)) return hres; if(is_number(space_val)) { double n = get_number(space_val); if(n >= 1) { int i, len; if(n > 10) n = 10; len = floor(n); for(i=0; i < len; i++) stringify_ctx.gap[i] = ' '; stringify_ctx.gap[len] = 0; } }else if(is_string(space_val)) { jsstr_t *space_str = get_string(space_val); size_t len = jsstr_length(space_str); if(len > 10) len = 10; jsstr_extract(space_str, 0, len, stringify_ctx.gap); } jsval_release(space_val); } hres = stringify(&stringify_ctx, argv[0]); if(SUCCEEDED(hres) && r) { assert(!stringify_ctx.stack_top); if(hres == S_OK) { jsstr_t *ret = jsstr_alloc_len(stringify_ctx.buf, stringify_ctx.buf_len); if(ret) *r = jsval_string(ret); else hres = E_OUTOFMEMORY; }else { *r = jsval_undefined(); } } heap_free(stringify_ctx.buf); heap_free(stringify_ctx.stack); return hres; }
static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *str; HRESULT hres; TRACE("\n"); hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(r) { jsstr_t *ret; WCHAR *buf; buf = jsstr_alloc_buf(jsstr_length(str), &ret); if(!buf) { jsstr_release(str); return E_OUTOFMEMORY; } jsstr_flush(str, buf); struprW(buf); *r = jsval_string(ret); } jsstr_release(str); return S_OK; }
/* 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, jsstr_length(sep_str), r); jsstr_release(sep_str); }else { hres = array_join(ctx, jsthis, length, default_separatorW, strlenW(default_separatorW), r); } return hres; }
/* ECMA-262 3rd Edition 9.2 */ HRESULT to_boolean(jsval_t val, BOOL *ret) { switch(jsval_type(val)) { case JSV_UNDEFINED: case JSV_NULL: *ret = FALSE; return S_OK; case JSV_OBJECT: *ret = get_object(val) != NULL; return S_OK; case JSV_STRING: *ret = jsstr_length(get_string(val)) != 0; return S_OK; case JSV_NUMBER: *ret = !isnan(get_number(val)) && get_number(val); return S_OK; case JSV_BOOL: *ret = get_bool(val); return S_OK; case JSV_VARIANT: FIXME("unimplemented for variant %s\n", debugstr_variant(get_variant(val))); return E_NOTIMPL; } assert(0); return E_FAIL; }
/* ECMA-262 3rd Edition 15.5.4.15 */ static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { INT start=0, end, length; jsstr_t *str; double d; HRESULT hres; TRACE("\n"); hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; length = jsstr_length(str); if(argc >= 1) { hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { jsstr_release(str); return hres; } if(d >= 0) start = is_int32(d) ? min(length, d) : length; } if(argc >= 2) { hres = to_integer(ctx, argv[1], &d); if(FAILED(hres)) { jsstr_release(str); return hres; } if(d >= 0) end = is_int32(d) ? min(length, d) : length; else end = 0; } else { end = length; } if(start > end) { INT tmp = start; start = end; end = tmp; } if(r) { jsstr_t *ret = jsstr_substr(str, start, end-start); if(ret) *r = jsval_string(ret); else hres = E_OUTOFMEMORY; } jsstr_release(str); return hres; }
static HRESULT String_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { StringInstance *string = (StringInstance*)jsthis; TRACE("%p\n", jsthis); *r = jsval_number(jsstr_length(string->str)); return S_OK; }
static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, unsigned argc, jsval_t *argv, jsval_t *r, const WCHAR *tagname, const WCHAR *attrname) { jsstr_t *str, *attr_value = NULL; HRESULT hres; hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(argc) { hres = to_string(ctx, argv[0], &attr_value); if(FAILED(hres)) { jsstr_release(str); return hres; } } else { attr_value = jsstr_undefined(); } if(r) { unsigned attrname_len = strlenW(attrname); unsigned tagname_len = strlenW(tagname); jsstr_t *ret; WCHAR *ptr; ptr = jsstr_alloc_buf(2*tagname_len + attrname_len + jsstr_length(attr_value) + jsstr_length(str) + 9, &ret); if(ptr) { *ptr++ = '<'; memcpy(ptr, tagname, tagname_len*sizeof(WCHAR)); ptr += tagname_len; *ptr++ = ' '; memcpy(ptr, attrname, attrname_len*sizeof(WCHAR)); ptr += attrname_len; *ptr++ = '='; *ptr++ = '"'; ptr += jsstr_flush(attr_value, ptr); *ptr++ = '"'; *ptr++ = '>'; ptr += jsstr_flush(str, ptr); *ptr++ = '<'; *ptr++ = '/'; memcpy(ptr, tagname, tagname_len*sizeof(WCHAR)); ptr += tagname_len; *ptr = '>'; *r = jsval_string(ret); } else { hres = E_OUTOFMEMORY; } } jsstr_release(attr_value); jsstr_release(str); return hres; }
const WCHAR *jsstr_rope_flatten(jsstr_rope_t *str) { WCHAR *buf; buf = heap_alloc((jsstr_length(&str->str)+1) * sizeof(WCHAR)); if(!buf) return NULL; jsstr_flush(str->left, buf); jsstr_flush(str->right, buf+jsstr_length(str->left)); buf[jsstr_length(&str->str)] = 0; /* Trasform to heap string */ jsstr_release(str->left); jsstr_release(str->right); str->str.length_flags |= JSSTR_FLAG_FLAT; return jsstr_as_heap(&str->str)->buf = buf; }
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; }
HRESULT jsval_to_variant(jsval_t val, VARIANT *retv) { switch(jsval_type(val)) { case JSV_UNDEFINED: V_VT(retv) = VT_EMPTY; return S_OK; case JSV_NULL: V_VT(retv) = VT_NULL; return S_OK; case JSV_OBJECT: V_VT(retv) = VT_DISPATCH; if(get_object(val)) IDispatch_AddRef(get_object(val)); V_DISPATCH(retv) = get_object(val); return S_OK; case JSV_STRING: { jsstr_t *str = get_string(val); V_VT(retv) = VT_BSTR; if(str->length_flags & JSSTR_FLAG_NULLBSTR) { V_BSTR(retv) = NULL; } else { V_BSTR(retv) = SysAllocStringLen(NULL, jsstr_length(str)); if(V_BSTR(retv)) jsstr_flush(str, V_BSTR(retv)); else return E_OUTOFMEMORY; } return S_OK; } case JSV_NUMBER: { double n = get_number(val); if(is_int32(n)) { V_VT(retv) = VT_I4; V_I4(retv) = n; } else { V_VT(retv) = VT_R8; V_R8(retv) = n; } return S_OK; } case JSV_BOOL: V_VT(retv) = VT_BOOL; V_BOOL(retv) = get_bool(val) ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; case JSV_VARIANT: V_VT(retv) = VT_EMPTY; return VariantCopy(retv, get_variant(val)); } assert(0); return E_FAIL; }
jsstr_t *jsstr_concat(jsstr_t *str1, jsstr_t *str2) { unsigned len1, len2; jsstr_t *ret; len1 = jsstr_length(str1); if(!len1) return jsstr_addref(str2); len2 = jsstr_length(str2); if(!len2) return jsstr_addref(str1); ret = jsstr_alloc_buf(len1+len2); if(!ret) return NULL; jsstr_flush(str1, ret->str); jsstr_flush(str2, ret->str+len1); return ret; }
/* ECMA-262 3rd Edition B.2.3 */ static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { int start=0, len, length; jsstr_t *str; double d; HRESULT hres; TRACE("\n"); hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; length = jsstr_length(str); if(argc >= 1) { hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { jsstr_release(str); return hres; } if(d >= 0) start = is_int32(d) ? min(length, d) : length; } if(argc >= 2) { hres = to_integer(ctx, argv[1], &d); if(FAILED(hres)) { jsstr_release(str); return hres; } if(d >= 0.0) len = is_int32(d) ? min(length-start, d) : length-start; else len = 0; } else { len = length-start; } hres = S_OK; if(r) { jsstr_t *ret = jsstr_substr(str, start, len); if(ret) *r = jsval_string(ret); else hres = E_OUTOFMEMORY; } jsstr_release(str); return hres; }
int jsstr_cmp(jsstr_t *str1, jsstr_t *str2) { unsigned len1 = jsstr_length(str1); unsigned len2 = jsstr_length(str2); const WCHAR *str; int ret; str = jsstr_try_flat(str2); if(str) { ret = jsstr_cmp_str(str1, str, min(len1, len2)); return ret || len1 == len2 ? ret : -1; } str = jsstr_try_flat(str1); if(str) { ret = jsstr_cmp_str(str2, str, min(len1, len2)); return ret || len1 == len2 ? -ret : 1; } return ropes_cmp(jsstr_as_rope(str1), jsstr_as_rope(str2)); }
jsstr_t *jsstr_concat(jsstr_t *str1, jsstr_t *str2) { unsigned len1, len2; jsstr_t *ret; len1 = jsstr_length(str1); if(!len1) return jsstr_addref(str2); len2 = jsstr_length(str2); if(!len2) return jsstr_addref(str1); ret = jsstr_alloc_buf(len1+len2); if(!ret) return NULL; memcpy(ret->str, str1->str, len1*sizeof(WCHAR)); memcpy(ret->str+len1, str2->str, len2*sizeof(WCHAR)); return ret; }
HRESULT create_regexp_var(script_ctx_t *ctx, jsval_t src_arg, jsval_t *flags_arg, jsdisp_t **ret) { unsigned flags, opt_len = 0; const WCHAR *opt = NULL; jsstr_t *src; HRESULT hres; if(is_object_instance(src_arg)) { jsdisp_t *obj; obj = iface_to_jsdisp((IUnknown*)get_object(src_arg)); if(obj) { if(is_class(obj, JSCLASS_REGEXP)) { RegExpInstance *regexp = (RegExpInstance*)obj; hres = create_regexp(ctx, regexp->str, regexp->jsregexp->flags, ret); jsdisp_release(obj); return hres; } jsdisp_release(obj); } } if(!is_string(src_arg)) { FIXME("src_arg = %s\n", debugstr_jsval(src_arg)); return E_NOTIMPL; } src = get_string(src_arg); if(flags_arg) { jsstr_t *opt_str; if(!is_string(*flags_arg)) { FIXME("unimplemented for %s\n", debugstr_jsval(*flags_arg)); return E_NOTIMPL; } opt_str = get_string(*flags_arg); opt = jsstr_flatten(opt_str); if(!opt) return E_OUTOFMEMORY; opt_len = jsstr_length(opt_str); } hres = parse_regexp_flags(opt, opt_len, &flags); if(FAILED(hres)) return hres; return create_regexp(ctx, src, flags, ret); }
static unsigned String_idx_length(jsdisp_t *jsdisp) { StringInstance *string = (StringInstance*)jsdisp; /* * NOTE: For invoke version < 2, indexed array is not implemented at all. * Newer jscript.dll versions implement it on string type, not class, * which is not how it should work according to spec. IE9 implements it * properly, but it uses its own JavaScript engine inside MSHTML. We * implement it here, but in the way IE9 and spec work. */ return string->dispex.ctx->version < 2 ? 0 : jsstr_length(string->str); }
static void jsstr_rope_extract(jsstr_rope_t *str, unsigned off, unsigned len, WCHAR *buf) { unsigned left_len = jsstr_length(str->left); if(left_len <= off) { jsstr_extract(str->right, off-left_len, len, buf); }else if(left_len >= len+off) { jsstr_extract(str->left, off, len, buf); }else { left_len -= off; jsstr_extract(str->left, off, left_len, buf); jsstr_extract(str->right, 0, len-left_len, buf+left_len); } }
static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, DWORD rem_flags, jsstr_t *str, match_state_t *ret) { HRESULT hres; hres = regexp_execute(regexp->jsregexp, ctx, &ctx->tmp_heap, str->str, jsstr_length(str), ret); if(FAILED(hres)) return hres; if(hres == S_FALSE) { if(rem_flags & REM_RESET_INDEX) set_last_index(regexp, 0); return S_FALSE; } if(!(rem_flags & REM_NO_CTX_UPDATE) && ctx->last_match != str) { jsstr_release(ctx->last_match); ctx->last_match = jsstr_addref(str); } if(!(rem_flags & REM_NO_CTX_UPDATE)) { DWORD i, n = min(sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0]), ret->paren_count); for(i=0; i < n; i++) { if(ret->parens[i].index == -1) { ctx->match_parens[i].index = 0; ctx->match_parens[i].length = 0; }else { ctx->match_parens[i].index = ret->parens[i].index; ctx->match_parens[i].length = ret->parens[i].length; } } if(n < sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0])) memset(ctx->match_parens+n, 0, sizeof(ctx->match_parens) - n*sizeof(ctx->match_parens[0])); } set_last_index(regexp, ret->cp-str->str); if(!(rem_flags & REM_NO_CTX_UPDATE)) { ctx->last_match_index = ret->cp-str->str-ret->match_len; ctx->last_match_length = ret->match_len; } return S_OK; }
static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r, const WCHAR *tagname) { unsigned tagname_len; jsstr_t *str, *ret; WCHAR *ptr; HRESULT hres; hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(!r) { jsstr_release(str); return S_OK; } tagname_len = strlenW(tagname); ptr = jsstr_alloc_buf(jsstr_length(str) + 2*tagname_len + 5, &ret); if(!ret) { jsstr_release(str); return E_OUTOFMEMORY; } *ptr++ = '<'; memcpy(ptr, tagname, tagname_len*sizeof(WCHAR)); ptr += tagname_len; *ptr++ = '>'; ptr += jsstr_flush(str, ptr); jsstr_release(str); *ptr++ = '<'; *ptr++ = '/'; memcpy(ptr, tagname, tagname_len*sizeof(WCHAR)); ptr += tagname_len; *ptr = '>'; *r = jsval_string(ret); return S_OK; }
/* ECMA-262 3rd Edition 15.5.4.5 */ static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *str; DWORD idx = 0; HRESULT hres; TRACE("\n"); hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(argc > 0) { double d; hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { jsstr_release(str); return hres; } if(!is_int32(d) || d < 0 || d >= jsstr_length(str)) { jsstr_release(str); if(r) *r = jsval_number(NAN); return S_OK; } idx = d; } if(r) { WCHAR c; jsstr_extract(str, idx, 1, &c); *r = jsval_number(c); } jsstr_release(str); return S_OK; }
/* ECMA-262 3rd Edition 15.5.4.5 */ static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsstr_t *str, *ret; INT pos = 0; HRESULT hres; TRACE("\n"); hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(argc) { double d; hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { jsstr_release(str); return hres; } pos = is_int32(d) ? d : -1; } if(!r) { jsstr_release(str); return S_OK; } if(0 <= pos && pos < jsstr_length(str)) { ret = jsstr_substr(str, pos, 1); if(!ret) return E_OUTOFMEMORY; } else { ret = jsstr_empty(); } *r = jsval_string(ret); 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; }
static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *argv, IDispatch **ret) { WCHAR *str = NULL, *ptr; unsigned len = 0, i = 0; bytecode_t *code; jsdisp_t *function; jsstr_t **params = NULL; int j = 0; HRESULT hres = S_OK; static const WCHAR function_anonymousW[] = {'f','u','n','c','t','i','o','n',' ','a','n','o','n','y','m','o','u','s','('}; static const WCHAR function_beginW[] = {')',' ','{','\n'}; static const WCHAR function_endW[] = {'\n','}',0}; if(argc) { params = heap_alloc(argc*sizeof(*params)); if(!params) return E_OUTOFMEMORY; if(argc > 2) len = (argc-2)*2; /* separating commas */ for(i=0; i < argc; i++) { hres = to_string(ctx, argv[i], params+i); if(FAILED(hres)) break; len += jsstr_length(params[i]); } } if(SUCCEEDED(hres)) { len += (sizeof(function_anonymousW) + sizeof(function_beginW) + sizeof(function_endW)) / sizeof(WCHAR); str = heap_alloc(len*sizeof(WCHAR)); if(str) { memcpy(str, function_anonymousW, sizeof(function_anonymousW)); ptr = str + sizeof(function_anonymousW)/sizeof(WCHAR); if(argc > 1) { while(1) { ptr += jsstr_flush(params[j], ptr); if(++j == argc-1) break; *ptr++ = ','; *ptr++ = ' '; } } memcpy(ptr, function_beginW, sizeof(function_beginW)); ptr += sizeof(function_beginW)/sizeof(WCHAR); if(argc) ptr += jsstr_flush(params[argc-1], ptr); memcpy(ptr, function_endW, sizeof(function_endW)); TRACE("%s\n", debugstr_w(str)); }else { hres = E_OUTOFMEMORY; } } while(i) jsstr_release(params[--i]); heap_free(params); if(FAILED(hres)) return hres; hres = compile_script(ctx, str, NULL, NULL, FALSE, FALSE, &code); heap_free(str); if(FAILED(hres)) return hres; if(code->global_code.func_cnt != 1 || code->global_code.var_cnt) { ERR("Invalid parser result!\n"); release_bytecode(code); return E_UNEXPECTED; } hres = create_source_function(ctx, code, code->global_code.funcs, NULL, &function); release_bytecode(code); if(FAILED(hres)) return hres; *ret = to_disp(function); return S_OK; }