[JSCRIPT]

* Sync with Wine 1.7.1.
CORE-7469

svn path=/trunk/; revision=60246
This commit is contained in:
Amine Khaldi 2013-09-20 12:14:54 +00:00
parent 528ebe204e
commit 6cc49a4a0b
23 changed files with 1872 additions and 1314 deletions

View file

@ -1,13 +1,9 @@
remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600)
add_definitions(
-D__WINESRC__
-D_USE_MATH_DEFINES)
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
spec2def(jscript.dll jscript.spec)
list(APPEND SOURCE
@ -37,11 +33,6 @@ list(APPEND SOURCE
vbarray.c
${CMAKE_CURRENT_BINARY_DIR}/jscript.def)
add_library(jscript SHARED ${SOURCE} rsrc.rc)
add_idl_headers(jscript_idlheader jscript_classes.idl)
add_typelib(jsglobal.idl)
list(APPEND jscript_rc_deps
${CMAKE_CURRENT_SOURCE_DIR}/jscript.rgs
${CMAKE_CURRENT_SOURCE_DIR}/jscript_classes.rgs
@ -49,16 +40,10 @@ list(APPEND jscript_rc_deps
set_source_files_properties(rsrc.rc PROPERTIES OBJECT_DEPENDS "${jscript_rc_deps}")
# jsglobal.tlb needs stdole2.tlb
add_dependencies(jscript jscript_idlheader stdole2)
if(NOT MSVC)
# FIXME: http://www.cmake.org/Bug/view.php?id=12998
#allow_warnings(jscript)
set_source_files_properties(${SOURCE} PROPERTIES COMPILE_FLAGS "-Wno-error")
endif()
add_library(jscript SHARED ${SOURCE} rsrc.rc)
add_idl_headers(jscript_idlheader jscript_classes.idl)
add_typelib(jsglobal.idl)
add_dependencies(jscript jscript_idlheader stdole2) # jsglobal.tlb needs stdole2.tlb
set_module_type(jscript win32dll)
target_link_libraries(jscript wine)
add_importlibs(jscript user32 ole32 oleaut32 advapi32 msvcrt kernel32 ntdll)

View file

@ -143,7 +143,8 @@ 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;
jsstr_t * progid_str;
const WCHAR *progid;
IDispatch *disp;
IUnknown *obj;
HRESULT hres;
@ -166,12 +167,12 @@ static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
return E_NOTIMPL;
}
hres = to_string(ctx, argv[0], &progid);
hres = to_flat_string(ctx, argv[0], &progid_str, &progid);
if(FAILED(hres))
return hres;
obj = create_activex_object(ctx, progid->str);
jsstr_release(progid);
obj = create_activex_object(ctx, progid);
jsstr_release(progid_str);
if(!obj)
return throw_generic_error(ctx, JS_E_CANNOT_CREATE_OBJ, NULL);

View file

@ -234,7 +234,7 @@ 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)
{
jsstr_t **str_tab, *ret = NULL;
jsstr_t **str_tab, *ret;
jsval_t val;
DWORD i;
HRESULT hres = E_FAIL;
@ -267,7 +267,6 @@ static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, cons
if(SUCCEEDED(hres)) {
DWORD seplen = 0, len = 0;
WCHAR *ptr;
seplen = strlenW(sep);
@ -283,25 +282,26 @@ static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, cons
}
}
if(SUCCEEDED(hres))
ret = jsstr_alloc_buf(len);
if(ret) {
ptr = ret->str;
if(SUCCEEDED(hres)) {
WCHAR *ptr = NULL;
if(str_tab[0])
ptr += jsstr_flush(str_tab[0], ptr);
ptr = jsstr_alloc_buf(len, &ret);
if(ptr) {
if(str_tab[0])
ptr += jsstr_flush(str_tab[0], ptr);
for(i=1; i < length; i++) {
if(seplen) {
memcpy(ptr, sep, seplen*sizeof(WCHAR));
ptr += seplen;
for(i=1; i < length; i++) {
if(seplen) {
memcpy(ptr, sep, seplen*sizeof(WCHAR));
ptr += seplen;
}
if(str_tab[i])
ptr += jsstr_flush(str_tab[i], ptr);
}
if(str_tab[i])
ptr += jsstr_flush(str_tab[i], ptr);
}else {
hres = E_OUTOFMEMORY;
}
}else {
hres = E_OUTOFMEMORY;
}
}
@ -337,15 +337,16 @@ static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigne
return hres;
if(argc) {
jsstr_t *sep;
const WCHAR *sep;
jsstr_t *sep_str;
hres = to_string(ctx, argv[0], &sep);
hres = to_flat_string(ctx, argv[0], &sep_str, &sep);
if(FAILED(hres))
return hres;
hres = array_join(ctx, jsthis, length, sep->str, r);
hres = array_join(ctx, jsthis, length, sep, r);
jsstr_release(sep);
jsstr_release(sep_str);
}else {
hres = array_join(ctx, jsthis, length, default_separatorW, r);
}

View file

@ -771,6 +771,7 @@ static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
}
DEFAULT_UNREACHABLE;
}
return E_FAIL;
}
static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *str)

View file

@ -492,7 +492,7 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset,
BOOL formatAD = TRUE;
WCHAR week[64], month[64];
jsstr_t *date_str;
jsstr_t *date_jsstr;
int len, size, year, day;
DWORD lcid_en;
WCHAR sign = '-';
@ -504,6 +504,8 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset,
}
if(r) {
WCHAR *date_str;
len = 21;
lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
@ -544,25 +546,25 @@ static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset,
offset = -offset;
}
date_str = jsstr_alloc_buf(len);
date_str = jsstr_alloc_buf(len, &date_jsstr);
if(!date_str)
return E_OUTOFMEMORY;
if(!show_offset)
sprintfW(date_str->str, formatNoOffsetW, week, month, day,
sprintfW(date_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->str, formatW, week, month, day,
sprintfW(date_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->str, formatUTCW, week, month, day,
sprintfW(date_str, formatUTCW, week, month, day,
(int)hour_from_time(time), (int)min_from_time(time),
(int)sec_from_time(time), year, formatAD?ADW:BCW);
*r = jsval_string(date_str);
*r = jsval_string(date_jsstr);
}
return S_OK;
}
@ -618,14 +620,18 @@ static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
return dateobj_to_string(date, r);
if(r) {
WCHAR *ptr;
date_len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
time_len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
date_str = jsstr_alloc_buf(date_len+time_len-1);
ptr = jsstr_alloc_buf(date_len+time_len-1, &date_str);
if(!date_str)
return E_OUTOFMEMORY;
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] = ' ';
GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, ptr, date_len);
GetTimeFormatW(ctx->lcid, 0, &st, NULL, ptr+date_len, time_len);
ptr[date_len-1] = ' ';
*r = jsval_string(date_str);
}
@ -681,6 +687,8 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsva
}
if(r) {
WCHAR *ptr;
len = 17;
lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
@ -713,11 +721,11 @@ static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsva
} while(day);
day = date_from_time(date->time);
date_str = jsstr_alloc_buf(len);
ptr = jsstr_alloc_buf(len, &date_str);
if(!date_str)
return E_OUTOFMEMORY;
sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, day, month, year,
sprintfW(ptr, 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));
@ -773,6 +781,8 @@ static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r)
time = local_time(date->time, date);
if(r) {
WCHAR *ptr;
len = 5;
lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
@ -807,10 +817,10 @@ static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r)
} while(day);
day = date_from_time(time);
date_str = jsstr_alloc_buf(len);
if(!date_str)
ptr = jsstr_alloc_buf(len, &date_str);
if(!ptr)
return E_OUTOFMEMORY;
sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, month, day, year);
sprintfW(ptr, formatAD?formatADW:formatBCW, week, month, day, year);
*r = jsval_string(date_str);
}
@ -856,7 +866,9 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
time = local_time(date->time, date);
if(r) {
date_str = jsstr_alloc_buf(17);
WCHAR *ptr;
ptr = jsstr_alloc_buf(17, &date_str);
if(!date_str)
return E_OUTOFMEMORY;
@ -870,11 +882,11 @@ static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
else sign = '-';
if(offset)
sprintfW(date_str->str, formatW, (int)hour_from_time(time),
sprintfW(ptr, 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->str, formatUTCW, (int)hour_from_time(time),
sprintfW(ptr, formatUTCW, (int)hour_from_time(time),
(int)min_from_time(time), (int)sec_from_time(time));
*r = jsval_string(date_str);
@ -908,11 +920,13 @@ static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD
return dateobj_to_date_string(date, r);
if(r) {
WCHAR *ptr;
len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
date_str = jsstr_alloc_buf(len);
if(!date_str)
ptr = jsstr_alloc_buf(len, &date_str);
if(!ptr)
return E_OUTOFMEMORY;
GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str->str, len);
GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, ptr, len);
*r = jsval_string(date_str);
}
@ -945,11 +959,13 @@ static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD
return Date_toTimeString(ctx, jsthis, flags, argc, argv, r);
if(r) {
WCHAR *ptr;
len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
date_str = jsstr_alloc_buf(len);
if(!date_str)
ptr = jsstr_alloc_buf(len, &date_str);
if(!ptr)
return E_OUTOFMEMORY;
GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str->str, len);
GetTimeFormatW(ctx->lcid, 0, &st, NULL, ptr, len);
*r = jsval_string(date_str);
}
@ -2038,7 +2054,9 @@ static inline HRESULT date_parse(jsstr_t *input_str, double *ret) {
DWORD lcid_en;
input_len = jsstr_length(input_str);
input = input_str->str;
input = jsstr_flatten(input_str);
if(!input)
return E_OUTOFMEMORY;
for(i=0; i<input_len; i++) {
if(input[i] == '(') nest_level++;

View file

@ -1524,8 +1524,15 @@ HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL
jsdisp = iface_to_jsdisp((IUnknown*)disp);
if(jsdisp) {
dispex_prop_t *prop;
const WCHAR *ptr;
hres = find_prop_name(jsdisp, string_hash(name->str), name->str, &prop);
ptr = jsstr_flatten(name);
if(!ptr) {
jsdisp_release(jsdisp);
return E_OUTOFMEMORY;
}
hres = find_prop_name(jsdisp, string_hash(ptr), ptr, &prop);
if(prop) {
hres = delete_prop(prop, ret);
}else {

View file

@ -346,7 +346,7 @@ void exec_release(exec_ctx_t *ctx)
heap_free(ctx);
}
static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id)
static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id)
{
IDispatchEx *dispex;
jsdisp_t *jsdisp;
@ -375,7 +375,7 @@ static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, WCHAR *name, BSTR
IDispatchEx_Release(dispex);
}else {
TRACE("using IDispatch\n");
hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, id);
}
if(name_bstr != bstr)
@ -729,10 +729,12 @@ static HRESULT interp_throw_type(exec_ctx_t *ctx)
{
const HRESULT hres = get_op_uint(ctx, 0);
jsstr_t *str = get_op_str(ctx, 1);
const WCHAR *ptr;
TRACE("%08x %s\n", hres, debugstr_jsstr(str));
return throw_type_error(ctx->script, hres, str->str);
ptr = jsstr_flatten(str);
return ptr ? throw_type_error(ctx->script, hres, ptr) : E_OUTOFMEMORY;
}
/* ECMA-262 3rd Edition 12.14 */
@ -828,9 +830,10 @@ static HRESULT interp_func(exec_ctx_t *ctx)
/* ECMA-262 3rd Edition 11.2.1 */
static HRESULT interp_array(exec_ctx_t *ctx)
{
jsstr_t *name_str;
const WCHAR *name;
jsval_t v, namev;
IDispatch *obj;
jsstr_t *name;
DISPID id;
HRESULT hres;
@ -844,15 +847,15 @@ static HRESULT interp_array(exec_ctx_t *ctx)
return hres;
}
hres = to_string(ctx->script, namev, &name);
hres = to_flat_string(ctx->script, namev, &name_str, &name);
jsval_release(namev);
if(FAILED(hres)) {
IDispatch_Release(obj);
return hres;
}
hres = disp_get_id(ctx->script, obj, name->str, NULL, 0, &id);
jsstr_release(name);
hres = disp_get_id(ctx->script, obj, name, NULL, 0, &id);
jsstr_release(name_str);
if(SUCCEEDED(hres)) {
hres = disp_propget(ctx->script, obj, id, &v);
}else if(hres == DISP_E_UNKNOWNNAME) {
@ -900,8 +903,9 @@ static HRESULT interp_memberid(exec_ctx_t *ctx)
{
const unsigned arg = get_op_uint(ctx, 0);
jsval_t objv, namev;
const WCHAR *name;
jsstr_t *name_str;
IDispatch *obj;
jsstr_t *name;
DISPID id;
HRESULT hres;
@ -913,7 +917,7 @@ static HRESULT interp_memberid(exec_ctx_t *ctx)
hres = to_object(ctx->script, objv, &obj);
jsval_release(objv);
if(SUCCEEDED(hres)) {
hres = to_string(ctx->script, namev, &name);
hres = to_flat_string(ctx->script, namev, &name_str, &name);
if(FAILED(hres))
IDispatch_Release(obj);
}
@ -921,8 +925,8 @@ static HRESULT interp_memberid(exec_ctx_t *ctx)
if(FAILED(hres))
return hres;
hres = disp_get_id(ctx->script, obj, name->str, NULL, arg, &id);
jsstr_release(name);
hres = disp_get_id(ctx->script, obj, name, NULL, arg, &id);
jsstr_release(name_str);
if(FAILED(hres)) {
IDispatch_Release(obj);
if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
@ -1392,10 +1396,11 @@ static HRESULT interp_instanceof(exec_ctx_t *ctx)
/* ECMA-262 3rd Edition 11.8.7 */
static HRESULT interp_in(exec_ctx_t *ctx)
{
const WCHAR *str;
jsstr_t *jsstr;
jsval_t obj, v;
DISPID id = 0;
BOOL ret;
jsstr_t *str;
HRESULT hres;
TRACE("\n");
@ -1407,16 +1412,16 @@ static HRESULT interp_in(exec_ctx_t *ctx)
}
v = stack_pop(ctx);
hres = to_string(ctx->script, v, &str);
hres = to_flat_string(ctx->script, v, &jsstr, &str);
jsval_release(v);
if(FAILED(hres)) {
IDispatch_Release(get_object(obj));
return hres;
}
hres = disp_get_id(ctx->script, get_object(obj), str->str, NULL, 0, &id);
hres = disp_get_id(ctx->script, get_object(obj), str, NULL, 0, &id);
IDispatch_Release(get_object(obj));
jsstr_release(str);
jsstr_release(jsstr);
if(SUCCEEDED(hres))
ret = TRUE;
else if(hres == DISP_E_UNKNOWNNAME)
@ -2001,11 +2006,11 @@ static HRESULT interp_eq2(exec_ctx_t *ctx)
BOOL b;
HRESULT hres;
TRACE("\n");
r = stack_pop(ctx);
l = stack_pop(ctx);
TRACE("%s === %s\n", debugstr_jsval(l), debugstr_jsval(r));
hres = equal2_values(r, l, &b);
jsval_release(l);
jsval_release(r);

View file

@ -82,12 +82,16 @@ static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags,
unsigned msg_len = msg ? jsstr_length(msg) : 0;
if(name_len && msg_len) {
ret = jsstr_alloc_buf(name_len + msg_len + 2);
if(ret) {
jsstr_flush(name, ret->str);
ret->str[name_len] = ':';
ret->str[name_len+1] = ' ';
jsstr_flush(msg, ret->str+name_len+2);
WCHAR *ptr;
ptr = jsstr_alloc_buf(name_len + msg_len + 2, &ret);
if(ptr) {
jsstr_flush(name, ptr);
ptr[name_len] = ':';
ptr[name_len+1] = ' ';
jsstr_flush(msg, ptr+name_len+2);
}else {
hres = E_OUTOFMEMORY;
}
}else if(name_len) {
ret = name;

View file

@ -318,15 +318,16 @@ static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret)
if(function->value_proc) {
DWORD name_len;
WCHAR *ptr;
name_len = strlenW(function->name);
str = jsstr_alloc_buf((sizeof(native_prefixW)+sizeof(native_suffixW))/sizeof(WCHAR) + name_len);
if(!str)
ptr = jsstr_alloc_buf((sizeof(native_prefixW)+sizeof(native_suffixW))/sizeof(WCHAR) + name_len, &str);
if(!ptr)
return E_OUTOFMEMORY;
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));
memcpy(ptr, native_prefixW, sizeof(native_prefixW));
memcpy(ptr += sizeof(native_prefixW)/sizeof(WCHAR), function->name, name_len*sizeof(WCHAR));
memcpy(ptr + name_len, native_suffixW, sizeof(native_suffixW));
}else {
str = jsstr_alloc_len(function->func_code->source, function->func_code->source_len);
if(!str)

View file

@ -278,7 +278,7 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
jsval_t *r)
{
jsstr_t *ret_str, *str;
const WCHAR *ptr;
const WCHAR *ptr, *buf;
DWORD len = 0;
WCHAR *ret;
HRESULT hres;
@ -291,11 +291,11 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
return S_OK;
}
hres = to_string(ctx, argv[0], &str);
hres = to_flat_string(ctx, argv[0], &str, &buf);
if(FAILED(hres))
return hres;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = buf; *ptr; ptr++) {
if(*ptr > 0xff)
len += 6;
else if(is_ecma_nonblank(*ptr))
@ -304,15 +304,14 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
len += 3;
}
ret_str = jsstr_alloc_buf(len);
if(!ret_str) {
ret = jsstr_alloc_buf(len, &ret_str);
if(!ret) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
len = 0;
ret = ret_str->str;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = buf; *ptr; ptr++) {
if(*ptr > 0xff) {
ret[len++] = '%';
ret[len++] = 'u';
@ -344,6 +343,7 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
jsval_t *r)
{
bytecode_t *code;
const WCHAR *src;
HRESULT hres;
TRACE("\n");
@ -365,8 +365,12 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
return E_UNEXPECTED;
}
src = jsstr_flatten(get_string(argv[0]));
if(!src)
return E_OUTOFMEMORY;
TRACE("parsing %s\n", debugstr_jsval(argv[0]));
hres = compile_script(ctx, get_string(argv[0])->str, NULL, NULL, TRUE, FALSE, &code);
hres = compile_script(ctx, src, 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);
@ -439,10 +443,10 @@ static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
jsval_t *r)
{
BOOL neg = FALSE, empty = TRUE;
const WCHAR *ptr;
DOUBLE ret = 0.0;
INT radix=0, i;
jsstr_t *str;
WCHAR *ptr;
HRESULT hres;
if(!argc) {
@ -464,11 +468,12 @@ static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
}
}
hres = to_string(ctx, argv[0], &str);
hres = to_flat_string(ctx, argv[0], &str, &ptr);
if(FAILED(hres))
return hres;
for(ptr = str->str; isspaceW(*ptr); ptr++);
while(isspaceW(*ptr))
ptr++;
switch(*ptr) {
case '+':
@ -521,7 +526,7 @@ static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
LONGLONG d = 0, hlp;
jsstr_t *val_str;
int exp = 0;
WCHAR *str;
const WCHAR *str;
BOOL ret_nan = TRUE, positive = TRUE;
HRESULT hres;
@ -531,12 +536,10 @@ static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flag
return S_OK;
}
hres = to_string(ctx, argv[0], &val_str);
hres = to_flat_string(ctx, argv[0], &val_str, &str);
if(FAILED(hres))
return hres;
str = val_str->str;
while(isspaceW(*str)) str++;
if(*str == '+')
@ -626,7 +629,7 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
jsval_t *r)
{
jsstr_t *ret_str, *str;
const WCHAR *ptr;
const WCHAR *ptr, *buf;
DWORD len = 0;
WCHAR *ret;
HRESULT hres;
@ -639,11 +642,11 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
return S_OK;
}
hres = to_string(ctx, argv[0], &str);
hres = to_flat_string(ctx, argv[0], &str, &buf);
if(FAILED(hres))
return hres;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = buf; *ptr; ptr++) {
if(*ptr == '%') {
if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1)
ptr += 2;
@ -655,15 +658,14 @@ static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
len++;
}
ret_str = jsstr_alloc_buf(len);
if(!ret_str) {
ret = jsstr_alloc_buf(len, &ret_str);
if(!ret) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
ret = ret_str->str;
len = 0;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = buf; *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));
@ -760,8 +762,8 @@ 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)
{
const WCHAR *ptr, *uri;
jsstr_t *str, *ret;
const WCHAR *ptr;
DWORD len = 0, i;
char buf[4];
WCHAR *rptr;
@ -775,11 +777,11 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
return S_OK;
}
hres = to_string(ctx, argv[0], &str);
hres = to_flat_string(ctx, argv[0], &str, &uri);
if(FAILED(hres))
return hres;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = uri; *ptr; ptr++) {
if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
len++;
}else {
@ -793,14 +795,13 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
}
}
ret = jsstr_alloc_buf(len);
if(!ret) {
rptr = jsstr_alloc_buf(len, &ret);
if(!rptr) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
rptr = ret->str;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = uri; *ptr; ptr++) {
if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
*rptr++ = *ptr;
}else {
@ -826,9 +827,11 @@ static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
{
jsstr_t *str, *ret;
WCHAR *ptr;
int i, len = 0, val, res;
const WCHAR *ptr, *uri;
jsstr_t *str, *ret_str;
unsigned len = 0;
int i, val, res;
WCHAR *ret;
char buf[4];
WCHAR out;
HRESULT hres;
@ -841,11 +844,11 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
return S_OK;
}
hres = to_string(ctx, argv[0], &str);
hres = to_flat_string(ctx, argv[0], &str, &uri);
if(FAILED(hres))
return hres;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = uri; *ptr; ptr++) {
if(*ptr != '%') {
len++;
}else {
@ -871,17 +874,15 @@ static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
}
}
ret = jsstr_alloc_buf(len);
ret = jsstr_alloc_buf(len, &ret_str);
if(!ret) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
len = 0;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = uri; *ptr; ptr++) {
if(*ptr != '%') {
ret->str[len] = *ptr;
len++;
*ret++ = *ptr;
}else {
for(i=0; i<4; i++) {
if(ptr[i*3]!='%' || hex_to_int(ptr[i*3+1])==-1 || (val=hex_to_int(ptr[i*3+2]))==-1)
@ -889,33 +890,34 @@ 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->str+len, 1);
res = MultiByteToWideChar(CP_UTF8, 0, buf, i+1, ret, 1);
if(res)
break;
}
ptr += i*3+2;
len++;
ret++;
}
}
TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret));
TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret_str));
jsstr_release(str);
if(r)
*r = jsval_string(ret);
*r = jsval_string(ret_str);
else
jsstr_release(ret);
jsstr_release(ret_str);
return S_OK;
}
static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
{
jsstr_t *str, *ret;
jsstr_t *str, *ret_str;
char buf[4];
const WCHAR *ptr;
const WCHAR *ptr, *uri;
DWORD len = 0, size, i;
WCHAR *ret;
HRESULT hres;
TRACE("\n");
@ -926,11 +928,11 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
return S_OK;
}
hres = to_string(ctx, argv[0], &str);
hres = to_flat_string(ctx, argv[0], &str, &uri);
if(FAILED(hres))
return hres;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = uri; *ptr; ptr++) {
if(is_uri_unescaped(*ptr))
len++;
else {
@ -943,22 +945,21 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
}
}
ret = jsstr_alloc_buf(len);
ret = jsstr_alloc_buf(len, &ret_str);
if(!ret) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
len = 0;
for(ptr = str->str; *ptr; ptr++) {
for(ptr = uri; *ptr; ptr++) {
if(is_uri_unescaped(*ptr)) {
ret->str[len++] = *ptr;
*ret++ = *ptr;
}else {
size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, buf, sizeof(buf), NULL, NULL);
for(i=0; i<size; i++) {
ret->str[len++] = '%';
ret->str[len++] = int_to_char((BYTE)buf[i] >> 4);
ret->str[len++] = int_to_char(buf[i] & 0x0f);
*ret++ = '%';
*ret++ = int_to_char((BYTE)buf[i] >> 4);
*ret++ = int_to_char(buf[i] & 0x0f);
}
}
}
@ -966,9 +967,9 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
jsstr_release(str);
if(r)
*r = jsval_string(ret);
*r = jsval_string(ret_str);
else
jsstr_release(ret);
jsstr_release(ret_str);
return S_OK;
}
@ -976,8 +977,8 @@ 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)
{
const WCHAR *ptr, *uri;
jsstr_t *str, *ret;
const WCHAR *ptr;
WCHAR *out_ptr;
DWORD len = 0;
HRESULT hres;
@ -990,11 +991,11 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
return S_OK;
}
hres = to_string(ctx, argv[0], &str);
hres = to_flat_string(ctx, argv[0], &str, &uri);
if(FAILED(hres))
return hres;
ptr = str->str;
ptr = uri;
while(*ptr) {
if(*ptr == '%') {
char octets[4];
@ -1044,14 +1045,13 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
}
}
ret = jsstr_alloc_buf(len);
out_ptr = jsstr_alloc_buf(len, &ret);
if(!ret) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
out_ptr = ret->str;
ptr = str->str;
ptr = uri;
while(*ptr) {
if(*ptr == '%') {
char octets[4];

View file

@ -326,6 +326,7 @@ 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,UINT32*) DECLSPEC_HIDDEN;
HRESULT to_string(script_ctx_t*,jsval_t,jsstr_t**) DECLSPEC_HIDDEN;
HRESULT to_flat_string(script_ctx_t*,jsval_t,jsstr_t**,const WCHAR**) 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;

View file

@ -144,6 +144,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
return FALSE;
break;
case DLL_PROCESS_DETACH:
if (lpv) break;
free_strings();
}

