mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
[JSCRIPT]
* Sync with Wine 1.7.1. CORE-7469 svn path=/trunk/; revision=60246
This commit is contained in:
parent
528ebe204e
commit
6cc49a4a0b
23 changed files with 1872 additions and 1314 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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, ®exp->dispex, REM_RESET_INDEX, string, &match);
|
||||
hres = regexp_match_next(ctx, ®exp->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, ®exp);
|
||||
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(®exp->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, ®exp->dispex, 0, str, &match);
|
||||
hres = regexp_match_next(ctx, ®exp->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, ®exp->dispex, str, FALSE, &match_result, &match_cnt);
|
||||
hres = regexp_match(ctx, ®exp->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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
@ -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 */
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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, ®exp);
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue