diff --git a/dlls/jscript/Makefile.in b/dlls/jscript/Makefile.in index 807f1927def..27377f4113e 100644 --- a/dlls/jscript/Makefile.in +++ b/dlls/jscript/Makefile.in @@ -15,6 +15,7 @@ C_SRCS = \ global.c \ jscript.c \ jscript_main.c \ + jsstr.c \ jsutils.c \ lex.c \ math.c \ diff --git a/dlls/jscript/activex.c b/dlls/jscript/activex.c index 270fb6bbbf3..c7b4e0a0869 100644 --- a/dlls/jscript/activex.c +++ b/dlls/jscript/activex.c @@ -141,9 +141,9 @@ static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid) static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + jsstr_t * progid; IDispatch *disp; IUnknown *obj; - BSTR progid; HRESULT hres; TRACE("\n"); @@ -168,8 +168,8 @@ static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag if(FAILED(hres)) return hres; - obj = create_activex_object(ctx, progid); - SysFreeString(progid); + obj = create_activex_object(ctx, progid->str); + jsstr_release(progid); if(!obj) return throw_generic_error(ctx, JS_E_CANNOT_CREATE_OBJ, NULL); diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index 3f06fdbc6c8..e25588054c8 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -234,22 +234,18 @@ static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, const WCHAR *sep, jsval_t *r) { - BSTR *str_tab, ret = NULL; + jsstr_t **str_tab, *ret = NULL; jsval_t val; DWORD i; HRESULT hres = E_FAIL; if(!length) { - if(r) { - BSTR ret = SysAllocStringLen(NULL, 0); - if(!ret) - return E_OUTOFMEMORY; - *r = jsval_string(ret); - } + if(r) + *r = jsval_string(jsstr_empty()); return S_OK; } - str_tab = heap_alloc_zero(length * sizeof(BSTR)); + str_tab = heap_alloc_zero(length * sizeof(*str_tab)); if(!str_tab) return E_OUTOFMEMORY; @@ -276,20 +272,30 @@ static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, cons seplen = strlenW(sep); if(str_tab[0]) - len = SysStringLen(str_tab[0]); - for(i=1; i < length; i++) - len += seplen + SysStringLen(str_tab[i]); + len = jsstr_length(str_tab[0]); + for(i=1; i < length; i++) { + len += seplen; + if(str_tab[i]) + len += jsstr_length(str_tab[i]); + if(len > JSSTR_MAX_LENGTH) { + hres = E_OUTOFMEMORY; + break; + } + } - ret = SysAllocStringLen(NULL, len); + if(SUCCEEDED(hres)) + ret = jsstr_alloc_buf(len); if(ret) { - DWORD tmplen = 0; + unsigned tmplen; + + ptr = ret->str; if(str_tab[0]) { - tmplen = SysStringLen(str_tab[0]); - memcpy(ret, str_tab[0], tmplen*sizeof(WCHAR)); + tmplen = jsstr_length(str_tab[0]); + memcpy(ptr, str_tab[0]->str, tmplen*sizeof(WCHAR)); + ptr += tmplen; } - ptr = ret + tmplen; for(i=1; i < length; i++) { if(seplen) { memcpy(ptr, sep, seplen*sizeof(WCHAR)); @@ -297,8 +303,8 @@ static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, cons } if(str_tab[i]) { - tmplen = SysStringLen(str_tab[i]); - memcpy(ptr, str_tab[i], tmplen*sizeof(WCHAR)); + tmplen = jsstr_length(str_tab[i]); + memcpy(ptr, str_tab[i]->str, tmplen*sizeof(WCHAR)); ptr += tmplen; } } @@ -308,26 +314,20 @@ static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, cons } } - for(i=0; i < length; i++) - SysFreeString(str_tab[i]); + for(i=0; i < length; i++) { + if(str_tab[i]) + jsstr_release(str_tab[i]); + } heap_free(str_tab); if(FAILED(hres)) return hres; - TRACE("= %s\n", debugstr_w(ret)); - - if(r) { - if(!ret) { - ret = SysAllocStringLen(NULL, 0); - if(!ret) - return E_OUTOFMEMORY; - } - - *r = jsval_string(ret); - }else { - SysFreeString(ret); - } + TRACE("= %s\n", debugstr_jsstr(ret)); + if(r) + *r = ret ? jsval_string(ret) : jsval_string(jsstr_empty()); + else + jsstr_release(ret); return S_OK; } @@ -346,15 +346,15 @@ static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigne return hres; if(argc) { - BSTR sep; + jsstr_t *sep; hres = to_string(ctx, argv[0], &sep); if(FAILED(hres)) return hres; - hres = array_join(ctx, jsthis, length, sep, r); + hres = array_join(ctx, jsthis, length, sep->str, r); - SysFreeString(sep); + jsstr_release(sep); }else { hres = array_join(ctx, jsthis, length, default_separatorW, r); } @@ -653,7 +653,7 @@ static HRESULT sort_cmp(script_ctx_t *ctx, jsdisp_t *cmp_func, jsval_t v1, jsval else *cmp = d < -0.0 ? -1 : 0; }else { - BSTR x, y; + jsstr_t *x, *y; hres = to_string(ctx, v1, &x); if(FAILED(hres)) @@ -661,10 +661,10 @@ static HRESULT sort_cmp(script_ctx_t *ctx, jsdisp_t *cmp_func, jsval_t v1, jsval hres = to_string(ctx, v2, &y); if(SUCCEEDED(hres)) { - *cmp = strcmpW(x, y); - SysFreeString(y); + *cmp = jsstr_cmp(x, y); + jsstr_release(y); } - SysFreeString(x); + jsstr_release(x); if(FAILED(hres)) return hres; } diff --git a/dlls/jscript/bool.c b/dlls/jscript/bool.c index 4f328fe9856..9449ef872dc 100644 --- a/dlls/jscript/bool.c +++ b/dlls/jscript/bool.c @@ -51,11 +51,9 @@ static HRESULT Bool_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns return throw_type_error(ctx, JS_E_BOOLEAN_EXPECTED, NULL); if(r) { - BSTR val; - - if(bool->val) val = SysAllocString(trueW); - else val = SysAllocString(falseW); + jsstr_t *val; + val = jsstr_alloc(bool->val ? trueW : falseW); if(!val) return E_OUTOFMEMORY; diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 7099a6ac8b0..981ae963ca8 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -766,8 +766,18 @@ static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *st case LT_STRING: *str = compiler_alloc_bstr(ctx, literal->u.wstr); break; - case LT_DOUBLE: - return double_to_bstr(literal->u.dval, str); + case LT_DOUBLE: { + jsstr_t *jsstr; + HRESULT hres; + + hres = double_to_string(literal->u.dval, &jsstr); + if(FAILED(hres)) + return hres; + + *str = SysAllocStringLen(jsstr->str, jsstr_length(jsstr)); + jsstr_release(jsstr); + break; + } default: assert(0); } diff --git a/dlls/jscript/date.c b/dlls/jscript/date.c index 1d645a2d56d..6ce1f46ee90 100644 --- a/dlls/jscript/date.c +++ b/dlls/jscript/date.c @@ -467,7 +467,6 @@ static SYSTEMTIME create_systemtime(DOUBLE time) static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; static const WCHAR formatW[] = { '%','s',' ','%','s',' ','%','d',' ', '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ', 'U','T','C','%','c','%','0','2','d','%','0','2','d',' ','%','d','%','s',0 }; @@ -492,18 +491,14 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, BOOL formatAD = TRUE; BSTR week, month; - BSTR date_str; + jsstr_t *date_str; int len, size, year, day; DWORD lcid_en, week_id, month_id; WCHAR sign = '-'; if(isnan(time)) { - if(r) { - BSTR ret = SysAllocString(NaNW); - if(!ret) - return E_OUTOFMEMORY; - *r = jsval_string(ret); - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } @@ -559,7 +554,7 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, offset = -offset; } - date_str = SysAllocStringLen(NULL, len); + date_str = jsstr_alloc_buf(len); if(!date_str) { SysFreeString(week); SysFreeString(month); @@ -567,16 +562,16 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, } if(!show_offset) - sprintfW(date_str, formatNoOffsetW, week, month, day, + sprintfW(date_str->str, formatNoOffsetW, week, month, day, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time), year, formatAD?ADW:BCW); else if(offset) - sprintfW(date_str, formatW, week, month, day, + sprintfW(date_str->str, formatW, week, month, day, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time), sign, offset/60, offset%60, year, formatAD?ADW:BCW); else - sprintfW(date_str, formatUTCW, week, month, day, + sprintfW(date_str->str, formatUTCW, week, month, day, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time), year, formatAD?ADW:BCW); @@ -617,10 +612,9 @@ static HRESULT Date_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; SYSTEMTIME st; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; int date_len, time_len; TRACE("\n"); @@ -629,12 +623,8 @@ static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(r) { - BSTR ret = SysAllocString(NaNW); - if(!ret) - return E_OUTOFMEMORY; - *r = jsval_string(ret); - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } @@ -646,12 +636,12 @@ static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag if(r) { date_len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0); time_len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0); - date_str = SysAllocStringLen(NULL, date_len+time_len-1); + date_str = jsstr_alloc_buf(date_len+time_len-1); if(!date_str) return E_OUTOFMEMORY; - GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, date_len); - GetTimeFormatW(ctx->lcid, 0, &st, NULL, &date_str[date_len], time_len); - date_str[date_len-1] = ' '; + GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str->str, date_len); + GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str->str+date_len, time_len); + date_str->str[date_len-1] = ' '; *r = jsval_string(date_str); } @@ -675,7 +665,6 @@ static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; static const WCHAR formatADW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ', '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 }; static const WCHAR formatBCW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ','B','.','C','.',' ', @@ -694,7 +683,7 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsva BOOL formatAD = TRUE; BSTR week, month; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; int len, size, year, day; DWORD lcid_en, week_id, month_id; @@ -702,12 +691,8 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsva return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(r) { - BSTR ret = SysAllocString(NaNW); - if(!ret) - return E_OUTOFMEMORY; - *r = jsval_string(ret); - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } @@ -756,13 +741,13 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsva } while(day); day = date_from_time(date->time); - date_str = SysAllocStringLen(NULL, len); + date_str = jsstr_alloc_buf(len); if(!date_str) { SysFreeString(week); SysFreeString(month); return E_OUTOFMEMORY; } - sprintfW(date_str, formatAD?formatADW:formatBCW, week, day, month, year, + sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, day, month, year, (int)hour_from_time(date->time), (int)min_from_time(date->time), (int)sec_from_time(date->time)); @@ -792,7 +777,6 @@ static HRESULT Date_toGMTString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, /* ECMA-262 3rd Edition 15.9.5.3 */ static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; static const WCHAR formatADW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',0 }; static const WCHAR formatBCW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',' ','B','.','C','.',0 }; @@ -808,18 +792,14 @@ static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r) BOOL formatAD = TRUE; BSTR week, month; - BSTR date_str; + jsstr_t *date_str; DOUBLE time; int len, size, year, day; DWORD lcid_en, week_id, month_id; if(isnan(date->time)) { - if(r) { - BSTR ret = SysAllocString(NaNW); - if(!ret) - return E_OUTOFMEMORY; - *r = jsval_string(ret); - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } @@ -870,13 +850,13 @@ static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r) } while(day); day = date_from_time(time); - date_str = SysAllocStringLen(NULL, len); + date_str = jsstr_alloc_buf(len); if(!date_str) { SysFreeString(week); SysFreeString(month); return E_OUTOFMEMORY; } - sprintfW(date_str, formatAD?formatADW:formatBCW, week, month, day, year); + sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, month, day, year); SysFreeString(week); SysFreeString(month); @@ -901,13 +881,12 @@ static HRESULT Date_toDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; static const WCHAR formatW[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d', ' ','U','T','C','%','c','%','0','2','d','%','0','2','d',0 }; static const WCHAR formatUTCW[] = { '%','0','2','d',':','%','0','2','d', ':','%','0','2','d',' ','U','T','C',0 }; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; DOUBLE time; WCHAR sign; int offset; @@ -918,18 +897,15 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(r) { - BSTR ret = SysAllocString(NaNW); - if(!ret) - return E_OUTOFMEMORY; - *r = jsval_string(ret); - } + if(r) + *r = jsval_string(jsstr_nan()); + return S_OK; } time = local_time(date->time, date); if(r) { - date_str = SysAllocStringLen(NULL, 17); + date_str = jsstr_alloc_buf(17); if(!date_str) return E_OUTOFMEMORY; @@ -943,11 +919,11 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, else sign = '-'; if(offset) - sprintfW(date_str, formatW, (int)hour_from_time(time), + sprintfW(date_str->str, formatW, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time), sign, offset/60, offset%60); else - sprintfW(date_str, formatUTCW, (int)hour_from_time(time), + sprintfW(date_str->str, formatUTCW, (int)hour_from_time(time), (int)min_from_time(time), (int)sec_from_time(time)); *r = jsval_string(date_str); @@ -959,10 +935,9 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; SYSTEMTIME st; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; int len; TRACE("\n"); @@ -971,12 +946,8 @@ static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(r) { - BSTR ret = SysAllocString(NaNW); - if(!ret) - return E_OUTOFMEMORY; - *r = jsval_string(ret); - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } @@ -987,10 +958,10 @@ static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD if(r) { len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0); - date_str = SysAllocStringLen(NULL, len); + date_str = jsstr_alloc_buf(len); if(!date_str) return E_OUTOFMEMORY; - GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, len); + GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str->str, len); *r = jsval_string(date_str); } @@ -1001,10 +972,9 @@ static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - static const WCHAR NaNW[] = { 'N','a','N',0 }; SYSTEMTIME st; DateInstance *date; - BSTR date_str; + jsstr_t *date_str; int len; TRACE("\n"); @@ -1013,12 +983,8 @@ static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL); if(isnan(date->time)) { - if(r) { - BSTR ret = SysAllocString(NaNW); - if(!ret) - return E_OUTOFMEMORY; - *r = jsval_string(ret); - } + if(r) + *r = jsval_string(jsstr_nan()); return S_OK; } @@ -1029,10 +995,10 @@ static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD if(r) { len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0); - date_str = SysAllocStringLen(NULL, len); + date_str = jsstr_alloc_buf(len); if(!date_str) return E_OUTOFMEMORY; - GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str, len); + GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str->str, len); *r = jsval_string(date_str); } @@ -2099,7 +2065,7 @@ static HRESULT create_date(script_ctx_t *ctx, jsdisp_t *object_prototype, DOUBLE return S_OK; } -static inline HRESULT date_parse(BSTR input, double *ret) { +static inline HRESULT date_parse(jsstr_t *input_str, double *ret) { static const DWORD string_ids[] = { LOCALE_SMONTHNAME12, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME5, @@ -2117,10 +2083,13 @@ static inline HRESULT date_parse(BSTR input, double *ret) { BOOL set_offset = FALSE, set_era = FALSE, ad = TRUE, set_am = FALSE, am = TRUE; BOOL set_hour_adjust = TRUE; TIME_ZONE_INFORMATION tzi; + const WCHAR *input; DateInstance di; DWORD lcid_en; - input_len = SysStringLen(input); + input_len = jsstr_length(input_str); + input = input_str->str; + for(i=0; iname), debugstr_jsval(val)); + hres = jsval_copy(val, &prop->u.val); if(FAILED(hres)) { prop->u.val = jsval_undefined(); @@ -1408,7 +1410,7 @@ HRESULT jsdisp_delete_idx(jsdisp_t *obj, DWORD idx) return delete_prop(prop); } -HRESULT jsdisp_is_own_prop(jsdisp_t *obj, BSTR name, BOOL *ret) +HRESULT jsdisp_is_own_prop(jsdisp_t *obj, const WCHAR *name, BOOL *ret) { dispex_prop_t *prop; HRESULT hres; diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index d1d85fa12e8..a76c291325d 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -72,9 +72,9 @@ static HRESULT stack_push(exec_ctx_t *ctx, jsval_t v) static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str) { - BSTR v; + jsstr_t *v; - v = SysAllocString(str); + v = jsstr_alloc(str); if(!v) return E_OUTOFMEMORY; @@ -332,23 +332,37 @@ void exec_release(exec_ctx_t *ctx) heap_free(ctx); } -static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id) +static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id) { IDispatchEx *dispex; + jsdisp_t *jsdisp; HRESULT hres; - hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); - if(FAILED(hres)) { - TRACE("using IDispatch\n"); - - *id = 0; - return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id); + jsdisp = iface_to_jsdisp((IUnknown*)disp); + if(jsdisp) { + hres = jsdisp_get_id(jsdisp, name, flags, id); + jsdisp_release(jsdisp); + return hres; } *id = 0; - hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id); - IDispatchEx_Release(dispex); - return hres; + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + if(SUCCEEDED(hres)) { + BSTR str = name_bstr; + + if(!str) + str = SysAllocString(name); + if(str) + hres = IDispatchEx_GetDispID(dispex, str, make_grfdex(ctx, flags|fdexNameCaseSensitive), id); + else + hres = E_OUTOFMEMORY; + IDispatchEx_Release(dispex); + return hres; + } + + TRACE("using IDispatch\n"); + + return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id); } static inline BOOL var_is_null(const VARIANT *v) @@ -423,12 +437,7 @@ static HRESULT equal2_values(jsval_t lval, jsval_t rval, BOOL *ret) case JSV_OBJECT: return disp_cmp(get_object(lval), get_object(rval), ret); case JSV_STRING: - if(!get_string(lval)) - *ret = !SysStringLen(get_string(rval)); - else if(!get_string(rval)) - *ret = !SysStringLen(get_string(lval)); - else - *ret = !strcmpW(get_string(lval), get_string(rval)); + *ret = jsstr_eq(get_string(lval), get_string(rval)); break; case JSV_NUMBER: *ret = get_number(lval) == get_number(rval); @@ -452,7 +461,7 @@ static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t for(item = ctx->named_items; item; item = item->next) { if(item->flags & SCRIPTITEM_GLOBALMEMBERS) { - hres = disp_get_id(ctx, item->disp, identifier, 0, &id); + hres = disp_get_id(ctx, item->disp, identifier, identifier, 0, &id); if(SUCCEEDED(hres)) { if(ret) exprval_set_idref(ret, item->disp, id); @@ -478,7 +487,7 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re if(scope->jsobj) hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id); else - hres = disp_get_id(ctx, scope->obj, identifier, fdexNameImplicit, &id); + hres = disp_get_id(ctx, scope->obj, identifier, identifier, fdexNameImplicit, &id); if(SUCCEEDED(hres)) { exprval_set_idref(ret, scope->obj, id); return S_OK; @@ -608,12 +617,19 @@ static HRESULT interp_forin(exec_ctx_t *ctx) } if(name) { + jsstr_t *str; + + str = jsstr_alloc_len(name, SysStringLen(name)); + SysFreeString(name); + if(!str) + return E_OUTOFMEMORY; + jsval_release(val); stack_pop(ctx); stack_push(ctx, jsval_number(id)); /* safe, just after pop() */ - hres = disp_propput(ctx->script, var_obj, var_id, jsval_string(name)); - SysFreeString(name); + hres = disp_propput(ctx->script, var_obj, var_id, jsval_string(str)); + jsstr_release(str); if(FAILED(hres)) return hres; @@ -806,8 +822,8 @@ static HRESULT interp_array(exec_ctx_t *ctx) { jsval_t v, namev; IDispatch *obj; + jsstr_t *name; DISPID id; - BSTR name; HRESULT hres; TRACE("\n"); @@ -827,8 +843,8 @@ static HRESULT interp_array(exec_ctx_t *ctx) return hres; } - hres = disp_get_id(ctx->script, obj, name, 0, &id); - SysFreeString(name); + hres = disp_get_id(ctx->script, obj, name->str, NULL, 0, &id); + jsstr_release(name); if(SUCCEEDED(hres)) { hres = disp_propget(ctx->script, obj, id, &v); }else if(hres == DISP_E_UNKNOWNNAME) { @@ -857,7 +873,7 @@ static HRESULT interp_member(exec_ctx_t *ctx) if(FAILED(hres)) return hres; - hres = disp_get_id(ctx->script, obj, arg, 0, &id); + hres = disp_get_id(ctx->script, obj, arg, arg, 0, &id); if(SUCCEEDED(hres)) { hres = disp_propget(ctx->script, obj, id, &v); }else if(hres == DISP_E_UNKNOWNNAME) { @@ -877,7 +893,7 @@ static HRESULT interp_memberid(exec_ctx_t *ctx) const unsigned arg = get_op_uint(ctx, 0); jsval_t objv, namev; IDispatch *obj; - BSTR name; + jsstr_t *name; DISPID id; HRESULT hres; @@ -897,8 +913,8 @@ static HRESULT interp_memberid(exec_ctx_t *ctx) if(FAILED(hres)) return hres; - hres = disp_get_id(ctx->script, obj, name, arg, &id); - SysFreeString(name); + hres = disp_get_id(ctx->script, obj, name->str, NULL, arg, &id); + jsstr_release(name); if(FAILED(hres)) { IDispatch_Release(obj); if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) { @@ -1118,16 +1134,16 @@ static HRESULT interp_double(exec_ctx_t *ctx) /* ECMA-262 3rd Edition 7.8.4 */ static HRESULT interp_str(exec_ctx_t *ctx) { - const WCHAR *str = get_op_str(ctx, 0); - BSTR bstr; + const WCHAR *arg = get_op_str(ctx, 0); + jsstr_t *str; - TRACE("%s\n", debugstr_w(str)); + TRACE("%s\n", debugstr_w(arg)); - bstr = SysAllocString(str); - if(!bstr) + str = jsstr_alloc(arg); + if(!str) return E_OUTOFMEMORY; - return stack_push(ctx, jsval_string(bstr)); + return stack_push(ctx, jsval_string(str)); } /* ECMA-262 3rd Edition 7.8 */ @@ -1376,7 +1392,7 @@ static HRESULT interp_in(exec_ctx_t *ctx) jsval_t obj, v; DISPID id = 0; BOOL ret; - BSTR str; + jsstr_t *str; HRESULT hres; TRACE("\n"); @@ -1395,9 +1411,9 @@ static HRESULT interp_in(exec_ctx_t *ctx) return hres; } - hres = disp_get_id(ctx->script, get_object(obj), str, 0, &id); + hres = disp_get_id(ctx->script, get_object(obj), str->str, NULL, 0, &id); IDispatch_Release(get_object(obj)); - SysFreeString(str); + jsstr_release(str); if(SUCCEEDED(hres)) ret = TRUE; else if(hres == DISP_E_UNKNOWNNAME) @@ -1425,40 +1441,34 @@ static HRESULT add_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, jsval_t * } if(is_string(l) || is_string(r)) { - BSTR lstr = NULL, rstr = NULL; + jsstr_t *lstr, *rstr = NULL; - if(is_string(l)) - lstr = get_string(l); - else - hres = to_string(ctx, l, &lstr); + hres = to_string(ctx, l, &lstr); + if(SUCCEEDED(hres)) + hres = to_string(ctx, r, &rstr); if(SUCCEEDED(hres)) { - if(is_string(r)) - rstr = get_string(r); - else - hres = to_string(ctx, r, &rstr); + unsigned len1, len2; + jsstr_t *ret_str; + + len1 = jsstr_length(lstr); + len2 = jsstr_length(rstr); + + ret_str = jsstr_alloc_buf(len1+len2); + if(ret_str) { + if(len1) + memcpy(ret_str->str, lstr->str, len1*sizeof(WCHAR)); + if(len2) + memcpy(ret_str->str+len1, rstr->str, len2*sizeof(WCHAR)); + *ret = jsval_string(ret_str); + }else { + hres = E_OUTOFMEMORY; + } } - if(SUCCEEDED(hres)) { - int len1, len2; - BSTR ret_str; - - len1 = SysStringLen(lstr); - len2 = SysStringLen(rstr); - - ret_str = SysAllocStringLen(NULL, len1+len2); - if(len1) - memcpy(ret_str, lstr, len1*sizeof(WCHAR)); - if(len2) - memcpy(ret_str+len1, rstr, len2*sizeof(WCHAR)); - ret_str[len1+len2] = 0; - *ret = jsval_string(ret_str); - } - - if(!is_string(l)) - SysFreeString(lstr); - else if(!is_string(r)) - SysFreeString(rstr); + jsstr_release(lstr); + if(rstr) + jsstr_release(rstr); }else { double nl, nr; @@ -1577,7 +1587,7 @@ static HRESULT interp_delete(exec_ctx_t *ctx) jsval_t objv, namev; IDispatchEx *dispex; IDispatch *obj; - BSTR name; + jsstr_t *name; BOOL ret; HRESULT hres; @@ -1602,8 +1612,17 @@ static HRESULT interp_delete(exec_ctx_t *ctx) hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex); if(SUCCEEDED(hres)) { - hres = IDispatchEx_DeleteMemberByName(dispex, name, make_grfdex(ctx->script, fdexNameCaseSensitive)); - ret = TRUE; + BSTR bstr; + + bstr = SysAllocStringLen(name->str, jsstr_length(name)); + if(bstr) { + hres = IDispatchEx_DeleteMemberByName(dispex, bstr, make_grfdex(ctx->script, fdexNameCaseSensitive)); + SysFreeString(bstr); + ret = TRUE; + }else { + hres = E_OUTOFMEMORY; + } + IDispatchEx_Release(dispex); }else { hres = S_OK; @@ -1611,7 +1630,7 @@ static HRESULT interp_delete(exec_ctx_t *ctx) } IDispatch_Release(obj); - SysFreeString(name); + jsstr_release(name); if(FAILED(hres)) return hres; @@ -2063,9 +2082,9 @@ static HRESULT less_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL gre } if(is_string(l) && is_string(r)) { - *ret = (strcmpW(get_string(l), get_string(r)) < 0) ^ greater; - SysFreeString(get_string(l)); - SysFreeString(get_string(r)); + *ret = (jsstr_cmp(get_string(l), get_string(r)) < 0) ^ greater; + jsstr_release(get_string(l)); + jsstr_release(get_string(r)); return S_OK; } @@ -2456,7 +2475,6 @@ static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, function_code while(exec_ctx->ip != -1) { op = code->instrs[exec_ctx->ip].op; - TRACE("top %d\n", exec_ctx->top); hres = op_funcs[op](exec_ctx); if(FAILED(hres)) { TRACE("EXCEPTION\n"); diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index cc602f642de..e127bfc81d4 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -38,7 +38,7 @@ static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { jsdisp_t *jsthis; - BSTR name = NULL, msg = NULL, ret = NULL; + jsstr_t *name = NULL, *msg = NULL, *ret = NULL; jsval_t v; HRESULT hres; @@ -49,10 +49,12 @@ static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, jsthis = get_jsdisp(vthis); if(!jsthis || ctx->version < 2) { if(r) { - BSTR ret = SysAllocString(object_errorW); - if(!ret) + jsstr_t *str; + + str = jsstr_alloc(object_errorW); + if(!str) return E_OUTOFMEMORY; - *r = jsval_string(ret); + *r = jsval_string(str); } return S_OK; } @@ -66,10 +68,6 @@ static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, jsval_release(v); if(FAILED(hres)) return hres; - if(!*name) { - SysFreeString(name); - name = NULL; - } } hres = jsdisp_propget_name(jsthis, messageW, &v); @@ -77,40 +75,36 @@ static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, if(!is_undefined(v)) { hres = to_string(ctx, v, &msg); jsval_release(v); - if(SUCCEEDED(hres) && !*msg) { - SysFreeString(msg); - msg = NULL; - } } } if(SUCCEEDED(hres)) { - if(name && msg) { - DWORD name_len, msg_len; + unsigned name_len = name ? jsstr_length(name) : 0; + unsigned msg_len = msg ? jsstr_length(msg) : 0; - name_len = SysStringLen(name); - msg_len = SysStringLen(msg); - - ret = SysAllocStringLen(NULL, name_len + msg_len + 2); + if(name_len && msg_len) { + ret = jsstr_alloc_buf(name_len + msg_len + 2); if(ret) { - memcpy(ret, name, name_len*sizeof(WCHAR)); - ret[name_len] = ':'; - ret[name_len+1] = ' '; - memcpy(ret+name_len+2, msg, msg_len*sizeof(WCHAR)); + memcpy(ret->str, name->str, name_len*sizeof(WCHAR)); + ret->str[name_len] = ':'; + ret->str[name_len+1] = ' '; + memcpy(ret->str+name_len+2, msg->str, msg_len*sizeof(WCHAR)); } - }else if(name) { + }else if(name_len) { ret = name; name = NULL; - }else if(msg) { + }else if(msg_len) { ret = msg; msg = NULL; }else { - ret = SysAllocString(object_errorW); + ret = jsstr_alloc(object_errorW); } } - SysFreeString(msg); - SysFreeString(name); + if(msg) + jsstr_release(msg); + if(name) + jsstr_release(name); if(FAILED(hres)) return hres; if(!ret) @@ -119,7 +113,7 @@ static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, if(r) *r = jsval_string(ret); else - SysFreeString(ret); + jsstr_release(ret); return S_OK; } @@ -189,7 +183,7 @@ static HRESULT create_error(script_ctx_t *ctx, jsdisp_t *constr, UINT number, const WCHAR *msg, jsdisp_t **ret) { jsdisp_t *err; - BSTR str; + jsstr_t *str; HRESULT hres; hres = alloc_error(ctx, NULL, constr, &err); @@ -202,13 +196,13 @@ static HRESULT create_error(script_ctx_t *ctx, jsdisp_t *constr, return hres; } - if(msg) str = SysAllocString(msg); - else str = SysAllocStringLen(NULL, 0); + if(msg) str = jsstr_alloc(msg); + else str = jsstr_empty(); if(str) { hres = jsdisp_propput_name(err, messageW, jsval_string(str)); if(SUCCEEDED(hres)) hres = jsdisp_propput_name(err, descriptionW, jsval_string(str)); - SysFreeString(str); + jsstr_release(str); }else { hres = E_OUTOFMEMORY; } @@ -225,7 +219,7 @@ static HRESULT error_constr(script_ctx_t *ctx, WORD flags, unsigned argc, jsval_ jsval_t *r, jsdisp_t *constr) { jsdisp_t *err; UINT num = 0; - BSTR msg = NULL; + jsstr_t *msg = NULL; HRESULT hres; if(argc) { @@ -250,8 +244,9 @@ static HRESULT error_constr(script_ctx_t *ctx, WORD flags, unsigned argc, jsval_ switch(flags) { case INVOKE_FUNC: case DISPATCH_CONSTRUCT: - hres = create_error(ctx, constr, num, msg, &err); - SysFreeString(msg); + hres = create_error(ctx, constr, num, msg ? msg->str : NULL, &err); + if(msg) + jsstr_release(msg); if(FAILED(hres)) return hres; @@ -263,6 +258,8 @@ static HRESULT error_constr(script_ctx_t *ctx, WORD flags, unsigned argc, jsval_ return S_OK; default: + if(msg) + jsstr_release(msg); FIXME("unimplemented flags %x\n", flags); return E_NOTIMPL; } @@ -346,7 +343,7 @@ HRESULT init_error_constr(script_ctx_t *ctx, jsdisp_t *object_prototype) jsdisp_t *err; INT i; - BSTR str; + jsstr_t *str; HRESULT hres; for(i=0; i < sizeof(names)/sizeof(names[0]); i++) { @@ -354,14 +351,14 @@ HRESULT init_error_constr(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres; - str = SysAllocString(names[i]); + str = jsstr_alloc(names[i]); if(!str) { jsdisp_release(err); return E_OUTOFMEMORY; } hres = jsdisp_propput_name(err, nameW, jsval_string(str)); - SysFreeString(str); + jsstr_release(str); if(SUCCEEDED(hres)) hres = create_builtin_constructor(ctx, constr_val[i], names[i], NULL, PROPF_CONSTR|1, err, constr_addr[i]); diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 7a32de7cb79..4cac3d6665b 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -245,9 +245,9 @@ static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDis return invoke_source(ctx, function, this_obj, argc, argv, r); } -static HRESULT function_to_string(FunctionInstance *function, BSTR *ret) +static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret) { - BSTR str; + jsstr_t *str; static const WCHAR native_prefixW[] = {'\n','f','u','n','c','t','i','o','n',' '}; static const WCHAR native_suffixW[] = @@ -257,15 +257,15 @@ static HRESULT function_to_string(FunctionInstance *function, BSTR *ret) DWORD name_len; name_len = strlenW(function->name); - str = SysAllocStringLen(NULL, sizeof(native_prefixW) + name_len*sizeof(WCHAR) + sizeof(native_suffixW)); + str = jsstr_alloc_buf((sizeof(native_prefixW)+sizeof(native_suffixW))/sizeof(WCHAR) + name_len); if(!str) return E_OUTOFMEMORY; - memcpy(str, native_prefixW, sizeof(native_prefixW)); - memcpy(str + sizeof(native_prefixW)/sizeof(WCHAR), function->name, name_len*sizeof(WCHAR)); - memcpy(str + sizeof(native_prefixW)/sizeof(WCHAR) + name_len, native_suffixW, sizeof(native_suffixW)); + memcpy(str->str, native_prefixW, sizeof(native_prefixW)); + memcpy(str->str + sizeof(native_prefixW)/sizeof(WCHAR), function->name, name_len*sizeof(WCHAR)); + memcpy(str->str + sizeof(native_prefixW)/sizeof(WCHAR) + name_len, native_suffixW, sizeof(native_suffixW)); }else { - str = SysAllocStringLen(function->func_code->source, function->func_code->source_len); + str = jsstr_alloc_len(function->func_code->source, function->func_code->source_len); if(!str) return E_OUTOFMEMORY; } @@ -316,7 +316,7 @@ static HRESULT Function_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, jsval_t *r) { FunctionInstance *function; - BSTR str; + jsstr_t *str; HRESULT hres; TRACE("\n"); @@ -331,7 +331,7 @@ static HRESULT Function_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, if(r) *r = jsval_string(str); else - SysFreeString(str); + jsstr_release(str); return S_OK; } @@ -475,7 +475,7 @@ HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned case DISPATCH_PROPERTYGET: { HRESULT hres; - BSTR str; + jsstr_t *str; hres = function_to_string(function, &str); if(FAILED(hres)) @@ -689,7 +689,7 @@ static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *arg DWORD len = 0, l; bytecode_t *code; jsdisp_t *function; - BSTR *params = NULL; + jsstr_t **params = NULL; int i=0, j=0; HRESULT hres = S_OK; @@ -698,7 +698,7 @@ static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *arg static const WCHAR function_endW[] = {'\n','}',0}; if(argc) { - params = heap_alloc(argc*sizeof(BSTR)); + params = heap_alloc(argc*sizeof(*params)); if(!params) return E_OUTOFMEMORY; @@ -708,7 +708,7 @@ static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *arg hres = to_string(ctx, argv[i], params+i); if(FAILED(hres)) break; - len += SysStringLen(params[i]); + len += jsstr_length(params[i]); } } @@ -720,8 +720,8 @@ static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *arg ptr = str + sizeof(function_anonymousW)/sizeof(WCHAR); if(argc > 1) { while(1) { - l = SysStringLen(params[j]); - memcpy(ptr, params[j], l*sizeof(WCHAR)); + l = jsstr_length(params[j]); + memcpy(ptr, params[j]->str, l*sizeof(WCHAR)); ptr += l; if(++j == argc-1) break; @@ -732,8 +732,8 @@ static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *arg memcpy(ptr, function_beginW, sizeof(function_beginW)); ptr += sizeof(function_beginW)/sizeof(WCHAR); if(argc) { - l = SysStringLen(params[argc-1]); - memcpy(ptr, params[argc-1], l*sizeof(WCHAR)); + l = jsstr_length(params[argc-1]); + memcpy(ptr, params[argc-1]->str, l*sizeof(WCHAR)); ptr += l; } memcpy(ptr, function_endW, sizeof(function_endW)); @@ -745,7 +745,7 @@ static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *arg } while(--i >= 0) - SysFreeString(params[i]); + jsstr_release(params[i]); heap_free(params); if(FAILED(hres)) return hres; diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 1c0f72c9794..8809ddca7a3 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -277,20 +277,21 @@ static HRESULT JSGlobal_Enumerator(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - BSTR ret, str; + jsstr_t *ret_str, *str; const WCHAR *ptr; DWORD len = 0; + WCHAR *ret; HRESULT hres; TRACE("\n"); if(!argc) { if(r) { - ret = SysAllocString(undefinedW); - if(!ret) + ret_str = jsstr_alloc(undefinedW); + if(!ret_str) return E_OUTOFMEMORY; - *r = jsval_string(ret); + *r = jsval_string(ret_str); } return S_OK; @@ -300,7 +301,7 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u if(FAILED(hres)) return hres; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(*ptr > 0xff) len += 6; else if(is_ecma_nonblank(*ptr)) @@ -309,14 +310,15 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u len += 3; } - ret = SysAllocStringLen(NULL, len); - if(!ret) { - SysFreeString(str); + ret_str = jsstr_alloc_buf(len); + if(!ret_str) { + jsstr_release(str); return E_OUTOFMEMORY; } len = 0; - for(ptr=str; *ptr; ptr++) { + ret = ret_str->str; + for(ptr = str->str; *ptr; ptr++) { if(*ptr > 0xff) { ret[len++] = '%'; ret[len++] = 'u'; @@ -334,12 +336,12 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u } } - SysFreeString(str); + jsstr_release(str); if(r) - *r = jsval_string(ret); + *r = jsval_string(ret_str); else - SysFreeString(ret); + jsstr_release(ret_str); return S_OK; } @@ -370,7 +372,7 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns } TRACE("parsing %s\n", debugstr_jsval(argv[0])); - hres = compile_script(ctx, get_string(argv[0]), NULL, NULL, TRUE, FALSE, &code); + hres = compile_script(ctx, get_string(argv[0])->str, NULL, NULL, TRUE, FALSE, &code); if(FAILED(hres)) { WARN("parse (%s) failed: %08x\n", debugstr_jsval(argv[0]), hres); return throw_syntax_error(ctx, hres, NULL); @@ -445,8 +447,8 @@ static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, BOOL neg = FALSE, empty = TRUE; DOUBLE ret = 0.0; INT radix=0, i; + jsstr_t *str; WCHAR *ptr; - BSTR str; HRESULT hres; if(!argc) { @@ -472,7 +474,7 @@ static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, if(FAILED(hres)) return hres; - for(ptr = str; isspaceW(*ptr); ptr++); + for(ptr = str->str; isspaceW(*ptr); ptr++); switch(*ptr) { case '+': @@ -509,7 +511,7 @@ static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, ret = NAN; } - SysFreeString(str); + jsstr_release(str); if(neg) ret = -ret; @@ -523,9 +525,9 @@ static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag jsval_t *r) { LONGLONG d = 0, hlp; + jsstr_t *val_str; int exp = 0; WCHAR *str; - BSTR val_str = NULL; BOOL ret_nan = TRUE, positive = TRUE; HRESULT hres; @@ -539,7 +541,7 @@ static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag if(FAILED(hres)) return hres; - str = val_str; + str = val_str->str; while(isspaceW(*str)) str++; @@ -605,7 +607,7 @@ static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag else exp += e; } - SysFreeString(val_str); + jsstr_release(val_str); if(ret_nan) { if(r) @@ -629,19 +631,20 @@ static inline int hex_to_int(const WCHAR wch) { static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - BSTR ret, str; + jsstr_t *ret_str, *str; const WCHAR *ptr; DWORD len = 0; + WCHAR *ret; HRESULT hres; TRACE("\n"); if(!argc) { if(r) { - ret = SysAllocString(undefinedW); - if(!ret) + ret_str = jsstr_alloc(undefinedW); + if(!ret_str) return E_OUTOFMEMORY; - *r = jsval_string(ret); + *r = jsval_string(ret_str); } return S_OK; @@ -651,7 +654,7 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, if(FAILED(hres)) return hres; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(*ptr == '%') { if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1) ptr += 2; @@ -663,14 +666,15 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, len++; } - ret = SysAllocStringLen(NULL, len); - if(!ret) { - SysFreeString(str); + ret_str = jsstr_alloc_buf(len); + if(!ret_str) { + jsstr_release(str); return E_OUTOFMEMORY; } + ret = ret_str->str; len = 0; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(*ptr == '%') { if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1) { ret[len] = (hex_to_int(*(ptr+1))<<4) + hex_to_int(*(ptr+2)); @@ -691,12 +695,12 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, len++; } - SysFreeString(str); + jsstr_release(str); if(r) - *r = jsval_string(ret); + *r = jsval_string(ret_str); else - SysFreeString(ret); + jsstr_release(ret_str); return S_OK; } @@ -715,9 +719,9 @@ static HRESULT JSGlobal_ScriptEngine(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl TRACE("\n"); if(r) { - BSTR ret; + jsstr_t *ret; - ret = SysAllocString(JScriptW); + ret = jsstr_alloc(JScriptW); if(!ret) return E_OUTOFMEMORY; @@ -767,10 +771,10 @@ static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, vdisp_t *jsthis, WORD static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { + jsstr_t *str, *ret; const WCHAR *ptr; DWORD len = 0, i; char buf[4]; - BSTR str, ret; WCHAR *rptr; HRESULT hres; @@ -778,7 +782,7 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags if(!argc) { if(r) { - ret = SysAllocString(undefinedW); + ret = jsstr_alloc(undefinedW); if(!ret) return E_OUTOFMEMORY; @@ -792,13 +796,13 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags if(FAILED(hres)) return hres; - for(ptr = str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') { len++; }else { i = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL)*3; if(!i) { - SysFreeString(str); + jsstr_release(str); return throw_uri_error(ctx, JS_E_INVALID_URI_CHAR, NULL); } @@ -806,13 +810,14 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags } } - rptr = ret = SysAllocStringLen(NULL, len); + ret = jsstr_alloc_buf(len); if(!ret) { - SysFreeString(str); + jsstr_release(str); return E_OUTOFMEMORY; } + rptr = ret->str; - for(ptr = str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') { *rptr++ = *ptr; }else { @@ -825,20 +830,20 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags } } - TRACE("%s -> %s\n", debugstr_w(str), debugstr_w(ret)); - SysFreeString(str); + TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret)); + jsstr_release(str); if(r) *r = jsval_string(ret); else - SysFreeString(ret); + jsstr_release(ret); return S_OK; } static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - BSTR str, ret; + jsstr_t *str, *ret; WCHAR *ptr; int i, len = 0, val, res; char buf[4]; @@ -849,7 +854,7 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags if(!argc) { if(r) { - ret = SysAllocString(undefinedW); + ret = jsstr_alloc(undefinedW); if(!ret) return E_OUTOFMEMORY; @@ -863,7 +868,7 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags if(FAILED(hres)) return hres; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(*ptr != '%') { len++; }else { @@ -880,7 +885,7 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags } if(!res) { - SysFreeString(str); + jsstr_release(str); return throw_uri_error(ctx, JS_E_INVALID_URI_CODING, NULL); } @@ -889,16 +894,16 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags } } - ret = SysAllocStringLen(NULL, len); + ret = jsstr_alloc_buf(len); if(!ret) { - SysFreeString(str); + jsstr_release(str); return E_OUTOFMEMORY; } len = 0; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(*ptr != '%') { - ret[len] = *ptr; + ret->str[len] = *ptr; len++; }else { for(i=0; i<4; i++) { @@ -907,7 +912,7 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags val += hex_to_int(ptr[i*3+1])<<4; buf[i] = val; - res = MultiByteToWideChar(CP_UTF8, 0, buf, i+1, ret+len, 1); + res = MultiByteToWideChar(CP_UTF8, 0, buf, i+1, ret->str+len, 1); if(res) break; } @@ -917,20 +922,20 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags } } - TRACE("%s -> %s\n", debugstr_w(str), debugstr_w(ret)); - SysFreeString(str); + TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret)); + jsstr_release(str); if(r) *r = jsval_string(ret); else - SysFreeString(ret); + jsstr_release(ret); return S_OK; } static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - BSTR str, ret; + jsstr_t *str, *ret; char buf[4]; const WCHAR *ptr; DWORD len = 0, size, i; @@ -940,7 +945,7 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W if(!argc) { if(r) { - ret = SysAllocString(undefinedW); + ret = jsstr_alloc(undefinedW); if(!ret) return E_OUTOFMEMORY; @@ -954,45 +959,45 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W if(FAILED(hres)) return hres; - for(ptr=str; *ptr; ptr++) { + for(ptr = str->str; *ptr; ptr++) { if(is_uri_unescaped(*ptr)) len++; else { size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL); if(!size) { - SysFreeString(str); + jsstr_release(str); return throw_uri_error(ctx, JS_E_INVALID_URI_CHAR, NULL); } len += size*3; } } - ret = SysAllocStringLen(NULL, len); + ret = jsstr_alloc_buf(len); if(!ret) { - SysFreeString(str); + jsstr_release(str); return E_OUTOFMEMORY; } len = 0; - for(ptr=str; *ptr; ptr++) { - if(is_uri_unescaped(*ptr)) - ret[len++] = *ptr; - else { + for(ptr = str->str; *ptr; ptr++) { + if(is_uri_unescaped(*ptr)) { + ret->str[len++] = *ptr; + }else { size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, buf, sizeof(buf), NULL, NULL); for(i=0; i> 4); - ret[len++] = int_to_char(buf[i] & 0x0f); + ret->str[len++] = '%'; + ret->str[len++] = int_to_char((BYTE)buf[i] >> 4); + ret->str[len++] = int_to_char(buf[i] & 0x0f); } } } - SysFreeString(str); + jsstr_release(str); if(r) *r = jsval_string(ret); else - SysFreeString(ret); + jsstr_release(ret); return S_OK; } @@ -1000,7 +1005,7 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - BSTR str, ret; + jsstr_t *str, *ret; const WCHAR *ptr; WCHAR *out_ptr; DWORD len = 0; @@ -1010,7 +1015,7 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W if(!argc) { if(r) { - ret = SysAllocString(undefinedW); + ret = jsstr_alloc(undefinedW); if(!ret) return E_OUTOFMEMORY; @@ -1024,7 +1029,7 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W if(FAILED(hres)) return hres; - ptr = str; + ptr = str->str; while(*ptr) { if(*ptr == '%') { char octets[4]; @@ -1032,7 +1037,7 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W int i, size, num_bytes = 0; if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) { FIXME("Throw URIError: Invalid hex sequence\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } octets[0] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2)); @@ -1043,18 +1048,18 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W } if(num_bytes == 1 || num_bytes > 4) { FIXME("Throw URIError: Invalid initial UTF character\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } for(i = 1; i < num_bytes; ++i) { if(*ptr != '%'){ FIXME("Throw URIError: Incomplete UTF sequence\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) { FIXME("Throw URIError: Invalid hex sequence\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } octets[i] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2)); @@ -1064,7 +1069,7 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W num_bytes ? num_bytes : 1, NULL, 0); if(size == 0) { FIXME("Throw URIError: Invalid UTF sequence\n"); - SysFreeString(str); + jsstr_release(str); return E_FAIL; } len += size; @@ -1074,13 +1079,14 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W } } - out_ptr = ret = SysAllocStringLen(NULL, len); + ret = jsstr_alloc_buf(len); if(!ret) { - SysFreeString(str); + jsstr_release(str); return E_OUTOFMEMORY; } + out_ptr = ret->str; - ptr = str; + ptr = str->str; while(*ptr) { if(*ptr == '%') { char octets[4]; @@ -1106,12 +1112,12 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W } } - SysFreeString(str); + jsstr_release(str); if(r) *r = jsval_string(ret); else - SysFreeString(ret); + jsstr_release(ret); return S_OK; } diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 8dfa0c89baa..16deac427b1 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -72,7 +72,8 @@ void script_release(script_ctx_t *ctx) if(ctx->cc) release_cc(ctx->cc); jsheap_free(&ctx->tmp_heap); - SysFreeString(ctx->last_match); + if(ctx->last_match) + jsstr_release(ctx->last_match); ctx->jscaller->ctx = NULL; IServiceProvider_Release(&ctx->jscaller->IServiceProvider_iface); @@ -724,6 +725,8 @@ static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface) return hres; } + ctx->last_match = jsstr_empty(); + ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL); if(ctx) { script_release(ctx); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 214adb21df9..99726885190 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -34,6 +34,7 @@ #include "wine/list.h" typedef struct _jsval_t jsval_t; +typedef struct _jsstr_t jsstr_t; typedef struct _script_ctx_t script_ctx_t; typedef struct _exec_ctx_t exec_ctx_t; typedef struct _dispex_prop_t dispex_prop_t; @@ -54,6 +55,41 @@ void jsheap_clear(jsheap_t*) DECLSPEC_HIDDEN; void jsheap_free(jsheap_t*) DECLSPEC_HIDDEN; jsheap_t *jsheap_mark(jsheap_t*) DECLSPEC_HIDDEN; +static inline void *heap_alloc(size_t len) +{ + return HeapAlloc(GetProcessHeap(), 0, len); +} + +static inline void *heap_alloc_zero(size_t len) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); +} + +static inline void *heap_realloc(void *mem, size_t len) +{ + return HeapReAlloc(GetProcessHeap(), 0, mem, len); +} + +static inline BOOL heap_free(void *mem) +{ + return HeapFree(GetProcessHeap(), 0, mem); +} + +static inline LPWSTR heap_strdupW(LPCWSTR str) +{ + LPWSTR ret = NULL; + + if(str) { + DWORD size; + + size = (strlenW(str)+1)*sizeof(WCHAR); + ret = heap_alloc(size); + memcpy(ret, str, size); + } + + return ret; +} + typedef struct jsdisp_t jsdisp_t; extern HINSTANCE jscript_hinstance DECLSPEC_HIDDEN; @@ -219,7 +255,7 @@ HRESULT jsdisp_propget_name(jsdisp_t*,LPCWSTR,jsval_t*) DECLSPEC_HIDDEN; HRESULT jsdisp_get_idx(jsdisp_t*,DWORD,jsval_t*) DECLSPEC_HIDDEN; HRESULT jsdisp_get_id(jsdisp_t*,const WCHAR*,DWORD,DISPID*) DECLSPEC_HIDDEN; HRESULT jsdisp_delete_idx(jsdisp_t*,DWORD) DECLSPEC_HIDDEN; -HRESULT jsdisp_is_own_prop(jsdisp_t*,BSTR,BOOL*) DECLSPEC_HIDDEN; +HRESULT jsdisp_is_own_prop(jsdisp_t*,const WCHAR*,BOOL*) DECLSPEC_HIDDEN; HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD, jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; @@ -242,7 +278,7 @@ HRESULT create_math(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN; HRESULT create_array(script_ctx_t*,DWORD,jsdisp_t**) DECLSPEC_HIDDEN; HRESULT create_regexp(script_ctx_t*,const WCHAR *,int,DWORD,jsdisp_t**) DECLSPEC_HIDDEN; HRESULT create_regexp_var(script_ctx_t*,jsval_t,jsval_t*,jsdisp_t**) DECLSPEC_HIDDEN; -HRESULT create_string(script_ctx_t*,const WCHAR*,DWORD,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_string(script_ctx_t*,jsstr_t*,jsdisp_t**) DECLSPEC_HIDDEN; HRESULT create_bool(script_ctx_t*,BOOL,jsdisp_t**) DECLSPEC_HIDDEN; HRESULT create_number(script_ctx_t*,double,jsdisp_t**) DECLSPEC_HIDDEN; HRESULT create_vbarray(script_ctx_t*,SAFEARRAY*,jsdisp_t**) DECLSPEC_HIDDEN; @@ -259,14 +295,14 @@ HRESULT to_number(script_ctx_t*,jsval_t,double*) DECLSPEC_HIDDEN; HRESULT to_integer(script_ctx_t*,jsval_t,double*) DECLSPEC_HIDDEN; HRESULT to_int32(script_ctx_t*,jsval_t,INT*) DECLSPEC_HIDDEN; HRESULT to_uint32(script_ctx_t*,jsval_t,DWORD*) DECLSPEC_HIDDEN; -HRESULT to_string(script_ctx_t*,jsval_t,BSTR*) DECLSPEC_HIDDEN; +HRESULT to_string(script_ctx_t*,jsval_t,jsstr_t**) DECLSPEC_HIDDEN; HRESULT to_object(script_ctx_t*,jsval_t,IDispatch**) DECLSPEC_HIDDEN; HRESULT variant_change_type(script_ctx_t*,VARIANT*,VARIANT*,VARTYPE) DECLSPEC_HIDDEN; HRESULT decode_source(WCHAR*) DECLSPEC_HIDDEN; -HRESULT double_to_bstr(double,BSTR*) DECLSPEC_HIDDEN; +HRESULT double_to_string(double,jsstr_t**) DECLSPEC_HIDDEN; typedef struct named_item_t { IDispatch *disp; @@ -325,7 +361,7 @@ struct _script_ctx_t { IDispatch *host_global; - BSTR last_match; + jsstr_t *last_match; match_result_t match_parens[9]; DWORD last_match_index; DWORD last_match_length; @@ -383,7 +419,7 @@ HRESULT create_jscaller(script_ctx_t*) DECLSPEC_HIDDEN; HRESULT regexp_match_next(script_ctx_t*,jsdisp_t*,DWORD,const WCHAR*,DWORD,const WCHAR**,match_result_t**, DWORD*,DWORD*,match_result_t*) DECLSPEC_HIDDEN; HRESULT parse_regexp_flags(const WCHAR*,DWORD,DWORD*) DECLSPEC_HIDDEN; -HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,BSTR,jsval_t*) DECLSPEC_HIDDEN; +HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,jsstr_t*,jsval_t*) DECLSPEC_HIDDEN; static inline BOOL is_class(jsdisp_t *jsdisp, jsclass_t class) { @@ -475,38 +511,3 @@ static inline void unlock_module(void) { InterlockedDecrement(&module_ref); } - -static inline void *heap_alloc(size_t len) -{ - return HeapAlloc(GetProcessHeap(), 0, len); -} - -static inline void *heap_alloc_zero(size_t len) -{ - return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); -} - -static inline void *heap_realloc(void *mem, size_t len) -{ - return HeapReAlloc(GetProcessHeap(), 0, mem, len); -} - -static inline BOOL heap_free(void *mem) -{ - return HeapFree(GetProcessHeap(), 0, mem); -} - -static inline LPWSTR heap_strdupW(LPCWSTR str) -{ - LPWSTR ret = NULL; - - if(str) { - DWORD size; - - size = (strlenW(str)+1)*sizeof(WCHAR); - ret = heap_alloc(size); - memcpy(ret, str, size); - } - - return ret; -} diff --git a/dlls/jscript/jscript_main.c b/dlls/jscript/jscript_main.c index bc1aa6ae462..75e44c07168 100644 --- a/dlls/jscript/jscript_main.c +++ b/dlls/jscript/jscript_main.c @@ -140,7 +140,11 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hInstDLL); jscript_hinstance = hInstDLL; + if(!init_strings()) + return FALSE; break; + case DLL_PROCESS_DETACH: + free_strings(); } return TRUE; diff --git a/dlls/jscript/jsstr.c b/dlls/jscript/jsstr.c new file mode 100644 index 00000000000..3586dad0584 --- /dev/null +++ b/dlls/jscript/jsstr.c @@ -0,0 +1,96 @@ +/* + * Copyright 2012 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "jscript.h" + +#include "wine/debug.h" + +const char *debugstr_jsstr(jsstr_t *str) +{ + return debugstr_wn(str->str, jsstr_length(str)); +} + +jsstr_t *jsstr_alloc_buf(unsigned len) +{ + jsstr_t *ret; + + if(len > JSSTR_MAX_LENGTH) + return NULL; + + ret = heap_alloc(FIELD_OFFSET(jsstr_t, str[len+1])); + if(!ret) + return NULL; + + ret->length_flags = len << JSSTR_LENGTH_SHIFT; + ret->ref = 1; + ret->str[len] = 0; + return ret; +} + +jsstr_t *jsstr_alloc_len(const WCHAR *buf, unsigned len) +{ + jsstr_t *ret; + + ret = jsstr_alloc_buf(len); + if(ret) + memcpy(ret->str, buf, len*sizeof(WCHAR)); + + return ret; +} + +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; +} + +static jsstr_t *empty_str, *nan_str; + +jsstr_t *jsstr_nan(void) +{ + return jsstr_addref(nan_str); +} + +jsstr_t *jsstr_empty(void) +{ + return jsstr_addref(empty_str); +} + +BOOL init_strings(void) +{ + static const WCHAR NaNW[] = { 'N','a','N',0 }; + + if(!(empty_str = jsstr_alloc_buf(0))) + return FALSE; + if(!(nan_str = jsstr_alloc(NaNW))) + return FALSE; + return TRUE; +} + +void free_strings(void) +{ + jsstr_release(empty_str); + jsstr_release(nan_str); +} diff --git a/dlls/jscript/jsstr.h b/dlls/jscript/jsstr.h new file mode 100644 index 00000000000..48a1d8d1213 --- /dev/null +++ b/dlls/jscript/jsstr.h @@ -0,0 +1,70 @@ +/* + * Copyright 2012 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +struct _jsstr_t { + unsigned length_flags; + unsigned ref; + WCHAR str[1]; +}; + +#define JSSTR_LENGTH_SHIFT 4 +#define JSSTR_MAX_LENGTH (1 << (32-JSSTR_LENGTH_SHIFT)) +#define JSSTR_FLAGS_MASK ((1 << JSSTR_LENGTH_SHIFT)-1) + +#define JSSTR_FLAG_NULLBSTR 1 + +static unsigned inline jsstr_length(jsstr_t *str) +{ + return str->length_flags >> JSSTR_LENGTH_SHIFT; +} + +jsstr_t *jsstr_alloc_len(const WCHAR*,unsigned) DECLSPEC_HIDDEN; +jsstr_t *jsstr_alloc_buf(unsigned) DECLSPEC_HIDDEN; + +static inline jsstr_t *jsstr_alloc(const WCHAR *str) +{ + return jsstr_alloc_len(str, strlenW(str)); +} + +static inline void jsstr_release(jsstr_t *str) +{ + if(!--str->ref) + heap_free(str); +} + +static inline jsstr_t *jsstr_addref(jsstr_t *str) +{ + str->ref++; + return str; +} + +static inline BOOL jsstr_eq(jsstr_t *str1, jsstr_t *str2) +{ + unsigned len = jsstr_length(str1); + return len == jsstr_length(str2) && !memcmp(str1->str, str2->str, len*sizeof(WCHAR)); +} + +int jsstr_cmp(jsstr_t*,jsstr_t*) DECLSPEC_HIDDEN; + +jsstr_t *jsstr_nan(void) DECLSPEC_HIDDEN; +jsstr_t *jsstr_empty(void) DECLSPEC_HIDDEN; + +BOOL init_strings(void) DECLSPEC_HIDDEN; +void free_strings(void) DECLSPEC_HIDDEN; + +const char *debugstr_jsstr(jsstr_t*) DECLSPEC_HIDDEN; diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c index 2f5d19cdd7d..ac26ef37d42 100644 --- a/dlls/jscript/jsutils.c +++ b/dlls/jscript/jsutils.c @@ -69,7 +69,7 @@ const char *debugstr_jsval(const jsval_t v) case JSV_OBJECT: return wine_dbg_sprintf("obj(%p)", get_object(v)); case JSV_STRING: - return debugstr_w(get_string(v)); + return wine_dbg_sprintf("str(%s)", debugstr_jsstr(get_string(v))); case JSV_NUMBER: return wine_dbg_sprintf("%lf", get_number(v)); case JSV_BOOL: @@ -210,11 +210,6 @@ jsheap_t *jsheap_mark(jsheap_t *heap) return heap; } -static BSTR clone_bstr(BSTR str) -{ - return SysAllocStringLen(str, str ? SysStringLen(str) : 0); -} - void jsval_release(jsval_t val) { switch(jsval_type(val)) { @@ -223,7 +218,7 @@ void jsval_release(jsval_t val) IDispatch_Release(get_object(val)); break; case JSV_STRING: - SysFreeString(get_string(val)); + jsstr_release(get_string(val)); break; case JSV_VARIANT: VariantClear(get_variant(val)); @@ -266,10 +261,8 @@ HRESULT jsval_copy(jsval_t v, jsval_t *r) *r = v; return S_OK; case JSV_STRING: { - BSTR str = clone_bstr(get_string(v)); - if(!str) - return E_OUTOFMEMORY; - *r = jsval_string(str); + jsstr_addref(get_string(v)); + *r = v; return S_OK; } case JSV_VARIANT: @@ -299,15 +292,14 @@ HRESULT variant_to_jsval(VARIANT *var, jsval_t *r) *r = jsval_number(V_R8(var)); return S_OK; case VT_BSTR: { - BSTR str; + 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; - if(V_BSTR(var)) { - str = clone_bstr(V_BSTR(var)); - if(!str) - return E_OUTOFMEMORY; - }else { - str = NULL; - } *r = jsval_string(str); return S_OK; } @@ -343,16 +335,19 @@ HRESULT jsval_to_variant(jsval_t val, VARIANT *retv) IDispatch_AddRef(get_object(val)); V_DISPATCH(retv) = get_object(val); return S_OK; - case JSV_STRING: + case JSV_STRING: { + jsstr_t *str = get_string(val); + V_VT(retv) = VT_BSTR; - if(get_string(val)) { - V_BSTR(retv) = clone_bstr(get_string(val)); + if(str->length_flags & JSSTR_FLAG_NULLBSTR) { + V_BSTR(retv) = NULL; + }else { + V_BSTR(retv) = SysAllocStringLen(str->str, jsstr_length(str)); if(!V_BSTR(retv)) return E_OUTOFMEMORY; - }else { - V_BSTR(retv) = NULL; } return S_OK; + } case JSV_NUMBER: { double n = get_number(val); @@ -459,7 +454,7 @@ HRESULT to_boolean(jsval_t val, BOOL *ret) *ret = get_object(val) != NULL; return S_OK; case JSV_STRING: - *ret = get_string(val) && *get_string(val); + *ret = jsstr_length(get_string(val)) != 0; return S_OK; case JSV_NUMBER: *ret = !isnan(get_number(val)) && get_number(val); @@ -491,9 +486,9 @@ static int hex_to_int(WCHAR c) } /* ECMA-262 3rd Edition 9.3.1 */ -static HRESULT str_to_number(BSTR str, double *ret) +static HRESULT str_to_number(jsstr_t *str, double *ret) { - const WCHAR *ptr = str; + const WCHAR *ptr = str->str; BOOL neg = FALSE; DOUBLE d = 0.0; @@ -669,14 +664,14 @@ HRESULT to_uint32(script_ctx_t *ctx, jsval_t val, DWORD *ret) return S_OK; } -static BSTR int_to_bstr(int i) +static jsstr_t *int_to_string(int i) { WCHAR buf[12], *p; BOOL neg = FALSE; if(!i) { static const WCHAR zeroW[] = {'0',0}; - return SysAllocString(zeroW); + return jsstr_alloc(zeroW); } if(i < 0) { @@ -696,24 +691,24 @@ static BSTR int_to_bstr(int i) else p++; - return SysAllocString(p); + return jsstr_alloc(p); } -HRESULT double_to_bstr(double n, BSTR *str) +HRESULT double_to_string(double n, jsstr_t **str) { - const WCHAR NaNW[] = {'N','a','N',0}; const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0}; if(isnan(n)) { - *str = SysAllocString(NaNW); + *str = jsstr_nan(); }else if(isinf(n)) { - *str = SysAllocString(n<0 ? InfinityW : InfinityW+1); + *str = jsstr_alloc(n<0 ? InfinityW : InfinityW+1); }else if(is_int32(n)) { - *str = int_to_bstr(n); + *str = int_to_string(n); }else { VARIANT strv, v; HRESULT hres; + /* FIXME: Don't use VariantChangeTypeEx */ V_VT(&v) = VT_R8; V_R8(&v) = n; V_VT(&strv) = VT_EMPTY; @@ -721,14 +716,15 @@ HRESULT double_to_bstr(double n, BSTR *str) if(FAILED(hres)) return hres; - *str = V_BSTR(&strv); + *str = jsstr_alloc(V_BSTR(&strv)); + SysFreeString(V_BSTR(&strv)); } return *str ? S_OK : E_OUTOFMEMORY; } /* ECMA-262 3rd Edition 9.8 */ -HRESULT to_string(script_ctx_t *ctx, jsval_t val, BSTR *str) +HRESULT to_string(script_ctx_t *ctx, jsval_t val, jsstr_t **str) { const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; const WCHAR nullW[] = {'n','u','l','l',0}; @@ -737,15 +733,15 @@ HRESULT to_string(script_ctx_t *ctx, jsval_t val, BSTR *str) switch(jsval_type(val)) { case JSV_UNDEFINED: - *str = SysAllocString(undefinedW); + *str = jsstr_alloc(undefinedW); break; case JSV_NULL: - *str = SysAllocString(nullW); + *str = jsstr_alloc(nullW); break; case JSV_NUMBER: - return double_to_bstr(get_number(val), str); + return double_to_string(get_number(val), str); case JSV_STRING: - *str = clone_bstr(get_string(val)); + *str = jsstr_addref(get_string(val)); break; case JSV_OBJECT: { jsval_t prim; @@ -760,7 +756,7 @@ HRESULT to_string(script_ctx_t *ctx, jsval_t val, BSTR *str) return hres; } case JSV_BOOL: - *str = SysAllocString(get_bool(val) ? trueW : falseW); + *str = jsstr_alloc(get_bool(val) ? trueW : falseW); break; default: FIXME("unsupported %s\n", debugstr_jsval(val)); @@ -778,7 +774,7 @@ HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp) switch(jsval_type(val)) { case JSV_STRING: - hres = create_string(ctx, get_string(val), SysStringLen(get_string(val)), &dispex); + hres = create_string(ctx, get_string(val), &dispex); if(FAILED(hres)) return hres; @@ -883,11 +879,20 @@ HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTY break; } case VT_BSTR: { - BSTR str; + jsstr_t *str; hres = to_string(ctx, val, &str); - if(SUCCEEDED(hres)) - V_BSTR(dst) = str; + if(FAILED(hres)) + break; + + if(str->length_flags & JSSTR_FLAG_NULLBSTR) { + V_BSTR(dst) = NULL; + break; + } + + V_BSTR(dst) = SysAllocStringLen(str->str, jsstr_length(str)); + if(!V_BSTR(dst)) + hres = E_OUTOFMEMORY; break; } case VT_EMPTY: diff --git a/dlls/jscript/jsval.h b/dlls/jscript/jsval.h index c75204faf37..963f59f6a08 100644 --- a/dlls/jscript/jsval.h +++ b/dlls/jscript/jsval.h @@ -19,6 +19,8 @@ #ifndef JSVAL_H #define JSVAL_H +#include "jsstr.h" + /* * jsval_t structure is used to represent JavaScript dynamically-typed values. * It's a (type,value) pair, usually represented as a structure of enum (type) @@ -56,7 +58,7 @@ struct _jsval_t { struct { union { IDispatch *obj; - BSTR str; + jsstr_t *str; BOOL b; VARIANT *v; UINT_PTR as_uintptr; @@ -68,7 +70,7 @@ struct _jsval_t { jsval_type_t type; union { IDispatch *obj; - BSTR str; + jsstr_t *str; double n; BOOL b; VARIANT *v; @@ -104,7 +106,7 @@ static inline jsval_t jsval_bool(BOOL b) return ret; } -static inline jsval_t jsval_string(BSTR str) +static inline jsval_t jsval_string(jsstr_t *str) { jsval_t ret; __JSVAL_TYPE(ret) = JSV_STRING; @@ -224,7 +226,7 @@ static inline double get_number(jsval_t v) return v.u.n; } -static inline BSTR get_string(jsval_t v) +static inline jsstr_t *get_string(jsval_t v) { return __JSVAL_STR(v); } diff --git a/dlls/jscript/number.c b/dlls/jscript/number.c index 933cf9256ec..b7a1a765bbd 100644 --- a/dlls/jscript/number.c +++ b/dlls/jscript/number.c @@ -91,12 +91,13 @@ static inline void dtoa(double d, WCHAR *buf, int size, int *dec_point) } } -static inline void number_to_fixed(double val, int prec, BSTR *out) +static inline jsstr_t *number_to_fixed(double val, int prec) { WCHAR buf[NUMBER_DTOA_SIZE]; int dec_point, size, buf_size, buf_pos; BOOL neg = FALSE; - BSTR str; + jsstr_t *ret; + WCHAR *str; if(val < 0) { neg = TRUE; @@ -122,7 +123,11 @@ static inline void number_to_fixed(double val, int prec, BSTR *out) if(prec) size += prec+1; - str = SysAllocStringLen(NULL, size); + ret = jsstr_alloc_buf(size); + if(!ret) + return NULL; + + str = ret->str; size = buf_pos = 0; if(neg) str[size++] = '-'; @@ -146,16 +151,16 @@ static inline void number_to_fixed(double val, int prec, BSTR *out) } } str[size++] = 0; - - *out = str; + return ret; } -static inline void number_to_exponential(double val, int prec, BSTR *out) +static inline jsstr_t *number_to_exponential(double val, int prec) { WCHAR buf[NUMBER_DTOA_SIZE], *pbuf; int dec_point, size, buf_size, exp_size = 1; BOOL neg = FALSE; - BSTR str; + jsstr_t *ret; + WCHAR *str; if(val < 0) { neg = TRUE; @@ -185,8 +190,12 @@ static inline void number_to_exponential(double val, int prec, BSTR *out) size = prec+4+exp_size; /* 4 = strlen(0.e+) */ if(neg) size++; - str = SysAllocStringLen(NULL, size); + ret = jsstr_alloc_buf(size); + if(!ret) + return NULL; + + str = ret->str; size = 0; pbuf = buf; if(neg) @@ -214,7 +223,7 @@ static inline void number_to_exponential(double val, int prec, BSTR *out) size += exp_size; str[size] = 0; - *out = str; + return ret; } /* ECMA-262 3rd Edition 15.7.4.2 */ @@ -224,7 +233,7 @@ static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u NumberInstance *number; INT radix = 10; DOUBLE val; - BSTR str; + jsstr_t *str; HRESULT hres; TRACE("\n"); @@ -326,7 +335,7 @@ static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u } else buf[idx] = '\0'; - str = SysAllocString(buf); + str = jsstr_alloc(buf); if(!str) return E_OUTOFMEMORY; } @@ -334,7 +343,7 @@ static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u if(r) *r = jsval_string(str); else - SysFreeString(str); + jsstr_release(str); return S_OK; } @@ -351,7 +360,7 @@ static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un NumberInstance *number; DOUBLE val; INT prec = 0; - BSTR str; + jsstr_t *str; HRESULT hres; TRACE("\n"); @@ -374,13 +383,15 @@ static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un if(FAILED(hres)) return hres; }else { - number_to_fixed(val, prec, &str); + str = number_to_fixed(val, prec); + if(!str) + return E_OUTOFMEMORY; } if(r) *r = jsval_string(str); else - SysFreeString(str); + jsstr_release(str); return S_OK; } @@ -390,7 +401,7 @@ static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla NumberInstance *number; DOUBLE val; INT prec = 0; - BSTR str; + jsstr_t *str; HRESULT hres; TRACE("\n"); @@ -415,13 +426,15 @@ static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla }else { if(!prec) prec--; - number_to_exponential(val, prec, &str); + str = number_to_exponential(val, prec); + if(!str) + return E_OUTOFMEMORY; } if(r) *r = jsval_string(str); else - SysFreeString(str); + jsstr_release(str); return S_OK; } @@ -430,8 +443,8 @@ static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags { NumberInstance *number; INT prec = 0, size; + jsstr_t *str; DOUBLE val; - BSTR str; HRESULT hres; if(!(number = number_this(jsthis))) @@ -458,15 +471,17 @@ static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags size = 1; if(size > prec) - number_to_exponential(val, prec-1, &str); + str = number_to_exponential(val, prec-1); else - number_to_fixed(val, prec-size, &str); + str = number_to_fixed(val, prec-size); + if(!str) + return E_OUTOFMEMORY; } if(r) *r = jsval_string(str); else - SysFreeString(str); + jsstr_release(str); return S_OK; } diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index 4d102f4bb9d..6c585f71181 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -67,11 +67,13 @@ static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u } if(r) { - BSTR ret = SysAllocStringLen(NULL, 9+strlenW(str)); + jsstr_t *ret; + + ret = jsstr_alloc_buf(9+strlenW(str)); if(!ret) return E_OUTOFMEMORY; - sprintfW(ret, formatW, str); + sprintfW(ret->str, formatW, str); *r = jsval_string(ret); } @@ -106,7 +108,7 @@ static HRESULT Object_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - BSTR name; + jsstr_t *name; DISPID id; HRESULT hres; @@ -125,7 +127,7 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl if(is_jsdisp(jsthis)) { BOOL result; - hres = jsdisp_is_own_prop(jsthis->u.jsdisp, name, &result); + hres = jsdisp_is_own_prop(jsthis->u.jsdisp, name->str, &result); if(FAILED(hres)) return hres; @@ -135,11 +137,19 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl } if(is_dispex(jsthis)) { - hres = IDispatchEx_GetDispID(jsthis->u.dispex, name, + BSTR bstr; + + bstr = SysAllocStringLen(name->str, jsstr_length(name)); + if(!bstr) + return E_OUTOFMEMORY; + + hres = IDispatchEx_GetDispID(jsthis->u.dispex, bstr, make_grfdex(ctx, fdexNameCaseSensitive), &id); + SysFreeString(bstr); } else { + OLECHAR *names = name->str; hres = IDispatch_GetIDsOfNames(jsthis->u.disp, &IID_NULL, - &name, 1, ctx->lcid, &id); + &names, 1, ctx->lcid, &id); } if(r) @@ -170,7 +180,7 @@ static HRESULT Object_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi case INVOKE_FUNC: return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); case DISPATCH_PROPERTYGET: { - BSTR ret = SysAllocString(default_valueW); + jsstr_t *ret = jsstr_alloc(default_valueW); if(!ret) return E_OUTOFMEMORY; *r = jsval_string(ret); diff --git a/dlls/jscript/regexp.c b/dlls/jscript/regexp.c index 84aea587ff2..4cb1a6797c4 100644 --- a/dlls/jscript/regexp.c +++ b/dlls/jscript/regexp.c @@ -3372,13 +3372,13 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, D /* FIXME: We often already have a copy of input string that we could use to store last match */ if(!(rem_flags & REM_NO_CTX_UPDATE) && - (!ctx->last_match || len != SysStringLen(ctx->last_match) || strncmpW(ctx->last_match, str, len))) { - BSTR last_match; + (!ctx->last_match || len != jsstr_length(ctx->last_match) || strncmpW(ctx->last_match->str, str, len))) { + jsstr_t *last_match; - last_match = SysAllocStringLen(str, len); + last_match = jsstr_alloc_len(str, len); if(!last_match) return E_OUTOFMEMORY; - SysFreeString(ctx->last_match); + jsstr_release(ctx->last_match); ctx->last_match = last_match; } @@ -3406,7 +3406,7 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, D ctx->match_parens[i].str = NULL; ctx->match_parens[i].len = 0; }else { - ctx->match_parens[i].str = ctx->last_match + result->parens[i].index; + ctx->match_parens[i].str = ctx->last_match->str + result->parens[i].index; ctx->match_parens[i].len = result->parens[i].length; } } @@ -3508,7 +3508,7 @@ static HRESULT RegExp_source(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns switch(flags) { case DISPATCH_PROPERTYGET: { RegExpInstance *This = regexp_from_vdisp(jsthis); - BSTR ret = SysAllocString(This->str); + jsstr_t *ret = jsstr_alloc(This->str); if(!ret) return E_OUTOFMEMORY; *r = jsval_string(ret); @@ -3595,11 +3595,11 @@ static HRESULT RegExp_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u return E_NOTIMPL; } -static HRESULT create_match_array(script_ctx_t *ctx, BSTR input, const match_result_t *result, +static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input, const match_result_t *result, const match_result_t *parens, DWORD parens_cnt, IDispatch **ret) { jsdisp_t *array; - BSTR str; + jsstr_t *str; int i; HRESULT hres = S_OK; @@ -3613,38 +3613,38 @@ static HRESULT create_match_array(script_ctx_t *ctx, BSTR input, const match_res return hres; for(i=0; i < parens_cnt; i++) { - str = SysAllocStringLen(parens[i].str, parens[i].len); + str = jsstr_alloc_len(parens[i].str, parens[i].len); if(!str) { hres = E_OUTOFMEMORY; break; } hres = jsdisp_propput_idx(array, i+1, jsval_string(str)); - SysFreeString(str); + jsstr_release(str); if(FAILED(hres)) break; } while(SUCCEEDED(hres)) { - hres = jsdisp_propput_name(array, indexW, jsval_number(result->str-input)); + hres = jsdisp_propput_name(array, indexW, jsval_number(result->str-input->str)); if(FAILED(hres)) break; - hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->str-input+result->len)); + hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->str-input->str+result->len)); if(FAILED(hres)) break; - hres = jsdisp_propput_name(array, inputW, jsval_string(input)); + hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr_addref(input))); if(FAILED(hres)) break; - str = SysAllocStringLen(result->str, result->len); + str = jsstr_alloc_len(result->str, result->len); if(!str) { hres = E_OUTOFMEMORY; break; } hres = jsdisp_propput_name(array, zeroW, jsval_string(str)); - SysFreeString(str); + jsstr_release(str); break; } @@ -3657,13 +3657,13 @@ static HRESULT create_match_array(script_ctx_t *ctx, BSTR input, const match_res return S_OK; } -static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, BSTR *input, +static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, jsstr_t **input, match_result_t *match, match_result_t **parens, DWORD *parens_cnt, BOOL *ret) { RegExpInstance *regexp; DWORD parens_size = 0, last_index = 0, length; const WCHAR *cp; - BSTR string; + jsstr_t *string; HRESULT hres; if(!is_vclass(jsthis, JSCLASS_REGEXP)) { @@ -3676,36 +3676,34 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, BSTR *i hres = to_string(ctx, arg, &string); if(FAILED(hres)) return hres; - length = SysStringLen(string); + length = jsstr_length(string); if(regexp->jsregexp->flags & JSREG_GLOB) { if(regexp->last_index < 0) { - SysFreeString(string); + jsstr_release(string); set_last_index(regexp, 0); *ret = FALSE; - if(input) { - *input = NULL; - } + if(input) + *input = jsstr_empty(); return S_OK; } last_index = regexp->last_index; } - cp = string + last_index; - hres = regexp_match_next(ctx, ®exp->dispex, REM_RESET_INDEX, string, length, &cp, parens, + cp = string->str + last_index; + hres = regexp_match_next(ctx, ®exp->dispex, REM_RESET_INDEX, string->str, length, &cp, parens, parens ? &parens_size : NULL, parens_cnt, match); if(FAILED(hres)) { - SysFreeString(string); + jsstr_release(string); return hres; } *ret = hres == S_OK; - if(input) { + if(input) *input = string; - }else { - SysFreeString(string); - } + else + jsstr_release(string); return S_OK; } @@ -3715,12 +3713,12 @@ static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig match_result_t *parens = NULL, match; DWORD parens_cnt = 0; BOOL b; - BSTR string; + jsstr_t *string; HRESULT hres; TRACE("\n"); - hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(NULL), &string, &match, &parens, &parens_cnt, &b); + hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(jsstr_empty()), &string, &match, &parens, &parens_cnt, &b); if(FAILED(hres)) return hres; @@ -3737,7 +3735,7 @@ static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig } heap_free(parens); - SysFreeString(string); + jsstr_release(string); return hres; } @@ -3745,21 +3743,21 @@ static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig jsval_t *r) { match_result_t match; - BSTR undef_str; + jsstr_t *undef_str; BOOL b; HRESULT hres; TRACE("\n"); if(!argc) { - undef_str = SysAllocString(undefinedW); + undef_str = jsstr_alloc(undefinedW); if(!undef_str) return E_OUTOFMEMORY; } hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(undef_str), NULL, &match, NULL, NULL, &b); if(!argc) - SysFreeString(undef_str); + jsstr_release(undef_str); if(FAILED(hres)) return hres; @@ -3890,7 +3888,7 @@ HRESULT create_regexp(script_ctx_t *ctx, const WCHAR *exp, int len, DWORD flags, HRESULT create_regexp_var(script_ctx_t *ctx, jsval_t src_arg, jsval_t *flags_arg, jsdisp_t **ret) { - const WCHAR *opt = emptyW, *src; + jsstr_t *src, *opt = NULL; DWORD flags; HRESULT hres; @@ -3927,14 +3925,14 @@ HRESULT create_regexp_var(script_ctx_t *ctx, jsval_t src_arg, jsval_t *flags_arg opt = get_string(*flags_arg); } - hres = parse_regexp_flags(opt, strlenW(opt), &flags); + hres = parse_regexp_flags(opt ? opt->str : NULL, opt ? jsstr_length(opt) : 0, &flags); if(FAILED(hres)) return hres; - return create_regexp(ctx, src, -1, flags, ret); + return create_regexp(ctx, src->str, -1, flags, ret); } -HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, BSTR str, jsval_t *r) +HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval_t *r) { static const WCHAR indexW[] = {'i','n','d','e','x',0}; static const WCHAR inputW[] = {'i','n','p','u','t',0}; @@ -3942,18 +3940,18 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, BSTR str, jsval_t * RegExpInstance *regexp = (RegExpInstance*)re; match_result_t *match_result; - DWORD match_cnt, i, length; + unsigned match_cnt, i, length; jsdisp_t *array; HRESULT hres; - length = SysStringLen(str); + length = jsstr_length(str); if(!(regexp->jsregexp->flags & JSREG_GLOB)) { match_result_t match, *parens = NULL; DWORD parens_cnt, parens_size = 0; - const WCHAR *cp = str; + const WCHAR *cp = str->str; - hres = regexp_match_next(ctx, ®exp->dispex, 0, str, length, &cp, &parens, &parens_size, &parens_cnt, &match); + hres = regexp_match_next(ctx, ®exp->dispex, 0, str->str, length, &cp, &parens, &parens_size, &parens_cnt, &match); if(FAILED(hres)) return hres; @@ -3973,7 +3971,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, BSTR str, jsval_t * return S_OK; } - hres = regexp_match(ctx, ®exp->dispex, str, length, FALSE, &match_result, &match_cnt); + hres = regexp_match(ctx, ®exp->dispex, str->str, length, FALSE, &match_result, &match_cnt); if(FAILED(hres)) return hres; @@ -3990,27 +3988,27 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, BSTR str, jsval_t * return hres; for(i=0; i < match_cnt; i++) { - BSTR tmp_str; + jsstr_t *tmp_str; - tmp_str = SysAllocStringLen(match_result[i].str, match_result[i].len); + tmp_str = jsstr_alloc_len(match_result[i].str, match_result[i].len); if(!tmp_str) { hres = E_OUTOFMEMORY; break; } hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str)); - SysFreeString(tmp_str); + jsstr_release(tmp_str); if(FAILED(hres)) break; } while(SUCCEEDED(hres)) { - hres = jsdisp_propput_name(array, indexW, jsval_number(match_result[match_cnt-1].str-str)); + hres = jsdisp_propput_name(array, indexW, jsval_number(match_result[match_cnt-1].str-str->str)); if(FAILED(hres)) break; hres = jsdisp_propput_name(array, lastIndexW, - jsval_number(match_result[match_cnt-1].str-str+match_result[match_cnt-1].len)); + jsval_number(match_result[match_cnt-1].str-str->str+match_result[match_cnt-1].len)); if(FAILED(hres)) break; @@ -4031,9 +4029,9 @@ static HRESULT global_idx(script_ctx_t *ctx, DWORD flags, DWORD idx, jsval_t *r) { switch(flags) { case DISPATCH_PROPERTYGET: { - BSTR ret = NULL; + jsstr_t *ret; - ret = SysAllocStringLen(ctx->match_parens[idx].str, ctx->match_parens[idx].len); + ret = jsstr_alloc_len(ctx->match_parens[idx].str, ctx->match_parens[idx].len); if(!ret) return E_OUTOFMEMORY; @@ -4120,9 +4118,9 @@ static HRESULT RegExpConstr_leftContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD switch(flags) { case DISPATCH_PROPERTYGET: { - BSTR ret; + jsstr_t *ret; - ret = SysAllocStringLen(ctx->last_match, ctx->last_match_index); + ret = jsstr_alloc_len(ctx->last_match->str, ctx->last_match_index); if(!ret) return E_OUTOFMEMORY; @@ -4146,9 +4144,9 @@ static HRESULT RegExpConstr_rightContext(script_ctx_t *ctx, vdisp_t *jsthis, WOR switch(flags) { case DISPATCH_PROPERTYGET: { - BSTR ret; + jsstr_t *ret; - ret = SysAllocString(ctx->last_match+ctx->last_match_index+ctx->last_match_length); + ret = jsstr_alloc(ctx->last_match->str+ctx->last_match_index+ctx->last_match_length); if(!ret) return E_OUTOFMEMORY; diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 6387896b2ca..8fb6b073536 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -29,9 +29,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); typedef struct { jsdisp_t dispex; - - WCHAR *str; - DWORD length; + jsstr_t *str; } StringInstance; static const WCHAR lengthW[] = {'l','e','n','g','t','h',0}; @@ -79,25 +77,16 @@ static inline StringInstance *string_this(vdisp_t *jsthis) return is_vclass(jsthis, JSCLASS_STRING) ? string_from_vdisp(jsthis) : NULL; } -static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, const WCHAR **str, DWORD *len, BSTR *val_str) +static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, jsstr_t **val) { StringInstance *string; - HRESULT hres; if((string = string_this(jsthis))) { - *str = string->str; - *len = string->length; - *val_str = NULL; + *val = jsstr_addref(string->str); return S_OK; } - hres = to_string(ctx, jsval_disp(jsthis->u.disp), val_str); - if(FAILED(hres)) - return hres; - - *str = *val_str; - *len = SysStringLen(*val_str); - return S_OK; + return to_string(ctx, jsval_disp(jsthis->u.disp), val); } static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, @@ -109,7 +98,7 @@ static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns case DISPATCH_PROPERTYGET: { StringInstance *string = string_from_vdisp(jsthis); - *r = jsval_number(string->length); + *r = jsval_number(jsstr_length(string->str)); break; } default: @@ -129,13 +118,8 @@ static HRESULT stringobj_to_string(vdisp_t *jsthis, jsval_t *r) return E_FAIL; } - if(r) { - BSTR str = SysAllocString(string->str); - if(!str) - return E_OUTOFMEMORY; - - *r = jsval_string(str); - } + if(r) + *r = jsval_string(jsstr_addref(string->str)); return S_OK; } @@ -159,29 +143,27 @@ static HRESULT String_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r, const WCHAR *tagname) { - const WCHAR *str; - DWORD length; - BSTR val_str = NULL; + jsstr_t *str; HRESULT hres; static const WCHAR tagfmt[] = {'<','%','s','>','%','s','<','/','%','s','>',0}; - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(r) { - BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname) + 5); + jsstr_t *ret = jsstr_alloc_buf(jsstr_length(str) + 2*strlenW(tagname) + 5); if(!ret) { - SysFreeString(val_str); + jsstr_release(str); return E_OUTOFMEMORY; } - sprintfW(ret, tagfmt, tagname, str, tagname); + sprintfW(ret->str, tagfmt, tagname, str->str, tagname); *r = jsval_string(ret); } - SysFreeString(val_str); + jsstr_release(str); return S_OK; } @@ -192,56 +174,44 @@ static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, unsig = {'<','%','s',' ','%','s','=','\"','%','s','\"','>','%','s','<','/','%','s','>',0}; static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; - StringInstance *string; - const WCHAR *str; - DWORD length; - BSTR attr_value, val_str = NULL; + jsstr_t *str, *attr_value = NULL; + const WCHAR *attr_str; + unsigned attr_len; HRESULT hres; - if(!(string = string_this(jsthis))) { - hres = to_string(ctx, jsval_disp(jsthis->u.disp), &val_str); - if(FAILED(hres)) - return hres; - - str = val_str; - length = SysStringLen(val_str); - } - else { - str = string->str; - length = string->length; - } + 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)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - } - else { - attr_value = SysAllocString(undefinedW); - if(!attr_value) { - SysFreeString(val_str); - return E_OUTOFMEMORY; - } + attr_str = attr_value->str; + attr_len = jsstr_length(attr_value); + }else { + attr_str = undefinedW; + attr_len = sizeof(undefinedW)/sizeof(WCHAR)-1; } if(r) { - BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname) - + strlenW(attr) + SysStringLen(attr_value) + 9); - if(!ret) { - SysFreeString(attr_value); - SysFreeString(val_str); - return E_OUTOFMEMORY; - } + jsstr_t *ret; - sprintfW(ret, tagfmtW, tagname, attr, attr_value, str, tagname); - *r = jsval_string(ret); + ret = jsstr_alloc_buf(2*strlenW(tagname) + strlenW(attr) + attr_len + jsstr_length(str) + 9); + if(ret) { + sprintfW(ret->str, tagfmtW, tagname, attr, attr_str, str->str, tagname); + *r = jsval_string(ret); + }else { + hres = E_OUTOFMEMORY; + } } - SysFreeString(attr_value); - SysFreeString(val_str); - return S_OK; + if(attr_value) + jsstr_release(attr_value); + jsstr_release(str); + return hres; } static HRESULT String_anchor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, @@ -278,15 +248,13 @@ static HRESULT String_bold(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - const WCHAR *str; - DWORD length; - BSTR ret, val_str; + jsstr_t *str, *ret; INT pos = 0; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; @@ -295,24 +263,23 @@ static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } pos = is_int32(d) ? d : -1; } if(!r) { - SysFreeString(val_str); + jsstr_release(str); return S_OK; } - if(0 <= pos && pos < length) - ret = SysAllocStringLen(str+pos, 1); - else - ret = SysAllocStringLen(NULL, 0); - SysFreeString(val_str); - if(!ret) { - return E_OUTOFMEMORY; + if(0 <= pos && pos < jsstr_length(str)) { + ret = jsstr_alloc_len(str->str+pos, 1); + if(!ret) + return E_OUTOFMEMORY; + }else { + ret = jsstr_empty(); } *r = jsval_string(ret); @@ -323,14 +290,13 @@ static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - const WCHAR *str; - BSTR val_str; - DWORD length, idx = 0; + jsstr_t *str; + DWORD idx = 0; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; @@ -339,12 +305,12 @@ static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - if(!is_int32(d) || d < 0 || d >= length) { - SysFreeString(val_str); + if(!is_int32(d) || d < 0 || d >= jsstr_length(str)) { + jsstr_release(str); if(r) *r = jsval_number(NAN); return S_OK; @@ -354,9 +320,9 @@ static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, } if(r) - *r = jsval_number(str[idx]); + *r = jsval_number(str->str[idx]); - SysFreeString(val_str); + jsstr_release(str); return S_OK; } @@ -364,7 +330,7 @@ static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - BSTR *strs = NULL, ret = NULL; + jsstr_t **strs, *ret = NULL; DWORD len = 0, i, l, str_cnt; WCHAR *ptr; HRESULT hres; @@ -372,7 +338,7 @@ static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns TRACE("\n"); str_cnt = argc+1; - strs = heap_alloc_zero(str_cnt * sizeof(BSTR)); + strs = heap_alloc_zero(str_cnt * sizeof(*strs)); if(!strs) return E_OUTOFMEMORY; @@ -386,20 +352,29 @@ static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns } if(SUCCEEDED(hres)) { - for(i=0; i < str_cnt; i++) - len += SysStringLen(strs[i]); - - ptr = ret = SysAllocStringLen(NULL, len); - for(i=0; i < str_cnt; i++) { - l = SysStringLen(strs[i]); - memcpy(ptr, strs[i], l*sizeof(WCHAR)); - ptr += l; + len += jsstr_length(strs[i]); + if(len > JSSTR_MAX_LENGTH) { + hres = E_OUTOFMEMORY; + break; + } + } + + ret = jsstr_alloc_buf(len); + if(ret) { + ptr = ret->str; + for(i=0; i < str_cnt; i++) { + l = jsstr_length(strs[i]); + memcpy(ptr, strs[i]->str, l*sizeof(WCHAR)); + ptr += l; + } + }else { + hres = E_OUTOFMEMORY; } } for(i=0; i < str_cnt; i++) - SysFreeString(strs[i]); + jsstr_release(strs[i]); heap_free(strs); if(FAILED(hres)) @@ -408,7 +383,7 @@ static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns if(r) *r = jsval_string(ret); else - SysFreeString(ret); + jsstr_release(ret); return S_OK; } @@ -440,28 +415,28 @@ static HRESULT String_fontsize(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - DWORD length, pos = 0; - const WCHAR *str; - BSTR search_str, val_str; + jsstr_t *search_str, *str; + int length, pos = 0; INT ret = -1; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; + length = jsstr_length(str); if(!argc) { if(r) *r = jsval_number(-1); - SysFreeString(val_str); + jsstr_release(str); return S_OK; } hres = to_string(ctx, argv[0], &search_str); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -476,15 +451,15 @@ static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un if(SUCCEEDED(hres)) { const WCHAR *ptr; - ptr = strstrW(str+pos, search_str); + ptr = strstrW(str->str+pos, search_str->str); if(ptr) - ret = ptr - str; + ret = ptr - str->str; else ret = -1; } - SysFreeString(search_str); - SysFreeString(val_str); + jsstr_release(search_str); + jsstr_release(str); if(FAILED(hres)) return hres; @@ -504,32 +479,32 @@ static HRESULT String_italics(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - BSTR search_str, val_str; - DWORD length, pos = 0, search_len; - const WCHAR *str; + unsigned pos = 0, search_len, length; + jsstr_t *search_str, *str; INT ret = -1; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(!argc) { if(r) *r = jsval_number(-1); - SysFreeString(val_str); + jsstr_release(str); return S_OK; } hres = to_string(ctx, argv[0], &search_str); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - search_len = SysStringLen(search_str); + search_len = jsstr_length(search_str); + length = jsstr_length(str); if(argc >= 2) { double d; @@ -544,16 +519,16 @@ static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags 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; + for(ptr = str->str+min(pos, length-search_len); ptr >= str->str; ptr--) { + if(!memcmp(ptr, search_str->str, search_len*sizeof(WCHAR))) { + ret = ptr-str->str; break; } } } - SysFreeString(search_str); - SysFreeString(val_str); + jsstr_release(search_str); + jsstr_release(str); if(FAILED(hres)) return hres; @@ -576,10 +551,8 @@ static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi jsval_t *r) { jsdisp_t *regexp = NULL; - const WCHAR *str; - DWORD length; - BSTR val_str = NULL; - HRESULT hres = S_OK; + jsstr_t *str; + HRESULT hres; TRACE("\n"); @@ -598,30 +571,24 @@ static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi } if(!regexp) { - BSTR match_str; + jsstr_t *match_str; hres = to_string(ctx, argv[0], &match_str); if(FAILED(hres)) return hres; - hres = create_regexp(ctx, match_str, SysStringLen(match_str), 0, ®exp); - SysFreeString(match_str); + hres = create_regexp(ctx, match_str->str, jsstr_length(match_str), 0, ®exp); + jsstr_release(match_str); if(FAILED(hres)) return hres; } - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); - if(SUCCEEDED(hres)) { - if(!val_str) - val_str = SysAllocStringLen(str, length); - if(val_str) - hres = regexp_string_match(ctx, regexp, val_str, r); - else - hres = E_OUTOFMEMORY; - } + hres = get_string_val(ctx, jsthis, &str); + if(SUCCEEDED(hres)) + hres = regexp_string_match(ctx, regexp, str, r); jsdisp_release(regexp); - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -659,13 +626,13 @@ static HRESULT strbuf_append(strbuf_t *buf, const WCHAR *str, DWORD len) return S_OK; } -static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, const WCHAR *str, match_result_t *match, - match_result_t *parens, DWORD parens_cnt, BSTR *ret) +static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, jsstr_t *str, match_result_t *match, + match_result_t *parens, DWORD parens_cnt, jsstr_t **ret) { jsval_t *argv; unsigned argc; jsval_t val; - BSTR tmp_str; + jsstr_t *tmp_str; DWORD i; HRESULT hres = S_OK; @@ -674,14 +641,14 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, const WCHAR *str, mat if(!argv) return E_OUTOFMEMORY; - tmp_str = SysAllocStringLen(match->str, match->len); + tmp_str = jsstr_alloc_len(match->str, match->len); if(!tmp_str) hres = E_OUTOFMEMORY; argv[0] = jsval_string(tmp_str); if(SUCCEEDED(hres)) { for(i=0; i < parens_cnt; i++) { - tmp_str = SysAllocStringLen(parens[i].str, parens[i].len); + tmp_str = jsstr_alloc_len(parens[i].str, parens[i].len); if(!tmp_str) { hres = E_OUTOFMEMORY; break; @@ -691,21 +658,15 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, const WCHAR *str, mat } if(SUCCEEDED(hres)) { - argv[parens_cnt+1] = jsval_number(match->str - str); - - tmp_str = SysAllocString(str); - if(!tmp_str) - hres = E_OUTOFMEMORY; - argv[parens_cnt+2] = jsval_string(tmp_str); + argv[parens_cnt+1] = jsval_number(match->str - str->str); + argv[parens_cnt+2] = jsval_string(str); } if(SUCCEEDED(hres)) hres = jsdisp_call_value(func, NULL, DISPATCH_METHOD, argc, argv, &val); - for(i=0; i < parens_cnt+3; i++) { - if(i != parens_cnt+1) - SysFreeString(get_string(argv[i])); - } + for(i=0; i <= parens_cnt; i++) + jsstr_release(get_string(argv[i])); heap_free(argv); if(FAILED(hres)) @@ -720,9 +681,8 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, const WCHAR *str, mat static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - const WCHAR *str; - DWORD parens_cnt = 0, parens_size=0, rep_len=0, length; - BSTR rep_str = NULL, match_str = NULL, ret_str, val_str; + DWORD parens_cnt = 0, parens_size=0, rep_len=0; + jsstr_t *rep_str = NULL, *match_str = NULL, *str; jsdisp_t *rep_func = NULL, *regexp = NULL; match_result_t *parens = NULL, match = {NULL,0}, **parens_ptr = &parens; strbuf_t ret = {NULL,0,0}; @@ -731,20 +691,15 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(!argc) { - if(r) { - if(!val_str) { - val_str = SysAllocStringLen(str, length); - if(!val_str) - return E_OUTOFMEMORY; - } - - *r = jsval_string(val_str); - } + if(r) + *r = jsval_string(str); + else + jsstr_release(str); return S_OK; } @@ -759,7 +714,7 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un if(!regexp) { hres = to_string(ctx, argv[0], &match_str); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } } @@ -776,8 +731,8 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un if(!rep_func) { hres = to_string(ctx, argv[1], &rep_str); if(SUCCEEDED(hres)) { - rep_len = SysStringLen(rep_str); - if(!strchrW(rep_str, '$')) + rep_len = jsstr_length(rep_str); + if(!strchrW(rep_str->str, '$')) parens_ptr = NULL; } } @@ -786,11 +741,11 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un if(SUCCEEDED(hres)) { const WCHAR *cp, *ecp; - cp = ecp = str; + cp = ecp = str->str; while(1) { if(regexp) { - hres = regexp_match_next(ctx, regexp, re_flags, str, length, &cp, parens_ptr, + hres = regexp_match_next(ctx, regexp, re_flags, str->str, jsstr_length(str), &cp, parens_ptr, &parens_size, &parens_cnt, &match); re_flags |= REM_CHECK_GLOBAL; @@ -804,10 +759,10 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un if(!match.len) cp++; }else { - match.str = strstrW(cp, match_str); + match.str = strstrW(cp, match_str->str); if(!match.str) break; - match.len = SysStringLen(match_str); + match.len = jsstr_length(match_str); cp = match.str+match.len; } @@ -817,18 +772,18 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un break; if(rep_func) { - BSTR cstr; + jsstr_t *cstr; hres = rep_call(ctx, rep_func, str, &match, parens, parens_cnt, &cstr); if(FAILED(hres)) break; - hres = strbuf_append(&ret, cstr, SysStringLen(cstr)); - SysFreeString(cstr); + hres = strbuf_append(&ret, cstr->str, jsstr_length(cstr)); + jsstr_release(cstr); if(FAILED(hres)) break; }else if(rep_str && regexp) { - const WCHAR *ptr = rep_str, *ptr2; + const WCHAR *ptr = rep_str->str, *ptr2; while((ptr2 = strchrW(ptr, '$'))) { hres = strbuf_append(&ret, ptr, ptr2-ptr); @@ -845,11 +800,11 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un ptr = ptr2+2; break; case '`': - hres = strbuf_append(&ret, str, match.str-str); + hres = strbuf_append(&ret, str->str, match.str-str->str); ptr = ptr2+2; break; case '\'': - hres = strbuf_append(&ret, ecp, (str+length)-ecp); + hres = strbuf_append(&ret, ecp, (str->str+jsstr_length(str))-ecp); ptr = ptr2+2; break; default: { @@ -882,11 +837,11 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un } if(SUCCEEDED(hres)) - hres = strbuf_append(&ret, ptr, (rep_str+rep_len)-ptr); + hres = strbuf_append(&ret, ptr, (rep_str->str+rep_len)-ptr); if(FAILED(hres)) break; }else if(rep_str) { - hres = strbuf_append(&ret, rep_str, rep_len); + hres = strbuf_append(&ret, rep_str->str, rep_len); if(FAILED(hres)) break; }else { @@ -902,39 +857,36 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un } if(SUCCEEDED(hres)) - hres = strbuf_append(&ret, ecp, (str+length)-ecp); + hres = strbuf_append(&ret, ecp, str->str+jsstr_length(str)-ecp); } if(rep_func) jsdisp_release(rep_func); - SysFreeString(rep_str); - SysFreeString(match_str); + if(rep_str) + jsstr_release(rep_str); + if(match_str) + jsstr_release(match_str); heap_free(parens); if(SUCCEEDED(hres) && match.str && regexp) { - if(!val_str) - val_str = SysAllocStringLen(str, length); - if(val_str) { - SysFreeString(ctx->last_match); - ctx->last_match = val_str; - val_str = NULL; - ctx->last_match_index = match.str-str; - ctx->last_match_length = match.len; - }else { - hres = E_OUTOFMEMORY; - } + jsstr_release(ctx->last_match); + ctx->last_match = jsstr_addref(str); + ctx->last_match_index = match.str-str->str; + ctx->last_match_length = match.len; } if(regexp) jsdisp_release(regexp); - SysFreeString(val_str); + jsstr_release(str); if(SUCCEEDED(hres) && r) { - ret_str = SysAllocStringLen(ret.buf, ret.len); + jsstr_t *ret_str; + + ret_str = jsstr_alloc_len(ret.buf, ret.len); if(!ret_str) return E_OUTOFMEMORY; - TRACE("= %s\n", debugstr_w(ret_str)); + TRACE("= %s\n", debugstr_jsstr(ret_str)); *r = jsval_string(ret_str); } @@ -946,22 +898,21 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns jsval_t *r) { jsdisp_t *regexp = NULL; - const WCHAR *str, *cp; + const WCHAR *cp; match_result_t match; - DWORD length; - BSTR val_str; + jsstr_t *str; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(!argc) { if(r) *r = jsval_null(); - SysFreeString(val_str); + jsstr_release(str); return S_OK; } @@ -976,20 +927,20 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns if(!regexp) { hres = create_regexp_var(ctx, argv[0], NULL, ®exp); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } } - cp = str; - hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX, str, length, &cp, NULL, NULL, NULL, &match); - SysFreeString(val_str); + cp = str->str; + hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX, str->str, jsstr_length(str), &cp, NULL, NULL, NULL, &match); + jsstr_release(str); jsdisp_release(regexp); if(FAILED(hres)) return hres; if(r) - *r = jsval_number(hres == S_OK ? match.str-str : -1); + *r = jsval_number(hres == S_OK ? match.str-str->str : -1); return S_OK; } @@ -997,23 +948,22 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - const WCHAR *str; - BSTR val_str; - DWORD length; - INT start=0, end; + int start=0, end, length; + jsstr_t *str; double d; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; + length = jsstr_length(str); if(argc) { hres = to_integer(ctx, argv[0], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -1034,7 +984,7 @@ static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi if(argc >= 2) { hres = to_integer(ctx, argv[1], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -1058,16 +1008,16 @@ static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi end = start; if(r) { - BSTR retstr = SysAllocStringLen(str+start, end-start); + jsstr_t *retstr = jsstr_alloc_len(str->str+start, end-start); if(!retstr) { - SysFreeString(val_str); + jsstr_release(str); return E_OUTOFMEMORY; } *r = jsval_string(retstr); } - SysFreeString(val_str); + jsstr_release(str); return S_OK; } @@ -1083,10 +1033,10 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi { match_result_t match_result; DWORD length, i, match_len = 0; - const WCHAR *str, *ptr, *ptr2, *cp; + const WCHAR *ptr, *ptr2, *cp; unsigned limit = UINT32_MAX; jsdisp_t *array, *regexp = NULL; - BSTR val_str, match_str = NULL, tmp_str; + jsstr_t *str, *match_str = NULL, *tmp_str; HRESULT hres; TRACE("\n"); @@ -1096,14 +1046,16 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi return E_NOTIMPL; } - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; + length = jsstr_length(str); + if(argc > 1 && !is_undefined(argv[1])) { hres = to_uint32(ctx, argv[1], &limit); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } } @@ -1121,13 +1073,13 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi if(!regexp) { hres = to_string(ctx, argv[0], &match_str); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } - match_len = SysStringLen(match_str); + match_len = jsstr_length(match_str); if(!match_len) { - SysFreeString(match_str); + jsstr_release(match_str); match_str = NULL; } } @@ -1135,15 +1087,15 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi hres = create_array(ctx, 0, &array); if(SUCCEEDED(hres)) { - ptr = cp = str; + ptr = cp = str->str; for(i=0; istr, length, &cp, NULL, NULL, NULL, &match_result); if(hres != S_OK) break; ptr2 = match_result.str; }else if(match_str) { - ptr2 = strstrW(ptr, match_str); + ptr2 = strstrW(ptr, match_str->str); if(!ptr2) break; }else { @@ -1152,14 +1104,14 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi ptr2 = ptr+1; } - tmp_str = SysAllocStringLen(ptr, ptr2-ptr); + 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)); - SysFreeString(tmp_str); + jsstr_release(tmp_str); if(FAILED(hres)) break; @@ -1173,14 +1125,14 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi } if(SUCCEEDED(hres) && (match_str || regexp) && istr+length) - ptr; if(len || match_str) { - tmp_str = SysAllocStringLen(ptr, len); + tmp_str = jsstr_alloc_len(ptr, len); if(tmp_str) { hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str)); - SysFreeString(tmp_str); + jsstr_release(tmp_str); }else { hres = E_OUTOFMEMORY; } @@ -1189,8 +1141,9 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi if(regexp) jsdisp_release(regexp); - SysFreeString(match_str); - SysFreeString(val_str); + if(match_str) + jsstr_release(match_str); + jsstr_release(str); if(SUCCEEDED(hres) && r) *r = jsval_obj(array); @@ -1218,23 +1171,22 @@ static HRESULT String_sub(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsign static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - const WCHAR *str; - BSTR val_str; - INT start=0, end; - DWORD length; + INT start=0, end, length; + jsstr_t *str; double d; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + 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)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -1245,7 +1197,7 @@ static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, if(argc >= 2) { hres = to_integer(ctx, argv[1], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -1264,14 +1216,14 @@ static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, } if(r) { - BSTR ret = SysAllocStringLen(str+start, end-start); + jsstr_t *ret = jsstr_alloc_len(str->str+start, end-start); if(!ret) { - SysFreeString(val_str); + jsstr_release(str); return E_OUTOFMEMORY; } *r = jsval_string(ret); } - SysFreeString(val_str); + jsstr_release(str); return S_OK; } @@ -1279,23 +1231,22 @@ static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - BSTR val_str; - const WCHAR *str; - INT start=0, len; - DWORD length; + int start=0, len, length; + jsstr_t *str; double d; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + 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)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -1306,7 +1257,7 @@ static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns if(argc >= 2) { hres = to_integer(ctx, argv[1], &d); if(FAILED(hres)) { - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -1320,14 +1271,14 @@ static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns hres = S_OK; if(r) { - BSTR ret = SysAllocStringLen(str+start, len); + jsstr_t *ret = jsstr_alloc_len(str->str+start, len); if(ret) *r = jsval_string(ret); else hres = E_OUTOFMEMORY; } - SysFreeString(val_str); + jsstr_release(str); return hres; } @@ -1341,56 +1292,56 @@ static HRESULT String_sup(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsign static HRESULT String_toLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - const WCHAR* str; - DWORD length; - BSTR val_str; + jsstr_t *str; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(r) { - if(!val_str) { - val_str = SysAllocStringLen(str, length); - if(!val_str) - return E_OUTOFMEMORY; + jsstr_t *ret; + + ret = jsstr_alloc_len(str->str, jsstr_length(str)); + if(!ret) { + jsstr_release(str); + return E_OUTOFMEMORY; } - strlwrW(val_str); - *r = jsval_string(val_str); + strlwrW(ret->str); + *r = jsval_string(ret); } - else SysFreeString(val_str); + jsstr_release(str); return S_OK; } static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - const WCHAR* str; - DWORD length; - BSTR val_str; + jsstr_t *str; HRESULT hres; TRACE("\n"); - hres = get_string_val(ctx, jsthis, &str, &length, &val_str); + hres = get_string_val(ctx, jsthis, &str); if(FAILED(hres)) return hres; if(r) { - if(!val_str) { - val_str = SysAllocStringLen(str, length); - if(!val_str) - return E_OUTOFMEMORY; + jsstr_t *ret; + + ret = jsstr_alloc_len(str->str, jsstr_length(str)); + if(!ret) { + jsstr_release(str); + return E_OUTOFMEMORY; } - struprW(val_str); - *r = jsval_string(val_str); + struprW(ret->str); + *r = jsval_string(ret); } - else SysFreeString(val_str); + jsstr_release(str); return S_OK; } @@ -1426,11 +1377,7 @@ static HRESULT String_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi case INVOKE_FUNC: return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL); case DISPATCH_PROPERTYGET: { - BSTR str = SysAllocString(This->str); - if(!str) - return E_OUTOFMEMORY; - - *r = jsval_string(str); + *r = jsval_string(jsstr_addref(This->str)); break; } default: @@ -1445,7 +1392,7 @@ static void String_destructor(jsdisp_t *dispex) { StringInstance *This = (StringInstance*)dispex; - heap_free(This->str); + jsstr_release(This->str); heap_free(This); } @@ -1512,29 +1459,29 @@ static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WOR unsigned argc, jsval_t *argv, jsval_t *r) { DWORD i, code; - BSTR ret; + jsstr_t *ret; HRESULT hres; TRACE("\n"); - ret = SysAllocStringLen(NULL, argc); + ret = jsstr_alloc_buf(argc); if(!ret) return E_OUTOFMEMORY; for(i=0; istr[i] = code; } if(r) *r = jsval_string(ret); else - SysFreeString(ret); + jsstr_release(ret); return S_OK; } @@ -1547,16 +1494,14 @@ static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags switch(flags) { case INVOKE_FUNC: { - BSTR str; + jsstr_t *str; if(argc) { hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; }else { - str = SysAllocStringLen(NULL, 0); - if(!str) - return E_OUTOFMEMORY; + str = jsstr_empty(); } *r = jsval_string(str); @@ -1566,16 +1511,16 @@ static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags jsdisp_t *ret; if(argc) { - BSTR str; + jsstr_t *str; hres = to_string(ctx, argv[0], &str); if(FAILED(hres)) return hres; - hres = create_string(ctx, str, SysStringLen(str), &ret); - SysFreeString(str); + hres = create_string(ctx, str, &ret); + jsstr_release(str); }else { - hres = create_string(ctx, NULL, 0, &ret); + hres = create_string(ctx, jsstr_empty(), &ret); } if(FAILED(hres)) @@ -1593,7 +1538,7 @@ static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags return S_OK; } -static HRESULT string_alloc(script_ctx_t *ctx, jsdisp_t *object_prototype, StringInstance **ret) +static HRESULT string_alloc(script_ctx_t *ctx, jsdisp_t *object_prototype, jsstr_t *str, StringInstance **ret) { StringInstance *string; HRESULT hres; @@ -1611,6 +1556,7 @@ static HRESULT string_alloc(script_ctx_t *ctx, jsdisp_t *object_prototype, Strin return hres; } + string->str = jsstr_addref(str); *ret = string; return S_OK; } @@ -1635,7 +1581,7 @@ HRESULT create_string_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdi static const WCHAR StringW[] = {'S','t','r','i','n','g',0}; - hres = string_alloc(ctx, object_prototype, &string); + hres = string_alloc(ctx, object_prototype, jsstr_empty(), &string); if(FAILED(hres)) return hres; @@ -1646,28 +1592,15 @@ HRESULT create_string_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdi return hres; } -HRESULT create_string(script_ctx_t *ctx, const WCHAR *str, DWORD len, jsdisp_t **ret) +HRESULT create_string(script_ctx_t *ctx, jsstr_t *str, jsdisp_t **ret) { StringInstance *string; HRESULT hres; - hres = string_alloc(ctx, NULL, &string); + hres = string_alloc(ctx, NULL, str, &string); if(FAILED(hres)) return hres; - if(len == -1) - len = strlenW(str); - - string->length = len; - string->str = heap_alloc((len+1)*sizeof(WCHAR)); - if(!string->str) { - jsdisp_release(&string->dispex); - return E_OUTOFMEMORY; - } - - memcpy(string->str, str, len*sizeof(WCHAR)); - string->str[len] = 0; - *ret = &string->dispex; return S_OK;