View file

@ -73,12 +73,12 @@ static void set_last_index(RegExpInstance *This, DWORD last_index)
}
static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
DWORD rem_flags, jsstr_t *str, match_state_t *ret)
DWORD rem_flags, jsstr_t *jsstr, const WCHAR *str, match_state_t *ret)
{
HRESULT hres;
hres = regexp_execute(regexp->jsregexp, ctx, &ctx->tmp_heap,
str->str, jsstr_length(str), ret);
str, jsstr_length(jsstr), ret);
if(FAILED(hres))
return hres;
if(hres == S_FALSE) {
@ -87,9 +87,9 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
return S_FALSE;
}
if(!(rem_flags & REM_NO_CTX_UPDATE) && ctx->last_match != str) {
if(!(rem_flags & REM_NO_CTX_UPDATE) && ctx->last_match != jsstr) {
jsstr_release(ctx->last_match);
ctx->last_match = jsstr_addref(str);
ctx->last_match = jsstr_addref(jsstr);
}
if(!(rem_flags & REM_NO_CTX_UPDATE)) {
@ -109,10 +109,10 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
memset(ctx->match_parens+n, 0, sizeof(ctx->match_parens) - n*sizeof(ctx->match_parens[0]));
}
set_last_index(regexp, ret->cp-str->str);
set_last_index(regexp, ret->cp-str);
if(!(rem_flags & REM_NO_CTX_UPDATE)) {
ctx->last_match_index = ret->cp-str->str-ret->match_len;
ctx->last_match_index = ret->cp-str-ret->match_len;
ctx->last_match_length = ret->match_len;
}
@ -120,11 +120,12 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
}
HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
DWORD rem_flags, jsstr_t *str, match_state_t **ret)
DWORD rem_flags, jsstr_t *jsstr, match_state_t **ret)
{
RegExpInstance *regexp = (RegExpInstance*)dispex;
match_state_t *match;
heap_pool_t *mark;
const WCHAR *str;
HRESULT hres;
if((rem_flags & REM_CHECK_GLOBAL) && !(regexp->jsregexp->flags & REG_GLOB)) {
@ -133,8 +134,12 @@ HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
return S_FALSE;
}
str = jsstr_flatten(jsstr);
if(!str)
return E_OUTOFMEMORY;
if(rem_flags & REM_ALLOC_RESULT) {
match = alloc_match_state(regexp->jsregexp, NULL, str->str);
match = alloc_match_state(regexp->jsregexp, NULL, str);
if(!match)
return E_OUTOFMEMORY;
*ret = match;
@ -154,7 +159,7 @@ HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
match = *ret;
}
hres = do_regexp_match_next(ctx, regexp, rem_flags, str, match);
hres = do_regexp_match_next(ctx, regexp, rem_flags, jsstr, str, match);
if(rem_flags & REM_NO_PARENS) {
(*ret)->cp = match->cp;
@ -171,7 +176,7 @@ HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
return hres;
}
static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, BOOL gflag,
static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *jsstr, BOOL gflag,
match_result_t **match_result, DWORD *result_cnt)
{
RegExpInstance *This = (RegExpInstance*)dispex;
@ -179,18 +184,23 @@ static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, B
match_state_t *result;
DWORD i=0, ret_size = 0;
heap_pool_t *mark;
const WCHAR *str;
HRESULT hres;
mark = heap_pool_mark(&ctx->tmp_heap);
result = alloc_match_state(This->jsregexp, &ctx->tmp_heap, str->str);
str = jsstr_flatten(jsstr);
if(!str)
return E_OUTOFMEMORY;
result = alloc_match_state(This->jsregexp, &ctx->tmp_heap, str);
if(!result) {
heap_pool_clear(mark);
return E_OUTOFMEMORY;
}
while(1) {
hres = do_regexp_match_next(ctx, This, 0, str, result);
hres = do_regexp_match_next(ctx, This, 0, jsstr, str, result);
if(hres == S_FALSE) {
hres = S_OK;
break;
@ -215,7 +225,7 @@ static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, B
}
}
ret[i].index = result->cp - str->str - result->match_len;
ret[i].index = result->cp - str - result->match_len;
ret[i++].length = result->match_len;
if(!gflag && !(This->jsregexp->flags & REG_GLOB)) {
@ -323,13 +333,56 @@ static HRESULT RegExp_lastIndex(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
static HRESULT RegExp_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
RegExpInstance *regexp;
unsigned len, f;
jsstr_t *ret;
WCHAR *ptr;
TRACE("\n");
if(!is_vclass(jsthis, JSCLASS_REGEXP)) {
FIXME("Not a RegExp\n");
return E_NOTIMPL;
}
regexp = regexp_from_vdisp(jsthis);
if(!r)
return S_OK;
len = jsstr_length(regexp->str) + 2;
f = regexp->jsregexp->flags;
if(f & REG_FOLD)
len++;
if(f & REG_GLOB)
len++;
if(f & REG_MULTILINE)
len++;
ptr = jsstr_alloc_buf(len, &ret);
if(!ptr)
return E_OUTOFMEMORY;
*ptr++ = '/';
ptr += jsstr_flush(regexp->str, ptr);
*ptr++ = '/';
if(f & REG_FOLD)
*ptr++ = 'i';
if(f & REG_GLOB)
*ptr++ = 'g';
if(f & REG_MULTILINE)
*ptr++ = 'm';
*r = jsval_string(ret);
return S_OK;
}
static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input,
static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input_str,
const match_state_t *result, IDispatch **ret)
{
const WCHAR *input;
jsdisp_t *array;
jsstr_t *str;
DWORD i;
@ -340,13 +393,17 @@ static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input,
static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};
static const WCHAR zeroW[] = {'0',0};
input = jsstr_flatten(input_str);
if(!input)
return E_OUTOFMEMORY;
hres = create_array(ctx, result->paren_count+1, &array);
if(FAILED(hres))
return hres;
for(i=0; i < result->paren_count; i++) {
if(result->parens[i].index != -1)
str = jsstr_substr(input, result->parens[i].index, result->parens[i].length);
str = jsstr_substr(input_str, result->parens[i].index, result->parens[i].length);
else
str = jsstr_empty();
if(!str) {
@ -361,15 +418,15 @@ static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input,
}
while(SUCCEEDED(hres)) {
hres = jsdisp_propput_name(array, indexW, jsval_number(result->cp-input->str-result->match_len));
hres = jsdisp_propput_name(array, indexW, jsval_number(result->cp-input-result->match_len));
if(FAILED(hres))
break;
hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->cp-input->str));
hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->cp-input));
if(FAILED(hres))
break;
hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr_addref(input)));
hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr_addref(input_str)));
if(FAILED(hres))
break;
@ -398,7 +455,8 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg,
RegExpInstance *regexp;
match_state_t *match;
DWORD last_index = 0;
jsstr_t *string;
const WCHAR *string;
jsstr_t *jsstr;
HRESULT hres;
if(!is_vclass(jsthis, JSCLASS_REGEXP)) {
@ -408,13 +466,13 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg,
regexp = regexp_from_vdisp(jsthis);
hres = to_string(ctx, arg, &string);
hres = to_flat_string(ctx, arg, &jsstr, &string);
if(FAILED(hres))
return hres;
if(regexp->jsregexp->flags & REG_GLOB) {
if(regexp->last_index < 0) {
jsstr_release(string);
jsstr_release(jsstr);
set_last_index(regexp, 0);
*ret = FALSE;
if(input)
@ -425,24 +483,24 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg,
last_index = regexp->last_index;
}
match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, string->str+last_index);
match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, string+last_index);
if(!match) {
jsstr_release(string);
jsstr_release(jsstr);
return E_OUTOFMEMORY;
}
hres = regexp_match_next(ctx, &regexp->dispex, REM_RESET_INDEX, string, &match);
hres = regexp_match_next(ctx, &regexp->dispex, REM_RESET_INDEX, jsstr, &match);
if(FAILED(hres)) {
jsstr_release(string);
jsstr_release(jsstr);
return hres;
}
*result = match;
*ret = hres == S_OK;
if(input)
*input = string;
*input = jsstr;
else
jsstr_release(string);
jsstr_release(jsstr);
return S_OK;
}
@ -596,10 +654,15 @@ static HRESULT alloc_regexp(script_ctx_t *ctx, jsdisp_t *object_prototype, RegEx
HRESULT create_regexp(script_ctx_t *ctx, jsstr_t *src, DWORD flags, jsdisp_t **ret)
{
RegExpInstance *regexp;
const WCHAR *str;
HRESULT hres;
TRACE("%s %x\n", debugstr_jsstr(src), flags);
str = jsstr_flatten(src);
if(!str)
return E_OUTOFMEMORY;
hres = alloc_regexp(ctx, NULL, &regexp);
if(FAILED(hres))
return hres;
@ -607,9 +670,8 @@ HRESULT create_regexp(script_ctx_t *ctx, jsstr_t *src, DWORD flags, jsdisp_t **r
regexp->str = jsstr_addref(src);
regexp->last_index_val = jsval_number(0);
regexp->jsregexp = regexp_new(ctx, &ctx->tmp_heap, regexp->str->str,
jsstr_length(regexp->str), flags, FALSE);
if(FAILED(hres)) {
regexp->jsregexp = regexp_new(ctx, &ctx->tmp_heap, str, jsstr_length(regexp->str), flags, FALSE);
if(!regexp->jsregexp) {
WARN("regexp_new failed\n");
jsdisp_release(&regexp->dispex);
return E_FAIL;
@ -621,8 +683,9 @@ HRESULT create_regexp(script_ctx_t *ctx, jsstr_t *src, DWORD flags, jsdisp_t **r
HRESULT create_regexp_var(script_ctx_t *ctx, jsval_t src_arg, jsval_t *flags_arg, jsdisp_t **ret)
{
jsstr_t *src, *opt = NULL;
DWORD flags;
unsigned flags, opt_len = 0;
const WCHAR *opt = NULL;
jsstr_t *src;
HRESULT hres;
if(is_object_instance(src_arg)) {
@ -650,22 +713,28 @@ HRESULT create_regexp_var(script_ctx_t *ctx, jsval_t src_arg, jsval_t *flags_arg
src = get_string(src_arg);
if(flags_arg) {
jsstr_t *opt_str;
if(!is_string(*flags_arg)) {
FIXME("unimplemented for %s\n", debugstr_jsval(*flags_arg));
return E_NOTIMPL;
}
opt = get_string(*flags_arg);
opt_str = get_string(*flags_arg);
opt = jsstr_flatten(opt_str);
if(!opt)
return E_OUTOFMEMORY;
opt_len = jsstr_length(opt_str);
}
hres = parse_regexp_flags(opt ? opt->str : NULL, opt ? jsstr_length(opt) : 0, &flags);
hres = parse_regexp_flags(opt, opt_len, &flags);
if(FAILED(hres))
return hres;
return create_regexp(ctx, src, flags, ret);
}
HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval_t *r)
HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *jsstr, jsval_t *r)
{
static const WCHAR indexW[] = {'i','n','d','e','x',0};
static const WCHAR inputW[] = {'i','n','p','u','t',0};
@ -674,21 +743,26 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
RegExpInstance *regexp = (RegExpInstance*)re;
match_result_t *match_result;
unsigned match_cnt, i;
const WCHAR *str;
jsdisp_t *array;
HRESULT hres;
str = jsstr_flatten(jsstr);
if(!str)
return E_OUTOFMEMORY;
if(!(regexp->jsregexp->flags & REG_GLOB)) {
match_state_t *match;
heap_pool_t *mark;
mark = heap_pool_mark(&ctx->tmp_heap);
match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, str->str);
match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, str);
if(!match) {
heap_pool_clear(mark);
return E_OUTOFMEMORY;
}
hres = regexp_match_next(ctx, &regexp->dispex, 0, str, &match);
hres = regexp_match_next(ctx, &regexp->dispex, 0, jsstr, &match);
if(FAILED(hres)) {
heap_pool_clear(mark);
return hres;
@ -698,7 +772,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
if(hres == S_OK) {
IDispatch *ret;
hres = create_match_array(ctx, str, match, &ret);
hres = create_match_array(ctx, jsstr, match, &ret);
if(SUCCEEDED(hres))
*r = jsval_disp(ret);
}else {
@ -710,7 +784,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
return S_OK;
}
hres = regexp_match(ctx, &regexp->dispex, str, FALSE, &match_result, &match_cnt);
hres = regexp_match(ctx, &regexp->dispex, jsstr, FALSE, &match_result, &match_cnt);
if(FAILED(hres))
return hres;
@ -729,7 +803,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
for(i=0; i < match_cnt; i++) {
jsstr_t *tmp_str;
tmp_str = jsstr_substr(str, match_result[i].index, match_result[i].length);
tmp_str = jsstr_substr(jsstr, match_result[i].index, match_result[i].length);
if(!tmp_str) {
hres = E_OUTOFMEMORY;
break;
@ -751,7 +825,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
if(FAILED(hres))
break;
hres = jsdisp_propput_name(array, inputW, jsval_string(str));
hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr));
break;
}

View file

@ -16,60 +16,203 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include "jscript.h"
#include <wine/debug.h>
/*
* This is the length of a string that is considered to be long enough to be
* worth the rope to avoid copy.
* This probably could be tuned, but keep it low for a while to better test rope's code.
*/
#define JSSTR_SHORT_STRING_LENGTH 8
/*
* This is the max rope depth. While faster to allocate, ropes may become slow at access.
*/
#define JSSTR_MAX_ROPE_DEPTH 100
const char *debugstr_jsstr(jsstr_t *str)
{
return debugstr_wn(str->str, jsstr_length(str));
return jsstr_is_inline(str) ? debugstr_wn(jsstr_as_inline(str)->buf, jsstr_length(str))
: jsstr_is_heap(str) ? debugstr_wn(jsstr_as_heap(str)->buf, jsstr_length(str))
: wine_dbg_sprintf("%s...", debugstr_jsstr(jsstr_as_rope(str)->left));
}
jsstr_t *jsstr_alloc_buf(unsigned len)
void jsstr_free(jsstr_t *str)
{
jsstr_t *ret;
switch(jsstr_tag(str)) {
case JSSTR_HEAP:
heap_free(jsstr_as_heap(str)->buf);
break;
case JSSTR_ROPE: {
jsstr_rope_t *rope = jsstr_as_rope(str);
jsstr_release(rope->left);
jsstr_release(rope->right);
break;
}
case JSSTR_INLINE:
break;
}
heap_free(str);
}
static inline void jsstr_init(jsstr_t *str, unsigned len, jsstr_tag_t tag)
{
str->length_flags = len << JSSTR_LENGTH_SHIFT | tag;
str->ref = 1;
}
WCHAR *jsstr_alloc_buf(unsigned len, jsstr_t **r)
{
jsstr_inline_t *ret;
if(len > JSSTR_MAX_LENGTH)
return NULL;
ret = heap_alloc(FIELD_OFFSET(jsstr_t, str[len+1]));
ret = heap_alloc(FIELD_OFFSET(jsstr_inline_t, buf[len+1]));
if(!ret)
return NULL;
ret->length_flags = len << JSSTR_LENGTH_SHIFT;
ret->ref = 1;
ret->str[len] = 0;
return ret;
jsstr_init(&ret->str, len, JSSTR_INLINE);
ret->buf[len] = 0;
*r = &ret->str;
return ret->buf;
}
jsstr_t *jsstr_alloc_len(const WCHAR *buf, unsigned len)
{
jsstr_t *ret;
WCHAR *ptr;
ret = jsstr_alloc_buf(len);
if(ret)
memcpy(ret->str, buf, len*sizeof(WCHAR));
ptr = jsstr_alloc_buf(len, &ret);
if(ptr)
memcpy(ptr, buf, len*sizeof(WCHAR));
return ret;
}
int jsstr_cmp(jsstr_t *str1, jsstr_t *str2)
static void jsstr_rope_extract(jsstr_rope_t *str, unsigned off, unsigned len, WCHAR *buf)
{
unsigned left_len = jsstr_length(str->left);
if(left_len <= off) {
jsstr_extract(str->right, off-left_len, len, buf);
}else if(left_len >= len+off) {
jsstr_extract(str->left, off, len, buf);
}else {
left_len -= off;
jsstr_extract(str->left, off, left_len, buf);
jsstr_extract(str->right, 0, len-left_len, buf+left_len);
}
}
void jsstr_extract(jsstr_t *str, unsigned off, unsigned len, WCHAR *buf)
{
switch(jsstr_tag(str)) {
case JSSTR_INLINE:
memcpy(buf, jsstr_as_inline(str)->buf+off, len*sizeof(WCHAR));
return;
case JSSTR_HEAP:
memcpy(buf, jsstr_as_heap(str)->buf+off, len*sizeof(WCHAR));
return;
case JSSTR_ROPE:
jsstr_rope_extract(jsstr_as_rope(str), off, len, buf);
return;
}
}
static int jsstr_cmp_str(jsstr_t *jsstr, const WCHAR *str, unsigned len)
{
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;
switch(jsstr_tag(jsstr)) {
case JSSTR_INLINE:
ret = memcmp(jsstr_as_inline(jsstr)->buf, str, len*sizeof(WCHAR));
return ret || jsstr_length(jsstr) == len ? ret : 1;
case JSSTR_HEAP:
ret = memcmp(jsstr_as_heap(jsstr)->buf, str, len*sizeof(WCHAR));
return ret || jsstr_length(jsstr) == len ? ret : 1;
case JSSTR_ROPE: {
jsstr_rope_t *rope = jsstr_as_rope(jsstr);
unsigned left_len = jsstr_length(rope->left);
return ret;
ret = jsstr_cmp_str(rope->left, str, min(len, left_len));
if(ret || len <= left_len)
return ret;
return jsstr_cmp_str(rope->right, str+left_len, len-left_len);
}
}
assert(0);
return 0;
}
#define TMP_BUF_SIZE 256
static int ropes_cmp(jsstr_rope_t *left, jsstr_rope_t *right)
{
WCHAR left_buf[TMP_BUF_SIZE], right_buf[TMP_BUF_SIZE];
unsigned left_len = jsstr_length(&left->str);
unsigned right_len = jsstr_length(&right->str);
unsigned cmp_off = 0, cmp_size;
int ret;
/* FIXME: We can avoid temporary buffers here. */
while(cmp_off < min(left_len, right_len)) {
cmp_size = min(left_len, right_len) - cmp_off;
if(cmp_size > TMP_BUF_SIZE)
cmp_size = TMP_BUF_SIZE;
jsstr_rope_extract(left, cmp_off, cmp_size, left_buf);
jsstr_rope_extract(right, cmp_off, cmp_size, right_buf);
ret = memcmp(left_buf, right_buf, cmp_size);
if(ret)
return ret;
cmp_off += cmp_size;
}
return left_len - right_len;
}
static inline const WCHAR *jsstr_try_flat(jsstr_t *str)
{
return jsstr_is_inline(str) ? jsstr_as_inline(str)->buf
: jsstr_is_heap(str) ? jsstr_as_heap(str)->buf
: NULL;
}
int jsstr_cmp(jsstr_t *str1, jsstr_t *str2)
{
unsigned len1 = jsstr_length(str1);
unsigned len2 = jsstr_length(str2);
const WCHAR *str;
int ret;
str = jsstr_try_flat(str2);
if(str) {
ret = jsstr_cmp_str(str1, str, min(len1, len2));
return ret || len1 == len2 ? ret : -1;
}
str = jsstr_try_flat(str1);
if(str) {
ret = jsstr_cmp_str(str2, str, min(len1, len2));
return ret || len1 == len2 ? -ret : 1;
}
return ropes_cmp(jsstr_as_rope(str1), jsstr_as_rope(str2));
}
jsstr_t *jsstr_concat(jsstr_t *str1, jsstr_t *str2)
{
unsigned len1, len2;
jsstr_t *ret;
WCHAR *ptr;
len1 = jsstr_length(str1);
if(!len1)
@ -79,16 +222,63 @@ jsstr_t *jsstr_concat(jsstr_t *str1, jsstr_t *str2)
if(!len2)
return jsstr_addref(str1);
ret = jsstr_alloc_buf(len1+len2);
if(len1 + len2 >= JSSTR_SHORT_STRING_LENGTH) {
unsigned depth, depth2;
jsstr_rope_t *rope;
depth = jsstr_is_rope(str1) ? jsstr_as_rope(str1)->depth : 0;
depth2 = jsstr_is_rope(str2) ? jsstr_as_rope(str2)->depth : 0;
if(depth2 > depth)
depth = depth2;
if(depth++ < JSSTR_MAX_ROPE_DEPTH) {
if(len1+len2 > JSSTR_MAX_LENGTH)
return NULL;
rope = heap_alloc(sizeof(*rope));
if(!rope)
return NULL;
jsstr_init(&rope->str, len1+len2, JSSTR_ROPE);
rope->left = jsstr_addref(str1);
rope->right = jsstr_addref(str2);
rope->depth = depth;
return &rope->str;
}
}
ptr = jsstr_alloc_buf(len1+len2, &ret);
if(!ret)
return NULL;
jsstr_flush(str1, ret->str);
jsstr_flush(str2, ret->str+len1);
jsstr_flush(str1, ptr);
jsstr_flush(str2, ptr+len1);
return ret;
}
static jsstr_t *empty_str, *nan_str, *undefined_str;
C_ASSERT(sizeof(jsstr_heap_t) <= sizeof(jsstr_rope_t));
const WCHAR *jsstr_rope_flatten(jsstr_rope_t *str)
{
WCHAR *buf;
buf = heap_alloc((jsstr_length(&str->str)+1) * sizeof(WCHAR));
if(!buf)
return NULL;
jsstr_flush(str->left, buf);
jsstr_flush(str->right, buf+jsstr_length(str->left));
buf[jsstr_length(&str->str)] = 0;
/* Trasform to heap string */
jsstr_release(str->left);
jsstr_release(str->right);
str->str.length_flags |= JSSTR_FLAG_FLAT;
return jsstr_as_heap(&str->str)->buf = buf;
}
static jsstr_t *empty_str, *nan_str, *undefined_str, *null_bstr_str;
jsstr_t *jsstr_nan(void)
{
@ -105,23 +295,40 @@ jsstr_t *jsstr_undefined(void)
return jsstr_addref(undefined_str);
}
jsstr_t *jsstr_null_bstr(void)
{
return jsstr_addref(null_bstr_str);
}
BOOL is_null_bstr(jsstr_t *str)
{
return str == null_bstr_str;
}
BOOL init_strings(void)
{
static const WCHAR NaNW[] = { 'N','a','N',0 };
static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
if(!(empty_str = jsstr_alloc_buf(0)))
if(!jsstr_alloc_buf(0, &empty_str))
return FALSE;
if(!(nan_str = jsstr_alloc(NaNW)))
return FALSE;
if(!(undefined_str = jsstr_alloc(undefinedW)))
return FALSE;
return TRUE;
if(!jsstr_alloc_buf(0, &null_bstr_str))
return FALSE;
return TRUE;
}
void free_strings(void)
{
jsstr_release(empty_str);
jsstr_release(nan_str);
jsstr_release(undefined_str);
if(empty_str)
jsstr_release(empty_str);
if(nan_str)
jsstr_release(nan_str);
if(undefined_str)
jsstr_release(undefined_str);
if(null_bstr_str)
jsstr_release(null_bstr_str);
}

View file

@ -16,35 +16,102 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* jsstr_t is a common header for all string representations. The exact layout of the string
* representation may be:
*
* - inline string - string bytes directly follow string headers.
* - heap string - a structure containing a pointer to buffer on the heap.
* - roper string - a product of concatenation of two strings. Instead of copying whole
* buffers, we may store just references to concatenated strings.
*
* String layout may change over life time of the string. Currently possible transformation
* is when a rope string becomes a heap stream. That happens when we need a real, linear
* zero-terminated buffer (a flat buffer). At this point the type of the string is changed
* and the new buffer is stored in the string, so that subsequent operations requiring
* a flat string won't need to flatten it again.
*
* In the future more layouts and transformations may be added.
*/
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
#define JSSTR_FLAG_LBIT 1
#define JSSTR_FLAG_FLAT 2
#define JSSTR_FLAG_TAG_MASK 3
typedef enum {
JSSTR_INLINE = JSSTR_FLAG_FLAT,
JSSTR_HEAP = JSSTR_FLAG_FLAT|JSSTR_FLAG_LBIT,
JSSTR_ROPE = JSSTR_FLAG_LBIT
} jsstr_tag_t;
static inline unsigned jsstr_length(jsstr_t *str)
{
return str->length_flags >> JSSTR_LENGTH_SHIFT;
}
static inline jsstr_tag_t jsstr_tag(jsstr_t *str)
{
return str->length_flags & JSSTR_FLAG_TAG_MASK;
}
static inline BOOL jsstr_is_inline(jsstr_t *str)
{
return jsstr_tag(str) == JSSTR_INLINE;
}
static inline BOOL jsstr_is_heap(jsstr_t *str)
{
return jsstr_tag(str) == JSSTR_HEAP;
}
static inline BOOL jsstr_is_rope(jsstr_t *str)
{
return jsstr_tag(str) == JSSTR_ROPE;
}
typedef struct {
jsstr_t str;
WCHAR buf[1];
} jsstr_inline_t;
typedef struct {
jsstr_t str;
WCHAR *buf;
} jsstr_heap_t;
typedef struct {
jsstr_t str;
jsstr_t *left;
jsstr_t *right;
unsigned depth;
} jsstr_rope_t;
jsstr_t *jsstr_alloc_len(const WCHAR*,unsigned) DECLSPEC_HIDDEN;
jsstr_t *jsstr_alloc_buf(unsigned) DECLSPEC_HIDDEN;
WCHAR *jsstr_alloc_buf(unsigned,jsstr_t**) DECLSPEC_HIDDEN;
static inline jsstr_t *jsstr_alloc(const WCHAR *str)
{
return jsstr_alloc_len(str, strlenW(str));
}
void jsstr_free(jsstr_t*) DECLSPEC_HIDDEN;
static inline void jsstr_release(jsstr_t *str)
{
if(!--str->ref)
heap_free(str);
if(!--str->ref) {
if(jsstr_is_inline(str))
heap_free(str);
else
jsstr_free(str);
}
}
static inline jsstr_t *jsstr_addref(jsstr_t *str)
@ -53,31 +120,74 @@ static inline jsstr_t *jsstr_addref(jsstr_t *str)
return str;
}
static inline BOOL jsstr_eq(jsstr_t *str1, jsstr_t *str2)
static inline jsstr_inline_t *jsstr_as_inline(jsstr_t *str)
{
unsigned len = jsstr_length(str1);
return len == jsstr_length(str2) && !memcmp(str1->str, str2->str, len*sizeof(WCHAR));
return CONTAINING_RECORD(str, jsstr_inline_t, str);
}
static inline jsstr_heap_t *jsstr_as_heap(jsstr_t *str)
{
return CONTAINING_RECORD(str, jsstr_heap_t, str);
}
static inline jsstr_rope_t *jsstr_as_rope(jsstr_t *str)
{
return CONTAINING_RECORD(str, jsstr_rope_t, str);
}
const WCHAR *jsstr_rope_flatten(jsstr_rope_t*) DECLSPEC_HIDDEN;
static inline const WCHAR *jsstr_flatten(jsstr_t *str)
{
return jsstr_is_inline(str) ? jsstr_as_inline(str)->buf
: jsstr_is_heap(str) ? jsstr_as_heap(str)->buf
: jsstr_rope_flatten(jsstr_as_rope(str));
}
void jsstr_extract(jsstr_t*,unsigned,unsigned,WCHAR*) DECLSPEC_HIDDEN;
static inline unsigned jsstr_flush(jsstr_t *str, WCHAR *buf)
{
unsigned len = jsstr_length(str);
memcpy(buf, str->str, len*sizeof(WCHAR));
if(jsstr_is_inline(str)) {
memcpy(buf, jsstr_as_inline(str)->buf, len*sizeof(WCHAR));
}else if(jsstr_is_heap(str)) {
memcpy(buf, jsstr_as_heap(str)->buf, len*sizeof(WCHAR));
}else {
jsstr_rope_t *rope = jsstr_as_rope(str);
jsstr_flush(rope->left, buf);
jsstr_flush(rope->right, buf+jsstr_length(rope->left));
}
return len;
}
static inline jsstr_t *jsstr_substr(jsstr_t *str, unsigned off, unsigned len)
{
return jsstr_alloc_len(str->str+off, len);
jsstr_t *ret;
WCHAR *ptr;
ptr = jsstr_alloc_buf(len, &ret);
if(ptr)
jsstr_extract(str, off, len, ptr);
return ret;
}
int jsstr_cmp(jsstr_t*,jsstr_t*) DECLSPEC_HIDDEN;
static inline BOOL jsstr_eq(jsstr_t *left, jsstr_t *right)
{
return jsstr_length(left) == jsstr_length(right) && !jsstr_cmp(left, right);
}
jsstr_t *jsstr_concat(jsstr_t*,jsstr_t*) DECLSPEC_HIDDEN;
jsstr_t *jsstr_nan(void) DECLSPEC_HIDDEN;
jsstr_t *jsstr_empty(void) DECLSPEC_HIDDEN;
jsstr_t *jsstr_undefined(void) DECLSPEC_HIDDEN;
jsstr_t *jsstr_null_bstr(void) DECLSPEC_HIDDEN;
BOOL is_null_bstr(jsstr_t*) DECLSPEC_HIDDEN;
BOOL init_strings(void) DECLSPEC_HIDDEN;
void free_strings(void) DECLSPEC_HIDDEN;

View file

@ -294,11 +294,13 @@ HRESULT variant_to_jsval(VARIANT *var, jsval_t *r)
case VT_BSTR: {
jsstr_t *str;
str = jsstr_alloc_len(V_BSTR(var), SysStringLen(V_BSTR(var)));
if(!str)
return E_OUTOFMEMORY;
if(!V_BSTR(var))
str->length_flags |= JSSTR_FLAG_NULLBSTR;
if(V_BSTR(var)) {
str = jsstr_alloc_len(V_BSTR(var), SysStringLen(V_BSTR(var)));
if(!str)
return E_OUTOFMEMORY;
}else {
str = jsstr_null_bstr();
}
*r = jsval_string(str);
return S_OK;
@ -351,7 +353,7 @@ HRESULT jsval_to_variant(jsval_t val, VARIANT *retv)
jsstr_t *str = get_string(val);
V_VT(retv) = VT_BSTR;
if(str->length_flags & JSSTR_FLAG_NULLBSTR) {
if(is_null_bstr(str)) {
V_BSTR(retv) = NULL;
}else {
V_BSTR(retv) = SysAllocStringLen(NULL, jsstr_length(str));
@ -502,16 +504,15 @@ static int hex_to_int(WCHAR c)
/* ECMA-262 3rd Edition 9.3.1 */
static HRESULT str_to_number(jsstr_t *str, double *ret)
{
const WCHAR *ptr = str->str;
const WCHAR *ptr;
BOOL neg = FALSE;
DOUBLE d = 0.0;
static const WCHAR infinityW[] = {'I','n','f','i','n','i','t','y'};
if(!ptr) {
*ret = 0;
return S_OK;
}
ptr = jsstr_flatten(str);
if(!ptr)
return E_OUTOFMEMORY;
while(isspaceW(*ptr))
ptr++;
@ -777,6 +778,23 @@ HRESULT to_string(script_ctx_t *ctx, jsval_t val, jsstr_t **str)
return *str ? S_OK : E_OUTOFMEMORY;
}
HRESULT to_flat_string(script_ctx_t *ctx, jsval_t val, jsstr_t **str, const WCHAR **ret_str)
{
HRESULT hres;
hres = to_string(ctx, val, str);
if(FAILED(hres))
return hres;
*ret_str = jsstr_flatten(*str);
if(!*ret_str) {
jsstr_release(*str);
return E_OUTOFMEMORY;
}
return S_OK;
}
/* ECMA-262 3rd Edition 9.9 */
HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp)
{
@ -897,7 +915,7 @@ HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTY
if(FAILED(hres))
break;
if(str->length_flags & JSSTR_FLAG_NULLBSTR) {
if(is_null_bstr(str)) {
V_BSTR(dst) = NULL;
break;
}

View file

@ -54,7 +54,7 @@ static inline NumberInstance *number_this(vdisp_t *jsthis)
return is_vclass(jsthis, JSCLASS_NUMBER) ? number_from_vdisp(jsthis) : NULL;
}
static inline void dtoa(double d, WCHAR *buf, int size, int *dec_point)
static inline void number_to_str(double d, WCHAR *buf, int size, int *dec_point)
{
ULONGLONG l;
int i;
@ -113,7 +113,7 @@ static inline jsstr_t *number_to_fixed(double val, int prec)
if(buf_size > NUMBER_DTOA_SIZE)
buf_size = NUMBER_DTOA_SIZE;
dtoa(val, buf, buf_size, &dec_point);
number_to_str(val, buf, buf_size, &dec_point);
dec_point++;
size = 0;
if(neg)
@ -125,11 +125,10 @@ static inline jsstr_t *number_to_fixed(double val, int prec)
if(prec)
size += prec+1;
ret = jsstr_alloc_buf(size);
str = jsstr_alloc_buf(size, &ret);
if(!ret)
return NULL;
str = ret->str;
size = buf_pos = 0;
if(neg)
str[size++] = '-';
@ -172,7 +171,7 @@ static inline jsstr_t *number_to_exponential(double val, int prec)
buf_size = prec+2;
if(buf_size<2 || buf_size>NUMBER_DTOA_SIZE)
buf_size = NUMBER_DTOA_SIZE;
dtoa(val, buf, buf_size, &dec_point);
number_to_str(val, buf, buf_size, &dec_point);
buf_size--;
if(prec == -1)
for(; buf_size>1 && buf[buf_size-1]=='0'; buf_size--)
@ -193,11 +192,10 @@ static inline jsstr_t *number_to_exponential(double val, int prec)
if(neg)
size++;
ret = jsstr_alloc_buf(size);
str = jsstr_alloc_buf(size, &ret);
if(!ret)
return NULL;
str = ret->str;
size = 0;
pbuf = buf;
if(neg)

View file

@ -71,12 +71,13 @@ static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
if(r) {
jsstr_t *ret;
WCHAR *ptr;
ret = jsstr_alloc_buf(9+strlenW(str));
if(!ret)
ptr = jsstr_alloc_buf(9+strlenW(str), &ret);
if(!ptr)
return E_OUTOFMEMORY;
sprintfW(ret->str, formatW, str);
sprintfW(ptr, formatW, str);
*r = jsval_string(ret);
}
@ -129,9 +130,14 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl
return hres;
if(is_jsdisp(jsthis)) {
const WCHAR *name_str;
BOOL result;
hres = jsdisp_is_own_prop(jsthis->u.jsdisp, name->str, &result);
name_str = jsstr_flatten(name);
if(name_str)
hres = jsdisp_is_own_prop(jsthis->u.jsdisp, name_str, &result);
else
hres = E_OUTOFMEMORY;
jsstr_release(name);
if(FAILED(hres))
return hres;
@ -163,7 +169,8 @@ static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD fl
static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
{
jsstr_t *name;
const WCHAR *name;
jsstr_t *name_str;
BOOL ret;
HRESULT hres;
@ -179,12 +186,12 @@ static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, W
return E_FAIL;
}
hres = to_string(ctx, argv[0], &name);
hres = to_flat_string(ctx, argv[0], &name_str, &name);
if(FAILED(hres))
return hres;
hres = jsdisp_is_enumerable(jsthis->u.jsdisp, name->str, &ret);
jsstr_release(name);
hres = jsdisp_is_enumerable(jsthis->u.jsdisp, name, &ret);
jsstr_release(name_str);
if(FAILED(hres))
return hres;

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,8 @@
/* A Bison parser, made by GNU Bison 2.5. */
/* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton interface for Bison's Yacc-like parsers in C
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -92,8 +90,8 @@
typedef union YYSTYPE
{
/* Line 1676 of yacc.c */
#line 145 "parser.y"
/* Line 2068 of yacc.c */
#line 144 "parser.y"
int ival;
const WCHAR *srcptr;
@ -116,8 +114,8 @@ typedef union YYSTYPE
/* Line 1676 of yacc.c */
#line 121 "parser.tab.h"
/* Line 2068 of yacc.c */
#line 119 "parser.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */

View file

@ -25,10 +25,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
#define YYLEX_PARAM ctx
#define YYPARSE_PARAM ctx
static int parser_error(const char*);
static int parser_error(parser_ctx_t*,const char*);
static void set_error(parser_ctx_t*,UINT);
static BOOL explicit_error(parser_ctx_t*,void*,WCHAR);
static BOOL allow_auto_semicolon(parser_ctx_t*);
@ -139,7 +136,9 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
%}
%pure_parser
%lex-param { parser_ctx_t *ctx }
%parse-param { parser_ctx_t *ctx }
%pure-parser
%start Program
%union {

View file

@ -90,6 +90,22 @@ static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, jsstr_t **val)
return to_string(ctx, jsval_disp(jsthis->u.disp), val);
}
static HRESULT get_string_flat_val(script_ctx_t *ctx, vdisp_t *jsthis, jsstr_t **jsval, const WCHAR **val)
{
HRESULT hres;
hres = get_string_val(ctx, jsthis, jsval);
if(FAILED(hres))
return hres;
*val = jsstr_flatten(*jsval);
if(*val)
return S_OK;
jsstr_release(*jsval);
return E_OUTOFMEMORY;
}
static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
{
@ -160,13 +176,12 @@ static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, j
tagname_len = strlenW(tagname);
ret = jsstr_alloc_buf(jsstr_length(str) + 2*tagname_len + 5);
ptr = jsstr_alloc_buf(jsstr_length(str) + 2*tagname_len + 5, &ret);
if(!ret) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
ptr = ret->str;
*ptr++ = '<';
memcpy(ptr, tagname, tagname_len*sizeof(WCHAR));
ptr += tagname_len;
@ -209,11 +224,10 @@ static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, unsig
unsigned attrname_len = strlenW(attrname);
unsigned tagname_len = strlenW(tagname);
jsstr_t *ret;
WCHAR *ptr;
ret = jsstr_alloc_buf(2*tagname_len + attrname_len + jsstr_length(attr_value) + jsstr_length(str) + 9);
if(ret) {
WCHAR *ptr = ret->str;
ptr = jsstr_alloc_buf(2*tagname_len + attrname_len + jsstr_length(attr_value) + jsstr_length(str) + 9, &ret);
if(ptr) {
*ptr++ = '<';
memcpy(ptr, tagname, tagname_len*sizeof(WCHAR));
ptr += tagname_len;
@ -349,8 +363,11 @@ static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
idx = d;
}
if(r)
*r = jsval_number(str->str[idx]);
if(r) {
WCHAR c;
jsstr_extract(str, idx, 1, &c);
*r = jsval_number(c);
}
jsstr_release(str);
return S_OK;
@ -360,52 +377,80 @@ 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)
{
unsigned len = 0, i, str_cnt;
jsstr_t **strs, *ret = NULL;
WCHAR *ptr;
jsstr_t *ret, *str;
HRESULT hres;
TRACE("\n");
str_cnt = argc+1;
strs = heap_alloc_zero(str_cnt * sizeof(*strs));
if(!strs)
return E_OUTOFMEMORY;
hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
hres = to_string(ctx, jsval_disp(jsthis->u.disp), strs);
if(SUCCEEDED(hres)) {
switch(argc) {
case 0:
ret = str;
break;
case 1: {
jsstr_t *arg_str;
hres = to_string(ctx, argv[0], &arg_str);
if(FAILED(hres)) {
jsstr_release(str);
return hres;
}
ret = jsstr_concat(str, arg_str);
jsstr_release(str);
if(!ret)
return E_OUTOFMEMORY;
break;
}
default: {
const unsigned str_cnt = argc+1;
unsigned len = 0, i;
jsstr_t **strs;
WCHAR *ptr;
strs = heap_alloc_zero(str_cnt * sizeof(*strs));
if(!strs) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
strs[0] = str;
for(i=0; i < argc; i++) {
hres = to_string(ctx, argv[i], strs+i+1);
if(FAILED(hres))
break;
}
}
if(SUCCEEDED(hres)) {
for(i=0; i < str_cnt; i++) {
len += jsstr_length(strs[i]);
if(len > JSSTR_MAX_LENGTH) {
hres = E_OUTOFMEMORY;
break;
if(SUCCEEDED(hres)) {
for(i=0; i < str_cnt; i++) {
len += jsstr_length(strs[i]);
if(len > JSSTR_MAX_LENGTH) {
hres = E_OUTOFMEMORY;
break;
}
}
if(SUCCEEDED(hres)) {
ptr = jsstr_alloc_buf(len, &ret);
if(ptr) {
for(i=0; i < str_cnt; i++)
ptr += jsstr_flush(strs[i], ptr);
}else {
hres = E_OUTOFMEMORY;
}
}
}
ret = jsstr_alloc_buf(len);
if(ret) {
ptr = ret->str;
for(i=0; i < str_cnt; i++)
ptr += jsstr_flush(strs[i], ptr);
}else {
hres = E_OUTOFMEMORY;
}
while(i--)
jsstr_release(strs[i]);
heap_free(strs);
if(FAILED(hres))
return hres;
}
}
for(i=0; i < str_cnt; i++)
jsstr_release(strs[i]);
heap_free(strs);
if(FAILED(hres))
return hres;
if(r)
*r = jsval_string(ret);
@ -442,28 +487,29 @@ 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)
{
jsstr_t *search_str, *str;
jsstr_t *search_jsstr, *jsstr;
const WCHAR *search_str, *str;
int length, pos = 0;
INT ret = -1;
HRESULT hres;
TRACE("\n");
hres = get_string_val(ctx, jsthis, &str);
hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
if(FAILED(hres))
return hres;
length = jsstr_length(str);
length = jsstr_length(jsstr);
if(!argc) {
if(r)
*r = jsval_number(-1);
jsstr_release(str);
jsstr_release(jsstr);
return S_OK;
}
hres = to_string(ctx, argv[0], &search_str);
hres = to_flat_string(ctx, argv[0], &search_jsstr, &search_str);
if(FAILED(hres)) {
jsstr_release(str);
jsstr_release(jsstr);
return hres;
}
@ -478,15 +524,15 @@ static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
if(SUCCEEDED(hres)) {
const WCHAR *ptr;
ptr = strstrW(str->str+pos, search_str->str);
ptr = strstrW(str+pos, search_str);
if(ptr)
ret = ptr - str->str;
ret = ptr - str;
else
ret = -1;
}
jsstr_release(search_str);
jsstr_release(str);
jsstr_release(search_jsstr);
jsstr_release(jsstr);
if(FAILED(hres))
return hres;
@ -507,31 +553,32 @@ static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
jsval_t *r)
{
unsigned pos = 0, search_len, length;
jsstr_t *search_str, *str;
jsstr_t *search_jsstr, *jsstr;
const WCHAR *search_str, *str;
INT ret = -1;
HRESULT hres;
TRACE("\n");
hres = get_string_val(ctx, jsthis, &str);
hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
if(FAILED(hres))
return hres;
if(!argc) {
if(r)
*r = jsval_number(-1);
jsstr_release(str);
jsstr_release(jsstr);
return S_OK;
}
hres = to_string(ctx, argv[0], &search_str);
hres = to_flat_string(ctx, argv[0], &search_jsstr, &search_str);
if(FAILED(hres)) {
jsstr_release(str);
jsstr_release(jsstr);
return hres;
}
search_len = jsstr_length(search_str);
length = jsstr_length(str);
search_len = jsstr_length(search_jsstr);
length = jsstr_length(jsstr);
if(argc >= 2) {
double d;
@ -546,16 +593,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->str+min(pos, length-search_len); ptr >= str->str; ptr--) {
if(!memcmp(ptr, search_str->str, search_len*sizeof(WCHAR))) {
ret = ptr-str->str;
for(ptr = str+min(pos, length-search_len); ptr >= str; ptr--) {
if(!memcmp(ptr, search_str, search_len*sizeof(WCHAR))) {
ret = ptr-str;
break;
}
}
}
jsstr_release(search_str);
jsstr_release(str);
jsstr_release(search_jsstr);
jsstr_release(jsstr);
if(FAILED(hres))
return hres;
@ -625,36 +672,54 @@ typedef struct {
DWORD len;
} strbuf_t;
static BOOL strbuf_ensure_size(strbuf_t *buf, unsigned len)
{
WCHAR *new_buf;
DWORD new_size;
if(len <= buf->size)
return TRUE;
new_size = buf->size ? buf->size<<1 : 16;
if(new_size < len)
new_size = len;
if(buf->buf)
new_buf = heap_realloc(buf->buf, new_size*sizeof(WCHAR));
else
new_buf = heap_alloc(new_size*sizeof(WCHAR));
if(!new_buf)
return FALSE;
buf->buf = new_buf;
buf->size = new_size;
return TRUE;
}
static HRESULT strbuf_append(strbuf_t *buf, const WCHAR *str, DWORD len)
{
if(!len)
return S_OK;
if(len + buf->len > buf->size) {
WCHAR *new_buf;
DWORD new_size;
new_size = buf->size ? buf->size<<1 : 16;
if(new_size < buf->len+len)
new_size = buf->len+len;
if(buf->buf)
new_buf = heap_realloc(buf->buf, new_size*sizeof(WCHAR));
else
new_buf = heap_alloc(new_size*sizeof(WCHAR));
if(!new_buf)
return E_OUTOFMEMORY;
buf->buf = new_buf;
buf->size = new_size;
}
if(!strbuf_ensure_size(buf, buf->len+len))
return E_OUTOFMEMORY;
memcpy(buf->buf+buf->len, str, len*sizeof(WCHAR));
buf->len += len;
return S_OK;
}
static HRESULT strbuf_append_jsstr(strbuf_t *buf, jsstr_t *str)
{
if(!strbuf_ensure_size(buf, buf->len+jsstr_length(str)))
return E_OUTOFMEMORY;
jsstr_flush(str, buf->buf+buf->len);
buf->len += jsstr_length(str);
return S_OK;
}
static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
jsstr_t *str, match_state_t *match, jsstr_t **ret)
jsstr_t *jsstr, const WCHAR *str, match_state_t *match, jsstr_t **ret)
{
jsval_t *argv;
unsigned argc;
@ -676,7 +741,7 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
if(SUCCEEDED(hres)) {
for(i=0; i < match->paren_count; i++) {
if(match->parens[i].index != -1)
tmp_str = jsstr_substr(str, match->parens[i].index, match->parens[i].length);
tmp_str = jsstr_substr(jsstr, match->parens[i].index, match->parens[i].length);
else
tmp_str = jsstr_empty();
if(!tmp_str) {
@ -688,8 +753,8 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
}
if(SUCCEEDED(hres)) {
argv[match->paren_count+1] = jsval_number(match->cp-str->str - match->match_len);
argv[match->paren_count+2] = jsval_string(str);
argv[match->paren_count+1] = jsval_number(match->cp-str - match->match_len);
argv[match->paren_count+2] = jsval_string(jsstr);
}
if(SUCCEEDED(hres))
@ -711,25 +776,26 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
{
DWORD rep_len=0;
jsstr_t *rep_str = NULL, *match_str = NULL, *str;
const WCHAR *str, *match_str = NULL, *rep_str = NULL;
jsstr_t *rep_jsstr, *match_jsstr, *jsstr;
jsdisp_t *rep_func = NULL, *regexp = NULL;
match_state_t *match = NULL, last_match = {0};
strbuf_t ret = {NULL,0,0};
DWORD re_flags = REM_NO_CTX_UPDATE|REM_ALLOC_RESULT;
DWORD rep_len=0;
HRESULT hres = S_OK;
TRACE("\n");
hres = get_string_val(ctx, jsthis, &str);
hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
if(FAILED(hres))
return hres;
if(!argc) {
if(r)
*r = jsval_string(str);
*r = jsval_string(jsstr);
else
jsstr_release(str);
jsstr_release(jsstr);
return S_OK;
}
@ -742,9 +808,9 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
}
if(!regexp) {
hres = to_string(ctx, argv[0], &match_str);
hres = to_flat_string(ctx, argv[0], &match_jsstr, &match_str);
if(FAILED(hres)) {
jsstr_release(str);
jsstr_release(jsstr);
return hres;
}
}
@ -759,18 +825,18 @@ 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);
hres = to_flat_string(ctx, argv[1], &rep_jsstr, &rep_str);
if(SUCCEEDED(hres))
rep_len = jsstr_length(rep_str);
rep_len = jsstr_length(rep_jsstr);
}
}
if(SUCCEEDED(hres)) {
const WCHAR *ecp = str->str;
const WCHAR *ecp = str;
while(1) {
if(regexp) {
hres = regexp_match_next(ctx, regexp, re_flags, str, &match);
hres = regexp_match_next(ctx, regexp, re_flags, jsstr, &match);
re_flags = (re_flags | REM_CHECK_GLOBAL) & (~REM_ALLOC_RESULT);
if(hres == S_FALSE) {
@ -786,13 +852,13 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
if(re_flags & REM_ALLOC_RESULT) {
re_flags &= ~REM_ALLOC_RESULT;
match = &last_match;
match->cp = str->str;
match->cp = str;
}
match->cp = strstrW(match->cp, match_str->str);
match->cp = strstrW(match->cp, match_str);
if(!match->cp)
break;
match->match_len = jsstr_length(match_str);
match->match_len = jsstr_length(match_jsstr);
match->cp += match->match_len;
}
@ -804,16 +870,16 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
if(rep_func) {
jsstr_t *cstr;
hres = rep_call(ctx, rep_func, str, match, &cstr);
hres = rep_call(ctx, rep_func, jsstr, str, match, &cstr);
if(FAILED(hres))
break;
hres = strbuf_append(&ret, cstr->str, jsstr_length(cstr));
hres = strbuf_append_jsstr(&ret, cstr);
jsstr_release(cstr);
if(FAILED(hres))
break;
}else if(rep_str && regexp) {
const WCHAR *ptr = rep_str->str, *ptr2;
const WCHAR *ptr = rep_str, *ptr2;
while((ptr2 = strchrW(ptr, '$'))) {
hres = strbuf_append(&ret, ptr, ptr2-ptr);
@ -830,11 +896,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->str, match->cp-str->str-match->match_len);
hres = strbuf_append(&ret, str, match->cp-str-match->match_len);
ptr = ptr2+2;
break;
case '\'':
hres = strbuf_append(&ret, ecp, (str->str+jsstr_length(str))-ecp);
hres = strbuf_append(&ret, ecp, (str+jsstr_length(jsstr))-ecp);
ptr = ptr2+2;
break;
default: {
@ -859,7 +925,7 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
}
if(match->parens[idx-1].index != -1)
hres = strbuf_append(&ret, str->str+match->parens[idx-1].index,
hres = strbuf_append(&ret, str+match->parens[idx-1].index,
match->parens[idx-1].length);
}
}
@ -869,11 +935,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->str+rep_len)-ptr);
hres = strbuf_append(&ret, ptr, (rep_str+rep_len)-ptr);
if(FAILED(hres))
break;
}else if(rep_str) {
hres = strbuf_append(&ret, rep_str->str, rep_len);
hres = strbuf_append(&ret, rep_str, rep_len);
if(FAILED(hres))
break;
}else {
@ -891,28 +957,28 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
}
if(SUCCEEDED(hres))
hres = strbuf_append(&ret, ecp, str->str+jsstr_length(str)-ecp);
hres = strbuf_append(&ret, ecp, str+jsstr_length(jsstr)-ecp);
}
if(rep_func)
jsdisp_release(rep_func);
if(rep_str)
jsstr_release(rep_str);
jsstr_release(rep_jsstr);
if(match_str)
jsstr_release(match_str);
jsstr_release(match_jsstr);
if(regexp)
heap_free(match);
if(SUCCEEDED(hres) && last_match.cp && regexp) {
jsstr_release(ctx->last_match);
ctx->last_match = jsstr_addref(str);
ctx->last_match_index = last_match.cp-str->str-last_match.match_len;
ctx->last_match = jsstr_addref(jsstr);
ctx->last_match_index = last_match.cp-str-last_match.match_len;
ctx->last_match_length = last_match.match_len;
}
if(regexp)
jsdisp_release(regexp);
jsstr_release(str);
jsstr_release(jsstr);
if(SUCCEEDED(hres) && r) {
jsstr_t *ret_str;
@ -933,20 +999,21 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
jsval_t *r)
{
jsdisp_t *regexp = NULL;
jsstr_t *str;
const WCHAR *str;
jsstr_t *jsstr;
match_state_t match, *match_ptr = &match;
HRESULT hres;
TRACE("\n");
hres = get_string_val(ctx, jsthis, &str);
hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
if(FAILED(hres))
return hres;
if(!argc) {
if(r)
*r = jsval_null();
jsstr_release(str);
jsstr_release(jsstr);
return S_OK;
}
@ -961,20 +1028,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, &regexp);
if(FAILED(hres)) {
jsstr_release(str);
jsstr_release(jsstr);
return hres;
}
}
match.cp = str->str;
hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX|REM_NO_PARENS, str, &match_ptr);
jsstr_release(str);
match.cp = str;
hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX|REM_NO_PARENS, jsstr, &match_ptr);
jsstr_release(jsstr);
jsdisp_release(regexp);
if(FAILED(hres))
return hres;
if(r)
*r = jsval_number(hres == S_OK ? match.cp-match.match_len-str->str : -1);
*r = jsval_number(hres == S_OK ? match.cp-match.match_len-str : -1);
return S_OK;
}
@ -1067,10 +1134,10 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
{
match_state_t match_result, *match_ptr = &match_result;
DWORD length, i, match_len = 0;
const WCHAR *ptr, *ptr2;
const WCHAR *ptr, *ptr2, *str, *match_str = NULL;
unsigned limit = UINT32_MAX;
jsdisp_t *array, *regexp = NULL;
jsstr_t *str, *match_str = NULL, *tmp_str;
jsstr_t *jsstr, *match_jsstr, *tmp_str;
HRESULT hres;
TRACE("\n");
@ -1080,16 +1147,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);
hres = get_string_flat_val(ctx, jsthis, &jsstr, &str);
if(FAILED(hres))
return hres;
length = jsstr_length(str);
length = jsstr_length(jsstr);
if(argc > 1 && !is_undefined(argv[1])) {
hres = to_uint32(ctx, argv[1], &limit);
if(FAILED(hres)) {
jsstr_release(str);
jsstr_release(jsstr);
return hres;
}
}
@ -1105,15 +1172,15 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
}
if(!regexp) {
hres = to_string(ctx, argv[0], &match_str);
hres = to_flat_string(ctx, argv[0], &match_jsstr, &match_str);
if(FAILED(hres)) {
jsstr_release(str);
jsstr_release(jsstr);
return hres;
}
match_len = jsstr_length(match_str);
match_len = jsstr_length(match_jsstr);
if(!match_len) {
jsstr_release(match_str);
jsstr_release(match_jsstr);
match_str = NULL;
}
}
@ -1121,16 +1188,16 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
hres = create_array(ctx, 0, &array);
if(SUCCEEDED(hres)) {
ptr = str->str;
match_result.cp = str->str;
ptr = str;
match_result.cp = str;
for(i=0; i<limit; i++) {
if(regexp) {
hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, str, &match_ptr);
hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, jsstr, &match_ptr);
if(hres != S_OK)
break;
ptr2 = match_result.cp - match_result.match_len;
}else if(match_str) {
ptr2 = strstrW(ptr, match_str->str);
ptr2 = strstrW(ptr, match_str);
if(!ptr2)
break;
}else {
@ -1160,7 +1227,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
}
if(SUCCEEDED(hres) && (match_str || regexp) && i<limit) {
DWORD len = (str->str+length) - ptr;
DWORD len = (str+length) - ptr;
if(len || match_str) {
tmp_str = jsstr_alloc_len(ptr, len);
@ -1177,8 +1244,8 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
if(regexp)
jsdisp_release(regexp);
if(match_str)
jsstr_release(match_str);
jsstr_release(str);
jsstr_release(match_jsstr);
jsstr_release(jsstr);
if(SUCCEEDED(hres) && r)
*r = jsval_obj(array);
@ -1337,15 +1404,16 @@ static HRESULT String_toLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
if(r) {
jsstr_t *ret;
WCHAR *buf;
ret = jsstr_alloc_buf(jsstr_length(str));
if(!ret) {
buf = jsstr_alloc_buf(jsstr_length(str), &ret);
if(!buf) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
jsstr_flush(str, ret->str);
strlwrW(ret->str);
jsstr_flush(str, buf);
strlwrW(buf);
*r = jsval_string(ret);
}
jsstr_release(str);
@ -1366,15 +1434,16 @@ static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
if(r) {
jsstr_t *ret;
WCHAR *buf;
ret = jsstr_alloc_buf(jsstr_length(str));
if(!ret) {
buf = jsstr_alloc_buf(jsstr_length(str), &ret);
if(!buf) {
jsstr_release(str);
return E_OUTOFMEMORY;
}
jsstr_flush(str, ret->str);
struprW(ret->str);
jsstr_flush(str, buf);
struprW(buf);
*r = jsval_string(ret);
}
jsstr_release(str);
@ -1525,14 +1594,15 @@ static const builtin_info_t StringInst_info = {
static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
WCHAR *ret_str;
DWORD i, code;
jsstr_t *ret;
HRESULT hres;
TRACE("\n");
ret = jsstr_alloc_buf(argc);
if(!ret)
ret_str = jsstr_alloc_buf(argc, &ret);
if(!ret_str)
return E_OUTOFMEMORY;
for(i=0; i<argc; i++) {
@ -1542,7 +1612,7 @@ static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WOR
return hres;
}
ret->str[i] = code;
ret_str[i] = code;
}
if(r)

View file

@ -91,7 +91,7 @@ reactos/dll/win32/inseng # Synced to Wine-1.7.1
reactos/dll/win32/iphlpapi # Out of sync
reactos/dll/win32/itircl # Synced to Wine-1.7.1
reactos/dll/win32/itss # Synced to Wine-1.7.1
reactos/dll/win32/jscript # Synced to Wine-1.5.26
reactos/dll/win32/jscript # Synced to Wine-1.7.1
reactos/dll/win32/loadperf # Synced to Wine-1.5.19
reactos/dll/win32/localspl # Synced to Wine-1.5.26
reactos/dll/win32/localui # Synced to Wine-1.5.19